The OCL editor

The OCL editor pops up when the user attempts to edit the conformity constraint or a derivation rule for a role of a pattern.




OCL is a statically typed, declarative, standard language dedicated to writing queries on models. The syntax of these queries is based upon the metamodel of the model being queried. Extensive documentation and tutorials about OCL can be found online; the official specification can be found at: http://www.omg.org/spec/OCL/.

The editor is composed of two text fields: the top one displays the queries being executed and their results, while the bottom one allows the user to edit the current query. When writing in the bottom field, pressing triggers a text box for syntax assistance. Pressing evaluates the expression being written. When the 'Ok' button is pressed, the result of the last successfully evaluated expression is returned.


Variables

Since OCL expressions are written in the context of a role, the OCL self variable represents an element associated to the role when the pattern is applied. Consequently, its type is the type of the pattern elements mapped to the role. For example, in the case of a derivation rule for merge target, the type of self is the one appearing in the 'Target type' line in the 'Application by merge' subsection.

Additionally, a role can depend on the roles above it. In other words, it is possible to refer to those roles via special variables. These variables are exactly like the self variable for those roles. There exists one variable for every role above the current one. It has the same name as the role, except that non-ID characters have been removed. For example, in a conformity constraint of a role 'Role 2', if there exists a role 'Role 1' above 'Role 2', then there exists a variable 'Role1' which refers to the elements associated to role 'Role 1' when the pattern has been applied.

Note that simply pressing on an empty expression allows seeing all available variables.


Operations

Specific operations are provided in addition to the standard ones for an easier navigation of the models. These additional operations are applicable on all elements. They are the following.
  • oclOwner(): returns the container of the receiver
  • oclOwners(): returns the whole chain of containers of the receiver
  • oclChildren(): returns the direct children of the receiver in the containment hierarchy
  • oclAllChildren(): returns all children of the receiver, i.e., the contents of the whole containment subtree
  • oclIsLeaf(): returns whether the receiver has no children
  • oclIsRoot(): returns whether the receiver has no container
  • oclTypeName(): returns the name of the type of the receiver

Note that the types of model elements, when mentioned in expressions, must be prefixed with the name of the package followed by '::', like in 'la::LogicalFunction'. The oclTypeName() operation is useful for obtaining these complete type names.


Examples
  • A container derivation rule which specifies that the pattern elements of the current role should be stored in the same container as that of previous role 'Role 1'.

    Role1.oclOwner()

  • A merge derivation rule for a role mapped to a Capella input port, which specifies that the role should be merged with the target port of role 'Main Exchange'. Role 'Main Exchange' is assumed to be above the current role and mapped to a Capella functional exchange.

    MainExchange.target

  • A conformity constraint on a role mapped to a Capella logical function, which states that every sub-function must have no more than 3 incoming exchanges and exactly 2 outgoing exchanges.

    let subFcs : Sequence(la::LogicalFunction) =
      self.subFunctions->collect(oclAsType(la::LogicalFunction)) in
    subFcs->forAll(f : la::LogicalFunction |
      f.inputs.incoming->size() <= 3 and
      f.outputs.outgoing->size() = 2)


Pattern-related operations

A few operations related to instances and patterns are also available.
  • patternInstances(): this operation is applicable to every model element; it returns the (possibly empty) set of pattern instances that the model element belongs to.
  • pattern(): this operation is applicable to a pattern instance obtained by the operation above; it returns the pattern of the instance. The returned pattern can then be queried for all its properties, for example its name.
  • patternElement(element): similarly to the operation above, this operation is applicable to a pattern instance; it takes as parameter a model element that belongs to the instance; it returns the pattern element that corresponds to the model element via the instance.