• No results found

Relationships and Constraints

Section 6.3.2 discussed a set of functions for matching, instantiating, transforming, query- ing and refining patterns. These functions are exposed in XMF as a JavaScript API. This API is used for defining intra- and cross model relationships and semantic rules for pro- viding modelling feedback.

6.6.1 Defining Intra- and Inter-Model Constraints

Constraints in XMF typically have the form “for all objects of type T in the model M, condition C must hold” or “for all elements O1 of type T1 in model M1 must exist an element O2 of type T2 in model M2 where O1.x=O2.y”. Formulating such constraints is primarily an interplay of the reference, refinement and query functionality: a referenced pattern is first refined by fixing a subset of its variables and then a query is performed with the refined pattern.

For example, the following query returns all classes with name “Student” from a given model:

query(refine(’class’, [{’$name’,’Student’}]),’classModel’) The parameter ’class’ is a string that references the class pattern. The argument

eral syntax for an array containing a JavaScript object. The result of refine is the class pattern with the name fixed to ’Student’. This refined pattern is used for querying the model referenced by the string ’classModel’. The result is a sequence of class instances represented as DOM tree fragments. There are further helper functions for for- mulating constraints. The function queryVar expects a pattern, a model and a vari- able name from the pattern. It performs a depth-first search for the pattern in the model, matches the pattern to the first occurrence and returns the value bound to the variable.

The function chain abstracts querying structures that are linked using references. For example, classes are linked in an inheritance relationship by adding to each child class of a class a parent reference. Following the parent references from any class to the root class “object” yields a chain of classes that are in an inheritance relationship. Retrieving this chain using the basic functions requires repeatedly calling queryVar to retrieve the reference, refine to refine the class pattern and query with the refined class to resolve the reference. The chain function hides all this. It expects as arguments a pattern that defines referencing and referenced objects, the variable that is the source of the reference, the variable that is the target of the reference (typically the id or name of a model element), a start value and an end value. It returns all elements between start and end. An example of the use of chain will be given below. Other functions of the API are assertwhich throws an exception if its argument does not yield a truth value and len which returns the length of a list. The function equalNode checks equality between two DOM tree nodes.

Listing 23 Constraints for InstanceOf Relationships

1 function checkInstanceOf(oID,cName){ 2 //the object with ID oID

3 var object=

4 query(refine(’object’,[{’$objectID’:oID}]),’objectModel’); 5

6 //assert that the object references the class

7 assert(eqNode(queryVar(’object’,object,’$class’),cName)) 8

9 //all classes that are in an inheritance relationship 10 //between cName and Object

11 var classes=chain(’class’,’$cname’,’$parent’,

12 cName,’Object’,’classModel’);

13

14 //attributes of all classes

15 var attributes=query(’attribute’,classes); 16

17 //all attribute values of the object

18 var attribValues=query(’attributeValue’,object); 19

20 //assert that the number of attribute values of the 21 //object equals the number of attributes of the classes 22 assert(len(attributes)==len(attribValues));

23

24 //assert that for every attribute value 25 //there is exactly one attribute

26 for(var i=0;i<attributes.childNodes.length;i++) { 27 var attrib=attributes.childNodes[i]; 28 var attribName=queryVar(’attribute’,attrib,’$aname’); 29 var avalue=query(refine(’attributeValue’, 30 [{’$attribName’:attribName}]),attribValues); 31 assert(len(avalue)==1); 32 } 33 return 1; 34 }

id and a class name as arguments. In lines 3 and 4, the object belonging to the object id argument is queried from the model. This is done by refining the object pattern with a binding from $objectID to the argument oID. The first check for the “instanceOf” re- lationship is performed in line 7 by asserting that the class reference in the object is equal to the argument cName. In lines 11 and 12, the chain function is used to query the class referenced by the cName argument and all its superclasses. On this result, a query using the attribute pattern is performed which yields all attributes of the classes (line 15). In line 18, the attribute values are queried from the object. Line 22 asserts that the length of the attributes from classes in the class inheritance chain equals the length of attribute values in the object. Finally, a for loop is used to check for every class attribute that there is exactly one attribute value in the object with the same name.

The current implementation of the constraint language as a JavaScript API can be im- proved by adding a syntactic interface that abstracts from the JavaScript code and defines an actual constraint language. This remains future work.

6.6.2 Interactive Modelling

In programming, various stages of program execution, e.g., compiling, running and de- bugging, provide feedback to the programmer as to the correctness of the program. For the user, this allows an interactive approach where feedback from the system leads to improvements in the program. Modelling, on the other hand, is a far more static process that lacks interactivity and feedback. This makes it difficult to grasp the implications of definitions in a model. One of the goals of XMF is to provide a more interactive mod- elling process. The use of constraints as defined above plays an important role in this respect. This is because constraints can be used to guide modelling and provide a basis for the modelling system to give feedback if a model violates constraints. Overall, XMF provides the following types of checks on models:

• Well-formedness of XML. Detects syntax errors in XML such as non-matching start- and end-tags in an element definition.

• Modelling language validity. Detects modelling language syntax errors. For exam- ple, if an object is missing an object id.

• Intra-model constraint satisfaction. Detects violations of rules in a single model. For example, if parent relationships between classes are circular.

• Inter-model constraint satisfaction. Detects violations of rules across different mod- els. For example, that the number of object relationships in an object model exceeds those defined by the multiplicities in the class model.

XMF offers feedback for all these errors. The first two checks look for syntactic errors by attempting to parse the XML (well-formedness) and by matching the XPLT pattern that defines the language with the model (validity). The latter two checks detect semantic errors and are based on constraint definitions with the scope of single or multiple models.