For the Boss class, I need the name of all the agents who made the sales with the highest value (something like: foreach agent, select agent name if he has
max(foreach command, total = total + price of the product * quantity from command).
How do I do this in OCL?
If you consider that you are at the root of the model (no context in particular) in order to select the 20
first top Agents:
Agent.allInstances()->sortedBy(- sale->collect(quantity*product.price)->sum())->subSequence(1, 20)
and from a Boss
instance:
self.workers->sortedBy(- sale->collect(quantity*product.price)->sum())->subSequence(1, 20)
The idea behind the request is (for the 1st one):
Agent.allInstances()
)...->sortedBy(...)
)... sale->...->sum()
)quantity*product.price
)...sale->collect(...)
)sum
one), inverse the result to have the top in first positions (... - sale->collect()->sum()...
)...->subSequence(1,X)
)EDIT>
Just a detail about association class navigation (from the "OCL Specification", p.21)
To specify navigation to association classes (Job and Marriage in the example), OCL uses a dot and the name of the association class
Following the early version of the specification, the Association Class
name is said to be put as lower case, in the later version, the name is let untouched.
EDIT2>
In order to get the higher score and the agents name who hits this highest score:
let score : Integer = -(self.workers->collect(sale->collect(quantity*product.price)->sum())->sortedBy(i | -i)->first())
in self.workers->select(sale->collect(quantity*product.price)->sum() = score).name
The first let select the higher score (collect all the scores, sort them in reverse order and select the first element), then select all the workers who have a score equals to the previously computed one.