You can use select in OCL to filter a collection and keep only the objects whose condition evaluates to true.
Syntax
sourceCollection->select(iterator | condition)| Part | Meaning |
|---|---|
sourceCollection
|
The collection to filter: a Set, Bag, or Sequence.
|
iterator
|
A local variable that represents one element from the source collection while the condition is evaluated. |
condition
|
A Boolean OCL expression. When it evaluates to true, the current element is included in the result.
|
select returns a new collection of the same type as its source collection. It does not return a single object. If you need one object from the filtered result, use first after select.
How select evaluates a collection
For each element in the source collection, OCL assigns that element to the iterator and evaluates the condition.
For example:
Customer.allInstances->select(customer | customer.Age > 50)This expression examines every Customer. The iterator is customer. A customer is included only when customer.Age > 50 is true.
Use an association as the source collection when you want to filter objects related to the current object.
self.Orders->select(order | order.IsPaid)In this example, self.Orders is the current object's orders. The result contains the orders for which IsPaid is true.
Use a descriptive iterator name when the condition refers to several attributes or associations:
self.Orders->select(order | order.Total > 1000 and order.IsPaid)The result contains only paid orders with a total greater than 1000.
Filter all instances of a class
Use allInstances when the source is every instance of a class.
Customer.allInstances->select(customer | customer.Age > 50)This returns the customers older than 50. Because the result is still a collection, you can continue the expression:
Customer.allInstances->select(customer | customer.Age > 50)->firstThis returns the first customer in the filtered collection. See first for details about retrieving the first element.
Match text
Use equality when the full value must match:
Person.allInstances->select(person | person.Identity = vSeekParam)Use sqlLike when you need to match part of a string. The % character means that any text can occur at that position:
Person.allInstances->select(person | person.Identity.sqlLike('%' + vSeekParam + '%'))This returns people whose Identity contains the value in vSeekParam.
Compose select with other operators
select produces a collection, so you can pass its result to another collection operator. For example, filter before taking the first result:
self.Orders->select(order | order.IsPaid)->firstKeep the filtering condition inside select and apply the next operation after the closing parenthesis. This makes it clear which objects are being filtered and which collection is used by the next operator.
Use in database-evaluated expressions
select can also occur inside PSEval, PSEvalValue, and PSEvalTuples expressions. For example:
SysUser.PSEval(SysUser.allInstances->select(user | user.Username = userName), 2, 0, '')Here, select filters SysUser instances by Username; PSEval evaluates the supplied OCL expression against the database. Read the relevant PSEval operator page before using this pattern, because those operators have result-subscription and query limitations.
