The Ecore/UML Programmers Guide describes the ways in which the Ecore or UML bindings of Eclipse OCL can be used from Java programs.
The Ecore binding has been available since Eclipse OCL 1.0.0 (Callisto). The UML binding was added in 1.1.0 (Europa). Both will remain for as long as necessary. Examples quality prototypes of the new UML-aligned Pivot binding were first available in 3.1.0 (Indigo). The Pivot binding became the preferred binding in 6.0.0 (Mars). The Pivot binding is described in a separate Pivot Programmers Guide.
The OCL Parser/Interpreter provides an implementation of the Object Constraint Language 2.4 specification for EMF-based metamodels and models. It offers OCL constraint and query parsing and evaluation, model-based validation, and provides an infrastructure for content assist in textual editors.
The following features are supported in the current version:
Classifier invariant constraints
Operation precondition and postcondition constraints and body conditions
Property constraints (initial-value and derivation)
Attribute and operation definitions (def: expressions)
Package context declaration
Basic values and types
Collection types
Navigation of attributes and association ends
Operation invocation
Iteration expressions (all standard iterators)
Let expressions
If expressions
Tuples
Message expressions, including unspecified values
Operations predefined by OCL: allInstances(), oclIsKindOf(), oclIsTypeOf(), oclAsType(), oclIsNew()
Escape syntax for illegal names: type, operation, attribute, etc. names that correspond to OCL reserved words can be escaped in the standard fashion using a leading underscore (‘_’). In addition, names that contain spaces or tabs can be escaped by enclosing them in double-quotes (‘"’; this is non-standard). e.g.,
self.ownedRule->forAll(c : Constraint | c._context = self)
The above constructs are supported by the parser for parsing and for evaluation, with the exception of the oclIsNew() operation and message expressions. All of the above are supported for both Ecore and UML models. The following are supported by default for UML (both in parsing and evaluation):
Navigation of non-navigable association ends (including those that are owned by the association)
Qualified association end navigation
Navigation to association classes, including source qualifiers
Operations predefined by OCL: oclIsInState()
The following features are provided in addition to the OCL specification:
String case conversion operations: toUpper(), toLower()
Support for comparison (<, <=, etc.) and sorting of any java
Comparable
s of conformant types
Transitive closure of associations: closure(expr : OCLExpression) iterator
Navigation of “hidden” opposites of references specified in Ecore models using a
Property.oppositeRoleName
annotation with source
http://schema.omg.org/spec/MOF/2.0/emof.xml
on the forward reference, producing an
OppositePropertyCallExp
expression
The OCL implementation is defined in plug-ins for convenient deployment in Eclipse, but as is the case for EMF, it can also be used stand-alone. The plug-ins are partitioned thus:
org.eclipse.ocl
: the core parsing, evaluation, and content assist services. Definition of the OCL Abstract Syntax Model and Environment API. These APIs are generic, independent of any particular metamodel (though using Ecore/EMF as the meta-meta-model).
org.eclipse.ocl.ecore
: implementation of the Ecore metamodel environment, binding the generic Environment and AST APIs to the Ecore language. Provides support for working with OCL constraints and queries targeting Ecore models.
org.eclipse.ocl.uml
: implementation of the UML metamodel environment, binding the generic Environment and AST APIs to the UML language. Provides support for working with OCL targeting UML models.
Please refer to the OCL Interpreter Tutorial for review of the code samples.
The OCL parser provides two APIs for parsing constraint and query expressions. The
OCLHelper
interface is designed primarily for parsing constraints and query expressions
embedded in models, such as Ecore or UML models. The
OCL
class serves as the main entrypoint into the parsing API but also implements the
parsing of
OCL documents, for example from
text files. In both cases, the concept of
Environment
is crucial.
The following diagram shows the core of the
Environment
API, that clients of the OCL parser interact with:
The
OCL
class is a generic type; its type parameters represent the various metaclasses
of the metamodels that OCL works with in the UML/MOF family of OMG specifications.
For example,
<C>
represents the Classifier
concept,
<O>
the Operation concept, etc. See
the discussion of
metamodels supported by OCL
for details of the mappings. The same type parameter names are used consistently
throughout the OCL APIs to represent the same metaclasses.
The
OCL
class defines instances of autonomous OCL
parsing and evaluation environments. It has a single root
Environment
created by an
EnvironmentFactory
implementation for a particular EMF-based metamodel. The OCL environment
consists, conceptually, of the model that is to be constrained together with
all of the constraints and additional operations and attributes defined (via
OCL) for the purpose of formulating constraints.
Environment
s nest. Usually the root environment has
no correlation to an element in the model, or it may correspond to some
Package
providing a default namespace (called a package
context). Alternatively, it may contain one or more nested environments
defining package namespaces. A package context contains one or more classifier
contexts, which in turn can contain operation and/or attribute contexts. Whereas
the purpose of a package context is primarily to assist in the look-up of named
model elements, the classifier, operation, and attribute contexts have deeper
meaning.
A classifier context defines the type of the
self
variable in OCL constraints and queries. By itself, it is the context for
invariant constraints for the context classifier. Additionally, as the parent
context for operation and attribute constraints, it indicates the classifier
in which context an operation or attribute constraint applies; this may be the
classifier that defines these features, or it may inherit them from some more
general classifier.
An
Environment
may contain named
Variable
s
to which OCL expressions can refer. The most common of these is
self
. Others include the parameters defined by an
operation (and its
result
), in the case of an
operation context. The OCL API even allows clients to add variables, in code,
to define “global” names.
The static factory methods on the
OCL
class are used
to create instances. It is a good practice to re-use the same OCL instance for
all parsing and evaluation of constraints and queries on a model while that
model is loaded (usually in some
ResourceSet
in an
editor). Using the shared environment factory for the Ecore
metamodel, we can create an OCL
environment suitable for parsing OCL constraints on any Ecore model and
evaluating them on instances of the model:
Several of the type parameters in the
OCL
generic type
signature are useful mostly within the OCL API. We leave them, here, as wildcards.
From an OCL instance, we can create a helper object with which to parse constraints
and additional operation/attribute definitions. This
OCLHelper
stores all of the instantiations of OCL template metaclasses (such as
CollectionType(T)
and
TupleType
and additional operation/attribute definitions in the root environment of the
OCL
that created it. This ensures that all of these
constructs are available for reuse in subsequent parsing.
The
OCLHelper
is primarily designed for parsing
constraints and query expressions embedded in models, providing the following
API for that purpose:
createQuery()
: parses a query expression
createConstraint()
: parses a constraint of a given
ConstraintKind
createInvariant()
: convenience for invariant constraints
createPrecondition()
: convenience for pre-condition constraints
createPostcondition()
: convenience for post-condition constraints
createBodyCondition()
: convenience for body conditions
createInitialValueExpression()
: convenience for attribute initial values
createDerivedValueExpression()
: convenience for attribute derived values
defineOperation()
: convenience for additional operation definitions
defineAttribute()
: convenience for additional attribute definitions
Different kinds of constraints require different context environments. The
setContext()
,
setOperationContext()
,
and
setAttributeContext()
methods create the appropriate
nested
Environment@s in the host @OCL
instance’s root environment.
The result of parsing a query expression is an
OCLExpression
,
an instance of the
Abstract Syntax Model . The
result of parsing a constraint is an instance of the
Constraint
metaclass defined by the
OCL
's
target metamodel .
Ecore does not define a
Constraint
metaclass, so the
OCL
binding for Ecore supplies one.
In the case of constraints on operations or attributes, the context consists
of two elements: the constrained operation/attribute and a classifier in the
context of which the constraint is to apply. This accounts for the possibility
that a classifier defines constraints on inherited features. As an example,
consider the
EModelElement::getEAnnotation(EString)
operation and
EReference::eReferenceType
property in the Ecore
metamodel. These can be constrained as follows: