context Shop::checkForDuplicates(catalog:Catalog)
post: result =
self.customer.books->flatten()->select(book|
catalog.books->contains(book)
)->forEach(book|
chapterNames->asSet()->size()=chapterNames->size()
)
customer
is a Set
; books
is either a Bag
or a Set
(depending on whether duplicate books are allowed, I'll assume it is a Bag
, though it doesn't matter). Then customer.books
is a bag of bags of books (one bag per each customer) and customer.books->flatten()
is a bag of all the books owned by customers.
catalog.books
is either a Bag
or a Set
(doesn't matter). The select
operation returns only those books that are contained in the given catalog
(and belongs to some Customer
, since we are selecting from the bag constructed before).
book.chapterNames
is a Sequence
(I assume that the association is ordered) with the name of chapters in that book. forAll
returns true
iff for every element in the collection (i.e. for every book in the given catalog, which is owned by a customer), the body evaluates as true
.
The trick now is relying on the operation Sequence::asSet()
, which returns all the elements from the sequence with duplicates removed. Then the size of the bag is equal to the size of the set iff no element was removed (i.e. if every element was unique).