2013-02-28 1 views
1

Je suis confronté à un défi en essayant de vérifier les doublons dans OCL.Recherche de doublons imbriqués dans OCL

Voici une simplification du diagramme de classes:

         +-----------+ 
             |ChapterName| 
             +-----------+ 
             ^0..* chapterNames 
              | 
             ^
              V 
       +-------+ books 0..* +----+ 
       |Catalog|<>------------>|Book| 
       +-------+    +----+ 
     catalogs 0..*^     ^0..* books 
        |      | 
        +----+ customers 0..* +--------+ 
        |Shop|<>-------------->|Customer| 
        +----+     +--------+ 

Les attributs de chaque classe sont déclarées comme suit:

  • Titre du chapitre
    • Nom
  • Catalogue
    • Catégorie

Problème: Ce que je veux vérifier est si un client a des livres avec des noms de chapitre en double, qui appartiennent également à une catégorie spécifique dans notre catalogue.

Je n'ai pas réussi à comprendre la logique. Ce que j'ai jusqu'ici est:

context Shop 
self.customers.books->select(cubks | cubks = 
    self.catalogs.books->select(cabks | cabks = cubks)->first()) 

... Qui devrait trouver les livres du catalogue dont un client a.

Question: Comment puis-je ajouter d'autres contraintes pour résoudre le problème ci-dessus?

Aussi. J'utilise Eclipse, EMF et la console OCL depuis Eclipse.

Répondre

1
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 est un Set; books est soit un Bag ou un Set (selon que les livres en double sont autorisés, je suppose qu'il s'agit d'un Bag, même si cela n'a pas d'importance). Puis customer.books est un sac de sacs de livres (un sac par client) et customer.books->flatten() est un sac de tous les livres appartenant à des clients.

catalog.books est soit un Bag ou un Set (peu importe). L'opération select renvoie uniquement les livres qui sont contenus dans le catalog donné (et appartient à certains Customer, puisque nous sélectionnons à partir du sac construit avant).

book.chapterNames est un Sequence (je suppose que l'association est ordonnée) avec le nom des chapitres dans ce livre. forAll renvoie true ssi pour chaque élément de la collection (c'est-à-dire pour chaque livre du catalogue donné, qui appartient à un client), le corps est évalué comme true.

L'astuce consiste maintenant à utiliser l'opération Sequence::asSet(), qui renvoie tous les éléments de la séquence avec les doublons supprimés. Ensuite, la taille du sac est égale à la taille de l'ensemble si aucun élément n'a été supprimé (c'est-à-dire si chaque élément était unique).