|
@@ -0,0 +1,246 @@
|
|
|
+HTTP interface
|
|
|
+==============
|
|
|
+
|
|
|
+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.
|
|
|
+While it is possible to directly send HTTP requests, it is recommended to create a wrapper, similar to the Python wrapper mentioned before.
|
|
|
+Otherwise, many of the more complex operations (e.g., process enactment) will quickly result in problems.
|
|
|
+Now follows a detailed description of how the HTTP interface works.
|
|
|
+An example implementation can be found in the Python wrapper, which should prove a valuable starting point for creating a new interface.
|
|
|
+
|
|
|
+Request and Reply format
|
|
|
+------------------------
|
|
|
+
|
|
|
+HTTP requests to the Modelverse use the POST format, and should be directed at the location at which the Modelverse server is running.
|
|
|
+The request itself is a URL encoded form of the following dictionary: {"op": operation, "value": value, "taskname": taskname}.
|
|
|
+In this format, the operation is either *set_input* or *get_output*, with the logical meanings (see further).
|
|
|
+Value is only present if the operation is *set_input*, and contains a JSON serialized value to set as input.
|
|
|
+For multiple simultaneous requests, it is possible to not use a key *value*, but a key *data*.
|
|
|
+If the data key is present, this should contain a JSON serialized representation of multiple invocations.
|
|
|
+The semantics is identical, except that only a single HTTP request (and reply) is used.
|
|
|
+Finally, the taskname indicates the task to which the request is targetted.
|
|
|
+Tasknames are provided by the Modelverse when necessary.
|
|
|
+Fetching data from the Modelverse is done using the *get_output* operation, which is blocking until an output is present.
|
|
|
+Note that a timeout might occur if no output becomes available within the time specified as the HTTP output.
|
|
|
+This is not a problem, but should be handled.
|
|
|
+Output requests are handled in a FIFO manner, as multiple calls can be made for output simultaneously.
|
|
|
+
|
|
|
+Apart from the primitive types usually supported by JSON, action language primitives can also be sent.
|
|
|
+These are JSON serialized as a dictionary, with a single key *value* and its value being the string representation of the element.
|
|
|
+For example, an *If* construct is serialized as {"value":"If"}.
|
|
|
+The Modelverse understands this special case, but your interface should also be able to handle such data.
|
|
|
+Note that communication of these internal primitive types is extremely rare.
|
|
|
+
|
|
|
+The reply to this request is simple.
|
|
|
+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.
|
|
|
+For a *get_output* operation, the reply contains a JSON serialized representation of the output data put in the Modelverse.
|
|
|
+This is always a primitive type of JSON, and will never be a list or dictionary.
|
|
|
+
|
|
|
+.. note::
|
|
|
+ Communication over HTTP uses a POST request to allow for unlimited amounts of data to be transfered.
|
|
|
+ Instead, the request parameters, normally part of the GET URL, are sent as data of the POST request.
|
|
|
+ The Modelverse ignores GET requests.
|
|
|
+ This nicely follows the REST standards, as all requests indeed alter the state of the Modelverse (contrary to GET requests).
|
|
|
+
|
|
|
+Examples
|
|
|
+^^^^^^^^
|
|
|
+
|
|
|
+To send the integer 1 to the task with name abc in the Modelverse, send the following data in the POST request::
|
|
|
+
|
|
|
+ op=set_input&value=1&taskname=abc
|
|
|
+
|
|
|
+To send the string def to the task with name xyz in the Modelverse, send the following data in the POST request::
|
|
|
+
|
|
|
+ op=set_input&value="def"&taskname=xyz
|
|
|
+
|
|
|
+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::
|
|
|
+
|
|
|
+ op=set_input&data=[1,"def"]&taskname=xyz
|
|
|
+
|
|
|
+To fetch the output value of a task xyz in the Modelverse, send the following HTTP request, which yields (possibly) the following answer::
|
|
|
+
|
|
|
+ op=get_output&taskname=xyz
|
|
|
+
|
|
|
+ "The output value is a string containing a JSON serialized value."
|
|
|
+
|
|
|
+Startup
|
|
|
+-------
|
|
|
+
|
|
|
+When starting up the Modelverse, only a simple task manager is running.
|
|
|
+To startup a new task, the task manager should be informed of the new name of the task, by sending it input.
|
|
|
+This is done using the following request::
|
|
|
+
|
|
|
+ op=set_input&value="name_of_new_task"&taskname=task_manager
|
|
|
+
|
|
|
+There is no reply from the task manager, and it is assumed that the task can now be used for communication.
|
|
|
+From this point on, communication with the created task can commence, following the operations specified next.
|
|
|
+
|
|
|
+.. warning::
|
|
|
+ This behaviour is likely to change in the near future, where the task manager will output the name of a new task, thereby preventing conflicting tasknames.
|
|
|
+
|
|
|
+Operations
|
|
|
+----------
|
|
|
+
|
|
|
+Upon startup of a task, the communication starts in verbose mode to allow for interactive use.
|
|
|
+This means that initially, every sent input will result in one (or multiple) output values.
|
|
|
+For a wrapper this is cumbersome, as it creates a lot of HTTP requests, and therefore it can be disabled with the input *quiet*.
|
|
|
+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*.
|
|
|
+
|
|
|
+The first two input values that are to be sent are the username and password, which can happen using the following request::
|
|
|
+
|
|
|
+ op=set_input&data=["my username","my password"]&taskname=name_of_new_task
|
|
|
+
|
|
|
+Depending on the output values received, it can be determined whether this is a new or existing user.
|
|
|
+If this is a new user, a subsequent request should again send the password to confirm the password.
|
|
|
+If this is an existing user, the task continues and is now logged in.
|
|
|
+
|
|
|
+When logged in, there are three possible modes: megamodelling, modelling, and service.
|
|
|
+Apart from the responses mentioned here, several other responses are also possible, though these are exceptions.
|
|
|
+All ordinary responses to operations start with *Success:*, or merely *Success* if there is no value to output.
|
|
|
+
|
|
|
+Megamodelling
|
|
|
+^^^^^^^^^^^^^
|
|
|
+
|
|
|
+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.
|
|
|
+It is in this mode that new models should be created, models should be deleted, or new transformations be defined.
|
|
|
+Additionally, as all user access control is modelled explicitly, this is also the mode in which user management is done.
|
|
|
+
|
|
|
+There are two operations to allow mode switching: *model_modify* and *service_register*.
|
|
|
+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.
|
|
|
+For example::
|
|
|
+
|
|
|
+ op=set_input&data=["model_modify","formalisms/ProcessModel","formalisms/SimpleClassDiagrams"]&taskname=xyz
|
|
|
+
|
|
|
+To go to service mode, send *service_register*, followed by the name of the service that is to be registered.
|
|
|
+For example::
|
|
|
+
|
|
|
+ op=set_input&data=["service_register","HUTN_compiler"]&taskname=xyz
|
|
|
+
|
|
|
+In megamodelling mode, the following simple operations are supported.
|
|
|
+For each request, the output normally starts with a *Success*, following the actual return value as a string.
|
|
|
+As all responses are strings, there is some encoding to them (e.g., split on newlines, split on colon, ...).
|
|
|
+Most are trivial to deserialize when the result comes in, and therefore we refer to the SCCD model.
|
|
|
+While operation and parameters are shown distinct in the table, the HTTP request merely sends them in exactly the same fashion.
|
|
|
+For example::
|
|
|
+
|
|
|
+ op=set_input&data=["model_mode","formalisms/ProcessModel","formalisms/PM"]&taskname=xyz
|
|
|
+
|
|
|
+
|
|
|
+Some more complex operations are mentioned below these standard operations.
|
|
|
+
|
|
|
++-------------------------------+----------------------------------------+
|
|
|
+| operation | parameters |
|
|
|
++-------------------------------+----------------------------------------+
|
|
|
+| model_move | model_name, new_location |
|
|
|
+| process_signature | process_name |
|
|
|
+| transformation_between | source_name, target_name |
|
|
|
+| model_render | model_name, mapper_name, rendered_name |
|
|
|
+| model_rendered | model_name, mapper_name |
|
|
|
+| verify | model_name, metamodel_name |
|
|
|
+| model_delete | model_name |
|
|
|
+| model_list | location |
|
|
|
+| model_list_full | location |
|
|
|
+| permission_modify | model_name, permissions |
|
|
|
+| permission_owner | model_name, owner |
|
|
|
+| permission_group | model_name, group |
|
|
|
+| group_create | group |
|
|
|
+| group_delete | group |
|
|
|
+| group_owner_add | group, user |
|
|
|
+| group_owner_delete | group, user |
|
|
|
+| group_join | group, user |
|
|
|
+| group_kick | group, user |
|
|
|
+| group_list | |
|
|
|
+| admin_promote | user |
|
|
|
+| admin_demote | user |
|
|
|
+| user_password | user, password |
|
|
|
+| transformation_read_signature | transformation_name |
|
|
|
+| verbose | |
|
|
|
+| quiet | |
|
|
|
+| folder_create | location |
|
|
|
+| add_conformance | model_name, metamodel_name |
|
|
|
+| model_types | model_name |
|
|
|
+| AL_text | location |
|
|
|
+| model_add | metamodel_name, model_name, code |
|
|
|
++-------------------------------+----------------------------------------+
|
|
|
+
|
|
|
+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.
|
|
|
+These operations are presented next.
|
|
|
+
|
|
|
++---------------------------+---------------------------------------------------+
|
|
|
+| operation | parameters |
|
|
|
++---------------------------+---------------------------------------------------+
|
|
|
+| model_overwrite | model_name, metamodel_name |
|
|
|
+| transformation_add_MANUAL | source_models\*, target_models\*, name |
|
|
|
+| transformation_add_AL | source_models\*, target_models\*, name |
|
|
|
+| transformation_add_MT | source_models\*, target_models\*, name |
|
|
|
+| transformation_execute | activity_name, source_models\*, target_models\* |
|
|
|
+| process_execute | process_name, model_bindings\* |
|
|
|
++---------------------------+---------------------------------------------------+
|
|
|
+
|
|
|
+Parameters marked with a \* are actually dictionaries, and should be sent as such.
|
|
|
+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.
|
|
|
+For example, the dictionary {"abc": "def", "ghi": "jkl"} is sent as five individual requests (or a single data request)::
|
|
|
+
|
|
|
+ ...&data=["abc","def","ghi","jkl",""]&...
|
|
|
+
|
|
|
+For the model_overwrite operation, the Modelverse will first perform some checks as to whether the overwritten model can indeed be overwritten.
|
|
|
+If so, it will output the reply *Waiting for model constructors...*, after which the actual code may be sent.
|
|
|
+The operations starting with transformation_add are similar, but they have two phases.
|
|
|
+First, they output the name of the merged metamodel, ready to be RAMified.
|
|
|
+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.
|
|
|
+As soon as all changes are made, any input will initiate RAMification.
|
|
|
+Second, the Modelverse will query for the code that specify the transformation.
|
|
|
+For manual operations, this query is not done.
|
|
|
+For AL, this query expects ActionLanguage code.
|
|
|
+For MT, this query expects a model conforming to the RAMified metamodel.
|
|
|
+Of course, these constructors can be passed an empty model, in which case the models have to be updated later on using model_modify.
|
|
|
+
|
|
|
+The transformation_execute operation and process_execute are special operations, in the sense that they (potentially) spawn other tasks.
|
|
|
+The output value of these operations is the name of a newly spawned task, on which execution should continue.
|
|
|
+These tasks might not be identical to other tasks, in the sense that they are purely able to communicate with the currently executing operation.
|
|
|
+This operation is rather complex, and we refer to the SCCD model for detailed information.
|
|
|
+The process_execute operation is similar, but instead of outputting only a single taskname, we output multiple, combined with the activity that spawned it.
|
|
|
+
|
|
|
+Modelling
|
|
|
+^^^^^^^^^
|
|
|
+
|
|
|
+In modelling mode, a single model is opened and ready to be modified.
|
|
|
+There are several supported operations, most of which are simple to use.
|
|
|
+To switch back to megamodelling mode, send the *exit* input.
|
|
|
+
|
|
|
++-------------------------------+-------------------------------+
|
|
|
+| operation | parameters |
|
|
|
++-------------------------------+-------------------------------+
|
|
|
+| help | |
|
|
|
+| instantiate_node | type, element |
|
|
|
+| instantiate_edge | type, element, source, target |
|
|
|
+| attr_add | element, attribute, value |
|
|
|
+| attr_delete | element, attribute |
|
|
|
+| attr_name | element, attribute, name |
|
|
|
+| attr_type | element, attribute, type |
|
|
|
+| attr_optional | element, attribute, optional |
|
|
|
+| delete | element |
|
|
|
+| list | |
|
|
|
+| list_full | |
|
|
|
+| JSON | |
|
|
|
+| read_outgoing | element, type |
|
|
|
+| read_incoming | element, type |
|
|
|
+| read | element |
|
|
|
+| read_attrs | element |
|
|
|
+| read_defined_attrs | element |
|
|
|
+| types | |
|
|
|
+| retype | element, type |
|
|
|
+| read_association_source | element |
|
|
|
+| read_association_destination | element |
|
|
|
+| connections_between | element, element |
|
|
|
+| all_instances | type |
|
|
|
+| define_attribute | element, attribute, type |
|
|
|
+| undefine_attribute | element, attribute |
|
|
|
++-------------------------------+-------------------------------+
|
|
|
+
|
|
|
+Some additional operations are again available that work in two phases.
|
|
|
+These operations are *attr_add_code* and *upload*, which first perform some checks and then wait for AL code or a model.
|
|
|
+
|
|
|
+Service
|
|
|
+^^^^^^^
|
|
|
+
|
|
|
+In service mode, the Modelverse blocks until the input *service_stop* is received, and this task is used to process the service.
|