Avant de commencer à expliquer le code du projet DOM-SSE Shapes, je vais tenter d'expliquer les grands principes de SSE. Le projet WST fournit plusieurs éditeurs (XML, CSS...) qui permettent de gérer des documents structurés (DOM, CSS...) à partir d'éditeurs. WST fournit par exemple un Editeur XML :

Tout au long de ce billet je m'appuierais sur l'exemple de l'éditeur XML de WST pour illustrer mes explications (de ce que j'ai pu comprendre sur SSE).
Un document structuré (DOM, CSS..) est géré par SSE à l'aide d'un modèle SSE. Le contenu d'un document structuré est initialisé dans un premier temps avec le contenu d'une instance IFile (fichier du workspace) qui est ouvert à l'aide d'un éditeur (XML, CSS...). Ce contenu peut être ensuite modifiable via divers éditeurs. Dans le cas du projet DOM-SSE Shapes, le contenu du fichier XML pourra être modifié via l'editeur "DOM-SSE Shapes" et via l'éditeur XML de WST. Vous pourrez remarquer que ces 2 editeurs ouverts en même temps et qui éditent le même fichier XML seront synchronisés.
Pour illustrer ce que signifie modèle SSE, étudions l'éditeur XML de WST qui se trouve dans le plugin org.eclipse.wst.xml.ui. Cet éditeur multi-pages est constitué de 2 pages (Source/Design). Il est géré par la classe org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart (qui etend MultiPageEditorPart) et est constitué de 2 pages :
L'editor StructuredTextEditor étend la classe standard org.eclipse.ui.editors.text.TextEditor et gère un modèle SSE qui est représenté par l'interface org.eclipse.wst.sse.core.internal.provisional.IStructuredModel à partir du contenu de l'éditeur. Un modèle SSE est capable de gérer un document structuré (DOM, CSS...) en fonction du contenu de l'éditeur. WST fournit par exemple plusieurs éditeurs capable de gérer divers document structuré comme XML, CSS. Chacun de ces documents structurés sont gérés par un type de modèle SSE et étendent IStructuredModel :
Dans le cas de l'editeur XML de WST, le modèle SSE est de type XML, appelé DOM-SSE (IDOMModel). Dans les billets EMF Shapes-WST, la classe EMF2DOMSSERenderer est utilisé pour sérializer le diagrame Shapes EMF en un XML de son choix et synchronizer l'instance EMF Shapes Diagram avec le DOM XML, qui permet au final de synchroniser le diagramme GEF avec d'autres éditeurs (XML, Texte...). EMF2DOMSSERenderer utilise en interne un DOM-SSE IDOMModel.
Voici les caractéristiques d'un modèle SSE que j'ai pu analyser :
Toutes les structures communes au modèle SSE se trouve dans le plugin core de WST org.eclipse.wst.sse.core. Ensuite chaque implémentation de modèle SSE a son propre plugin. Par exemple le modèle SSE de type DOM se trouve dans le plugin org.eclipse.wst.xml.core.
Les éditeurs (XML, DOM-SSE Shapes...) doivent récupérer un modèle SSE à partir d'un IFile. Ceci s'effectue à l'aide de l'instance manager de modèle org.eclipse.wst.sse.core.internal.provisional.IModelManager comme ceci :
IFile file = ...
IModelManager manager = StructuredModelManager.getModelManager();
IStructuredModel model = manager.getExistingModelForRead(file);
if (model == null) {
model = manager.getModelForRead(file);
}
Ce code permet de récupérer un modèle SSE en lecture à partir d'un fichier du workspace :
ATTENTION!!! Il se peut que le modèle SSE récupéré soit null si le content type du fichier est inconnu. Par exemple si vous modifiez l'extension d'un fichier *.xml en *.unknown et que vous ouvrez l'éditeur XML le message "Unsupported Content Type" s'affiche :

Dans le cas ou on souhaite récupérer un modèle SSE de type DOM, il faut caster IStructuredModel en IDOMModel :
IStructuredModel model = ...;
IDOMModel domModel = (IDOMModel)model;
Ce qui donne :
IFile file = ...
IModelManager manager = StructuredModelManager.getModelManager();
IStructuredModel model = manager.getExistingModelForRead(file);
if (model == null) {
model = manager.getModelForRead(file);
}
IDOMModel domModel = (IDOMModel)model;
Il existe aussi les méthodes get*ModelForEdit qui permet de récupérer un modèle SSE en mode édition, qui doivent être utilisées si vous souhaitez modifier le DOM. Les méthodes get*ModelForRead qui permet de récupérer un modèle SSE en mode lecture, le permettent aussi, mais j'ai tenté d'expliquer les différences de mode (lecture, édition) dans la section getModel*ForRead OU getModel*ForEdit? du billet suivant.
L'interface IStructuredModel qui représente un modèle SSE fournit plusieurs méthodes :
Lorsque le document structuré d'un modèle SSE doit être modifié (plusieurs modifications doivent être effectuées), il est fortement conseillé pour des raisons de performances d'utiliser les méthodes IStructuredModel#aboutToChangeModel() et IStructuredModel#changeModel(). En effet un modèle SSE est observable et à chaque modification du document structuré, les listeners IModelStateListener branchés sur le modèle SSE se déclenchent.
L'utilisation de ces 2 méthodes s'effectue comme suit :
IStructuredModel model = ...
// 1. Indique que l'on souhaite modifier le document structuré
model.aboutToChangeModel();
// 2. Modification du document structuré
... // Ici aucun listener ne sera déclenché
// 3. Indique que l'on a fini de modifier le document structuré.
mode.changeModel();
// Ici les listeners se sont déclenchés
Par exemple si on souhaite ajouter 2 éléments XML à un DOM avec le modèle DOM-SSE, ceci donne :
IStructuredModel model = ...
IDOMModel domModel = (IDOMModel)model;
// 1. Indique que l'on souhaite modifier le DOM
domModel.aboutToChangeModel();
// 2. Modification du DOM en ajoutant 2 element
org.w3c.dom.Document document = domModel.getDocument();
Element elt1 = document.createElement("rectangle");
document.appendChild(elt1);
Element elt2 = document.createElement("ellipse");
document.appendChild(elt2); // Ici aucun listener ne sera déclenché
// 3. Indique que l'on a fini de modifier le DOM.
domModel.changeModel();
// Ici les listeners se sont déclenchés
Dans ce cas-ci UNE seule notification sera effectuée. Il est bien sur possible de modifier le DOM sans faire appel aux 2 méthodes aboutToChangeModel() et changedModel() du modèle SSE, mais si vous ne les utiliser pas, une notification se declenchera à chaque modification du DOM. Dans l'exemple ci-dessus, DEUX notifications s'effectueront (le DOM est modifiés 2 fois en ajoutant les 2 elements XML elt1 et elt2) si vous n'utilisez pas les 2 méthodes du modèle SSE.
Un modèle SSE est capable de gérer l'état dirty du document structuré. Lorsque le modèle SSE est récupéré pour la première fois, l'état dirty est positionné à false. Dès que le document structuré est modifié, l'état dirty est positionné à true. Dans le projet "DOM-SSE Shapes", nous allons implémenter la méthode EditorPart#isDirty() en utilisant l'état dirty du modèle SSE pour être en cohérence avec le document structuré DOM.
Un modèle SSE est capable de sauvegarder le contenu d'un document structuré à l'aide des méthodes save :
ATTENTION!!! Tout appel des méthodes save, modifie l'etat dirty à true du modèle SSE. Je me suis fait avoir lorsque j'ai souhaité sauvegarder le modèle SSE dans l'outputStream System.out pour tracer les modifications du DOM.
La méthode IStructuredModel#releaseFromRead() permet de reinitialiser le document structuré associé au modèle SSE. Autrement dit si on modifie le document structuré et que l'on appelle cette méthode, le document structuré se ré-initialise avec le contenu de départ. Cette méthode est utilisé dans le projet "DOM-SSE Shapes" pour gérer le cas ou l'utilisateur modifie le DOM via l'interface SWT et ferme l'éditeur sans sauvegarder.
Lorsque un document structuré est modifié, son modèle SSE associé est capable de notifier ces changements. Ces changements peuvent être observés en ajoutant au modèle SSE une implémentation un listener IModelStateListener :
Voici le code qui permet d'ajouter un listener IModelStateListener :
IStructuredModel model = ...
model.addModelStateListener(new IModelStateListener() {
public void modelAboutToBeChanged(IStructuredModel model) {
}
public void modelAboutToBeReinitialized(
IStructuredModel structuredModel) {
}
public void modelChanged(IStructuredModel model) {
}
public void modelDirtyStateChanged(IStructuredModel model,
boolean isDirty) {
}
public void modelReinitialized(IStructuredModel structuredModel) {
}
public void modelResourceDeleted(IStructuredModel model) {
}
public void modelResourceMoved(IStructuredModel oldModel,
IStructuredModel newModel) {
}
});
Dans notre cas, les méthodes qui nous intéresserons seront :
L'éditeur XML utilise (via StructuredTextEditor) un modèle SSE de type XML, appelé DOM-SSE (IDOMModel) qui se trouve dans le plugin org.eclipse.wst.xml.core. Ce DOM-SSE maintient au mieux en interne un document w3c DOM en fonction du contenu XML saisi dans l'éditeur. Ce DOM peut être récupéré à partir du modèle SSE IStructuredModel obtenu par IModelManager que l'on caste en IDOMModel comme suit :
IStructuredModel model = ...
IDOMModel domModel = (IDOMModel)model;
org.w3c.dom.Document document = domModel.getDocument();
Il est alors possible de modifier directement ce DOM w3c (en ajoutant des élements, en modifiant des attributs....), et l'éditeur XML reste toujours synchronisé, c'est à dire que modifier la valeur d'un attribut d'un élément donnée via l'API DOM est tout de suite reflété dans l'éditeur (le texte change, et l'éditeur passe en était dirty).
Notez toutefois qu'il vous est possible de caster touts les types w3c (Node, Attr, Element, etc.) en leur version structurés IDOM* (IDOMNode, IDOMAttr, IDOMElement, etc.). Ces types là vous donnent la possibilité de faire le lien entre le Document DOM et la notion de Document JFace org.eclipse.jface.text.IDocument (les offsets par exemple). IDOMNode offre entre autre 2 méthodes supplémentatires par rapport au type Node w3c qui sont :
Le contenu XML de l'éditeur peut en effet ne pas être valide, lorsque l'utilisateur est en train de saisir un contenu XML dans l'editeur.
Par exemple, si l'editeur XML a le contenu suivant :
<root title="bla"
Le DOM valide en interne sera :
<root title="bla" />
Si l'editeur XML a le contenu suivant :
<root title="bla" >
<a
Le DOM valide en interne sera :
<root title="bla" >
<a />
</root/>
Un DOM-SSE est donc capable de construire un DOM avec un contenu XML qui peut ne pas être valide.
Cet article n'a pas de Commentaires/Pingbacks pour le moment...
Vous devez être identifié pour poster un commentaire.
| Lun | Mar | Mer | Jeu | Ven | Sam | Dim |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 |
Copyright © 2000-2012 - www.developpez.com