# Tutorial: OCL Validation Constraints

## Contents

- Overview
- References
- Specifying a Batch Mode OCL Constraint
- Specifying a Live Mode OCL Constraint
- Evaluating the OCL Constraints
- Summary

## Overview

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]

## References

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:

- For an environment in which to test the constraint that you will create in this tutorial, install the Library Metamodel example which provides a generated editor and the Validation example which provides menu actions for batch and live validation.
- `org.eclipse.emf.validation.constraintProviders` extension point.
- `org.eclipse.emf.validation.constraintParsers` extension point.
- OCL 2.0 specification.

[back to top]

## Specifying a Batch Mode OCL Constraint

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:

- 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]

## Specifying a Live Mode OCL Constraint

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]

## Evaluating the OCL Constraints

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]

## Summary

To illustrate how to implement constraints in the EMF Validation Framework using OCL, we

1. Created a batch mode OCL constraint.
2. Created a live mode OCL constraint.
3. 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.