🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Part 1 OCL Common Expressions
This page was created by Alexandra on 2016-12-21. Last edited by Wikiadmin on 2026-07-29.

You can use this introduction to write and test common OCL queries against a small model in MDriven Designer; it is for modelers who are new to OCL and the MDriven Debugger.

Object Constraint Language (OCL) is a declarative query language used to describe and retrieve information from your model. An OCL expression has no side effects: evaluating it must not create objects or change values. In MDriven, use EAL (Extended Action Language) when you need to change data.

This session uses a small fruit model to show how a query starts with objects, produces a collection, and then narrows, orders, or selects values from that collection. Watch the Common expressions walkthrough.

Start with a small model

Create a class such as Orange with an integer attribute weight. You can add a second class, Apple, with the same attribute when you want to compare expressions across types.

Model element Purpose in the examples
Orange A class whose instances are queried.
weight : Integer A value used for ordering and filtering.
Apple A second class used to demonstrate that each class has its own instances.

For example, if your model contains four Orange objects with weights 18, 25, 10, and 30, a query can retrieve all four objects and then sort or filter them.

Test expressions in the MDriven Debugger

Use the MDriven Debugger to evaluate an expression and inspect its result while you build the model.

  1. Start the system prototype for your model.
  2. Open the MDriven Debugger.
  3. Enter an OCL expression and evaluate it. For example, retrieve the Orange objects with Orange.allInstances.
  4. Read the returned objects and their attribute values in the debugger.
  5. When you add or change classes, reread the model before querying the new class. For example, after adding Apple, reread the model before evaluating Apple.allInstances.

The debugger treats consecutive non-empty lines as one expression. Leave an empty line between expressions that must be evaluated separately.

Create test data with EAL

OCL queries do not modify the model. To create objects or assign a value during an experiment, start the expression with action:, which switches to EAL.

action: Orange.create

You can then assign a weight to a selected object using the assignment operator :=. For example, select an Orange object and assign its weight:

action: Orange.allInstances@0.weight := 18

The @0 index selects the first item in a collection because this index is zero-based. Use EAL only for actions such as creating an object or assigning an attribute. Return to OCL for queries, derivations, and other expressions that must remain side-effect-free.

Retrieve objects with allInstances

allInstances retrieves the instances of a class. It is a common starting point for an expression that works across all stored objects of a type.

Orange.allInstances

With four Orange objects, this expression returns a collection containing those four objects. You can follow it with another operation because an expression result can be the input to the next expression.

For example, ask for the number of Orange objects:

Orange.allInstances.size

If there are four objects, the result is 4.

Select an item from a collection

You can index a collection with @. Indexing starts at zero.

Orange.allInstances@0

This returns the first Orange in the returned collection. Indexing is useful while exploring data in the debugger, but do not assume that an un-ordered collection has a meaningful business order. Order the collection before choosing a first or last item when the order matters.

Order results

Use orderBy to sort a collection by a property. In this example, the result is sorted by increasing weight:

Orange.allInstances.orderBy(weight)

For Orange weights 18, 25, 10, and 30, the ordered result has weights 10, 18, 25, and 30. Use descending ordering when you want the highest value first:

Orange.allInstances.orderByDescending(weight)

You can use a loop variable when the expression needs an explicit name for each object being processed. A pipe (|) separates the variable from the expression that uses it:

Orange.allInstances.orderBy(oneOrange | oneOrange.weight)

Here, oneOrange is the loop variable. It represents one Orange at a time. The short form orderBy(weight) is useful when the property name is enough; name the loop variable when a longer expression needs clarity.

Choose the first or last result

After ordering a collection, use first or last to return one object.

Orange.allInstances.orderBy(weight).first

This returns the Orange with the lowest weight. To return the Orange with the highest weight, order descending and take the first item, or order ascending and take the last item:

Orange.allInstances.orderByDescending(weight).first

These expressions demonstrate composition: each operation works on the result produced by the operation to its left.

Filter results with select

Use select to retain only objects for which a Boolean condition is true. This expression returns Orange objects heavier than 20:

Orange.allInstances.select(weight > 20)

For weights 18, 25, 10, and 30, the result contains the Orange objects weighing 25 and 30. The condition can also use an explicit loop variable:

Orange.allInstances.select(oneOrange | oneOrange.weight > 20)

The loop variable becomes important when the condition refers to more than one property or navigates to related objects. You can combine Boolean conditions in a selection. For example, a condition can use and, or, or not; see Part 2 OCL: Operators for operator details.

Use OCL for derived information

A derived attribute is an attribute whose value is calculated from an OCL expression rather than entered independently. In the fruit example, a derived presentation value can combine the object type and its weight, such as "Apple with weight 15 grams." When the weight changes, the derived value updates from its derivation expression.

Use derived attributes to keep a repeated calculation in one place. This session continues with derivation rules in Part 3 OCL: Derivation properties.

Common mistakes

  • Do not use OCL to create objects or assign attribute values. Use action: and EAL for changes.
  • Reread the model in the debugger after adding a class or changing the model structure; otherwise, the running executor does not know about the new type.
  • Leave a blank line between separate debugger expressions.
  • Do not select an indexed, first, or last item from an un-ordered collection when the result must be predictable. Apply an ordering first.
  • Use a loop variable after | when a collection expression becomes difficult to read or requires an explicit object reference.

Next steps

Continue to Part 2 OCL: Operators to learn more operators and collection behavior. For a broader guide to where OCL is used in MDriven, see OCL Expressions.

See also