|
@@ -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.
|