http.rst 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. HTTP interface
  2. ==============
  3. If you want to use the Modelverse on an as of yet unsupported platform, you will have to make use of the HTTP interface directly.
  4. While it is possible to directly send HTTP requests, it is recommended to create a wrapper, similar to the Python wrapper mentioned before.
  5. Otherwise, many of the more complex operations (e.g., process enactment) will quickly result in problems.
  6. Now follows a detailed description of how the HTTP interface works.
  7. An explanation of the semantics of these operations can be found in the Python wrapper, as these operations are almost a 1-to-1 mapping, with the Python wrapper being a reference implementation.
  8. The Python wrapper proves a valuable starting point for creating new interfaces.
  9. Request and Reply format
  10. ------------------------
  11. HTTP requests to the Modelverse use the POST format, and should be directed at the location at which the Modelverse server is running.
  12. The request itself is a URL encoded form of the following dictionary: ``{"op": operation, "value": value, "taskname": taskname}``.
  13. In this format, the operation is either *set_input* or *get_output*, with the logical meanings (see further).
  14. Value is only present if the operation is *set_input*, and contains a JSON serialized value to set as input.
  15. For multiple simultaneous requests, it is possible to not use a key *value*, but a key *data*.
  16. If the data key is present, this should contain a JSON serialized representation of multiple invocations.
  17. The semantics is identical, except that only a single HTTP request (and reply) is used, thereby optimizing performance.
  18. Finally, the taskname indicates the task to which the request is targetted.
  19. Tasknames are provided by the Modelverse when necessary.
  20. Fetching data from the Modelverse is done using the *get_output* operation, which is blocking until an output is present.
  21. Note that a timeout might occur if no output becomes available within the time specified as the HTTP output.
  22. This is not a problem, but should be handled.
  23. Output requests are handled in a FIFO manner, as multiple calls can be made for output simultaneously.
  24. Apart from the primitive types usually supported by JSON, action language primitives can also be sent.
  25. These are JSON serialized as a dictionary, with a single key *value* and its value being the string representation of the element.
  26. For example, an *If* construct is serialized as ``{"value":"If"}``.
  27. The Modelverse understands this special case, but the interface should also be able to handle such data.
  28. Note that communication of these internal primitive types is extremely rare.
  29. The reply is always very simple.
  30. For a *set_input* operation, the reply merely indicates that the input is put in the input queue of the task, and the content of the reply can be ignored.
  31. This does **NOT** mean that the input has been processed by the task itself, but only that the input is visible to the task.
  32. For a *get_output* operation, the reply contains a JSON serialized representation of the output data put in the Modelverse.
  33. This is always a primitive type of JSON, and will never be a list or dictionary.
  34. .. note::
  35. Communication over HTTP uses a POST request to allow for arbitrary amounts of data to be transfered.
  36. The Modelverse ignores GET requests.
  37. This nicely follows the REST standards, as all requests indeed have the potential to alter the state of the Modelverse: only the MvK gives semantics to the operations, and a *read* command could very well write out something.
  38. Examples
  39. ^^^^^^^^
  40. To send the integer 1 to the task with name *abc* in the Modelverse, send the following data in the POST request::
  41. op=set_input&value=1&taskname=abc
  42. To send the string *def* to the task with name *xyz* in the Modelverse, send the following data in the POST request::
  43. op=set_input&value="def"&taskname=xyz
  44. To send both the integer 1 and the string *def* to the task with name *abc* in the Modelverse, send either two seperate requests, or a single request::
  45. op=set_input&data=[1,"def"]&taskname=xyz
  46. To fetch the output value of a task *xyz* in the Modelverse, send the following HTTP request, which yields (possibly) the following answer::
  47. op=get_output&taskname=xyz
  48. "The output value is a string containing a JSON serialized value."
  49. Additional keys can be provided, but they are ignored by the Modelverse.
  50. Startup
  51. -------
  52. When starting up the Modelverse, only a simple task manager is running.
  53. A new task can be created by querying this task manager for a new taskname.
  54. This is done by fetching the output of the task manager as follows::
  55. op=get_output&taskname=task_manager
  56. The reply to this query contains a new taskname to be used in subsequent requests.
  57. For legacy purposes, it is also possible to send a new taskname to the task manager directly, which will subsequently be generated if it doesn't exist yet.
  58. This approach is deprecated, as it is easy to run into problems when two users request the same taskname.
  59. These problems are avoided when using the new approach, as the Modelverse guarantees that it always outputs a unique taskname.
  60. Additionally, the new approach allows the task manager to prepare new tasks, such that they are available much sooner.
  61. Operations
  62. ----------
  63. Upon startup of a task, the communication starts in verbose mode to allow for interactive use.
  64. This means that initially, every sent input will result in one (or multiple) output values.
  65. For a wrapper this is cumbersome, as it creates a lot of HTTP requests (and overhead).
  66. It is possible to reduce the amount of communication by sending the input *quiet*.
  67. For a more detailed overview of all operations, their order and possible interleavings, and their possible responses, we refer to the SCCD model in *wrappers/classes/modelverse.xml*.
  68. The first two input values that are to be sent are the username and password, which can happen using the following request::
  69. op=set_input&data=["my username","my password"]&taskname=name_of_new_task
  70. Depending on the output values received, it can be determined whether this is a new or existing user.
  71. If this is a new user, a subsequent request should again send the password to confirm the password.
  72. If this is an existing user, the task continues and is now logged in.
  73. When logged in, there are three possible modes: megamodelling, modelling, and service.
  74. Apart from the responses mentioned here, several other responses are also possible, though these are exceptions.
  75. All ordinary responses to operations start with *Success:*, or merely *Success* if there is no value to output.
  76. Megamodelling
  77. ^^^^^^^^^^^^^
  78. In megamodelling mode, which is the first mode to be entered after login, users can modify the megamodel, containing the relation of all models in the Modelverse.
  79. It is in this mode that new models should be created, models should be deleted, or new transformations be defined.
  80. Additionally, as all user access control is modelled explicitly in this same megamodel, this is also the mode in which user management is done.
  81. There are two operations to allow mode switching: *model_modify* and *service_register*.
  82. To go to modelling, send *model_modify*, followed by the name of the model you wish to open and the name of the metamodel that should be used.
  83. For example::
  84. op=set_input&data=["model_modify","formalisms/ProcessModel","formalisms/SimpleClassDiagrams"]&taskname=xyz
  85. To go to service mode, send *service_register*, followed by the name of the service that is to be registered.
  86. For example::
  87. op=set_input&data=["service_register","HUTN_compiler"]&taskname=xyz
  88. In megamodelling mode, the following simple operations are supported.
  89. For each request, the output normally starts with a *Success*, following the actual return value as a string.
  90. As all responses are strings, there is some encoding to them (e.g., split on newlines, split on colon, ...).
  91. Most are trivial to deserialize when the result comes in, and therefore we refer to the SCCD model.
  92. While operation and parameters are shown distinct in the table, the HTTP request merely sends them in exactly the same fashion.
  93. For example::
  94. op=set_input&data=["model_modify","formalisms/ProcessModel","formalisms/PM"]&taskname=xyz
  95. For each operation, we specify some information on the return value.
  96. If the return value is only *"Success"*, this means that no return value is sent.
  97. Otherwise, the return value starts with *"Success: "*, and the return value starts afterwards.
  98. This is used to distinguish successful execution from exceptions.
  99. The returnvalue can consist of a single value, or of a list of values, encoded as a single string, separated by newline characters.
  100. For example, the result of *"model_list"* can be the string *"Success: a\nb\nc"*, indicating that execution was successful and that the models *a*, *b*, and *c* are present at the requested location.
  101. More complex returnvalues specify multiple elements in a single line (i.e., a tuple), for which the order and encoding is described in more detail.
  102. Some more complex operations are mentioned below these standard operations.
  103. ============================= ====================================== ====================================================================
  104. operation parameters returnvalue
  105. ============================= ====================================== ====================================================================
  106. model_move model_name, new_location (none)
  107. process_signature process_name set of dictionary entries "key : metamodel"
  108. transformation_between source_name, target_name set of locations
  109. model_render model_name, mapper_name, rendered_name JSON representation of model
  110. model_rendered model_name, mapper_name set of locations
  111. verify model_name, metamodel_name string containing conformance result ("OK" indicates conforming)
  112. model_delete model_name (none)
  113. model_list location set of locations
  114. model_list_full location set of "permission owner group location"
  115. permission_modify model_name, permissions (none)
  116. permission_owner model_name, owner (none)
  117. permission_group model_name, group (none)
  118. group_create group (none)
  119. group_delete group (none)
  120. group_owner_add group, user (none)
  121. group_owner_delete group, user (none)
  122. group_join group, user (none)
  123. group_kick group, user (none)
  124. group_list set of group names
  125. admin_promote user (none)
  126. admin_demote user (none)
  127. user_password user, password (none)
  128. transformation_read_signature transformation_name set of "type key metamodel" with type either I (input) or O (output)
  129. verbose (none)
  130. quiet (none)
  131. folder_create location (none)
  132. add_conformance model_name, metamodel_name (none)
  133. model_types model_name set of "location type_mapping conformance_semantics"
  134. AL_text location AL text representation
  135. model_add metamodel_name, model_name, code (none)
  136. ============================= ====================================== ====================================================================
  137. More complex operations have multiple phases, as there is a modification step involved, or a preliminary check before the next piece of data can be forwarded.
  138. These operations are presented next.
  139. ========================= =============================================== ==========================
  140. operation parameters returnvalue
  141. ========================= =============================================== ==========================
  142. model_overwrite model_name, metamodel_name (none)
  143. transformation_add_MANUAL source_models\*, target_models\*, name (none)
  144. transformation_add_AL source_models\*, target_models\*, name (none)
  145. transformation_add_MT source_models\*, target_models\*, name (none)
  146. transformation_execute activity_name, source_models\*, target_models\* (none) or "Failure"
  147. process_execute process_name, model_bindings\* (none)
  148. ========================= =============================================== ==========================
  149. Parameters marked with a \* are actually dictionaries, and should be sent as such.
  150. Since the Modelverse has no primitive notion of dictionaries, a dictionary is expanded as a sequence of key value pairs, terminated with an empty key.
  151. For example, the dictionary ``{"abc": "def", "ghi": "jkl"}`` is sent as five individual requests (or a single data request)::
  152. ...&data=["abc","def","ghi","jkl",""]&...
  153. For the model_overwrite operation, the Modelverse will first perform some checks as to whether the overwritten model can indeed be overwritten.
  154. If so, it will output the reply *Waiting for model constructors...*, after which the actual code may be sent.
  155. The operations starting with *transformation_add* are similar, but they have two phases.
  156. First, they output the name of the merged metamodel, ready to be RAMified.
  157. There is then the possibility to modify this metamodel before RAMification starts, by logging in using a different task, modifying the model, and storing the changes.
  158. As soon as all changes are made, any input will initiate RAMification.
  159. Second, the Modelverse will query for the code that specify the transformation.
  160. For manual operations, this query is not done.
  161. For AL, this query expects ActionLanguage code.
  162. For MT, this query expects a model conforming to the RAMified metamodel.
  163. Of course, these constructors can be passed an empty model, in which case the models have to be updated later on using *model_modify*.
  164. The *transformation_execute* operation and *process_execute* are special operations, in the sense that they (potentially) spawn other tasks.
  165. The output value of these operations is the name of a newly spawned task, on which execution should continue.
  166. These tasks might not be identical to other tasks, in the sense that they are purely able to communicate with the currently executing operation.
  167. This operation is rather complex, and we refer to the SCCD model for detailed information.
  168. The *process_execute* operation is similar, but instead of outputting only a single taskname, we output multiple, combined with the activity that spawned it.
  169. Modelling
  170. ^^^^^^^^^
  171. In modelling mode, a single model is opened and ready to be modified.
  172. There are several supported operations, most of which are simple to use.
  173. To switch back to megamodelling mode, send the *exit* input.
  174. ============================ ============================= ======================================================
  175. operation parameters returnvalue
  176. ============================ ============================= ======================================================
  177. instantiate_node type, element ID of created element
  178. instantiate_edge type, element, source, target ID of created element
  179. attr_add element, attribute, value (none)
  180. attr_delete element, attribute (none)
  181. attr_name element, attribute, name (none)
  182. attr_type element, attribute, type (none)
  183. attr_optional element, attribute, optional (none)
  184. delete element (none)
  185. list set of element IDs
  186. list_full set of " ID : type"
  187. JSON JSON representation of model
  188. read_outgoing element, type set of element IDs
  189. read_incoming element, type set of element IDs
  190. read element string containing type, source, destination, and value
  191. read_attrs element set of "name : value"
  192. read_defined_attrs element set of "name : attribute_type"
  193. types set of element IDs
  194. retype element, type (none)
  195. read_association_source element element ID
  196. read_association_destination element element ID
  197. connections_between element, element set of element IDs
  198. all_instances type set of element IDs
  199. define_attribute element, attribute, type (none)
  200. undefine_attribute element, attribute (none)
  201. ============================ ============================= ======================================================
  202. Some additional operations are again available that work in two phases.
  203. These operations are *attr_add_code* and *upload*, which first perform some checks and then wait for AL code or a model, again using the *"Waiting for X constructors..."* output.
  204. Service
  205. ^^^^^^^
  206. In service mode, the Modelverse blocks until the input *service_stop* is received, and this task is used to process the service.
  207. While in this mode, this task is used to communicate with the various external services connecting to it.