The EMF Validation Framework provides an extension point for plug-ins to add support for different constraint languages. One of the languages supported is the Object Constraint Language (OCL) version 2.0.
This tutorial will illustrate how to contribute constraints using OCL.
This tutorial assumes that the reader is familiar with the Eclipse extension point architecture. There is an abundance of on-line help in Eclipse for those unfamiliar with extension points.
To see the complete source code for the examples shown in this tutorial, install the OCL Validation Example plug-in into your workspace.
Other references:
org.eclipse.emf.validation.constraintProviders
extension point.org.eclipse.emf.validation.constraintParsers
extension point.
Our batch constraint will assert that a Writer
in the Library
example metamodel must not write books in more than two genres
(BookCategory
).
We start with the extension declaration and definition of a category for our constraints:
<extension point="org.eclipse.emf.validation.constraintProviders"> <category name="%category.name" id="emf-validation-example/ocl"> %category.description </category>
The category name and description are localized in the plugin.properties file:
category.name = Example OCL Constraints category.description = Category for example OCL constraints illustrating the use \ of Object Constraint Language in validation.
Next, we indicate the
EPackage
(s)
for which we are providing
constraints, by referencing one or more namespace URIs. We opt to cache
constraints for performance, which is usually recommended for constraints
declared statically in XML. The <constraints>
element
groups related constraints that belong to the same categories. In this case,
we have only one category for both of our constraints:
<constraintProvider cache="true"> <package namespaceUri="http:///org/eclipse/emf/metamodel/example/pde/library.ecore/1.0.0"/> <constraints categories="emf-validation-example/ocl">
Inside of the <constraints>
element, we declare a constraint
with the following meta-data:
EClass
(es) to which the constraint
applies.
The body of the <constraints>
element contains the
OCL constraint expression.
Note: The OCL constraint text does not include the package declaration, context declaration, or "inv:" invariant indicator.
CDATA sections are convenient for escaping the arrow (->
) and
comparison operators:
<constraint lang="OCL" severity="WARNING" mode="Batch" name="%example1.name" id="example1" statusCode="101"> <description>%example1.desc</description> <message>%example1.msg</message> <target class="Writer"/> <![CDATA[ self.books->collect(b : Book | b.category)->asSet()->size() <= 2 ]]> </constraint>
The localized strings in the plugin.properties file follow the usual pattern.
The one exception is the message string, which for OCL constraints can specify
the {0}
placeholder one or more times to be replaced by the label
for the element that was validated (see the
MessageFormat
API for details). Usually, the label will look something like
"Writer Isaac Asimov"; this can be customized via the
IItemLabelProvider
adapter mechanism in the EMF.Edit framework:
example1.name = Example OCL Constraint (Batch Mode) example1.desc = Example of a batch mode (user-requested) validation constraint in OCL. example1.msg = "{0}" has written books in too many genres.
Creating a live-mode constraint is very similar; the main differences are that
mode
attribute is "Live"Book
's author
reference is
Set
.
The following constraint asserts that a Book
's reference to its
author
must not be null
. Because it is a live mode
constraint, it is triggered by an editor in response to
Notification
s
of changes to books' author references. Add this into the same
<constraints>
element as the previous constraint:
<constraint lang="OCL" severity="ERROR" mode="Live" name="%example2.name" id="example2" statusCode="102"> <description>%example2.desc</description> <message>%example2.msg</message> <target class="Book"> <event name="Set"> <feature name="author"/> </event> </target> not author.oclIsUndefined() </constraint>
And, of course, the localized strings:
example2.name = Example OCL Constraint (Live Mode) example2.desc = Example of a live mode (automatic) validation constraint in OCL. example2.msg = "{0}" must have an author.
To see these two new constraints in action, we must create an environment in which they can be triggered by the validation framework. One such environment is the core validation example. This example installs the Library Editor with menu actions for batch and live validation. It provides other constraints, but will also include the constraints that we added in this tutorial. Try creating writers with diverse interests and unattributed books to see!
To illustrate how to implement constraints in the EMF Validation Framework using OCL, we
Copyright (c) 2000,2008 IBM Corporation, Zeligsoft Inc. and others. All Rights Reserved.