Relation to the UML Metamodel

Self

Each OCL expression is written in the context of an instance of a specific type. In an OCL expression, the reserved word
self is used to refer to the contextual instance. For instance, if the context is Company, then self refers to an instance of
company.
 

Specifying the UML context

The context of an OCL expression within a UML model can be specified through a so-called context declaration at the beginning of an OCL expression. The context declaration of the constraints in the following sections is shown.

If the constraint is shown in a diagram, with the proper stereotype and the dashed lines to connect it to its contextual element, there is no need for an explicit context declaration in the test of the constraint. The context declaration is optional.
 

Invariants

The OCL expression can be part of an Invariant which is a Constraint stereotyped as an «invariant». When the invariant is associated with a Classifier, the latter is referred to as a "type" in this chapter. An OCL expression is an invariant of the type and must be true for all instances of that type at any time. (Note that all OCL expressions that express invariants are of the type Boolean.)

For example, if in the context of the Company type in Figure 1 , the following expression would specify an invariant that the number of employees must always exceed 50:

self.numberOfEmployees > 50

where self is an instance of type Company. (We can view self as the object from where we start evaluating the expression.) This invariant holds for every instance of the Company type.

The type of the contextual instance of an OCL expression, which is part of an invariant, is written with the context keyword, followed by the name of the type as follows. The label inv: declares the constraint to be an «invariant» constraint.

context Company inv:
self.numberOfEmployees > 50

In most cases, the keyword self can be dropped because the context is clear, as in the above examples. As an alternative for self, a different name can be defined playing the part of self:

context c : Company inv:
c.numberOfEmployees > 50

This invariant is equivalent to the previous one.

Optionally, the name of the constraint may be written after the inv keyword, allowing the constraint to be referenced by name. In the following example the name of the constraint is enoughEmployees. In the UML 1.4 metamodel, this name is a (meta-)attribute of the metaclass Constraint that is inherited from ModelElement.

context c : Company inv enoughEmployees:
c.numberOfEmployees > 50
 

Pre- and Postconditions

The OCL expression can be part of a Precondition or Postcondition, corresponding to «precondition» and «postcondition» stereotypes of Constraint associated with an Operation or other behavioral feature. The contextual instance self then is an instance of the type which owns the operation or method as a feature. The context declaration in OCL uses the context keyword, followed by the type and operation declaration. The stereotype of constraint is shown by putting the labels `pre:' and `post:' before the actual Preconditions and Postconditions

context Typename::operationName(param1 : Type1, ... ): ReturnType
pre : param1 > ...
post: result = ...

The name self can be used in the expression referring to the object on which the operation was called. The reserved word result denotes the result of the operation, if there is one. The names of the parameters (param1) can also be used in the OCL xpression. In the example diagram, we can write:

context Person::income(d : Date) : Integer
post: result = 5000

Optionally, the name of the precondition or postcondition may be written after the pre or post keyword, allowing the constraint to be referenced by name. In the following example the name of the precondition is parameterOk and the name of the postcondition is resultOk. In the UML metamodel, these names are the values of the attribute name of the metaclass Constraint that is inherited from ModelElement.

context Typename::operationName(param1 : Type1, ... ): ReturnType
pre parameterOk: param1 > ...
post resultOk : result = ...
 

Package

Context

The above context declaration is precise enough when the package in which the Classifier belongs is clear from the environment. To specify explicitly in which package invariant, pre or postcondition Constraints belong, these constraints can be enclosed between 'package' and 'endpackage' statements. The package statements have the syntax:

package Package::SubPackage
context X inv:
... some invariant ...
context X::operationName(..)
pre: ... some precondition ...
endpackage

An OCL file (or stream) may contain any number package statements, thus allowing all invariant, preconditions and postconditions to be written and stored in one file. This file may co-exist with a UML model as a separate entity.
 

Operation Body Expression

An OCL expression may be used to indicate the result of a query operation. This can be done using the following syntax:

context Typename::operationName(param1 : Type1, ... ): ReturnType
body: -- some expression

The expression must conform to the result type of the operation. Like in the pre- and postconditions, the parameters may be used in the expression. Pre-, and postconditions, and body expressions may be mixed together after one operation context. For example:

context Person::getCurrentSpouse() : Person
pre: self.isMarried = true
body: self.mariages->select( m | m.ended = false ).spouse
 

Initial and Derived Values

An OCL expression may be used to indicate the initial or derived value of an attribute or association end. This can be done using the following syntax:

context Typename::attributeName: Type
init: -- some expression representing the initial value
context Typename::assocRoleName: Type
derive: -- some expression representing the derivation rule

The expression must conform to the result type of the attribute. In the case the context is an association end the expression must conform to the classifier at that end when the multiplicity is at most one, or Set or OrderedSet when the multiplicity may be more than one. Initial, and derivation expressions may be mixed together after one context. For example:

context Person::income : Integer
init: parents.income->sum() * 1% -- pocket allowance
derive: if underAge
then parents.income->sum() * 1% -- pocket allowance
else job.salary -- income from regular job
endif
 

Other Types of Expressions

Any OCL expression can be used as the value for an attribute of the UML metaclass Expression or one of its subtypes. In that case, the semantics section describes the meaning of the expression. A special subclass of Expression, called ExpressionInOcl is used for this purpose. See Section "The Use of Ocl Expressions in UML Models - Introduction"  for a definition.