You can use these examples to predict the result of OCL collection navigation and to test collection and simple-value expressions in the OCL Editor.
Understand collection results
A collection is a group of values or objects. When an OCL expression starts with more than one object, navigating to a property or association can produce a value for each object.
For example, assume that:
Thinghas a multi-valued association namedDetails.- There are several
Thingobjects.
The expression:
Thing.allinstances.Detailsreturns one collection containing the Details from all Thing objects. It does not return one nested collection per Thing.
This behavior is called flattening: MDriven reduces a collection of collections to one collection of the contained values. In plain terms, OCL follows each Details link for every Thing and combines the results.
| Expression shape | Result shape | Example |
|---|---|---|
| One object navigated to one value | One value | A Thing navigated to a single-valued name returns that name.
|
| One object navigated to many values | One collection | One Thing navigated to Details returns its details.
|
| Many objects navigated to many values | One flattened collection | Thing.allinstances.Details returns the details from all things.
|
Why flattening matters
Flattening lets you continue working with the combined result. For example, after navigating from all Thing objects to their details, you can apply an appropriate collection operator to the resulting collection rather than first handling a separate collection for each Thing.
Use the OCL Collection Operators page to identify operators available for a collection. For a direct comparison of two collections, see symmetricDifference.
Transform a collection with collect
Use collect when you want to explicitly evaluate an expression for every item in a collection. collect is an OCL operator: it returns a new result and does not modify the source collection.
Customer.allInstances->collect(c | c.Name)This returns a collection of customer names. Here, c is the variable that represents the current Customer, and c.Name is the expression evaluated for each customer.
You can also derive a value for every item:
Customer.allInstances->collect(c | c.Age + 1)This returns each customer's age increased by one. For syntax, execution contexts, and further examples, see collect.
Select an element from a collection
Use first when you need the first element of a collection.
Customer.allinstances->select(a | a.Age > 50)->firstThis first filters customers to those older than 50, then returns the first customer in that result. See first for additional examples and its behavior when the operand is not already a collection.
Work with simple values
After an OCL expression resolves to a simple value such as a string, double, int, DateTime, or Boolean, MDriven exposes the applicable .NET Framework operations for that value type.
For example, if an expression returns a string, use the OCL Editor to inspect the operations available for that string. The available string operations include compare, indexof, and split.
Numeric values such as float, double, decimal, and int can be converted to decimal with toDecimal. Use this conversion when the next part of your expression requires a decimal value.
Test an expression in the OCL Editor
- Open the OCL Editor in the context where you want to evaluate the expression.
- Enter an expression that produces a collection or simple value, such as
Thing.allinstances.Details. - Inspect the result type and the operations offered by the editor.
- Extend the expression with an operator appropriate for that result. For example, use
collectto derive one value per collection item, orfirstto obtain the first item. - If you need an operator that changes model data, use EAL rather than OCL. OCL transforms input into a result; it does not change state.
Collection behavior to keep in mind
- OCL collection expressions transform collections into new results. They do not mutate raw-data collections.
- The collection type affects whether duplicate values and ordering are significant. See Collections for the distinction between sets and bags.
- Do not assume that collection navigation preserves per-parent grouping. Navigation such as
Thing.allinstances.Detailsis flattened. - Use the operator-specific pages for exact syntax and behavior, including Empty for testing whether a collection has no elements.
