瀏覽代碼

Updated documentation for the addition of hierarchy

Yentl Van Tendeloo 8 年之前
父節點
當前提交
0c1c851e17
共有 7 個文件被更改,包括 110 次插入89 次删除
  1. 4 4
      doc/actionlanguage.rst
  2. 25 25
      doc/metamodelling.rst
  3. 2 2
      doc/modeller_modellanguage.rst
  4. 44 32
      doc/modelling.rst
  5. 17 8
      doc/permissions.rst
  6. 3 3
      doc/process_enactment.rst
  7. 15 15
      doc/transformations.rst

+ 4 - 4
doc/actionlanguage.rst

@@ -24,13 +24,13 @@ In the context of Finite State Automata, it is often necessary to define actions
 Upon execution of the transition, the associated action is executed.
 When defining a model, we can also upload code snippets as attribute values::
 
-    >>> instantiate_attr_code("my_fsa", "transition_1", "action", open("actions/transition_1.alc", "r").read())
+    >>> instantiate_attr_code("models/my_fsa", "transition_1", "action", open("actions/transition_1.alc", "r").read())
 
 This will assign the action stored in the file *actions/transition_1.alc* to the *action* attribute of the transition.
 Of course, it is not necessary to open a file for this, as the function itself could just as well be inlined.
 The only requirement on the value, is that it is a string that can be parsed as Action Language::
 
-    >>> instantiate_attr_code("my_fsa", "transition_1", "action", \
+    >>> instantiate_attr_code("models/my_fsa", "transition_1", "action", \
     ...     """
     ...     include "primitives.alh"
     ...     Void function action(model : Element):
@@ -42,8 +42,8 @@ Action language attributes are considered identical to any other attribute.
 The exception is of course that they are assigned using the code specific function, as otherwise we would have uploaded a string.
 Note the difference between the assignment of a string, and the assignment of action code::
 
-    >>> instantiate_attr("my_fsa", "transition_1", "action", open("actions/transition_1.alc", "r").read())
-    >>> instantiate_attr_code("my_fsa", "transition_1", "action", open("actions/transition_1.alc", "r").read())
+    >>> instantiate_attr("models/my_fsa", "transition_1", "action", open("actions/transition_1.alc", "r").read())
+    >>> instantiate_attr_code("models/my_fsa", "transition_1", "action", open("actions/transition_1.alc", "r").read())
 
 The first line assigns a string to the attribute, and is therefore not executable, nor is it parsed or considered in any way.
 The second line assigns code to the attribute, and is therefore executable, and parsed upon assignment.

+ 25 - 25
doc/metamodelling.rst

@@ -12,7 +12,7 @@ To create a metamodel, you have to instantiate the *SimpleClassDiagrams* metamod
 While there is no restriction that this has to be *SimpleClassDiagrams*, for now we assume that this is the only possible meta-language.
 Therefore, to create the PetriNets language, we execute::
 
-    >>> model_add("PetriNets", "SimpleClassDiagrams")
+    >>> model_add("formalisms/PetriNets", "models/SimpleClassDiagrams")
 
 From then on, we can simply use the PetriNets metamodel as if it were a model.
 Again, the *model_add* operation can take an optional third parameter, specifying the textual representation of the model.
@@ -31,20 +31,20 @@ Class
 Creating a class is easy, and very similar to usual modelling.
 To define the *Place* concept, which can later on be used in models, we merely define this as a new class::
 
-    >>> instantiate("PetriNets", "Class", ID="Place")
+    >>> instantiate("formalisms/PetriNets", "Class", ID="Place")
 
 Note that here we must define an ID to get a sensible name to use.
 Of course, this ID does not need to be used, and the returned (randomized) ID can just as well be used.
 Nonetheless, if it is used, it becomes non-intuitive to use in future requests.
 In the instance of this newly created language, we can immediately use the new concept::
 
-    >>> instantiate("PetriNets", "Class", ID="Place")
+    >>> instantiate("formalisms/PetriNets", "Class", ID="Place")
     >>> instantiate("my_pn", "Place")
 
 If the ID was not used, we must remember the ID that was provided to us::
 
-    >>> pn_place = instantiate("PetriNets", "Class")
-    >>> instantiate("my_pn", pn_place)
+    >>> pn_place = instantiate("formalisms/PetriNets", "Class")
+    >>> instantiate("models/my_pn", pn_place)
 
 While this is more reliable, it becomes difficult to refer to the concept in the future without any clue as to what it resembles.
 Later on, this can be solved with concrete syntax, in which case modellers can identify the concepts based on their visual representation.
@@ -55,7 +55,7 @@ Association
 Creating a link between two concepts is very similar.
 For example, to create the *P2T* association, merely create an instance of association, using the same remarks as before::
 
-    >>> instantiate("PetriNets", "Association", edge=("Place", "Transition"), ID="P2T")
+    >>> instantiate("formalisms/PetriNets", "Association", edge=("Place", "Transition"), ID="P2T")
 
 Inheritance
 ^^^^^^^^^^^
@@ -64,29 +64,29 @@ A useful concept is the use of inheritance, whereby the inheriting class can tak
 To create this, simply instantiate the *Inheritance* association as usual.
 For example, it is possible to structure the *PetriNets* model (in an admittedly strange way) such that there is a generic concept of *NamedElement* and *Arc*::
 
-    >>> instantiate("PetriNets", "Class", ID="NamedElement")
-    >>> instantiate("PetriNets", "Class", ID="Place")
-    >>> instantiate("PetriNets", "Class", ID="Transition")
-    >>> instantiate("PetriNets", "Inheritance", edge=("Place", "NamedElement"))
-    >>> instantiate("PetriNets", "Inheritance", edge=("Transition", "NamedElement"))
+    >>> instantiate("formalisms/PetriNets", "Class", ID="NamedElement")
+    >>> instantiate("formalisms/PetriNets", "Class", ID="Place")
+    >>> instantiate("formalisms/PetriNets", "Class", ID="Transition")
+    >>> instantiate("formalisms/PetriNets", "Inheritance", edge=("Place", "NamedElement"))
+    >>> instantiate("formalisms/PetriNets", "Inheritance", edge=("Transition", "NamedElement"))
 
 In the Modelverse, inheritance is possible between any two instances, including associations.
 To define the *Arc* relation, we act similar::
 
-    >>> instantiate("PetriNets", "Association", edge=("NamedElement", "NamedElement"), ID="Arc")
-    >>> instantiate("PetriNets", "Association", edge=("Place", "Transition"), ID="P2T")
-    >>> instantiate("PetriNets", "Association", edge=("Transition", "Place"), ID="T2P")
-    >>> instantiate("PetriNets", "Inheritance", edge=("P2T", "Arc"))
-    >>> instantiate("PetriNets", "Inheritance", edge=("T2P", "Arc"))
+    >>> instantiate("formalisms/PetriNets", "Association", edge=("NamedElement", "NamedElement"), ID="Arc")
+    >>> instantiate("formalisms/PetriNets", "Association", edge=("Place", "Transition"), ID="P2T")
+    >>> instantiate("formalisms/PetriNets", "Association", edge=("Transition", "Place"), ID="T2P")
+    >>> instantiate("formalisms/PetriNets", "Inheritance", edge=("P2T", "Arc"))
+    >>> instantiate("formalisms/PetriNets", "Inheritance", edge=("T2P", "Arc"))
 
 Instantiating attributes
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
 Instantiating attributes is similar as it was before::
 
-    >>> attr_assign("PetriNets", "NamedElement", "name", "NamedElement")
-    >>> attr_assign("PetriNets", "Transition", "name", "Transition")
-    >>> attr_assign("PetriNets", "Place", "name", "Place")
+    >>> attr_assign("formalisms/PetriNets", "NamedElement", "name", "NamedElement")
+    >>> attr_assign("formalisms/PetriNets", "Transition", "name", "Transition")
+    >>> attr_assign("formalisms/PetriNets", "Place", "name", "Place")
 
 Note that this *name* attribute is in no way related to the *name* attributes at the *my_pn* level.
 Indeed, the *name* in *PetriNets* specifies the name of the class.
@@ -112,7 +112,7 @@ We distinguish between two types of constraints: local and global constraints.
 Local constraints are defined at the level of a single class or association.
 For example, if the number of tokens must always be non-negative, this can be specified as follows::
 
-    >>> attr_assign_code("PetriNets", "Place", "constraints", \
+    >>> attr_assign_code("formalisms/PetriNets", "Place", "constraints", \
     ...     """
     ...     String function constraint(model : Element, name : String):
     ...         if (integer_gte(read_attribute(model, name, "tokens"), 0)):
@@ -125,8 +125,8 @@ Instead, a specific *GlobalConstraint* element must be instantiated.
 This element has a *constraint* attribute, which specifies the constraint to evaluate in the global context.
 For example, when, for some reason, the number of places must always be larger than the number of transitions::
 
-    >>> constraint = instantiate("PetriNets", "GlobalConstraint")
-    >>> attr_assign_code("PetriNets", constraint, "constraint", \
+    >>> constraint = instantiate("formalisms/PetriNets", "GlobalConstraint")
+    >>> attr_assign_code("formalisms/PetriNets", constraint, "constraint", \
     ...     """
     ...     String function constraint(model : Element):
     ...         if (set_len(allInstances(model, "Place")) > set_len(allInstances(model, "Transition"))):
@@ -156,12 +156,12 @@ While many other tools provide a set of primitives, which cannot be altered in a
 If the language engineer wants the concepts of a *Natural*, for example, it is not required that the attribute is specified as an Integer, with an additional constraint on each and every attribute that is defined this way.
 It is possible to define a new attribute type as follows::
 
-    >>> instantiate("PetriNets", "SimpleAttribute", ID="Natural")
+    >>> instantiate("formalisms/PetriNets", "SimpleAttribute", ID="Natural")
 
 But now, the attribute is constrained in no way: it is merely called Natural, but can even contain a string.
 The attribute type must be constrained::
 
-    >>> attr_assign_code("PetriNets", "Natural", "constraint", \
+    >>> attr_assign_code("formalisms/PetriNets", "Natural", "constraint", \
     ...     """
     ...     String function constraint(value : Element):
     ...         if (is_physical_integer(value)):
@@ -179,6 +179,6 @@ This offers additional possibilities, such as defining complex attributes as if
 The next step is to define the attribute itself.
 This can be easily done as follows::
 
-    >>> define_attribute("PetriNets", "Place", "tokens", "Natural")
+    >>> define_attribute("formalisms/PetriNets", "Place", "tokens", "Natural")
 
 For the name, *String* can be defined similarly (using *is_physical_string*).

+ 2 - 2
doc/modeller_modellanguage.rst

@@ -176,11 +176,11 @@ The question remains how to use this model representation with the Modelverse.
 The *model_add* operation can be extended with an additional parameter, specifying a textual model.
 It will then create a new model and initialize it with the model specified textually::
 
-    >>> model_add("my_pn", "PetriNets", open("my_pn.mvc", "r").read())
+    >>> model_add("models/my_pn", "formalisms/PetriNets", open("my_pn.mvc", "r").read())
 
 Another function that can be used, is the *model_overwrite* function, which overwrites an existing model with the content of the provided textual model::
 
-    >>> model_overwrite("my_pn", "PetriNets", open("my_pn.mvc", "r").read())
+    >>> model_overwrite("models/my_pn", "formalisms/PetriNets", open("my_pn.mvc", "r").read())
 
 Note that *model_overwrite* can also be used without the textual model parameter, in which case it will clear the specified model.
 That is, overwrite the model with an empty model.

+ 44 - 32
doc/modelling.rst

@@ -15,7 +15,7 @@ Creating a model
 
 Creating a new instance of PetriNets is simple, and can be done using the *model_add* operation of the wrapper::
 
-    >>> model_add("my_pn", "PetriNets")
+    >>> model_add("models/my_pn", "formalisms/PetriNets")
 
 The first parameter of the operation indicates the name that we would like to give to our newly created model.
 This name is available to all users, and is therefore a unique identifier.
@@ -24,11 +24,23 @@ The value needs to be a name that is available in the Modelverse, and readable t
 
 To get a list of currently available models, users can query the Modelverse with the *model_list* operation::
 
-    >>> model_list()
-    [("PetriNets", "SimpleClassDiagrams"), ("SimpleClassDiagrams", "SimpleClassDiagrams"), ("ProcessModel", "SimpleClassDiagrams"), ...]
+    >>> model_list("")
+    ["formalisms/", "models/", "administration/", "users/", "type mappings/"]
 
-This list contains the various models, and the metamodel of these models.
-Note that this operation does not specify anything about the permissions of the supplied models.
+This list contains the various entries in the specified location.
+Note that this operation does not specify anything about the permissions of the supplied entries.
+Entries that end with a forward slash (/) are folders, and can subsequently be listed::
+
+    >>> model_list("formalisms")
+    ["Bottom", "SimpleClassDiagrams", "Tracability", ...]
+
+    >>> model_list("users/admin")
+    []
+
+Depending on permissions, not all folders can be listed::
+    
+    >>> model_list("administration")
+    PermissionDenied("administration")
 
 Modifying a model
 -----------------
@@ -43,7 +55,7 @@ Create
 
 1. *instantiate* creates a new instance in the model, for example a new PetriNet place::
 
-        >>> instantiate("my_pn", "Place")
+        >>> instantiate("models/my_pn", "Place")
         __12345
 
     The operation requires the model on which we are working, and the type of the element you want to instantiate.
@@ -52,20 +64,20 @@ Create
 
     When instantiating an edge, the optional *edge* parameter must be passed with the identifiers to connect::
         
-        >>> instantiate("my_pn", "Place")
+        >>> instantiate("models/my_pn", "Place")
         p1
-        >>> instantiate("my_pn", "Transition")
+        >>> instantiate("models/my_pn", "Transition")
         t1
-        >>> instantiate("my_pn", "P2T", edge=("p1", "t1"))
+        >>> instantiate("models/my_pn", "P2T", edge=("p1", "t1"))
         p2t1
 
 2. *attr_assign* assigns attributes of a specific model element.
    For example, it specifies the name and number of tokens of our PetriNet place::
    
-        >>> instantiate("my_pn", "Place")
+        >>> instantiate("models/my_pn", "Place")
         p1
-        >>> attr_assign("my_pn", "p1", "name", "place 1")
-        >>> attr_assign("my_pn", "p1", "tokens", 2)
+        >>> attr_assign("models/my_pn", "p1", "name", "place 1")
+        >>> attr_assign("models/my_pn", "p1", "tokens", 2)
 
    The value of the attribute can be any simple primitive: string, integer, float, or boolean.
    When the attribute already exists, its value is overwritten.
@@ -76,39 +88,39 @@ Read
 
 1. *read* reads out basic information about a queried element, such as its type and the source and target (if it is an edge)::
 
-        >>> instantiate("my_pn", "Place")
+        >>> instantiate("models/my_pn", "Place")
         p1
-        >>> read("my_pn", "p1")
+        >>> read("models/my_pn", "p1")
         ("Place, None)
-        >>> instantiate("my_pn", "Transition")
+        >>> instantiate("models/my_pn", "Transition")
         t1
-        >>> instantiate("my_pn", "P2T", edge=("p1", "t1"))
+        >>> instantiate("models/my_pn", "P2T", edge=("p1", "t1"))
         p2t1
-        >>> read("my_pn", "p2t1")
+        >>> read("models/my_pn", "p2t1")
         ("P2T", ("p1", "t1"))
 
 2. *read_attrs* reads out the attributes of a specific element, in a dictionary form.
    This operation can be used to read out, for example, the number of tokens of a specific place::
 
-        >>> instantiate("my_pn", "Place")
+        >>> instantiate("models/my_pn", "Place")
         p1
-        >>> attr_assign("my_pn", "p1", "name", "place 1")
-        >>> attr_assign("my_pn", "p1", "tokens", 2)
-        >>> read_attrs("my_pn", "p1")
+        >>> attr_assign("models/my_pn", "p1", "name", "place 1")
+        >>> attr_assign("models/my_pn", "p1", "tokens", 2)
+        >>> read_attrs("models/my_pn", "p1")
         {"name": "place 1", "tokens": 2}
    
 3. *types* reads out the list of types that can be instantiated in this model.
    All calls to instantiate should act upon one of these types.
    For PetriNets, this returns the concepts of the domain::
 
-        >>> types()
+        >>> types("models/my_pn")
         ["Place", "Transition", "P2T", "T2P", ...]
 
 4. *element_list_nice* reads out a simple JSON-like representation of the model.
    This includes all information about the model and can be used to fetch the complete model in one go.
    For example, to read out a simple PetriNet::
 
-        >>> element_list_nice("my_pn")
+        >>> element_list_nice("models/my_pn")
         [{"id": "p1", "type": "Place", "name": "place 1", "tokens": 1},
          {"id": "p2", "type": "Place", "name": "place 2", "tokens": 2},
          {"id": "t1", "type": "Transition"},
@@ -120,7 +132,7 @@ Read
    This takes into account inheritance relation.
    For example, to read out all outgoing P2T links of a place::
 
-        >>> read_outgoing("my_pn", "p1", "P2T")
+        >>> read_outgoing("models/my_pn", "p1", "P2T")
         ["p2t"]
 
    It is possible to get all outgoing associations as well, by leaving the type empty (the empty string).
@@ -128,7 +140,7 @@ Read
 6. *read_incoming* similarly reads out all incoming associations of a certain type, for a specific element.
    For example, to read out all incoming T2P links of a place::
 
-        >>> read_incoming("my_pn", "p2", "T2P")
+        >>> read_incoming("models/my_pn", "p2", "T2P")
         ["t2p"]
 
    Again, the type can be set to the empty string to return all incoming associations.
@@ -136,20 +148,20 @@ Read
 7. *read_association_source* reads out the source of a specific association, and can be used in conjunction with *read_outgoing* and *read_incoming*.
    For example, to read out which is the source of an arc::
 
-        >>> read_association_source("my_pn", "p2t")
+        >>> read_association_source("models/my_pn", "p2t")
         p1
 
 8. *read_association_destination* similarly reads out the destination of a specific association.
    For example, to read out the target of an arc::
 
-        >>> read_association_destination("my_pn", "p2t")
+        >>> read_association_destination("models/my_pn", "p2t")
         t1
 
 9. *connections_between* reads out the set of all association types that can be created between two elements in the model.
    This also takes into account inheritance information.
    For example, to find out which association types can connect a place and transition::
 
-        >>> connections_between("my_pn", "p1", "t1")
+        >>> connections_between("models/my_pn", "p1", "t1")
         ["P2T"]
 
     If no associations are allowed, the list is empty.
@@ -157,7 +169,7 @@ Read
 10. *all_instances* read out the set of all instances of a specific type in the model.
     For example, to find all Places in our PetriNet model::
 
-        >>> all_instances("my_pn", "Place")
+        >>> all_instances("models/my_pn", "Place")
         ["p1", "p2"]
 
 Delete
@@ -169,15 +181,15 @@ Delete
    Associations, however, are removed.
    For example, to remove place p1::
 
-        >>> element_list_nice("my_pn")
+        >>> element_list_nice("models/my_pn")
         [{"id": "p1", "type": "Place", "name": "place 1", "tokens": 1},
          {"id": "p2", "type": "Place", "name": "place 2", "tokens": 2},
          {"id": "t1", "type": "Transition"},
          {"id": "p2t", "type": "P2T", "__source": "p1", "__target": "t1", "weight": 1},
          {"id": "t2p", "type": "T2P", "__source": "t1", "__target": "p2", "weight": 2},
         ]
-        >>> delete_element("my_pn", "p1")
-        >>> element_list_nice("my_pn")
+        >>> delete_element("models/my_pn", "p1")
+        >>> element_list_nice("models/my_pn")
         [{"id": "p2", "type": "Place", "name": "place 2", "tokens": 2},
          {"id": "t1", "type": "Transition"},
          {"id": "t2p", "type": "T2P", "__source": "t1", "__target": "p2", "weight": 2},

+ 17 - 8
doc/permissions.rst

@@ -28,17 +28,26 @@ This indicates that the owner can read and write the model, the owning group can
 
 Models can be queried for their permission information with the *model_list_full* operation::
 
-    >>> model_list_full()
-    [("my_pn", "PetriNets", "user1", "group1", "200"),
-     ("my_pn2", "PetriNets", "user2", "group1", "210"),
-     ("my_pn3", "PetriNets", "user2", "group2", "210"),
-     ("my_pn4", "PetriNets", "user2", "group2", "211"),
+    >>> model_list_full("models/petrinets/")
+    [("my_pn", "user1", "group1", "200"),
+     ("my_pn2", "user2", "group1", "210"),
+     ("my_pn3", "user2", "group2", "210"),
+     ("my_pn4", "user2", "group2", "211"),
      ...
     ]
 
 In this case, user1 can modify my_pn, as he is the owner (permission 2: read/write), read my_pn2, as he is a member of group1 (permission 1: read), and has no access to my_pn3, as he is neither owner, nor in the group (permission 0: none).
 All users can read my_pn4, independent of their group (permission 1: read).
 
+Folder permissions
+^^^^^^^^^^^^^^^^^^
+
+Similar to models, folders can also have permissions, owners, and an owning group.
+In this case, a readable folder is required to perform a *model_list* operation on that folder.
+A writable folder is required to create new entries (either models or new folders) in that folder.
+Note that this permission system leads to interesting situations, as in the UNIX permission model, where a folder cannot be read, but its contained files can (if their exact name is used).
+When a file was already created, overwriting that file does not require any permissions of the folder at all.
+
 Permission management
 ^^^^^^^^^^^^^^^^^^^^^
 
@@ -49,17 +58,17 @@ To alter the permissions, we have access to several operations.
 1. *permission_modify* changes the permissions of a model to the specified string.
    For example, to make my_pn readable for everyone::
    
-    >>> permission_modify("my_pn", "211")
+    >>> permission_modify("models/my_pn", "211")
 
 2. *permission_owner* changes the owner of a model, thereby possibly revoking our own permission, but passing it on to someone else.
    For example, to make user2 the owner of our PetriNet model::
 
-    >>> permission_owner("my_pn", "user2")
+    >>> permission_owner("models/my_pn", "user2")
 
 3. *permission_group* changes the owning group of a model, thereby possibly revoking permissions for several users.
    For example, to make group2 the owning group of our PetriNet model::
 
-    >>> permission_group("my_pn", "group2")
+    >>> permission_group("models/my_pn", "group2")
 
 Meta-level propagation
 ^^^^^^^^^^^^^^^^^^^^^^

+ 3 - 3
doc/process_enactment.rst

@@ -15,9 +15,9 @@ Enacting process models
 
 To enact the process model, such as *query_state_space*, you must execute the following operation::
 
-    >>> process_execute("query_state_space", "my_", {})
+    >>> process_execute("models/query_state_space", "my_", {})
 
-There are three parameters to this function, the first obviously being the name of the process model, as shown in *model_list*.
+There are three parameters to this function, the first obviously being the name of the process model.
 The second parameter is a prefix for the models used in the process model.
 When executing a process model, data is processed and produced.
 By providing a prefix, the names of these models are first prefixed with the prefix, before they are resolved.
@@ -40,7 +40,7 @@ The call then becomes::
     ...     instantiate(None, "P2T", (p, t))
     ...     # Alternatively, we could have used raw_input() or so to prompt the user
     ...
-    >>> process_execute("query_state_space", "my_", {"refine_petrinet": callback})
+    >>> process_execute("models/query_state_space", "my_", {"models/refine_petrinet": callback})
 
 When the process executes *refine_petrinet*, the callback function is executed, and the manual operation is terminated when the function terminates.
 Other types of operation, such as *model transformations* and *action language* can also have a callback function, but this is usually less important to end users and is therefore not elaborated on here.

+ 15 - 15
doc/transformations.rst

@@ -12,7 +12,7 @@ To create a model transformation, users must specify a set of source metamodels
 The model transformation will afterwards get a signature of these models.
 To create a simple Petri Net simulation transformation, we use the operation *transformation_add_MT* as follows::
 
-    >>> transformation_add_MT({"PN": "PetriNets"}, {"PN": "PetriNets"}, "pn_simulate", open("pn_simulate.mvc", "r").read())
+    >>> transformation_add_MT({"PN": "formalisms/PetriNets"}, {"PN": "formalisms/PetriNets"}, "models/pn_simulate", open("pn_simulate.mvc", "r").read())
 
 The first dictionary we pass, is the input dictionary: it specifies the name the model elements will get in the LHS, and the expected type of them.
 Similarly, the output dictionary specifies the name of output elements and their types.
@@ -24,7 +24,7 @@ For example, all types in the previous model transformation will be renamed by p
 All types are renamed, in order to make multiple inputs with the same type possible.
 For example, when combining two models, both of the same type, but one of them being the *master*, it is possible to do the following::
 
-    >>> transformation_add_MT({"master": "PetriNets", "slave": "PetriNets"}, {"result": "PetriNets"}, "pn_merge", open("pn_merge.mvc", "r").read())
+    >>> transformation_add_MT({"master": "formalisms/PetriNets", "slave": "formalisms/PetriNets"}, {"result": "formalisms/PetriNets"}, "models/pn_merge", open("pn_merge.mvc", "r").read())
 
 In this case, the LHS can match specifically for elements of the master (e.g., *master/Place*).
 
@@ -159,13 +159,13 @@ Invocation
 
 The actual binding is only done later on, upon invocation, and goes as follows::
 
-    >>> transformation_execute_MT("pn_simulate", {"PN": "my_pn"}, {"PN": "my_pn"})
+    >>> transformation_execute_MT("models/pn_simulate", {"PN": "models/my_pn"}, {"PN": "models/my_pn"})
 
 In this case, the model transformation takes the model *my_pn* as input for the *pn_simulate* model transformation, and writes out the result in *my_pn*.
 As the output model matches the input model, the model transformation is effectively in-place.
 For out-place transformations, it is possible to specify a different output model, in which case the model is implicitly copied as well::
 
-    >>> transformation_execute_MT("pn_simulate", {"PN": "my_pn"}, {"PN": "my_simulated_pn"})
+    >>> transformation_execute_MT("pn_simulate", {"PN": "models/my_pn"}, {"PN": "models/my_simulated_pn"})
 
 Model transformation invocation has no effect on the original model in this case.
 Also, model transformations always happen on a copy of the original model.
@@ -178,10 +178,10 @@ Signature
 After a model transformation is defined, it is easy to forget exactly which parameters it takes, and what were the types of these parameters.
 Therefore, the *transformation_read_signature* function can be used to read out the signature of model transformations::
 
-    >>> transformation_read_signature("pn_simulate")
-    ({"pn": "PetriNets"}, {"pn": "PetriNets"})
-    >>> transformation_read_signature("pn_merge")
-    ({"master": "PetriNets", "slave": "Petrinets"}, {"result": "PetriNets"})
+    >>> transformation_read_signature("models/pn_simulate")
+    ({"pn": "formalisms/PetriNets"}, {"pn": "formalisms/PetriNets"})
+    >>> transformation_read_signature("models/pn_merge")
+    ({"master": "formalisms/PetriNets", "slave": "formalisms/Petrinets"}, {"result": "formalisms/PetriNets"})
 
 Querying
 ^^^^^^^^
@@ -189,16 +189,16 @@ Querying
 Similarly, it is often easy to forget which transformations are supported between a source and target metamodel.
 Therefore the *transformation_between* function can be used to query for all transformations that take a certain metamodel as input, and generate another metamodel as output::
 
-    >>> transformation_between("PetriNets", "PetriNets")
-    ["pn_optimize", "pn_simulate", "pn_rename", "pn_combine"]
+    >>> transformation_between("formalisms/PetriNets", "formalisms/PetriNets")
+    ["models/pn_optimize", "models/pn_simulate", "models/pn_rename", "models/pn_combine"]
 
-    >>> transformation_between("PetriNets", "ReachabilityGraph")
-    ["pn_analyze"]
+    >>> transformation_between("formalisms/PetriNets", "formalisms/ReachabilityGraph")
+    ["models/pn_analyze"]
 
 Note that this operation does not take into account other input or output metamodels::
 
-    >>> transformation_between("PetriNets", "Boolean")
-    ["analyze_query", "is_safe", "conforms"]
+    >>> transformation_between("formalisms/PetriNets", "formalisms/Boolean")
+    ["models/analyze_query", "models/is_safe", "models/conforms"]
 
 Tracability links
 -----------------
@@ -221,7 +221,7 @@ For example, to define a tracability link between a *PetriNets/Transition* and *
 
     >>> def callback():
     ...     instantiate(None, "Association", edge=("PetriNets/Transition", "ReachabilityGraph/Transition"), ID="PN2RG_Transition")
-    >>> transformation_add_MT({"PetriNets": "PetriNets"}, {"ReachabilityGraph": "ReachabilityGraph"}, "pn_analyse", open("models/pn_analyse.mvc", "r").read(), callback)
+    >>> transformation_add_MT({"PetriNets": "formalisms/PetriNets"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/pn_analyse", open("models/pn_analyse.mvc", "r").read(), callback)
 
 As the forward slash (/) is already used to distinguish between the metamodel tag and the original entity, entities defined through a callback function should not contain this same symbol.