Checking Constraints with the Check Language

Checking Constraints with the Check Language

An alternative to checking constraints with pure Java, is the declarative constraint checking language Check . For details of this language take a look at the Check language reference. We will provide a simple example here.

We start by defining the constraint itself. We create a new file called checks.chk in the src folder of our project. It is important that this file resides in the classpath! The file has the following content:

import data;
context Attribute ERROR
   "Names must be more than one char long" :
   name.length > 1;

This constraint says that for the metaclass data::Attribute, we require that the name be more than one characters long. If this expression evaluates to false, the error message given before the colon will be reported. A checks file can contain any number of such constraints. They will be evaluated for all instances of the respective metaclass.

To show a somewhat more involved constraint example, this one ensures that the names of the attributes have to be unique:

context Entity ERROR
  "Names of Entity attributes must be unique":
  attribute.forAll(a1| attribute.notExists(a2| a1 != a2 && a1.name == a2.name ) );

The following piece of XML is the workflow file we have already used above.

<workflow>
  <property file="workflow.properties"/>

  ..

  <component class="org.eclipse.emf.mwe.utils.Reader">
    <uri value="platform:/resource/${modelFile}" />
    ..
  </component>
</workflow>

After reading the model, we add an additional component, namely the CheckComponent .

<component
    class="org.eclipse.xtend.check.CheckComponent">

As with the code generator, we have to explain to the checker what meta-meta-model and which metamodel we use.

  <metaModel id="mm"
   class="org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel">
  </metaModel>

We then have to provide the checks file. The component tries to load the file by appending .chk to the name and searching the classpath – that is why it has to be located in the classpath.

   <checkFile value="checks"/>

Finally, we have to tell the engine on which model or part of the model the checks should work. In general, you can use the <expressionvalue="..."/> element to define an arbitrary expression on slot contents. For our purpose, where we want to use the complete EMF data structure in the model slot, we can use the shortcut emfAllChildrenSlot property, which returns the complete subtree below the content element of a specific slot, including the slot content element itself.

   <emfAllChildrenSlot value="model"/>
  </component>

Running the workflow produces an error in case the length of the name is not greater than one. Again, it makes sense to add the skipOnError="true" to those subsequent component invocations that need to be skipped in case the constraint check found errors (typically code generators or transformers).