This tutorial has been refreshed for Eclipse 2021-06; Eclipse 4.20, EMF 2.26, OCL 6.15.0.
The graphical styling of some screenshots may be slightly out of date.
In this example you will
Get an Overview of the Complete OCL language
Load a Complete OCL document into a third party application
Enhance Ecore validation for derived properties
Validate an Ecore model using additional Complete OCL validation
Enhance UML validation
Validate a UML model using additional Complete OCL validation
Enhance Xtext validation
Validate an Xtext grammar using additional Complete OCL validation
By itself, OCL is almost useless, since without any models to operate on, the constraints cannot achieve a great deal.
The simplest way to make OCL useful is to embed OCL expressions within a model to enrich the basic structural characteristics of a model with more complex behavior. OCLinEcore provides this capability for Ecore models. Papyrus provides comparable capabilities for UML models.
This tutorial introduces the Complete OCL language which may be used to provide a self-standing document that complements a pre-existing meta-model.
All the material for this tutorial is available as part of the CompleteOCLTutorial Example project that you may load by selecting New then Example... using the right button context menu of the Project Explorer. This should give the New Example dialog in which you can select the OCL (OCL Constraint Language) Plugins and the Complete OCL Tutorial and then Next.
Then Finish.
If you do not see these example projects, follow the Instructions for installing the OCL Editors.
The resulting project has a few test files.
The Complete OCL language is described in detail in the Complete OCL section of this documentation. In this tutorial we will provide just a brief overview of the language. If not already open, double click on ExtraEcoreValidation.ocl to show the following text that provides examples of many important aspects of the Complete OCL syntax.
The import statement is a serious omission from the OMG specification, since without it, any attempt to align the Complete OCL constraints with external models relies on implementation-specific magic. The import statement is therefore an extension that the Pivot-based Eclipse OCL prototypes for a future OCL specification revision.
Zero or more import statements may be present to specify the URIs of external model elements and optionally alias names for those elements. In the example:
import ecore : 'http://www.eclipse.org/emf/2002/Ecore#/'
http://www.eclipse.org/emf/2002/Ecore
specifies the URI of the Ecore metamodel and
#/
is the fragment URI
navigating to the root element which is the Ecore package. The
ecore
specifies an alias for this package, which happens
to be the same as the name of the package. Within the Complete OCL document, the imported model element may be referred to by its
alias.
When using the Ecore and UML bindings, the Java API support for using Complete OCL documents requires implementation-specific magic; the imported models must be loaded into the package registry by the invoking code. Import statements are not used.
Prior to the Juno release, import statements were not understood and so there was a usage conflict between Pivot and Ecore/UML bindings. Preparation of a Complete OCL document using the Xtext editor, or usage with Pivot model and Xtext parser required import statements. But re-use with the Ecore and UML LPG parser required the import statements to be removed.
Since Juno, the LPG parser ignores the import statements, so they may be left in.
A package context declaration may bracket declarations that complement model elements within the complemented package.
package ecore
...
endpackage
This specifies that additional Complete OCL declarations will complement the pre-existing declarations of
the
ecore
package.
Multiple package context declarations may be used to complement multiple packages.
The package context declaration may be omitted if subsequent classifier context declarations have a fully qualified name identifying the package.
A classifier context declaration introduces declarations that complement subsequent model elements within the complemented classifier.
context EModelElement
The classifier context is terminated by a
context
or an
endpackage
.
Additional operations and properties may be defined for use within the Complete OCL document. These features may be used as if they were part of the complemented meta-model.
def: asError(verdict : Boolean) : Boolean =
if verdict then true else null endif
def: hasDerivation : Boolean = eAnnotations->select(source.startsWith(
'http://www.eclipse.org/emf/2002/Ecore/OCL'))->notEmpty()
A definition starts with the new feature name, then the parameters for operations and the feature type followed by an OCL expression that evaluates the operation or the property.
For properties such as
hasDerivation
there is very little difference between a property definition
hasDerivation
and a parameter-less operation definition
hasDerivation()
. The property definition
and usage is two characters shorter and may seem more natural. The operation definition has the advantage that
it can be overloaded in derived classes.
Invariants may be imposed on a complemented meta-model. The invariant comprises the name of the invariant followed by an OCL expression that evaluates true when the invariant is satisfied.
inv DerivationIsTransient: hasDerivation implies transient
These invariants are executed when a model is validated in an application that has loaded the complementing Complete OCL document. The significance of this is explained in OCL->Load Document Menu Action.
The readability of constraints can be significantly enhanced by the use of let-variables or the re-use, as above, of the
hasDerivation
helper property.
Eclipse OCL supports two extensions to invariants that allow the validation failure messages and severities to be customized.
inv DerivationIsVolatile(
'"volatile" must be specified for derived feature ' + self.toString()):
asError(hasDerivation implies volatile)
The invariant name may be followed by a parenthesized OCL expression that computes a String to be used as the validation failure message.
The severity of a validation failure may be controlled by the non-true value evaluated by the invariant expression.
a
false
return indicates a warning severity
a
null
return indicates an error severity
an
invalid
return indicates a fatal severity
See Custom Validation Messages for more details.
Complete OCL also allows an incomplete operation or property declaration in the complemented meta-model to be completed.
initial value expressions or derived value constraints may be specified for properties.
body expressions and precondition/postcondition constraints may be specified for operations.
These facilities are of limited use since OCLinEcore avoids the need for incomplete meta-models.
The major disclaimer in the above is that the Complete OCL only complements the complemented meta-model in applications that have loaded the Complete OCL.
Prior to the Juno release, this meant that Complete OCL was only usable in custom Java applications since no standard modeling applications would load the complementing document.
The OCL->Load Document menu action enables a Complete OCL document to be loaded into a wide variety of applications.
The OCL->Load Document menu action is added to the right button menu of applications with a ResourceSet accessible from the current selection.
It has been observed that the extra menu action is not always immediately available, so if you do not see it, hit Esc to cancel the menu, select something corresponding to a model object and right click again.
Since Mars, suitable applications are
an editor generated from an Ecore meta-model
the Sample Ecore Editor
the UML Model Editor
the Papyrus Model Editor
your model editor
an editor generated by Xtext
the Xtext Editor
the MWE2 Editor
the OCLinEcore Editor
your DSL editor
The OCL->Load Document menu action activates the Load Complete OCL Document dialog in which you can browse Registered Complete OCL Documents, the File system or the Workspace for one or more Complete OCL documents to load, or often more conveniently you can just Drag and Drop them from an Operating System Explorer or an Eclipse Explorer.
After clicking OK the documents load.
Behind the scenes, it is necessary to install global wrappers around all complemented packages. These wrappers are sensitive to the ResourceSet for which complementing has been requested and so although this incurs a small performance penalty for use of the complemented packages in other applications, it should not affect the functional behavior of other applications.
The Sample Ecore Editor has acquired many useful validation rules, so that for many usages just invoking Validate is quite sufficient. But what if it isn’t? Perhaps you have some style conventions that you wish to apply. Perhaps the built-in rules are not sufficient.
Prior to Juno and the OCL->Load Document capability, your only choice would be to check out the Ecore Editor and create a custom variant. Now you can use Complete OCL to extend the Sample Ecore Editor.
We will revisit the ExtraEcoreValidation.ocl document that we have just examined and use it to rectify inadequate checking of derived properties by the Sample Ecore Editor. The document provides six invariants, at least three of which detect problems that were encountered by users during the Indigo release cycle.
The EMF code generation templates have a simple treatment of
volatile
. Non-volatile variables have an associated field which is returned by the
get
operation. This overrides any derivation that might be supplied.
inv DerivationIsVolatile: asError(hasDerivation implies volatile)
We therefore want to diagnose that if an EStructuralFeature has a derivation then the volatile declaration is also present to avoid the derivation being ignored.
This problem is so serious that the basic expression is wrapped in the
asError
operation to convert the
default
true
/
false
okay/warning severity into the
true
/
null
okay/error severity.
The EMF code generation templates have a similarly simple treatment of
transient
. Non-transient variables will be
serialized as part of a model save. This is not usually appropriate since the derived value is redundant and can be
recomputed when the model is loaded again.
inv DerivationIsTransient: hasDerivation implies transient
We therefore want to diagnose that a derivation is not serialized because of a default non-transient declaration.
Composition is handled directly by EMF and it is not clear that it is appropriate to define an alternate meaning of composition. It is pretty certain that EMF will not permit an alternate semantics.
inv DerivationIsNotComposed: asError(hasDerivation implies not containment)
We therefore want to diagnose if a derivation is attempting to specify alternate composition semantics and report an error if this occurs.
Opposites are also handled directly by EMF, but it is possible to replace this functionality. However if the forward functionality is replaced, it is very unlikely that EMF’s default reverse functionality will be appropriate.
inv DerivationWithOppositeHasOppositeDerivation:
hasDerivation and eOpposite <> null implies eOpposite.hasDerivation
We therefore want to diagnose that a derivation that redefines the forward semantic of opposite also redefines the corresponding reverse semantics.
An initial value for a property may be specified as a simple default value or as a derived expression.
inv DerivationIsUninitialized:
hasDerivation implies defaultValue.oclIsUndefined()
We want to diagnose the occlusion of the derived expression by a default value.
In the previous section we described additional Complete OCL validation constraints to detect problems with inadequate Sample Ecore diagnosis of derived properties. We will now apply those constraints to a test file.
Select EcoreTestFile.ecore and use the right button menu to Open With->Sample Ecore Model Editor. This is probably the default for double-clicking with the left button, but if you open with the OCLinEcore editor the required validation will not work (in Juno).
Now right click within the Sample Ecore Editor pane as described in OCL->Load Document Menu Action and load ExtraEcoreValidation.ocl. An additional Resource is shown in the editor tree.
Select a model element such as the Bad package and use the right button menu to invoke Validate.
This shows an error. Depending on the order in which the constraints are evaluated, you may also see one or two warnings. You should use the Validity View to see all failures.
If we now open EcoreTestFile.ecore with the OCLinEcore editor we can see that the transient and volatile keywords are indeed missing.
You may edit the Complete OCL to experiment with alternate constraints or messages.
However the Complete OCL complements the meta-model and EMF does not support live modification of meta-models. It is therefore necessary to restart the Sample Ecore Editor and Reload the modified Complete OCL document in order to exploit the changes.
A solution for this may occur in a future release.
The extension of the Sample Ecore Editor validation described in Validating Ecore with additional Complete OCL is applicable to any tree editor generated by EMF tooling.
The ExtraUMLValidation.ocl file provides a very simple style check that class names start with an upper case letter.
The UML meta-model is imported and an invariant is specified for the Class classifier which is fully qualified to avoid the need for a surrounding package context declaration.
You may open the PapyrusTestFile.uml with the UML Model Editor, load the ExtraUMLValidation.ocl, select the Model and then Validate in the same way as for the Ecore example.
Unfortunately the Papyrus UML editor does not use the EValidator framework and so loading Complete OCL documents into Papyrus fails to enhance validation capabilities. To use additional Complete OCL functionality, you may load and validate in the UML Model Editor, then start the Papyrus editor which will then show the problem markers on diagram elements. Alternatively you may use Validity View concurrently with Papyrus.
Xtext editors use EValidator and so a Complete OCL document may be loaded into an Xtext editor, including Xtext itself, to provide enhanced validation.
The ExtraXtextValidation.ocl file provides some demonstration style checks.
The Xtext root package is imported and within the package declaration context for the xtext package, invariants are supplied for four classes. These are all just examples of how constraints may use the Xtext model. It is not suggested that users should use all of these constraints for real grammars.
context ReferencedMetamodel
inv NoAnonymousImports: alias <> null
This invariant diagnoses whether any import statements omit the
as xxxx
model name.
context Action
inv NoActions : false
This invariant diagnoses whenever an
{xxx}
action statement is used.
context ParserRule
inv CamelCaseName : name.matches('[A-Z][A-Za-z]*')
This invariant verifies that the name of a parser rule starts with an upper case letter and uses only letters.
context xtext::TerminalRule
inv UpperName : name = name.toUpperCase()
This invariant verifies that the name of a terminal rule is uppercase.
You may open the XtextTestFile.xtext with the Xtext Editor, load the ExtraXtextValidation.ocl and then Validate in the same way as the Ecore example.
The additional validations appear as warning markers in the editor.
Unfortunately Xtext does not have a nice toString() method for its Concrete Syntax tree so the descriptions of erroneous elements are a little inelegant.
You may edit the Xtext test file to delete the “as ecore” in the import statement and see that the additional Complete OCL constraints are contributing to the ongoing functionality of the editor.
The Complete OCL editor is invoked automatically for an existing or new *.ocl file. You can create an empty file using either New->File or a partial content file using New->Other... followed by OCL and Complete OCL File. The editor is Xtext-based and so has most of the facilities that you find in many other Eclipse editors.
The Royal and Loyal Example was first provided by Jos Warmer and Anneke Kleppe in The Object Constraint Language: Getting Your Models Ready for MDA and has subsequently been used in many tutorials. The example provides substantial examples of Complete OCL and Essential OCL. The models are available by invoking New->Example...->OCL (Object Constraint Language) Plugins.
To illustrate how to work with Complete OCL we have
Examined the Complete OCL language
Examined constraints to rectify inadequate Ecore validation of derived features
Loaded Complete OCL constraints to enhance validation of an Ecore model
Loaded Complete OCL constraints to enhance validation of a UML model
Loaded Complete OCL constraints to enhance validation of an Xtext grammar