Contents
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.
[
back to top]
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:
[
back to top]
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="https:///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:
-
a unique ID. If it does not already begin with the plug-in ID,
the framework prepends the plug-in ID to it to make it unique.
-
an evaluation mode, either "Batch" or "Live".
-
a severity, either "ERROR", "WARNING", or "INFO".
-
a language, in this case "OCL".
-
a status code (which is used for the message in the workspace .log file).
It needs not be unique.
-
a localized name and description, for display in the enablement UI
in the preference pages.
-
a localized message to display when the constraint is violated.
-
the name(s) of the
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.
[
back to top]
Creating a live-mode constraint is very similar; the main differences are that
- the value of the
mode
attribute is "Live"
-
the target definition optionally includes specific features and events
on which the constraint is triggered. In this case, the constraint fires
when a
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.
[
back to top]
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!
[
back to top]
To illustrate how to implement constraints in the EMF Validation Framework
using OCL, we
- Created a batch mode OCL constraint.
- Created a live mode OCL constraint.
- Evaluated these constraints on model elements using the core validation example in the Library Editor.
[
back to top]
Copyright (c) 2000,2008 IBM Corporation, Zeligsoft Inc. and others. All Rights Reserved.