Parsing Constraints and Queries

Parsing Constraints and Queries

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 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().

OCL Handles

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.

[Text for cut and paste]

Alternatively you may leave the OCL instance to create the ResourceSet.

[Text for cut and paste]

It is good practice to invoke dispose() explicitly to release all OCL-related Resource references promptly rather than rely on garbage collection.

[Text for cut and paste]

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.

Class Context

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.

[Text for cut and paste]

Operation and Property Contexts

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:

[Text for cut and paste]

Errors

The preceding examples are simplified by the assumption that there will be no parsing errors. In practice ParserExceptions should be caught and handled in an appropriate way by the application.

[Text for cut and paste]

The OCL Helper

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. An OCLHelper will give a small performance benefit for multiple parses but not as much as direct use of an underlying ParserContext 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 given ConstraintKind

* 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 values

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