Browse Source

Proofread and update the wrappers

Yentl Van Tendeloo 3 years ago
parent
commit
eaab7d042a
4 changed files with 41 additions and 87 deletions
  1. 33 79
      doc/wrappers.rst
  2. 1 1
      wrappers/classes/modelverse.xml
  3. 6 6
      wrappers/modelverse.py
  4. 1 1
      wrappers/modelverse_SCCD.py

+ 33 - 79
doc/wrappers.rst

@@ -2,7 +2,7 @@ Wrappers
 ========
 
 Several wrappers can be defined for the Modelverse, as the Modelverse is merely a service running externally.
-To communicate effectively, and automatically, a programming language wrapper is recommended.
+To communicate effectively and automatically, a programming language wrapper is recommended.
 Nonetheless, it is possible to communicatie manually as well.
 These are some of the implemented wrappers.
 
@@ -20,17 +20,17 @@ Python
 The first real wrapper is the Python-based wrapper.
 It provides a set of functions for use by Python code.
 These functions wrap not only the interface, but also provides simple error handling through the use of Python exceptions and contains the model and action language compilers.
+Since it is relatively minimal and provides a complete implementation of a Modelverse Interface, it is considered as a reference implementation for the Modelverse protocol.
 An overview of all functions and associatied exceptions is provided below.
 All operations happen *synchronously*, meaning that they block until the Modelverse has performed the requested operation.
 
-Note that some functions are only applicable in a certain *context*.
+Note that some functions are only applicable in a certain context.
 In practice, this means that you should first issue the *init* and *login* operations, as otherwise your connection with the Modelverse will not have started up yet.
 
 For each function, we provide an example to indicate how this operation can be used.
-In these first examples, assume that all referenced elements are present, all permissions are granted, etc.
-For each exception, then, we provide an example where it can occur.
+In these first examples, we assume that all referenced elements are present, all permissions are granted, etc.
+Afterwards, we provide an overview of all exceptions, together with an example.
 In these examples, the problem is often caused by an non-existing element or unsatisfied permissions.
-From the example, it should be clear what the problem is.
 
 Initialization Function
 ^^^^^^^^^^^^^^^^^^^^^^^
@@ -327,20 +327,20 @@ Transformations
 
 .. function:: transformation_between(source, target)
 
-   List all transformations that originate at *source* and end at *target*.
-   Transformations can still be selected, even if they take more source models than those specified in the parameters.
+   List all transformations that take at least all elements in *source* as input, with an exact match in tags, and that generate at least all elements in *target*, again with the same tags.
+   An empty dictionary means that there is no constraint on that part, but there must be at least one tag specified.
 
    Examples:
 
-   * To fetch all endogenous transformations on PetriNets, assuming that some were previously defined.
+   * To fetch all endogenous transformations on PetriNets on the *PN* tag, assuming that some were previously defined.
 
-     >>> transformation_between("formalisms/PetriNets", "formalisms/PetriNets")
-     ["PN_simulate", "PN_optimize"]
+     >>> transformation_between({"PN": "formalisms/PetriNets"}, {})
+     ["PN_simulate", "PN_optimize", "PN_to_matrix"]
 
-   * To fetch all transformations from a DSL to PetriNets, assuming that multiple people created different denotational semantics.
+   * To fetch all endogenous transformations on PetriNets on the *PN* tag that modify the model in-place, assuming that some were previously defined.
 
-     >>> transformation_between("RPGame", "PetriNets")
-     ["denotational1", "denotational_2", "denotational_3"]
+     >>> transformation_between({"PN": "formalisms/PetriNets"}, {"PN": "formalisms/PetriNets"})
+     ["PN_simulate", "PN_optimize"]
 
 .. function:: transformation_add_MT(source_metamodels, target_metamodels, operation_name, code, callback=lambda: None)
 
@@ -404,7 +404,7 @@ Transformations
 
      >>> transformation_add_MANUAL({"pn": "formalisms/PetriNets", "requirements": "formalisms/Requirements"}, {"pn": "formalisms/PetriNets"}, "models/pn_refine_req")
 
-.. function:: transformation_execute_AL(operation_name, input_models_dict, output_models_dict, statechart=None)
+.. function:: transformation_execute_AL(operation_name, input_models_dict, output_models_dict, statechart=None, traceability_model="", fetch_output=True)
 
    Executes the Action Language model *operation_name* with *input_models_dict* as inputs and *output_models_dict* as outputs.
    For both dicts, the contents describe the mapping between the parameter names of the operation to the names in the Modelverse.
@@ -412,6 +412,8 @@ Transformations
    A *statechart* tuple can be defined when the action language model requires user input or output.
    This is used to communicate with the executing code directly.
    For more information about this, refer to the execution of transformations.
+   The *traceability* model can optionally be specified, which then loads in the selected model to create the traceability links between all models, and all changes are stored to this model as well.
+   The *fetch_output* parameter ensures that the output thread is closed after this call. This is useful if the activity is forever running and no other communication has to happen with the MvI.
 
    Examples:
 
@@ -423,20 +425,20 @@ Transformations
 
    Executes the manual model operation *operation_name*.
    Furthermore, this is identical to *transformation_execute_AL*, with the exception of the *callback* function.
-   In this case, the callback function can be just another series of Modelverse operations, though pertaining to a single model.
-   As such, the *model_name* parameter of these operations **MUST** be set to *None*.
+   In this case, the callback function can be just another series of Modelverse operations, though pertaining to a single model, which is passed as a parameter.
+   As such, the *model_name* parameter of these operations **MUST** be set to the parameter.
 
    Examples:
 
    * To execute a manual operation, which requires you to refine a PetriNets instance.
 
-     >>> def callback():
-     ...     p1 = instantiate(None, "pn/Place")
-     ...     t1 = instantiate(None, "pn/Transition")
-     ...     instantiate(None, "pn/P2T", (p1, t1))
+     >>> def callback(model):
+     ...     p1 = instantiate(model, "pn/Place")
+     ...     t1 = instantiate(model, "pn/Transition")
+     ...     instantiate(model, "pn/P2T", (p1, t1))
      >>> transformation_execute_MANUAL("models/pn_refine", {"pn": "models/my_pn"}, {"pn": "models/my_pn"}, callback)
 
-.. function:: transformation_execute_MT(operation_name, input_models_dict, output_models_dict, statechart=None)
+.. function:: transformation_execute_MT(operation_name, input_models_dict, output_models_dict, statechart=None, traceability_model="", fetch_output=True)
 
    Executes the model transformation operation *operation_name*.
    Identical to *transformation_execute_AL*.
@@ -700,7 +702,6 @@ Modelling
 
    Returns a list of all types usable in the model named *model_name*.
    This is similar to executing *element_list* on the metamodel of this model.
-   It attempts to filter out most unusable elements.
 
    Examples:
 
@@ -709,18 +710,6 @@ Modelling
      >>> types("formalisms/PetriNets")
      ["Class", "Association", "SimpleAttribute", ...]
 
-.. function:: types_full(model_name)
-
-   Returns a list of all types usable in the model named *model_name*.
-   In contrast to *types*, this includes hidden elements as well (i.e., those starting with __)
-
-   Examples:
-
-   * To get a list of all types usable in the PetriNets metamodel (i.e., when altering the metamodel itself).
-
-     >>> types("formalisms/PetriNets")
-     ["Class", "Association", "SimpleAttribute", "__12345", ...]
-
 .. function:: read_info(model_name, ID)
 
    Read the content of model element *ID* in model *model_name*.
@@ -822,7 +811,7 @@ Modelling
 
      >>> delete_element("models/my_pn", "p1")
      >>> delete_element("models/my_pn", "p1_to_t1")
-     UnknownIdentifierException("p1_to_t1")
+     UnknownElement("p1_to_t1")
 
 Attribute Manipulation
 ^^^^^^^^^^^^^^^^^^^^^^
@@ -1341,30 +1330,9 @@ For each exception, its superclasses are also indicated after the colon.
 
 .. exception:: UnknownIdentifier : ModelverseException
 
-   The specified element identifier could not be resolved in the specified model in the Modelverse.
-   The exception contains the identifier causing the problem, as there might be multiple identifiers used in a single request.
-
-   Examples:
-
-   * When reading out a non-existing element in a PetriNets model.
-
-     >>> read("models/my_pn", "p0")
-     UnknownIdentifier("p0")
-
-   * When reading out the allowed connections between two elements, of which neither exists.
-
-     >>> connections_between("models/my_pn", "p0", "t0")
-     UnknownIdentifier("p0")
-
-   * When reading out the allowed connections between two elements, of which the target doesn't exists.
-
-     >>> connections_between("models/my_pn", "p1", "t0")
-     UnknownIdentifier("t0")
-
-   * When instantiating a non-existing element in the meta-model.
-
-     >>> instantiate("models/my_pn", "CapacityConstrainedPlace")
-     UnknownIdentifier("CapacityConstrainedPlace")
+   The specified identifier could not be resolved in the Modelverse.
+   This is an abstract exception, for which several specializations exist.
+   The exception always contains the identifier causing the problem, as there might be multiple identifiers used in a single request.
 
 .. exception:: CompilationError : ModelverseException
 
@@ -1523,19 +1491,6 @@ For each exception, its superclasses are also indicated after the colon.
      >>> instantiate("formalisms/PetriNets", "Class", ID="Place")
      ElementExists()
 
-.. exception:: ModelExists : ExistsError
-
-   The identifier to give to the newly created model already exists.
-   Note that some operations, such as model transformation, will default to overwriting a model if it already exists, but still is used as a target.
-   Of course, permissions of the overwritten model need to allow for this.
-
-   Examples:
-
-   * When the model "my_pn" already exists.
-
-     >>> model_add("models/my_pn", "PetriNets")
-     ModelExists("models/my_pn")
-
 .. exception:: FolderExists : ExistsError
 
    The folder you want to create already exists.
@@ -1694,21 +1649,19 @@ Actually, the Python interface presented before is built using this SCCD interfa
 The operations are identical and have the same signature, although they are invoked differently.
 
 To make a request to the Modelverse, an event has to be raised called *action*.
-The first parameter of this event is the operation to invoke, as a string (*e.g.*, 'read_info').
-The second parameter specifies an ID that can be used in the response event to identify which event this is the response to.
-The third parameter is unused.
-The fourth parameter is a list of all the parameters to this function (*e.g.*, ["my_pn"]).
+The first parameter of this event is the operation to invoke, as a string (*e.g.*, ``"read_info"``).
+The second parameter specifies an ID that can be used in the response event to identify which event this is the response to, or set to *None*.
+The third parameter is a list of all the parameters to this function (*e.g.*, ``["my_pn"]``).
 For example::
 
     <raise event="action">
         <parameter expr="'read_info'"/>
         <parameter expr="None"/>
-        <parameter expr="None"/>
         <parameter expr="['my_pn']"/>
     </raise>
 
 When this request is processed, the Modelverse will reply with the *mv_result* event, containing the result.
-The first parameter is the ID passed on in the original request.
+The first parameter is the ID passed on in the original request, or *None* if the ID was set to *None*.
 The second parameter contains the result.
 It is possible to wait on this event as follows::
 
@@ -1733,7 +1686,7 @@ If something went wrong, the event *mv_exception* will be raised instead::
     </transition>
 
 The use of the SCCD interface is particularly interesting in case asynchronous communication is required.
-In contrast to the Python interface, requests don't block, making it possible to do additional computations in the background, or even work in a multi-threaded context.
+In contrast to the Python interface, requests don't block, making it possible to do additional computations in the background, or even work in a multi-threaded context (using the *ID* parameter).
 Note, however, that the SCCD interface is more difficult to use with callbacks and other statecharts, as you will have to manually make the linkage with ports.
 For this, we refer to the implementation.
 
@@ -1743,3 +1696,4 @@ Custom
 Other wrappers can be made as desired, in whatever language required.
 This is due to the fact that the Modelverse communicates only through XML/HTTPRequests.
 As such, all languages that support this, can simply mimic the interface used by any of the implemented wrappers.
+We refer to the Python wrapper as the reference implementation.

+ 1 - 1
wrappers/classes/modelverse.xml

@@ -242,7 +242,7 @@
 
                         <transition event="http_client_timeout" target="../../wait_for_action/disconnected">
                             <raise event="exception">
-                                <parameter expr="'NetworkException'"/>
+                                <parameter expr="'ConnectionError'"/>
                                 <parameter expr="'Connection timeout'"/>
                             </raise>
                         </transition>

+ 6 - 6
wrappers/modelverse.py

@@ -404,14 +404,14 @@ def __transformation_execute(operation_name, input_models_dict, output_models_di
         threading.Thread(target=_process_SC, args=[statechart, port_sc, taskname]).start()
     return OUTPUT()
 
-def transformation_execute_MT(operation_name, input_models_dict, output_models_dict, statechart=None, tracability_model="", fetch_output=True):
-    return __transformation_execute(operation_name, input_models_dict, output_models_dict, statechart, tracability_model, fetch_output)
+def transformation_execute_MT(operation_name, input_models_dict, output_models_dict, statechart=None, traceability_model="", fetch_output=True):
+    return __transformation_execute(operation_name, input_models_dict, output_models_dict, statechart, traceability_model, fetch_output)
 
-def transformation_execute_AL(operation_name, input_models_dict, output_models_dict, statechart=None, tracability_model="", fetch_output=True):
-    return __transformation_execute(operation_name, input_models_dict, output_models_dict, statechart, tracability_model, fetch_output)
+def transformation_execute_AL(operation_name, input_models_dict, output_models_dict, statechart=None, traceability_model="", fetch_output=True):
+    return __transformation_execute(operation_name, input_models_dict, output_models_dict, statechart, traceability_model, fetch_output)
 
-def transformation_execute_MANUAL(operation_name, input_models_dict, output_models_dict, callback=None, tracability_model=""):
-    INPUT("transformation_execute", [operation_name, input_models_dict, output_models_dict, tracability_model])
+def transformation_execute_MANUAL(operation_name, input_models_dict, output_models_dict, callback=None, traceability_model=""):
+    INPUT("transformation_execute", [operation_name, input_models_dict, output_models_dict, traceability_model])
     taskname = OUTPUT()
 
     _process_OP(callback, taskname)

+ 1 - 1
wrappers/modelverse_SCCD.py

@@ -2815,7 +2815,7 @@ class Modelverse(RuntimeClassBase):
         return self.i == 1
     
     def _initialized_behaviour_init_waiting_http_client_2_exec(self, parameters):
-        self.raiseInternalEvent(Event("exception", None, ['NetworkException', 'Connection timeout']))
+        self.raiseInternalEvent(Event("exception", None, ['ConnectionError', 'Connection timeout']))
     
     def _initialized_behaviour_operations_login_wait_prompt_1_0_exec(self, parameters):
         self.raiseInternalEvent(Event("request", None, [self.parameters[0]]))