Friday, June 28, 2013

Change Impact Analysis & Constraint Violation Detection

by: Markus Zoffi, Christina Zrelski, Roland Jöbstl, Christian Johannes Tomaschitz 

Whenever teamwork is part of the development process, one is not capable to avoid merging of double edited files. However, if these files only contain code the merge process can be resolved very easily, but if there are more complex constructs - like models - the merging process also increases its complexity. During the participation of the Advanced Model Engineering Lecture we worked on an efficient way to detect constraint violations after merging the models, which is presented in the following.

Goal of the Project

The overall idea of this project was concentrated on performing a change impact analysis of parallely evolved model versions. Thereby every model version in itself was valid, but the conjunction of different and/or parallel modifications caused one or more violations in constraints. The resulting constraint violations should not only be detected, we also wanted to identify the cause of the violation.

Defining Metamodel and OCL Constraints

The first step and general setup for the project was to create a simple metamodel and add some OCL constraints. Our metamodel is basically a simplification of an UML class diagram, it contains four classes: the class SimpleClassDiagram, SimpleClass, SimpleAttribute and SimpleRelation.

A SimpleClassDiagram consists of a number of SimpleClasses, which can in turn specify inheritance (superclass relation), attributes (relation to SimpleAttribute) and relations (bidirectional relation to SimpleRelation). A SimpleAttribute specifies certain properties of a SimpleClass, each one having a name and type, whereas a SimpleRelation defines the relation between classes as well as the properties of the relation itself (minCardinality, maxCardinality).


Afterwards we defined some basic OCL constraints in the metamodel (using OCLinEcore) which could be easily violated during a merge process for our testing purposes.
The following five constraints were used:

  • Unique Attribute Name:
    context SimpleClass
    inv: self.attributes->isUnique(name);
  • Limit Number Of Attributes:
    context SimpleClass
    inv: self.attributes->size() < 6;
  • Attribute Name Not Empty:
    context SimpleAttribute
    inv: self.name->notEmpty();
  • Cardinality of Relation Within Range:
    context SimpleRelation
    inv: self.minCardinality > -1 and self.maxCardinality < 50 and self.minCardinality <= self.maxCardinality;

Merging the Models 

In the context of model merging and diffmodel analysis we used the EMF Compare Framework, which provides comparison and merge facility for any kind of EMF models. For the merging task we use a three-way-merge, which means that two revised versions and their common ancestor model had to be specified. Thereby the ancestor model is treated as a reference for identifying and connecting the differences.

Detecting the Violations 

The first step was to iterate over the given models and identify which model elements matched to each other. Afterwards, for each two matching elements the differences between them were detected.
Thereby, each difference corresponds to a change (where change means, ADD, CHANGE, DELETE, MOVE Operation). In detail, all model elements that changed were processed and compared to the invalid trace object. The goal thereby was to identify the model element which was responsible for the validation error in the OCL constraint. These information was then processed in a further step to generate the output for the user.

Demonstrating our approach
For our demonstration let's take the following two models:


The merging process leads to a constraint violation with the Limit Number of Attributes constraint with the following output.



Monday, April 29, 2013

How to create an EMF Profile

Whenever you want to store additional information to EMF-based models and you cannot or don't want to change the respective metamodel, EMF Profiles provide a convenient solution for extending metamodels in a non-intrusive and lightweight manner; comparable to how UML profiles allow to extend UML. For extending a metamodel, all you have to do is to create a profile, which can then be applied to models in order to store the additional information you want to add to the original model. In the following, we show how profiles are created step by step.

Extending the library metamodel

For illustrating the process of creating a profile, we extend the well-known library example metamodel. This metamodel basically contains three classes: the class Library, Writer, and Book.

Now assume, we need to add additional information to library models without having to change the metamodel and, thus, without the need to re-generate the model-, edit-, and editor code. In particular, we want to be able to store whether a book is an ebook and, if it is an ebook, in which format it is available (such as ePub or PDF). Additionally, we want to be able to annotate books with tags.

Creating a profile project

To create a new profile project, we start the dedicated wizard for profile projects by selecting File > New > Other and select EMF Profile > EMF Profile Project.


After clicking Next, we enter a name for the profile project, as well as additional information about the profile, such as its name and its namespace URI. For the name and the namespace URI, it is recommendable to apply the same naming conventions as for metamodels.


After hitting the Finish button, the wizard creates the EMF profile project and opens the created empty EMF profile diagram, which has been initialized with the information provided in the wizard already, as can be seen in the Properties view.

Modeling the profile

A profile consists of stereotypes, which extend EClasses of metamodels. In our scenario, we want to store additional information to instances of the class Book of the library metamodel. Thus, we will create stereotypes that extend the class Book. Therefore, we first have to import the class Book. To do that, we use the popup menu (right-click the canvas of the profile diagram editor). In the popup menu, we now select Import Metamodel Element... and choose the extlibrary metamodel and, in the next step, the EClass Book. As a result, we obtain a shortcut to Book in our profile diagram canvas.



Now, we can start creating stereotypes using the palette in the profile diagram editor. To store whether a book (i.e., an instance of the class Book) is an ebook, we create the stereotype EBook. As we want to apply this stereotype to instances of Book, we create an Extension relationship from the created stereotype to the imported class Book. Extension relationships have a multiplicity (e.g., 0..1, 0..*, 2..4, etc.). This multiplicity specifies how often a stereotype can be (and must be) applied within one profile application to an instance of the extended class (e.g., Book). In our scenario, the stereotype EBook should not be mandatory, since we might have books that are not ebooks and, thus, should not be annotated with the stereotype EBook. Thus, we use a lower-bound multiplicity of 0. Further, it wouldn't make any sense to apply the stereotype EBook multiple times to the same book. To prohibit multiple applications, we set the upper-bound multiplicity to 1.


Stereotypes may carry additional data. One way to allow for adding additional data is to add tagged values to stereotypes. Since we want to store the format of an ebook, we add the tagged value named format to the stereotype EBook. Tagged values are basically attributes and can have primitive Ecore types, such as EString, EBoolean, ect., as well as custom EEnum types. We want to store whether an EBook is available in the format of EPUB or PDF; thus, we create a new EEnum named EBookFormat with two literals, EPUB and PDF, and set the type of the attribute format to EBookFormat.

Side note: Although this isn't needed in our example, stereotypes may, in general, also contain cross references to existing model elements (in the base model or in the profile application), as well as containment references (i.e., the stereotype application owns additional model elements). For creating references, just use the palette in the diagram editor and set the properties of the added reference accordingly. You can also use inheritance among stereotypes, if needed.

As mentioned above, we also want to be able to annotate books with tags. Therefore, we add another stereotype named TaggedBook, which also extends the class Book, and add a tagged value named tags of type EString to the created stereotype. To enable multiple tags for one book, we may set tags to be multi-valued (i.e., an upper-bound of -1 in the properties of the tagged value) and/or set the multiplicity of the stereotype to be 0..*, which specifies that the stereotype TaggedBook may be applied arbitrarily often to one instance of a book.

Registered profiles

Having finished the profile, we may validate it and save it. If the profile is valid, it will be registered automatically to the local profile registry. You may inspect all currently registered profiles using the Registered EMF Profiles view, which can be added using Window > Show View > Other... > EMF Profiles > Registered EMF Profiles.


As can be seen in the screenshot above, the created profile has been registered correctly. Note that you can still modify your profile; it will be synchronized automatically with the local profile registry, as long as your profile is valid. If it is invalid, it will disappear from the registry until you fix the validation error.

Once your profile is available in the local registry you can apply it to models that conform to the extlibrary metamodel. This, however, will be covered in future posts... so make sure to stay tuned.