Index: topia/doc/EntityGen.rst diff -u /dev/null topia/doc/EntityGen.rst:1.1 --- /dev/null Mon May 30 16:58:46 2005 +++ topia/doc/EntityGen.rst Mon May 30 16:58:41 2005 @@ -0,0 +1,302 @@ +================================ +Génération des Entités par ToPIA +================================ + +Pour une classe XXX définie dans le diagramme de classe qui a le stéréotype +<>. + + +Les classes engendrées +---------------------- + +Pour toute classe ou interface générée, si cet objet nécessite une référence +sur un autre objet elle doit avoir une visibilité suffisante sur cet objet, +soit simplment par le fait que les deux objets se situent dans le même package, +soit en utilisant le "fully qualified name", soit en faisant un import. A +l'heure actuelle (0.31), ToPIA suppose que les entités se situent dans le même +package ce qui pose problème si ce n'est pas le cas. + +TODO A l'avenir, il serait +préférable d'utiliser directement le fully qualified name plutôt qu'un import +dans la mesure où, dans le cas contraire, des conflits risquent de se produire +si deux classes portant le même nom dans deux packages différents sont utilisés +dans le même objet. + +- Interface XXX : +Générée par ObjectModelToEntityGenerator. + +Représente l'entité dans son ensemble, +c'est à dire une interface comprenant les signatures de tous les accesseurs sur +ses attributs et de toutes ses opérations. Cette interface étend TopiaEntity. + +- Classe XXXImpl : +Générée par ObjectModelToEntityImplGenerator. + +Représente l'implantation de +l'interface XXX et qui étend AbstractTopiaEntity. Cette classe comprend un +constructeur qui met à jour les attributs creationDate, topiaId, version, +lastUpdateDate, etc... définis dans AbstractTopiaEntity. De plus, c'est dans +cette classe que sont déclarés les attributs de l'entité ainsi qu'un attribut +boolean `_Modified_` pour chacun d'entre eux. L'implémentation des +accesseurs est faite ici avec si nécessaire un contrôle d'accès en fonction +des paramètres de sécurité. L'implémentation des opérations est faite par +délégation sur l'objet XXXOperation associé. Enfin, la méthode +`set_allProperties_` qui prend toutes les valeurs de l'objet TopiaEntity passé +en paramètre et les utilisent comme valeur pour l'objet courant (y compris le +topiaId, version ...) + +- Interface XXXOperation : +Générée par ObjectToModelEntityOperationGenerator. + +L'interface étend AbstractEntityOperation et contient toutes +les signatures des opérations de l'entité en y rajoutant en premier argument +une variable du type de l'entité. + +- Classe XXXOperationRouteur : +Générée par ObjectModelToEntityOperationRouterGenerator. + +Cette classe implémente l'interface XXXOperation pour prendre en compte la +distribution. Si l'appel de la méthode doit être local, elle appelle +directement la méthode sur l'implantation faite par le développeur, si elle +doit être distante utilise le DistributionHelper pour faire l'appel. + +- Classe XXXOperationImpl : +NON GENEREE par ToPIA. + +L'utilisateur n'a qu'à implanter l'interface reprenant les opérations de +l'entité et de déclarer sa classe dans le fichier de proprietes du context. + +- Interface XXXPersistenceService : +Générée par ObjectModelToEntityPersistenceServiceGenerator. + +Cette interface comprend les déclarations de deux méthodes finds pour chaque +attribut : findBy, findAllBy ainsi qu'une méthode pour +trouver une entité XXX par son topiaId. + +- Classe XXXPersistenceServiceImpl : +Générée par ObjectModelToEntityPersistenceServiceImplGenerator. + +Cette classe implémente XXXPersistenceService en utilisant la méthode find +de AbstractPersistenceService qu'elle étend ainsi que les TopiaQuery. + + +Associations +------------ + +En UML, la navigabilité des associations peuvent être de 3 types : pas de +navigabilité, unidirectionnelle ou bidirectionnelle. Si aucune navigabilité +n'est spécifiée, on considère qu'elle est bidirectionnelle. Dans le cas d'une +navigabilité bidirectionnelle, chacun des participants de l'association a une +responsabilité sur l'association et gardera donc une référence sur le ou les +objets concernés par l'association. La navigabilité unidirectionnelle en UML +est représentée par une flêche allant d'un objet A à un objet B. Dans ce cas, +seul l'objet A est responsable de l'association et aura donc une référence sur +la ou les instances de B mais B n'aura aucune référence sur les éventuelles +instances de A. + +Quatre principaux types de multiplicités différentes existent en UML : 0..1, 1, +1..* et `*`. +En ce qui concerne les objets générés par ToPIA, seuls deux types sont +retranscrits : 1 et `*`. En effet, actuellement, les types non pris en compte ont la +particularité de comporter un 0. + +Les différents types d'associations au niveau d'une entité sont donc : + +- multiplicité normale (1) +Une multiplicité de 1 sera représentée par une référence sur un objet (cet +objet pouvant ne pas avoir de valeur (0)). + +- multiplicité naire (*) +Une multiplicité de `*` sera représentée par une Collection d'objets du type +souhaité. (Les cas d'une multiplicité précise (3, 12..15, ...) est traitée +comme une multiplicité de `*`). Les Collections créées sont de type ArrayList (??? pkoi ???). +Attention tout de même car ToPIA à l'heure +actuelle n'est écrit qu'en Java 1.4 et donc dépourvu de l'usage des templates +Java. Ainsi, les collection créées pourraient très bien contenir d'autres types +d'objets. Cependant les méthodes d'ajout, de retrait ou tout simplement de +manipulation des objets contenus dans ces collections sont écrites en utilisant +les types voulus interdisant ainsi d'utiliser d'autres types. + +On veut pouvoir représenter toutes les multiplicités suivantes : + +- 0..1 : Un attribut sans contrôle de multiplicité + +- 1 : Un attribut simple mais sans la possibilité de suppression. Seulement remplacement. + +- 1.. `*` : Une collection qui ne peut être vide + +- `*` : Une collection sans contrôle de multiplicité + +- p : (exactement p) impossible de supprimer ou ajouter. Seul le remplacement est possible en utilisant l'index. + +- p..q : (entre p et q) collection avec contrôle de multiplicité. Addition permise si non au max, et suppression permise si non au min. + +On veut pouvoir se servir des index, alors les collections utilisées seront des +List. De manière à pouvoir définir des multiplicités pour les attributs, on +utilisera des org.codelutin.util.BoundedList pour lesquelles on peut spécifier +des bornes min et max pour le nombre d'éléments. + +Une association peut être maintenue d'un ou des deux cotés de la relation. Dans +le cas d'associations unidirectionnelles, seul le coté responsable de +l'association conserve une référence sur celle-ci. Dans le cas contraire, les 2 +participants conserveront les références. Il faudra donc s'assurer à chaque +ajout/modification/suppression sur une extrémité d'une relation que les +participants concernés seront bien informés des éventuels changements. + +Quelques problèmes se présentent tout de même. Dans le cas d'une association +1-1 entre une instance de A et une instance de B. Si l'on veut changer auprès +de A, l'instance de B à utiliser, il faudra remplacer la précédente instance de +B. On s'assurera que la nouvelle instance de B référence également bien A. Par +contre, que devient l'ancienne instance de B ? Comme A a changé d'attribut B, +l'ancien B ne doit pas être associé à cette instance de A, mais alors quelle +pourrait-etre la valeur de l'attribut A pour B ? Si l'on choisit de supprimer +l'ancienne instance de B, on agit alors comme s'il s'agissait d'une composition +alors que, à priori, ce n'est pas le cas. Cependant, après réflexion, il ne +nous est venu aucun cas où une relation 1-1 pourrait avoir un sens si ce n'est +au sein d'une composition, c'est pourquoi nous considérerons que dans un tel +cas il s'agisse d'une erreur de modélisation et une association 1-1 sera +remplacée par une association 0..1-0..1 afin d'éviter toute incohérence dans +l'application. Toutefois, il est important d'être vigilant car la plupart des +outils de modélisation UML utilisent comme valeur par défaut pour les +associations les multiplicités 1-1. + +Le même genre de problème se présente indéniablement dans le cas d'une +multiplicité bornée. Il est alors difficile d'ajouter un élément et si il faut +en remplacer un, comment savoir lequel ? On se contentera pour l'instant de +faire un simple ajout. + + +Classes d'association +--------------------- + +ToPIA (dans sa version 0.31) ne gère pas vraiment les classes d'association. +Par exemple, soit une classe d'association C faisant la liaison entre A et B. A +l'heure actuelle, A et B se comportent de la même manière que dans le cas d'une +association classique. De plus, la classe d'association générée se comporte +comme une entité classique hormis le fait qu'elle ne possède aucune référence +sur les entités qu'elle devrait relier. + +Pour palier à ce manque, on se propose de transformer la classe d'association +en classe à part entière. Ainsi les informations sur l'association sont +déportées dans la classe d'association. Un objet A qui devrait avoir une +collection d'objets B (dont la classe d'association A-B est C) aura en réalité +une collection d'objets C lequels auront chacun une référence sur B. La classe +d'association en question aura ses propres attributs qui seront associés à une +et une seule association entre deux instances de A et de B. Lorsque l'on voudra +la liste des B associés à un A, il faudra faire un parcours des C que contient +A et renvoyer tous les B correspondants. + + +Attributs +--------- + +Pour les attributs de multiplicité normale, les méthodes générées sont : + + - get() + + - is_Modified_() + + - set(...) + + +Pour les attributs d'une plus grande multiplicité, les méthodes sont : + + - Collection get() // Retourne une Collection non modifiable (les + éléments de la collection restent modifiables malgré tout ! (On pourrait + faire en sorte qu'ils ne le soient pas grâce au fait que chaque entité est + interfacée, on pourrait donc utiliser des proxy pour limiter l'accès à + certaines méthodes - notamment les set)) + + - boolean is_Modified_() + + - add() + + - add(Collection) + + - add(Collection, boolean) // Ajoute la collection et duplique les + éléments si le booleen est true + + - remove(() + + +TODO : Ajouter les suivants : + + - int size() //Possibilité d'optimisation + + - Iterator Iterator() // obtenu par get.iterator() + + - boolean Contains( singleValue) // obtenu par get.contains(...) + + - boolean ContainsAll(Collection) // obtenu par get.containsAll(...) + + - get(int) + + - set(int, value) + + +Agrégation / Composition +------------------------ + +A l'heure actuelle (ToPIA 0.31) les agrégations et compositions sont traitées +comme de simple associations. A ce titre, la multiplicité implicite des +compositions (0..1) n'est pas prise en compte, c'est la multiplicité de +l'association qui prédomine. + +On introduit la notion de classes dépendantes d'autres classes, ce qui signifie +que lorsqu'une classe est supprimée, celles qui en sont dépendantes sont +également supprimées. + +Pour ce qui est de la composition, un objet composite contiendra de facon +classique une référence ou une collection d'objets composants qui seront +systématiquement ajoutés à la liste des objets dépendants de celui-ci. +Puisqu'un objet composant un autre objet n'a de sens sans lui, la création d'un +objet composant se fera depuis l'objet composé. On ne proposera pas de méthode +pour rattacher un composant à l'objet qu'il compose. Contrairement au problème +rencontré précédemment avec les associations 1-1, ici, un objet sera détruit +s'il n'est plus référencé par con composite. + + +Héritage +-------- + +- Classes + +Pour une classe, l'interface XXX générée étend les superinterfaces et +l'éventuelle superclasse de l'entité. + +Au niveau de la classe XXXImpl, elle +implémente systématiquement l'interface XXX précédemment générée. Si l'entité +ne dispose d'aucune superclasse, elle hérite de AbstractTopiaEntity. Dans le +cas contraire, elle hérite simplement de sa superclasse (XXXImpl) qui, +normalement, a également été générée par ToPIA. + +L'interface XXXOperation étend +de TopiaEntityOperation des superinterfaces (XXXOperation) et de l'éventuelle +superclasse (XXXOperation). + +De même que pour XXXImpl, XXXOperationRouter étend +AbstractTopiaElement ou la superclasse XXXOperationRouter si elle existe. De +plus, elle implémente l'interface XXXOperation précédemment générée. + +La classe XXXOperationImpl qui doit être écrite par le développeur doit se +faire en respectant l'héritage des entités. +Si une entité B hérite d'une entité A ayant toutes les deux des +opérations alors le développeur doit implanter une classe pour l'entité A +puis une classe pour l'entité B qui hérite de l'implantation de l'entité A. + +Le même schéma est reproduit pour XXXPersistenceService et +XXXPersistenceServiceImpl. + +- Interfaces + +A partir de toute entité XXX stéréotypée +interface (en plus du stéréotype entity) est créée une interface Java (XXX) qui +hérite de TopiaEntity. Par contre, si une interface possède elle-même +une ou plusieurs superinterfaces, l'interface générée n'étendra pas ses +superinterfaces (0.31). La classe XXXImpl n'est par contre pas générée. De même +la classe XXXOpRouter n'est pas non plus générée alors que XXXOperation est +générée et hérite de TopiaEntityOperation mais pas de sa ou ses superinterfaces. + +TODO : Corriger la gestion des supersuperinterfaces.