endm
Classes, attributes and references are qualified with their containers’ names, so that classes with the same name belonging to different packages, as well as attributes and references of different classes, are distinguished. For example, assuming that all the classes in the model are included in a packagePS, identifiersMachineandoutwould really beMachine@PSand out@Machine@PS(orout@Conveyor@PS). These qualifications are omitted here to improve readability. The interested reader is referred to Appendix B to see an example of a metamodel definition (namely, the Ecore metamodel) where these qualifications are shown.
4.1.2 Representing Models with Maude
Once we have described a metamodel in Maude as a MEL theory, we can represent models conforming to it by means of Maude terms that belong to this MEL theory. In particular, we represent models as structures of sort@Modelof the formmm{obj1 obj2 ...objN}, where mm is the constant that represent the metamodel, andobji are the objects that constitute the model.
Objects are record-like structures of the form< o : c | a1:v1# ...# an:vn >, where o is the object identifier (of sort Oid), c is the class the object belongs to (a subsort of sort @Class), and ai : vi are attribute-value pairs (of sort @StructuralFeatureInstance). Attribute-value pairs, which represent both (Ecore) attributes and references, are constructed in such a way that attribute names (of sort@Attributeor@Reference, respectively) are distinguished from attribute values (of sortOCL-Type), and therefore, they can be accessed independently with a simple Maude match instead of making use of metalevel operations—as done when using the representation suggested in [44].
For instance, the following Maude specification describes the production system model depicted in Figures 3.3 and 3.5:
op psModel : −> @Model . eq psModel
= ProductionSystem {
< ’p : Plant | els : Sequence{ ’heg # ’hag # ’c1 # ’c2 # ’t1 # ’a # ’c3 # ’t2 # ’u } >
< ’heg : HeadGen | in : null # out : ’c1 # counter : 10 # xPos : 1 # yPos : 3 >
< ’hag : HandleGen | in : null # out : ’c2 # counter : 10 # xPos : 1 # yPos : 1 >
< ’c1 : Conveyor | parts : Sequence{} # out : ’t1 # xPos : 2 # yPos : 3 >
< ’c2 : Conveyor | parts : Sequence{} # out : ’t1 # xPos : 2 # yPos : 1 >
< ’t1 : Tray | parts : Sequence{} # capacity : 4 # xPos : 3 # yPos : 2 >
< ’a : Assembler | in : ’t1 # out : ’c3 # xPos : 4 # yPos : 2 >
< ’c3 : Conveyor | parts : Sequence{} # out : ’t2 # xPos : 5 # yPos : 2 >
< ’t2 : Tray | parts : Sequence{} # capacity : 4 # xPos : 6 # yPos : 2 >
< ’u : User | parts : Sequence{} # xPos : 6 # yPos : 3 >
} .
References are represented by object identifiers, which are in turn represented by quoted identifiers (identifiers prefixed by a quote). Attribute and reference values are specified by OCL expressions, which are fully supported thanks to mOdCL. We have applied some renamings to the original mOdCL specifications to adapt it to our Maude representation of model and meta-models. For instance, the , operator is now named # , and therefore elements of sequences and ordered sets are now separated by hash marks. The interested reader is referred to Ap-pendix A for more details on our algebraic constructors and the renamings we have applied to mOdCL specifications.
Finally, note that metamodels can also be seen as models that conform to meta-metamodels, and therefore they can be represented as Maude terms of sort@Model too. The MEL theory that defines their constructors will represent a meta-metamodel, such as the MOF or Ecore metamodel.
4.1.2.1 The Conformance Relationship
As we previously mentioned, once we have described a metamodel in Maude as a MEL theory, we can represent models conforming to such a metamodel by means of Maude terms that belong to the @Model sort, but it does not mean that all the terms of this sort will represent models which really conform to the metamodel that the MEL theory describes. If we want to ensure this, we have to check that the term of sort@Modelobeys the structuring rules specified by the properties of the metamodel elements, such as the types of the objects being referenced, or the cardinality of the structural features.
The correct construction of the objects in a model is checked by the Maude type system. In addition, other metamodel properties (such as the valid types of the objects being referenced) is expressed in terms of thevalidModelpredicate that define the well-formedness rules that any valid model should conform to. Thus, given a variableOBJSET of sortSet{@Object}, we define a sort for every model type by means of membership axioms as follows:
s o r t PS@Model .
s u b s o r t PS@Model < @Model .
cmb ProductionSystem { OBJSET } : PS@Model i f validModel( ProductionSystem { OBJSET }) .
Membership axioms (mb) and conditional membership axioms (cmb) assign sorts to terms.
Thus, a term of sort@Modelbecomes also of sortPS@Modelif its metamodel is Production-Systemand the objects that constitute it fulfills all the metamodel properties. This last
require-ment is checked with thevalidModel operation; the following is an excerpt of its
9 v a r s SFS SFS’ : Set{@StructuralFeatureInstance} .
10 v a r s ATTIS : Set{@AttributeInstance} .
11 v a r s REFIS : Set{@ReferenceInstance} .
12 v a r ATT : @Attribute .
19 op validModel : @Model−> Bool .
20 eq validModel( MODEL ) = validModelAux ( MODEL , MODEL ) .
21
22 op validModelAux : @Model @Model−> Bool .
23 eq validModelAux( MM { none } , MODEL ) = true .
31 op validAttributes : MyList @Object−> Bool .
32 eq validAttributes( nil , < O : C | empty >) = true .
39 and−then (<< VALUE −> asSequence ( ) −> isEmpty ( ) >> or−else
40 subTypeOf( meta ( VALUE ) , type ( ATT ) ) )
41 and−then validAttributes ( ATTS , < O : C | ATTIS >) .
42 eq validAttributes( ATTS , < O : C | ATTIS >) = false [ owise ] .
43
44 op validReferences : MyList @Object @Model−> Bool .
45 eq validReferences( nil , < O : C | empty >, MODEL ) = true .
46 eq validReferences( ( REF REFS ) , < O : C | ( REF : VALUE # REFIS ) >, MODEL ) =
47 ( isUnique ( REF ) == isUnique ( VALUE ) )
48 and−then ( isOrdered ( REF ) == isOrdered ( VALUE ) )
49 and−then ( isMany ( REF ) == isMany ( VALUE ) )
50 and−then ( lowerBound ( REF ) <=Card size ( VALUE ) )
51 and−then ( size ( VALUE ) <=Card upperBound ( REF ) )
52 and−then validRefType ( << VALUE −> asSequence ( ) >>, type ( REF ) , MODEL )
53 and−then ( ( opposite ( REF ) == null ) or−else
54 validOpposites(<< VALUE−> asSequence ( ) >>, opposite ( REF ) , O , MODEL ) )
55 and−then validReferences ( REFS , < O : C | REFIS >, MODEL ) .
56 eq validReferences( REFS , < O : C | REFIS >, MODEL ) = false [ owise ] .
57
58 op validRefType : Sequence @Class @Model−> Bool .
59 eq validRefType( Sequence{mt−ord} , C , MODEL ) = true .
60 eq validRefType( Sequence{O # LO} , C ’ , MM { < O : C | SFS > OBJSET }) =
61 isSubClass( C , C ’ )
62 and−then validRefType ( Sequence{LO} , C ’ , MM { < O : C | SFS > OBJSET }) .
63 eq validRefType( SEQ , C , MODEL ) = false [ owise ] .
64
65 op validOpposites : Sequence @Reference Oid @Model−> Bool .
66 eq validOpposites( Sequence{mt−ord} , REF , SRC , MODEL ) = true .
67 eq validOpposites( Sequence{O # LO} , REF , SRC ,
68 MM { < O : C | ( REF : VALUE # SFS ) > OBJSET }) =
69 << VALUE−> asSequence ( ) −> includes ( SRC ) >>
70 and−then validOpposites ( Sequence{LO} , REF , SRC ,
71 MM { < O : C | ( REF : VALUE # SFS ) > OBJSET }) .
72 eq validOpposites( SEQ , REF , O , MODEL ) = false [ owise ] .
73
74 . . .
75 endm
The validModelAuxoperation is recursively applied over every object of the model. It checks whether the object class belongs to the specified metamodel or to the Ecore meta-model, since this one is imported in every metamodel. Then, it checks with the auxiliary validReferencesandvalidAttributesoperations (a) that every reference and attribute value fulfills the properties of the structural feature specified in the metamodel, such as its cardinality or type; and (b) that no attribute or reference is missing or borrowed from another class. Metamodel properties can be accessed directly from the model thanks to the equations we define for every metamodel. Most of the equations defined for attributes and references, such asisOrderedandisUnique, are defined over attributes and references values (of sort OCL-Type) too, in order to check their correspondence (see Appendix A). Themetaoperator (see line 40 in the above excerpt of code) obtains from a term of sortOCL-Typeits primitive data type. The<=Cardoperator is used to check whether a cardinality value is less or equal than another (it considers the*symbol).
Note that we do not need to access Maude’s metalevel in any moment. Furthermore, our notation allows to easily separate attributes and references in a match (see line 24), and attribute
and reference names from their values (see lines33and46), thus facilitating the specification of model operations.
Further structural constraints can also be checked with the mOdCL tool (see Section 2.2.4).
The mOdCL tool allows us to specify OCL invariants and then check them on any specific model. For instance, the following invariant specifies that the capacity of any tray is not ex-ceeded:
1 op noCapacityExceeded : −> OCL−Exp .
2 eq noCapacityExceeded = context Tray inv ( self . parts−> size ( ) <= self . capacity ) .
This invariant can be checked over thepsModelmodel we defined in Section 4.1.2 by typing:
1 Maude> r e d u c e << noCapacityExceeded ; psModel >> .
2
3 r e s u l t Bool: true
The<< ; >>operator evaluates the OCL expression given as the first argument in the context of the model given as the second argument.