Browse Source

Merge branch 'master' into testing

Yentl Van Tendeloo 7 years ago
parent
commit
41990c25e1
5 changed files with 249 additions and 20 deletions
  1. 1 1
      bootstrap/core_algorithm.alc
  2. 0 2
      bootstrap/mini_modify.alc
  3. 1 0
      doc/developer.rst
  4. 247 0
      doc/http.rst
  5. 0 17
      wrappers/classes/modelverse.xml

+ 1 - 1
bootstrap/core_algorithm.alc

@@ -2415,7 +2415,7 @@ Void function user_function_skip_init(user_id : String):
 		elif (cmd == "process_execute"):
 			output(cmd_process_execute(single_input("Process to execute?"), dict_input("Model bindings to use?")))
 		elif (cmd == "process_signature"):
-			output(cmd_process_signature(single_input("Process to execute?")))
+			output(cmd_process_signature(single_input("Process to query?")))
 		elif (cmd == "transformation_between"):
 			output(cmd_transformation_between(dict_input("Source signature?"), dict_input("Target signature?")))
 		elif (cmd == "model_render"):

+ 0 - 2
bootstrap/mini_modify.alc

@@ -473,8 +473,6 @@ Boolean function modify(model : Element, write : Boolean):
 			output(cmd_help_m(write))
 		elif (cmd == "exit"):
 			return True!
-		elif (cmd == "drop"):
-			return False!
 		elif (cmd == "upload"):
 			output(cmd_upload(write, model))
 		elif (cmd == "instantiate_node"):

+ 1 - 0
doc/developer.rst

@@ -5,6 +5,7 @@ Using the Modelverse as a Developer
    :maxdepth: 2
 
    Scripts <scripts>
+   HTTP interface <http>
    Wrappers <wrappers>
    Model representation <model>
    Modelverse components <components>

+ 247 - 0
doc/http.rst

@@ -0,0 +1,247 @@
+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 explanation of the semantics of these operations can be found in the Python wrapper.
+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.

+ 0 - 17
wrappers/classes/modelverse.xml

@@ -1848,7 +1848,6 @@
                         <state id="recognized" initial="manual">
                             <state id="manual">
                                 <transition cond="self.expect_action('exit')" target="../../../../leaving_manual"/>
-                                <transition cond="self.expect_action('drop')" target="../../../../leaving_manual_drop"/>
 
                                 <transition cond="self.actions and self.actions[0]['parameters'][0] != self.current_model" target="../../../../leaving_manual"/>
                             </state>
@@ -1859,12 +1858,6 @@
                                         <parameter expr="'exit'"/>
                                     </raise>
                                 </transition>
-
-                                <transition cond="self.expect_action('drop')" target="../../../../operations/store_on_scripted/history">
-                                    <raise event="request">
-                                        <parameter expr="'drop'"/>
-                                    </raise>
-                                </transition>
                             </state>
 
                             <transition cond="self.expect_action('element_list')" target="../../../operations/element_list">
@@ -2099,16 +2092,6 @@
 
                     <transition cond="self.expect_response('Success', pop=True)" target="../wait_for_action/megamodelling"/>
                 </state>
-
-                <state id="leaving_manual_drop">
-                    <onentry>
-                        <raise event="request">
-                            <parameter expr="'drop'"/>
-                        </raise>
-                    </onentry>
-
-                    <transition cond="self.expect_response('Success', pop=True)" target="../wait_for_action/megamodelling"/>
-                </state>
             </state>
 
             <state id="queue">