février
2009
Le billet précédant explique comment sérializer l’instance EMF ShapesDiagram en instanciant soit même l’implémentation EMF Resource ShapesResourceImpl :
Resource resource = new ShapesResourceImpl();
Ce procédé fonctionne, mais n’est pas le plus propre, car il est conseillé d’utiliser les ResourceSet EMF pour obtenir une instance Resource au lieu d’instancier soit même resource :
Resource resource = resourceSet.createResource(uri);
Le but de ce billet est d’expliquer dans un premier temps les grands principes de ResourceSet et d’implémenter le mécanisme qui permettra d’instancier notre implémentation ShapesResourceImpl à partir d’un ResourceSet.
Vous pouvez télécharger le projet org.eclipse.gef.examples.shapes.emfwst_1.0.0.zip expliqué dans ce billet.
Rappel sur ResourceSet EMF
Resource EMF
Une Resource EMF est un conteneur pour les objets persistés (save() et load()).Ces objets persisté sont accéssibles via Resource#getContents(). Resource EMF est utilisé pour sérializer les objets (sérialisation Xml, Xmi, Ecore, Emof…). EMF propose par exemple les implémentations XMLResourceImpl (pour sérializer en XML) et XMIResourceImpl pour sérializer en XMI).
Dans notre cas une instance EMF ShapesDiagram est gérée (chargement, sauvegarde) à l’aide d’une Resource EMF (ShapesResourceImpl). Pour rappel voici le code de chargement d’une instance ShapesDiagram EMF :
URI uri = URI.createPlatformResourceURI(file.getFullPath().toString());
resource.setURI(uri);
...
resource.load(Collections.EMPTY_MAP);
...
diagram = (ShapesDiagram)resource.getContents().get(0);
...
ResourceSet EMF
Un ResourceSet EMF est un contexte commun pour différentes ressources se référençant. Un ResourceSet EMF peut être utilisé en tant que factory pour la création de ressources. C’est ce rôle de factory qui nous intéressera dans ce billet. EMF propose ResourceSetImpl une implémentation de ResourceSet.
Si on reprend l’exemple de départ de Shapes EMF on peut obtenir une Resource EMF comme ceci :
URI uri = URI.createPlatformResourceURI(file.getFullPath().toString());
resource = resourceSet.createResource(uri);
Si vous éditer le fichier *.shapesemf, vous pourrez constater que celui-ci est sérializer en XMI. En effet ResourceSetImpl#createResource(URI uri) retourne par defaut une instance de XMIResourceImpl.
Il est possible de configurer de plusieurs manières ResourceSet pour qu’il retourne une instance Resource de son choix. Il est par exemple possible d’indiquer que tous les fichier d’extension « shapesemf » doivent se sérializer avec XMLResourceImpl (au lieu de XMIResourceImpl) pour obtenir une sérialisation XML (et pas XMI) comme ceci :
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("shapesemf", new XMLResourceFactoryImpl());
Voici le code de XMLResourceFactoryImpl :
{
/**
* Constructor for XMLResourceFactoryImpl.
*/
public XMLResourceFactoryImpl()
{
super();
}
/**
* Creates an XMLResourceImpl and returns it.
*/
@Override
public Resource createResource(URI uri)
{
return new XMLResourceImpl(uri);
}
}
Comme on peut le voir, La classe XMLResourceFactoryImpl est une implémentation de Resource.Factory, qui retourne une instance XMLResourceImpl.
ResourceSet Shapes EMF
Dans ce billet, nous allons utiliser la technique de factory décrit ci-dessus et implémenter notre propre factory de resource ShapesResourceFactoryImpl pour retourner une instances ShapesResoureImpl.
ShapesResourceFactoryImpl
ShapesResourceFactoryImpl est notre implémentation EMF de factory Resource qui va retourner une instance EMF Resource org.eclipse.gef.examples.shapes.emf.translator.ShapesResourceImpl. Cette factory étend la classe org.eclipse.wst.common.internal.emf.resource.TranslatorResourceFactory qui implémente Resource.Factory en utilisant les Translators.Créer la classe ShapesResourceFactoryImpl comme suit :
import org.eclipse.emf.common.util.URI;
import org.eclipse.wst.common.internal.emf.resource.EMF2DOMRendererFactoryDefaultHandler;
import org.eclipse.wst.common.internal.emf.resource.Renderer;
import org.eclipse.wst.common.internal.emf.resource.TranslatorResource;
import org.eclipse.wst.common.internal.emf.resource.TranslatorResourceFactory;
public class ShapesResourceFactoryImpl extends TranslatorResourceFactory {
public ShapesResourceFactoryImpl() {
super(EMF2DOMRendererFactoryDefaultHandler.INSTANCE
.getDefaultRendererFactory());
}
protected TranslatorResource createResource(URI uri, Renderer renderer) {
return new ShapesResourceImpl(uri, renderer);
}
}
Voici quelques explications de ShapesResourceFactoryImpl:
- TranslatorResourceFactory#createResource(URI, Renderer) : retourne dans notre cas une instance de ShapesResourceImpl.
-
le constructeur ShapesResourceFactoryImpl renseigne l’instance Renderer WST à utiliser à l’aide du code
EMF2DOMRendererFactoryDefaultHandler.INSTANCE.getDefaultRendererFactory()
ShapesResourceImpl
La classe ShapesResourceImpl doit être modifiée. Le constructeur ne gère plus le Renderer utilisé (c’est la factory resource qui le gère maintenant). Modifier le constructeur ShapesResourceImpl comme suit :
super(uri, renderer);
}
Utilisation ShapesResourceFactoryImpl
Le projet Shapes EMF utilise une instance Resource EMF à deux endroits :
- ShapesEditor : dans l’editeur Shapes au moment de charger/sauvegarder une instance EMF ShapesDiagram
- ShapesCreationWizard : dans le wizard de création d’un fichier *.shapesemfwst.
Il faut donc modifier le code du projet pour utiliser notre ShapesResourceFactoryImpl et plus directement ShapesResourceImpl.
Modification ShapesCreationWizard
Modifier ShapesCreationWizard#getInitialContents() comme suit :
ShapesDiagram diagram = (ShapesDiagram) createDefaultContent();
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().
put("shapesemfwst", new ShapesResourceFactoryImpl());
URI uri = URI.createPlatformResourceURI("tmp.shapesemfwst");
Resource resource = resourceSet.createResource(uri);
...
Modification ShapesEditor
Supprimer la variable resource de ShapesEditor et ajouter la variable ResourceSet et initialiser la dans le constructeur ShapesEditor comme suit :
private ResourceSet resourceSet;
...
public ShapesEditor() {
setEditDomain(new DefaultEditDomain(this));
resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().
put("shapesemfwst", new ShapesResourceFactoryImpl());
}
...
Modifier ShapesEditor#createOutputStream(OutputStream os) comme suit :
...
Resource resource = (Resource)resourceSet.getResources().get(0);
...
Modifier ShapesEditor#doSave(IProgressMonitor monitor) comme suit :
...
Resource resource = (Resource)resourceSet.getResources().get(0);
...
Modifier ShapesEditor#setInput(IEditorInput input) comme suit :
...
URI uri = URI.createPlatformResourceURI(file.getFullPath().toString());
Resource resource = resourceSet.createResource(uri);
...
Articles récents
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step5]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step4]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step3]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step2]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step1]
Commentaires récents
- Conception d’un Editeur Eclipse de workflow XML [step 0] dans
- Conception d’un Editeur Eclipse de workflow XML [step 19] dans
- Conception d’un Editeur Eclipse de workflow XML [step 7] dans
- Conception d’un Editeur Eclipse de workflow XML [step 7] dans
- Conception d’un Editeur Eclipse de workflow XML [step 7] dans