Index: topia2/doc/ContactUseCases.png Index: topia2/doc/UseCase.rst diff -u /dev/null topia2/doc/UseCase.rst:1.1 --- /dev/null Tue May 29 10:08:39 2007 +++ topia2/doc/UseCase.rst Tue May 29 10:08:33 2007 @@ -0,0 +1,205 @@ +Topia Use Case +============== + +ToPIA permet la génération de navigation à partir du modèle UML sous forme de +diagrammes états/transitions. +Le framework fournit de plus une implémentation de cette génération basée +sur le framework MVC `Tapestry `_. + +Besoin +------ +Le besoin initial était d'utiliser au maximum les différents état du système. +Dans le cas d'un site internet par exemple, une même page peut être utilisée +pour créer un contact, et plus tard pour modifier un contact. + +Cependant, un état à un utilisation différente suivant le cas d'utilisation +utilisé. + +Ce framework permet donc de générer la navigation sous une forme quelconque, et +de baser cette navigation sur un moteur gérant les cas d'utilisation. + + +Générateur +---------- +Les générateurs de code utilisés font partie de LutinGenerator. Celui-ci permet +de charger le modèle en mémoire, mais ne fournit aucune implémentation +spécifique. +ToPIA fournit les templates de génération (notemment celui basé sur Tapestry). + + +Modèle UML +---------- +Le modèle UML de base doit respecter quelques conventions pour que la génération +se passe bien. + +En voici un exemple (ArgoUML) : + +.. image:: ContactUseCases.png + +Voici les différents points à respecter : + + * Toutes les parties réutilisables doivent appartenir à sous cas d'utilisation + spécifique. + * Tout sous cas d'utilisation doit disposer d'un état initial et d'un moins un + état final. + +Comme on peut le voir sur l'image, le cas d'utilisation en bas utilise d'autre +sous use case. Mais il ne dispose pas lui même d'état final. Il n'est donc pas +réutilisable. + + +Chargement du modele +-------------------- +LutinGenerator charge le modèle en mémoire sous la forme d'un modèle d'objets +java et appelle le template de génération spécifié dans la configuration. +Le template peut ensuite parcourir ce modèle aisément et générer les données +dont il a besoin. + +Configuration ++++++++++++++ +Voici la configuration maven de déclaration des templates: + +:: + + + lutinplugin + maven-generator-plugin + 0.xx + + + Generator + generate-sources + + + src/xmi + + target/gen/xmi/ + + target/gen/models/ + + **/*.*model + + org.codelutin.topia.generator.TapestryWebGenerator + + target/gen/java + + + + zargo2xmi + + xmi2statemodel + + generate + + + + + + lutinlib + topia + 2.0.xx + compile + + + + + +Nom de package +-------------- + +Une convention est utilisée dans le nom de package pour déterminer quel est la +racine de la structure (utilisée pour la génération basée sur tapestry par +exemple). + +Le motif utilisé est "web". Il désigne la racine. + +Exemple: + org.codelutin.chorem.web.projectManagement + +Ainsi, via tapestry l'url "/projectManagement" pourra être utilisée. + + +Génération Tapestry +------------------- +La génération sur Tapestry produit une classe abstraite par état déclaré dans le +modèle. +Ces classes abstraites : + + * déclare les autres pages(états) vers lesquelles elle peuvent naviguer. + Ces sont des références traitées par tapestry (annotations). + Chaque référence à pour type la classe concrête implémentée par le + développeur. + * gère l'entrée et la sortie des Use Case. + +Le developpeur doit donc developper l'implémentation tapestry en faisant +référence aux méthodes fournies dans les classes abstraites à hériter pour +naviguer. + +Exemple issue de la génération du modèle à l'image 1, voici la classe abstraite +SocietyView générée à partir du modèle : + +:: + + public abstract class AbstractSocietyView extends UseCasePage { + + public Object onActionFromOk() { + return leaveUseCase(); + } + + @InjectPage + private SocietyForm societyForm; + + protected SocietyForm getSocietyForm() { + return societyForm; + } + + public Object onActionFromEdit() { + enterUseCase(); + return societyForm; + } + + protected final String getUseCaseName() { + return "sv"; + } + } + +Conformément à la spécification : + * cet état est lié à l'état SocietyForm (état initial du sous cas d'utilisation + utilisé) + * dispose d'une action "ok" quittant le use case courant + * dispose d'une action "edit" entrant dans un nouveau use case + +Pour la partie développeur, voici un exemple consitant à appeler une action +avant d'effectuer la réelle navigation : + +:: + + public class SocietyView extends AbstractSocietyView { + + [...] + + @Override + public Object onActionFromEdit() { + + // action + getSocietyForm.setSociety(s); + + // appele de la super methode + return super.onActionFromEdit(); + } + + [...] + } + +Hiérarchie d'héritage +--------------------- +Comme on peut le voir, les classes implémentées par le développeur héritent des +des classes abstraites générées, l'empêchant ainsi d'utiliser son propre +héritage. + +Il est possible de spécifier une classe que toutes les classes abstraites +devront hériter via le fichier de propriété associé au modèle. + +Le propriété : + model.tagvalue.usecaseengineextendedclass=BasePage +spécifie que toutes les classes générées hériteront de la classe BasePage. \ No newline at end of file