This section may be contrasted with the corresponding Parsing Constraints and Queries for the Ecore binding to see examples of the changes needed to migrate from the Ecore binding to the Pivot binding.
The OCL parser provides two APIs for parsing constraint and query expressions using the
OCL
Facade.
The
OCL
class provides both a Facade and a Handle for the various objects that support different aspects of OCL parsing and evaluation.
The
OCL
class is a simple type.
There is no need for the many template parameters that parameterize the equivalent OCL class for the Ecore/UML bindings.
Behind the scenes,
OCL
instances share an
EnvironmentFactory
that creates and owns the primary support objects and provides an API to create these and other important artefacts.
The
ProjectManager
supports the discovery of metamodels to resolve URI references.
OCL.NO_PROJECTS
is a very lightweight
ProjectManager
supporting access only to those models known to the external
ResourceSet
.
OCL.CLASS_PATH
is a heavyweight
ProjectManager
supporting access to models registered with plugins on the Java classpath.
The external
ResourceSet
is a potentially user-supplied
ResourceSet
to manage the external metamodels such as Ecore or UML models or Xtext Concrete Syntax models.
The external metamodels are converted to the normalized Pivot representation under control of the
MetamodelManager
which maintains the normalized representation in an Abstract Syntax as
ResourceSet
.
A merged view of the normalized metamodels is provided by the
CompleteModel
under control of the
CompleteEnvironment
that also supervises a
StandardLibrary
,
TupleManager
and
LambdaManager
for more specialized aspects of the merge. The
CompleteEnvironment
API supports synthesis of Collection and Map types.
Access to the normalized representations from diverse contexts, in particular from generated Java code, requires an ability to discover the merged representation of e.g. the
Boolean type from the minimal concept of a
Boolean type-id. The
IdResolver
performs the id-to-object conversion.
When Pivot models are derived from Xtext source text, a Concrete Syntax representation is converted to the normalized Abstract Syntax. The
CS2ASMapping
tracks the equivalences in this conversion so that tooling can reverse the navigation to discover appropriate text to highlight in a source editor for an underlying model element.
The
OCL
handle may also reference a
ModelManager
. This is used to identify objects during evaluation of operations such as
allInstnaces()
.
The static factory methods of the
OCL
class are used to create new instances. These are suitable for suitable for parsing OCL constraints
on any Ecore or UML model and evaluating them on instances of the model.
If you already have models loaded in a
ResourceSet
, you may activate OCL functionality by creating a new
OCL
instance specifying that OCL should exploit that ResourceSet.
Alternatively you may leave the
OCL
instance to create the
ResourceSet
.
It is good practice to invoke
dispose()
explicitly to release all
OCL-related Resource references promptly rather than rely on garbage collection.
When repeated parsing and evaluation occurs on a model, it is very beneficial to re-use rather than
re-create the underyling OCL support objects. This is easily achieved in simple scenarios by re-using the
OCL
instance directly. In more complex scenarios the handle behavior of an
OCL
instance can be exploited
to create multiple handles for diverse usages each of which is disposed when complete. The dispose of the
underlying OCL support occurs when the final handle disposes.
Parsing an OCL expression requires a classifier to define the type of
self
. This is passed to
createInvariant()
, which enforces a Boolean result type, or to
createQuery()
, which allows any result type.
The result of parsing a query expression or a constraint is an
ExpressionInOCL
,
an instance of the
Abstract Syntax Model.
In the case of constraints on operations or properties, the context consists
of two elements: the constrained operation/property and a classifier that
defines the type of
self
while parsing the OCL. The classifier is deduced as the
container of the operation or property. These can be constrained as follows:
The preceding examples are simplified by the assumption that there will be no parsing errors. In practice
ParserException
s should be caught and handled in an appropriate way by the application.
The Ecore/UML bindings for OCL provide an OCLHelper class to assist in creating queries. A similar class is available with the Pivot binding for compatibility although it is largely redundant since the
OCL
class class be used directly. AnOCLHelper
will give a small performance benefit for multiple parses but not as much as direct use of an underlyingParserContext
or a structuring multiple queries in a Complete OCL document.From an OCL instance, we can create a helper object with which to parse constraints and additional operation/attribute definitions.
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 givenConstraintKind
*
createInvariant()
: convenience for invariant constraints*
createPrecondition()
: convenience for pre-condition constraints*
createPostcondition()
: convenience for post-condition constraints*
createBodyCondition()
: convenience for body conditions*
createDerivedValueExpression()
: convenience for attribute derived valuesDifferent kinds of constraints require different context environments. The
setContext()
,setOperationContext()
, andsetAttributeContext()
methods create the appropriate nestedEnvironment
s in the hostOCL
instance’s root environment.The Ecore/UML bindings variously produce a Constraint or OCLExpression result. A Constraint has too much context and an OCLExpression too little. An ExpressionInOCL produced by the Pivot binding is just right.