Collection syntax contains some subtleties worth learning. It is helpful when writing collection expressions to step through them, left to right, as though you were reading a sentence. This helps you better understand how the pieces combine to create the full expression. It also helps you to know what else you can safely add to the expression to increase its utility. Use this approach in order to dissect the following expression:

Collection1 -> sortedBy(attribute1) -> last.attribute2
  1. Collection1
    This expression returns the collection {e1, e2, e3, e4, e5,…en} where ex is an element (an entity) in Collection1. You already know that alias Collection1 represents the entire collection.
  2. Collection1 -> sortedBy(attribute1)
    This expression returns the collection {e1, e2, e3, e4, e5,…en} arranged in ascending order based on the values of attribute1 (call it the index).
  3. Collection1 -> sortedBy(attribute1) -> last

    This expression returns {en} where en is the last element in Collection1 when sorted by attribute1.

    This expression returns a specific entity (element) from Collection1. It does not return a specific value, but once you identify a specific entity, you can easily reference the value of any attribute it contains, as in the following, which returns {en.attribute2}:

  4. Collection1 -> sortedBy(attribute1) -> last.attribute2

    Entity Context

    The complete expression not only returns a specific value, but just as important, it also returns the entity to which the value belongs. This entity context is important because it allows you to do things to the entity itself, like assign a value to one of its attributes. For example:

    Collection1 -> sortedBy(attribute1) -> last.attribute2=‘xyz’

    The preceding expression assigns the value of xyz to attribute2 of the entity whose attribute1 is highest in Collection1. Contrast this with the following:

    Collection1.attribute1 -> sortedBy(attribute1) -> last

    This expression returns a single integer value, like 14.

    Notice that all you have now is a number, a value. You lost the entity context, so you cannot do anything to the entity that owns the attribute with value of 14. In many cases, this is just fine. Take for example:

    Collection1.attribute1 -> sortedBy(attribute1) -> last > 10

    In preceding expression, it is not important that you know which element has the highest value of attribute1, all you want to know is if the highest value (whomever it “belongs” to) is greater than 10.

    Understanding the subtleties of collection syntax and the concept of entity context is important because it helps you use the returned entities or values correctly, for example:

    Return the lower of the following two values:

    • 12
    • The age of the oldest child in the family

    What is really being compared here? Do you care which child is oldest? Do you need to know his or her name? No. You simply need to compare the age of that child (whichever one is oldest) with the value of 12. So, this is the expression that models this logic:

    family.age -> sortedByDesc(age) -> first.min(12)

    The Minimum value COLLECTION operator is an operator that acts upon numeric data types (Integer or Decimal). And because family.age -> sortedByDesc(age) -> first returns a number, it is legal and valid to use .min at the end of this expression.

    What about this scenario: Name the youngest child Junior.

    family -> sortedByDesc(age) -> last.name='Junior'

    Now return a specific entity – that of the youngest child – and assign to its name a value of Junior. You need to keep the entity context in order to make this assignment, and the preceding expression accomplishes this.