Model validation example: Papyrus UML
Although model queries and incrementally evaluated queries in particular have many usage scenarios, our case study in particular focuses on finding violations of structural well-formedness constraints. The domain (Ecore metamodel) used in the example is (the standard EMF representation of) UML2, and the example contains some graph patterns over UML2 models that express conditions when well-formedness or modeling convention rules are violated.
To illustrate the usage of the model query code generated from these graph patterns, including some lesser known features of the EMF-IncQuery API, a set of separate plug-ins is provided to extend the popular UML editor Papyrus with on-the-fly model validation capabilities, based on the incremental model queries. Due to the incremental nature of EMF-IncQuery, the appearance and disappearance of well-formedness / convention violations are easy to detect and react upon. The set of current violations are incrementally maintained and marked in the model using Eclipse problem markers (see Problems View).
Obtaining the example
- Make sure you have Papyrus installed (tested with version 0.7.2). If you have Eclipse Modeling, Papyrus is available through the Eclipse Modeling Components Discovery (Help > Install Modeling Components).
Check out the source projects from Subversion:
- In the workspace of your runtime Eclipse, check out the example Papyrus project:
This is an Eclipse plug-in that contains a simple, quick&dirty validator framework (independent from UML and Papyrus). An Eclipse extension point is provided by this plug-in, through which constraints can be registered. When the validator framework is initialized on an EMF model, it will load all contributed constraints and will start to monitor them. Each constraint is primarily defined by an EMF-IncQuery graph pattern whose match set identifies the violations of the constraint.
In addition to simply executing the queries and retrieving the results, it is also neccessary to inform the user about the current violations in the model. Fortunately, this task can be carried out without modifications to the modeling system (Papyrus in this example), as problems can be indicated in a separate view. We have opted to use the standard problem markers provided by Eclipse, where problems are bound to files and can be listed in the Problems View. Potentially, a more tight cooperation with the modeling tool would have its advantages over this solution, such as being able to indicate the actual location of violations within the model, directly in the graphical editor of the tool.
The final task is handling model evolution, i.e. reacting to changes in the result set of the query. When a new violation is detected, a new problem marker should be created; when a previously detected violation ceases to occur, the corresponding problem marker should be removed. The challenge is in detecting when these changes occur. The incremental query evaluation engine of EMF-IncQuery includes a feature called delta monitor that serves the purposes of monitoring the difference of the result set of a query from a given point in time onward. In our particular case, delta monitors can be used to report which violations have appeared or disappeared since the last time they were checked. There still remains one issue: when to check. EMF-IncQuery provides a callback hook that is invoked whenever the result set has been updated. This can be used entirely automatically and without cooperation from the modeling tool, so our case study relies on this callback mechanism to update the problem markers. Unfortunately, each step of a complex model manipulation operation will do some partial updates in the model, resulting in the invocation of the callback mechanism mentioned above. In this case, the routine that updates problem markers may observe the model in an inconsistent intermediate state. Therefore the problem markers may show erroneous results for a very short amount of time, while the modeling tool is in the middle of a model manipulation sequence. In case of tighter integration between the modeling tool and the model validator, it can be ensured that the problem marker update routine is called only when the model is in a semantically consistent state.
- https://viatra.inf.mit.bme.hu/svn/incquery/trunk/runtime/org.eclipse.viatra2.emf.incquery.validation.ui and https://viatra.inf.mit.bme.hu/svn/incquery/trunk/runtime/org.eclipse.viatra2.emf.incquery.validation.ui.gmf
These helper plug-ins (likewise independent from UML and Papyrus) define various kinds of Eclipse GUI actions. The actions initialize the validator components contained in the previous package, so that the violation patterns will be incrementally evaluated and markers will be maintained. Remarkably, all of this is performed non-intrusively, without any modification to the code of the modeling tool (Papyrus in this example). Issuing these GUI actions on a model element selection is neccessary so that a reference could be obtained to the run-time EMF model within the modeling tool. The selected model element is used to identify the EMF resource containing the model, and the validation framework is applied to this resource, initializing the incremental matchers of contributed constraints to evaluate against this EMF resource.
Although these plug-ins are not dependent on UML, they provide a simple default way to initialize the validator. Other scenarios may call for different methods to achieve this.
This is the EMF-IncQuery project that defines the queries against the UML model. The source file of the queries is located at models/vtcl/my_uml_validation.vtcl. The file contains four graph patterns that match violations of well-formedness contraints or modeling conventions in UML models, as well as some helper patterns. The patterns in the file altogether demonstrate several language features, including disjunction, positive and negative pattern call, attribute checks, and shareable (non-injective) patterns. The example Papyrus project contains some violations of each of these constraints.
This is the Eclipse plug-in that contains the actual UML-specific constraints, and the only one that is actually Papyrus-specific. They are based on the EMF-IncQuery patterns defined in the UML query project above, and are contributed to the generic validator framework described before.
Additionally, through an Eclipse extension point, a context menu item is contributed that will be active on model elements in a Papyrus editor. This menu item executes the GUI actions described in the preceding projects to intialize the validation framework.
The simple, non-intrusive version of the quick & dirty UML Validator application can be created in about $250$~lines of Java code altogether. Extending it with new well-formedness constraints is simple and requires very little coding:
- First in the query project, the graph pattern identifying the violations of the constraint - let's say MyViolation - should be defined in the vtcl file linked above.
- Source code should be regenerated to catch up with changes in the pattern.
- A new class inheriting Constraint<MyViolationSignature> should be placed in package org.eclipse.viatra2.emf.incquery.examples.uml.papyrus.constraints in the final papyrus-specific plug-in project.
- The class should override getMessage() to return a textual description of the problem kind, and matcherFactory() to return MyViolationMatcher.FACTORY. Optionally, prettyPrintSignature() can be overridden to provide a customized verbose description of a violation instance (see InheritanceDiamondConstraint for example).
- Add an extension entry for your constraint class in plugin.xml.
Being a quick example, the solution could be improved in many ways. Here are a few of them:
The pattern inheritanceDiamond admits a great deal of symmetry, resulting in several duplicate markers for every actual violation.
- Pattern variables B and C are interchangeable, therefore every match (A, B, C, D) will be accompanied by a match (A, C, B, D). The symmetry can be broken by enforcing an ordering on one of the attributes of B and C; e.g. the name of B should come first lexicographically.
- If the supertyping is not direct and there are intermediate classes e.g. between A and B, there will be many matches of the pattern. This can be reduced by enforcing e.g. that neither B nor C have any subclasses that would still make a diamond with the rest of the elements.
- The pattern unreferencedClass could take inheritance into account.
- The Papyrus editor could be modified so that the validation is started automatically, without the need of manual initialization through a context menu entry.
- Current violations should be indicated somehow on the UML diagram displayed by Papyrus, in addition to the Eclipse Problems View.
- The marker text uses the name of elements. When names are changed in the model, however, this text is not updated. Two possible solutions: (a) use EMF databinding to keep a View continuously up-to-date, or (b) include the name attribute in the parameter list of the EMF-IncQuery pattern, so that a change in the name results in a completely new pattern match and a corresponding new marker.
- Listen for the event when the editor is closed, and deconstruct the validator component (+remove markers).