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 small changes needed to migrate from the Ecore binding to the Pivot binding.

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 OCL Environment

The OCL API provides a Facade for the various objects that support different aspects of OCL parsing and evaluation activities in a that spans activities for which the meta-models remain unchanged. A new OCL Facade is required if the meta-models change.

The OCL class is a simple type.

There is no need for the Ecore/UML template parameters that parameterize the equivalent Ecore/UML class.

Behind the scenes, the unified Pivot variants of the primary UML, OCL and user and meta-models, complementing Complete OCL documents and Standard Libraries are maintained by a MetaModelManager , which also maintains all the collection and tuple specialization singletons so that they can be shared by subsequent processing. A distinct MetaModelManager is required for each combination of primary meta-models and complementing Complete OCL documents and so for safety a new MetaModelManager is created for each OCL session. Increased metya-model sharing can be achieved by re-using MetaModelManager s when constructing a PivotEnvironmentFactory .

An OCL parsing activity maintains the root and nested parsing context in Environment instances which are created by an EnvironmentFactory .

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.

Creating an OCL Environment

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). It is also good practice to invoke dispose() to release all OCL-related Resource references.

Using the shared Pivot environment factory , we can create an OCL environment suitable for parsing OCL constraints on any Ecore model and evaluating them on instances of the model:

[Text for cut and paste]

The OCL Helper

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 result of parsing a query expression or a constraint is an ExpressionInOCL , an instance of the Abstract Syntax Model.

The Ecore/UML binding variously produces a Constraint or OCLEXpression result. A Constraint has too much context and an OCLExpression too little. An ExpressionInOCL is just right.

[Text for cut and paste]

Operation and Attribute Contexts

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:

[Text for cut and paste]