|
@@ -1,11 +1,11 @@
|
|
|
-Operations
|
|
|
+Activities
|
|
|
==========
|
|
|
|
|
|
-While model transformations are in many tools considered to be the only types of operations on models, this is not necessarily the case in the Modelverse.
|
|
|
-Indeed, MPM advocates to use the most appropriate formalism, and, as model transformations are models themselves, this should also apply to specifying operations.
|
|
|
-As such, we extend the notion of model transformations to more general model operations.
|
|
|
+While model transformations are in many tools considered to be the only types of activity on models, this is not necessarily the case in the Modelverse.
|
|
|
+Indeed, MPM advocates to use the most appropriate formalism, and, as model transformations are models themselves, this should also apply to specifying activities.
|
|
|
+As such, we extend the notion of model transformations to more general activities.
|
|
|
|
|
|
-Model operations come in three types, depending on how they are ideally specified: model transformations, manual operations, and action language.
|
|
|
+Activities come in three types, depending on how they are ideally specified: model transformations, manual activities, and action language.
|
|
|
In the remainder of this section, we will show all types, and what situation they are ideally suited for.
|
|
|
|
|
|
Model Transformations
|
|
@@ -16,7 +16,7 @@ The LHS is used to match elements in the host model, and the RHS is put in its p
|
|
|
As this could also be combined with a visual concrete syntax, it could even become possible for domain experts to create a model transformation without too much programming knowledge.
|
|
|
|
|
|
Nonetheless, model transformations are a completely different paradigm, based solely on matching and rewriting.
|
|
|
-Some operations have a long history in computer science, and have therefore efficient or simple procedural algorithms.
|
|
|
+Some formalisms have a long history in computer science, and have therefore efficient and/or simple procedural algorithms.
|
|
|
For example, computing the reachability graph of a PetriNets instance can certainly be done with model transformations, but will be overly difficult.
|
|
|
On the other hand, procedural algorithms are relatively easy (when implemented naively).
|
|
|
|
|
@@ -86,44 +86,54 @@ For example, when defining the PetriNets analysis in action language, which is a
|
|
|
>>> code = \
|
|
|
... """
|
|
|
... include "primitives.alh"
|
|
|
+ ... include "modelling.alh"
|
|
|
+ ... ...
|
|
|
+ ...
|
|
|
... Element function explore_state(model : Element, state : Element):
|
|
|
... ...
|
|
|
...
|
|
|
- ... Element function main(model : Element):
|
|
|
+ ... Boolean function main(model : Element):
|
|
|
... String initial
|
|
|
... initial = instantiate_node(model, "ReachabilityGraph/Initial")
|
|
|
... instantiate_attribute(model, initial, "name", "state_0")
|
|
|
... ...
|
|
|
- ... return model!
|
|
|
+ ... return True!
|
|
|
... """
|
|
|
>>> transformation_add_AL({"PetriNets": "formalisms/PetriNets"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/pn_analyse", code, callback)
|
|
|
- >>> transformation-execute_AL("models/pn_analyse", {"PetriNets": "models/my_pn"}, {"ReachabilityGraph": "models/generated_reachability"})
|
|
|
+ >>> transformation_execute_AL("models/pn_analyse", {"PetriNets": "models/my_pn"}, {"ReachabilityGraph": "models/generated_reachability"})
|
|
|
+
|
|
|
+An activity will have to return a boolean, similar to how a model transformation had to end in either success or failure.
|
|
|
+If the boolean is true, the activity is deemed to have terminated successfully and the changes are made to the models listed in the output dictionary.
|
|
|
+If the boolean is false, the activity is deemed to have failed and no changes are made to the models in the output dictionary.
|
|
|
|
|
|
-Manual Operations
|
|
|
+Manual Activities
|
|
|
-----------------
|
|
|
|
|
|
-Some other operations simply cannot be automated.
|
|
|
-For example, translating natural language descriptions of requirements of a model to the actual model is not something that can be automated, at least for now.
|
|
|
-The only solution, therefore, is to do these operations manually, thereby requiring user intervention.
|
|
|
+Some activities simply cannot be automated.
|
|
|
+For example, translating natural language descriptions of requirements of a model to the actual model is not something that can trivially be automated.
|
|
|
+The only solution, therefore, is to do this manually, thereby requiring user intervention.
|
|
|
|
|
|
-Even though they are manual, they can still be partially automated: merging and splitting based on tags can still be done before and after the manual operation.
|
|
|
+Even though they are manual, they can still be partially automated: merging and splitting based on tags can still be done before and after the manual activity.
|
|
|
|
|
|
The functions on action language are exposed using the *transformation_add_MANUAL* and *transformation_execute_MANUAL* operations.
|
|
|
Their signature is identical to that of model transformations, except that now there is no model to provide with the *transformation_add_MANUAL*.
|
|
|
As with model transformations, the names of model entities are prefixed with their tags.
|
|
|
+This has to be taken into account when doing the manual changes to the model.
|
|
|
|
|
|
-For example, when defining an operation to refine or revise a model in a DSL with respect to the requirements, such as the RPGame language from before::
|
|
|
+For example, when defining an activity to refine or revise a model in a DSL with respect to the requirements, such as the PetriNets language from before::
|
|
|
|
|
|
>>> def callback(model):
|
|
|
- ... instantiate(model, "Association", edge=("Requirements/Actor", "RPGame/Player"))
|
|
|
- >>> transformation_add_MANUAL({"RPGame": "formalisms/RPGame", "Requirements": "formalisms/Requirements"}, {"RPGame": "formalisms/RPGame"}, "revise_rpg", callback)
|
|
|
+ ... instantiate(model, "Association", edge=("Requirements/Actor", "PetriNets/Place"))
|
|
|
+ >>> transformation_add_MANUAL({"PetriNets": "formalisms/PetriNets", "Requirements": "formalisms/Requirements"}, {"PetriNets": "formalisms/PetriNets"}, "revise_pn", callback)
|
|
|
|
|
|
Its execution, however, differs significantly from before, as we will see next.
|
|
|
|
|
|
+Manual activities are deemed to always terminate successfully, and must therefore not return a boolean.
|
|
|
+
|
|
|
Execution callbacks
|
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
-As specified before, manual operations require user intervention during execution.
|
|
|
+As specified before, manual activities require user intervention during execution.
|
|
|
The *transformation_execute_MANUAL* operation is therefore not a simple function that is executed and returns after some time: user input must be given.
|
|
|
For this, an additional argument is provided as callback function.
|
|
|
This callback function can be any sequence of operations again, such that it is possible to create or alter the model.
|
|
@@ -135,38 +145,33 @@ As before, the first parameter of the operations (*model_name*) should be set to
|
|
|
For example, to specify the operations that have to be done in a manual operation, all in Python syntax::
|
|
|
|
|
|
>>> def callback(model):
|
|
|
- ... tiles = [instantiate(model, "RPGame/Tile") for _ in range(100)]
|
|
|
- ... left_links = [instantiate(model, "RPGame/left", edge=(tiles[i], tiles[i+1])) for i in range(len(tiles) - 1)]
|
|
|
+ ... places = [instantiate(model, "PetriNets/Place") for _ in range(100)]
|
|
|
... ...
|
|
|
- >>> transformation_execute_MANUAL("revise_rpg", {"RPGame": "models/my_rpg", "Requirements": "models/rpg_requirements"}, {"RPGame": "models/my_rpg"}, callback)
|
|
|
+ >>> transformation_execute_MANUAL("revise_pn", {"PetriNets": "models/my_pn", "Requirements": "models/pn_requirements"}, {"PetriNets": "models/my_pn"}, callback)
|
|
|
|
|
|
Alternatively, the operations might only be known at runtime, thereby requiring user interaction.
|
|
|
Note that, in this case, the code in the callback is effectively the user interface offered to the user in this specific context.
|
|
|
-As such, the code can be completely tailored to the domain and problem at hand (e.g., a *create random level* operation).
|
|
|
+As such, the code can be completely tailored to the domain and problem at hand::
|
|
|
|
|
|
>>> def callback(model):
|
|
|
... while True:
|
|
|
- ... print("Please perform operation on RPGame!)"
|
|
|
+ ... print("Please perform operation on PetriNet!)"
|
|
|
... inp = raw_input()
|
|
|
- ... if inp == "new tile":
|
|
|
- ... instantiate(model, "RPGame/Tile")
|
|
|
- ... elif inp == "create random level":
|
|
|
+ ... if inp == "new place":
|
|
|
+ ... instantiate(model, "PetriNets/Place")
|
|
|
... ...
|
|
|
... ...
|
|
|
- >>> transformation_execute_MANUAL("revise_rpg", {"RPGame": "models/my_rpg", "Requirements": "models/rpg_requirements"}, {"RPGame": "models/my_rpg"}, callback)
|
|
|
+ >>> transformation_execute_MANUAL("revise_pn", {"PetriNets": "models/my_pn", "Requirements": "models/pn_requirements"}, {"PetriNets": "models/my_pn"}, callback)
|
|
|
|
|
|
-Manual operations are not the only operations which might require user input.
|
|
|
+Manual activities are not the only operations which might require user input.
|
|
|
Model transformations and action language can just as well query the users for input.
|
|
|
-This is done the same way: by defining a callback function.
|
|
|
-Note that they are slightly different, in the sense that their callback functions have no option to call any of the Modelverse operations.
|
|
|
-Instead, the callback is invoked when the action language, either standalone or in the actions/constraints of model transformations, executes the *input* or *output* operations.
|
|
|
-The return value of the callback is made available to the action language (fragment) when it executes the *input* operations, and can be a single primitive type, or a list.
|
|
|
-In case it is a list, the primitive types are offered to the action language individually, requiring multiple *input* calls.
|
|
|
+This is done the same way: by defining a callback.
|
|
|
+Note that they are slightly different, in the sense that their callback is not a function in Python, but governed by a Statechart, as discussed next.
|
|
|
|
|
|
Statechart callbacks
|
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
-While manual operations can refer to a Python function as callback, this is not the case for the execution of a model transformation or action language fragment.
|
|
|
+While manual activities can refer to a Python function as callback, this is not the case for the execution of a model transformation or action language fragment.
|
|
|
In this case, a more complex interaction is required, which depends on the use of SCCD (Statecharts + Class Diagrams).
|
|
|
When executing the activity, a reference to a running statechart is passed, instead of a callback function.
|
|
|
This statechart can have an input and output port, which can be used to communicate with the Modelverse.
|
|
@@ -217,7 +222,7 @@ Its definition is shown below::
|
|
|
</class>
|
|
|
</diagram>
|
|
|
|
|
|
-Similarly, the SCCD model could have raised input to its output port (*outp*), which would then be received in the transformation.
|
|
|
+Similarly, the SCCD model could have raised input to its output port (*outp*), which would then be received in the activity.
|
|
|
Note that the call to *transformation_execute_MT* is always blocking and always returns whether or not the activity was successfully terminated.
|
|
|
|
|
|
Process Model
|