Table of Contents
ArgoUML est un AGL UML écrit en java et disponible sous licence BSD.
Le but de cet AGL est de guider l'utilisateur dans l'utilisation du logiciel et de la notation UML au travers d'un mécanisme de critiques et d'assistants. L'utilisateur bénéficie de plus de toute la puissance de la notation UML puisqu'ArgoUML dispose de la librairie NSUML qui est une représentation du métamodèle UML 1.3.
Les sources d'ArgoUML étant disponibles sur le web, il est possible d'analyser de fonctionnement et de participer au développement de ce programme. De plus, ArgoUML dispose d'un système de chargement de modules permettant a quiquonque de développer du code pour ArgoUML et de le diffuser séparément.
ArgoUML sait ouvrir, fermer des projets, afficher et éditer des diagrammes, générer du code ...
Pour faire tout cela il utilise deux librairies en plus de la librairie standard du Java :
NSUML qui enregistre les éléments du modèle dans une structure statique calquée sur le MétaModèle UML.
GEF (Graphic Editing Framework) fournit une bibliothèque permettant aux applications Java d'éditer vectoriellement des schémas.
OCL-Argo qui permet à ArgoUML de supporter le langage OCL de description de contraintes.
L'arborescence du code d'argo est précise et définie comme suit :
build : ici sont placés tous les fichiers générés lors de la compilation d'argo ainsi que les archives générées.
conf : (non utilisé)
documentation : on y trouve toute la documentation (cookbook, faq, ...)
extra : (non utilisé)
lib : les librairies externes à argo
modules : les fichiers de chacun des modules
src : les anciennes sources
src_new : les sources depuis la dernière réorganisation
tools: (non utilisé)
www : Le site web
ArgoUML est organisé en packages.
Nous allons a présent décrire les packages principaux d'Argo :
kernel
uml
ui
xml
Le package kernel contient le "coeur" d'Argo : la classe Project. On y trouve aussi la gestion de l'historique grace à la classe History.
Le package uml contient tout ce qui concerne l'uml dans Argo.
Les diagrammes
La liaison entre la représentation graphique et le modèle à travers les DiagramRenderer et les GraphModel
La génération de code et le reverse engineering.
Les panels de propriété, permettant de paramétrer les éléments du modèle ainsi que les différents éléments qui y sont affichés.
Le package ui gère l'interface graphique, au travers notemment du singleton ProjectBrowser qui n'est autre que la fenêtre principale d'ArgoUML.
On trouve dans xml les différents parsers xml pour les fichiers utilisés par Argo :
argo pour lire les .argo
xmi pour lire les .xmi qui décrivent le modèle uml sur lequel on travaille ce parser n'est maintenant plus qu'un wrapper vers le parser fournit par la bibliotheque NSUML.
pgml qui permet de lire la partie graphique des diagrammes, enregistrée par GEF au format PGML (en attendant le svg).
Nous allons maintenant nous intéresser au fonctionnement d'ArgoUML.
Le démarrage d'ArgoUML s'effectue en six phases :
Création du ProjectBrowser (fenêtre principale)
Argo fixe la taille des fenêtres
Chargement du Projet
Chargement du ProjectBrowser
Initialisation des modules
Préload des classes
Project est une des classes les plus importantes d'ArgoUML, puisque c'est au travers de cette classe que le programme gère le projet.
Project offre des méthodes pour charger et sauver un projet. Une fois que le projet est chargée, Project gère celui-ci en créant ou en détruisant les ProjectMembers (qui correspondent aux fichiers enregistrés dans l'archive .zargo). Les ProjectMembers sont soit le modèle UML, soit un diagramme.
La figure suivante montre comment Project ouvre un fichier .zargo. Cette séquence se déroule au démarrage, si l'utilisateur a lancé Argo en spécifiant sur la ligne de commande le projet à ouvrir. Main va alors créer l'instance de Projet en lui demandant d'ouvrir le fichier spécifié.
Le diagramme de séquence suivant montre la liaison entre Project et un ProjectMember de type XMI pour l'enregistrement d'un modèle.
ProjectBrowser correspond à la fenêtre principale d'ArgoUML.
Elle est instanciée lors du démarrage d'ArgoUML, à ce moment, elle est chargée de créer tous les éléments de l'interface graphique.
La classe UMLAction qui dérive de AbstractAction (présente dans l'API Java, permet d'encapsuler des methodes qui seront appellées lors d'une sélection dans un menu.
ArgoUML utilise des Listeners pour mettre à jour les éléments de l'interface.
Cette utilisation est visible par exemple lorsque l'on modifie le nom d'une classe dans le panel de propriétés, ce nom est modifié en temps réel sur la figure représentant cette classe. Si on analyse ce comportement, on se rends compte que les éléments de l'interface implémentent MElementListener, qui leur permettent de réagir à une modification du modèle.
La Classe MElementEvent permet alors de faire circuler l'information désirée.
Le GraphModel emmet lui aussi des évènements à travers des listeners (enregistrés par les layers) lorsqu'un élément a été ajouté ou enlevé du diagramme.
ArgoUML dispose en plus d'un système de gestion des évènements, on retrouve les mécanismes de cette gestion d'évènements dans le package org.argouml.application.events .
GEF est la librairie utilisée par Argo pour gérer l'affichage desdiagrammes. Pour comprendre comment fonctionne l'interface graphique d'Argo (voire Argo lui-même), il est nécéssaire de comprendre le fonctionnement de GEF.
Il peut être très intéressant de lire la documentation de GEF que l'on peut trouver sur le site de GEF http://gef.tigris.org/.
Editor est la classe centrale de GEF. Il s'agit de l'interface à travers laquelle on édite un document graphique.
Editor est constituée de :
Un LayerManager chargé de gérer les différents layers
Un SelectionManager chargé de gérer la sélection
Un ModeManager générant les modes à l'aide d'une pile
ModeManager correspond a une pile qui doit gérer les Modes. Les différents evénements en provenance de l'interface graphique sont envoyés au Mode qui se situe en haut de la pile. Celui-ci peut alors agir ou envoyer le message au mode suivant.
Voici le diagramme d'activité de ModeCreate (le mode dans lequel est l'éditeur lorsque l'utilisateur souhaite ajouter une figure au diagramme).
LayerManager est chargé de gérer les différents Layers pour Editor. Les Layers ont pour mission de dessiner les figures et de les ordonner (placement devant/derrière, position).
La classe UMLDiagram est la base utilisée par tous les diagrammes dans Argo. Elle dérive de la classe Diagram de GEF.
Un Diagram est constitué de
Un Layer
Un GraphModel
Une Toolbar
Un Title
Pour chaque type de diagramme UML disponible dans Argo, il existe un package (dans org.argouml.uml.diagram) qui contient les classes permettant au diagramme de fonctionner.
On y trouve principalement :
Elles représentent les éléments du dessin. Les figures dans Argo sont de deux types les FigNodeModelElement qui représentent les noeuds, ou bien FigEdgeModelElement qui représentent les liaisons entre les différents noeuds.
Celui-ci permet de relier les éléments du modèle au diagramme. C'est par lui que sont créées les éléments du diagramme.
Un DiagramRenderer permettant d'associer à chaque élément du modèle, la figure correspondante. Il est appellé par le Layer du type PerspectiveLayer quand celui-ci apprends qu'un nouvel élément a été ajouté au modèle et veut l'ajouter au dessin.
Pour insérer une élément du modèle dans le diagramme, le layer apelle la méthode getFigNodeFor(myMModelElement) du DiagramRenderer puis insère la figure renvoyée.
Voici un diagramme de séquence explicitant l'insertion d'une connection entre deux éléments d'un diagramme. Il permet de mieux comprendre le fonctionnement du GraphModel et du DiagramRenderer.
Le diagramme de séquence suivant montre au travers de l'exemple du diagramme de classe comment est ajouté un diagramme au projet, suite à la demande de l'utilisateur de l'ajouter à travers les menus.
Les figures sont des éléments d'un Layer.
Il y a deux types de figures : FigNode et FigEdge. Les edges étant en fait des arcs entre les différents Node.
Les Figures utilisées dans ArgoUML implémentent MElementListener, ce qui leur permet de réagir à des changements de l'élément du modèle qui leur est associé.
ArgoUML présente les informations portées par les éléments du modèle dans un onglet appellé panneau de propriété.
A chaque classe peut être associé un panneau de propriété. Lorsque l'utilisateur sélectionne un objet dans l'aire de dessin, le panneau de propriété correspondant à sa classe est affiché et mis à jour pour représenter l'objet qu'il est sensé décrire.
Pour associer un Panneau de propriétés à une classe d'objets, il faut l'enregistrer auprès du DetailsPane.
PropPanel implémente MElementListener, ce qui indique qu'il écoute les modification de l'élément qu'il représente (s'il représente un objet de la classe MModelElement).
PropPanel utilise ensuite un dispatcher (de la classe UMLChangeDispatch) pour répercuter les changements sur les éléments du panel de propriétés. La methode dispatch de la classe UMLChangeDispatcher cherche tous les fils d'un container et mets à jour les fils du type : UMLUserInterfaceComponent. Si un fils est un container, on réitère dispatch sur ce fils. Cette methode est appellée de manière asynchrone par les Swing une fois que l'interface est updatée.
Le dispatcher sera aussi utilisé lors d'un changement de modèle (par exemple on passe de la classe foo à la classe bar qui ont le même panel de propriété puisque ce sont tous les deux des classes, mais qui ne portent pas la même information. Il faut dans ce cas mettre à jour tous les champs du panel. Dans ce cas, la methode dispatch s'occupe en plus d'enregistrer le bon MElementListener pour que le panel écoute le bon élement du modele.
Au niveau du code source d'argo, les modules sont placés dans un répertoire source différent de celui d'Argo (dans le répertoire module). Ils disposent de leur propre architecture de répertoires :
build : dans lequel sont placés les .class et les .jar résultant d'une compilation du module
lib : dans lequel on peut mettre toutes les librairies (sous forme de fichiers .jar) dont dépend le module
src : dans lequel se trouve le code source du module
Note : En ce qui concerne le code source, vu que l'archive du module se trouve dans le classpath, si vous utilisez la même arborescence de packages qu'ArgoUML, les packages correspondront.
Plusieurs fichiers permettent de configurer le module.
module.properties qui est utilisé par ant pour la compilation, il permet de spécifier entre autre le nom du module et le nom de l'archive qui sera créée
manifest.mf, placé dans le package racine, permet de configurer le .jar qui sera générer. Il contient des informations concernant le module et qui seront lues par le chargeur pour l'initialiser comme par exemple le nom de la classe qui implémente l'interface ArgoModule.
build.xml, le fichier de configuration de ant, qui devra être modifié si par exemple vous voulez inclure des fichiers dans le .jar qui ne sont pas des classes générées par le processus de compilation.
Les modules sont chargés par le ModuleLoader. Celui-ci est initialisé pendant la phase de démarrage d'Argo.
Il y quatre types de modules, et donc quatre manières de charger un module. Lors de son initialisation, ModuleLoader charge les modules des quatre types.
Une fois que la classe du module que l'on veut charger est récupérée (méthode différente suivant le type de module employé), une instance de cette classe est créée à l'aide de la méthode loadClassFromLoader. Puis la méthode initializeModule() est appellée sur l'objet fraichement créé.
L'interface Pluggable permet d'écrire des plug-ins pour ArgoUML. Les plugins sont un cas particulier des modules. Ils sont donc chargés en tant que modules dans ArgoUML. Par contre ils possèdent une interface qui leur permet d'être pris en charge directement par un composant d'Argo (les mécanismes d'insertion dans Argo sont donc clairement définis module).
Lorsqu'Argo a besoin d'un plugin d'un type donné, il va le demander à ModuleLoader via getPlugin ou getPlugins en passant comme paramètre le contexte désiré. ModuleLoader ira demander aux PlugIns chargés, du type demandé, grâce à la méthode inContext si ceux-ci correspondent au contexte. Si c'est le cas, le Pluggable sera renvoyé à Argo.
Une Action est une classe dont la méthode actionPerformed exécute une suite d'actions. Dans Argo, on associe les actions aux entrées dans les menus où aux boutons.
Les Cmd sont les actions de GEF. Leur action peut être paramétrée avant utilisation.
L'interface qui permet d'éditer un diagramme. Son comportement est géré par une machine d'état : ModeManager.
GEF (Graphic Editing Framework) est une librairie destinée à remprésenter des données sous forme d'un dessin vectoriel. Elle est utilisée par ArgoUML pour gérer la représentation graphique des diagrammes UML.
Un layer représente une feuille de dessin. C'est le layer qui gère les différentes figures.
Un mode correspond à un comportement de l'éditeur. Lorsque l'éditeur est dans le mode ModeSelect par exemple, l'utilisateur peut sélectionner des figures présentes dans la zone de dessin. Les Mode sont gérés pour l'Editor par le ModeManager.
Un module correspond à un code extérieur à ArgoUML pouvant être inséré dans celui-ci. L'interface des modules est définie par Module.
NSUML est une librairie représentant le métamodèle UML. Actuellement, ArgoUML utilise une version de NSUML lui permettant de travailler sur UML 1.3.
Pluggable est l'interface définissant les méthodes que doit implémenter un Plug-In dans ArgoUML.
Le ProjectBrowser est la fenêtre principale d'ArgoUML.
Un ProjectMember correspond à un membre du projet, c'est une entité qui pourra être sauvegardée par ArgoUML, donc soit un diagramme, qui sera enregistré dans le format .pgml soit un modèle UML, enregistré par NSUML au format xmi.
Les panneaux de propriétés permettent de voir et d'éditer les propriétés des différents éléments du modèle.
A chaque élément est associé un panneau de propriété qui reflète son état.