Détails d'une transformation de modèle à modèle spécifiant un URI pour sa cible

Vous pouvez modifier le code source généré pour une transformation de modèle à modèle afin de permettre aux utilisateurs de cette transformation de spécifier un URI comme fichier de modèle cible.

L'exécution d'une transformation de modèle à modèle génère un modèle en mémoire. Par défaut, dans le cadre du post-traitement de la transformation, l'infrastructure de transformation écrit le contenu du modèle généré en mémoire dans un fichier situé dans l'espace de travail. Lorsqu'un utilisateur crée une configuration de transformation pour la transformation de modèle à modèle, il peut spécifier le fichier comme conteneur cible de la transformation, ou bien il peut créer un nouveau conteneur cible. Dans une configuration de transformation, une propriété de la transformation nommée "target container" (conteneur cible) contient le nom de fichier du modèle cible. Ce fichier doit déjà exister dans l'espace de travail au moment où la transformation est exécutée.

Ce projet exemple de transformation montre comment personnaliser le code source de la transformation générée afin de fournir aux utilisateurs un autre moyen de configurer le conteneur cible. En tant qu'auteur de transformations, après avoir généré le code source d'une transformation de modèle à modèle, vous pouvez personnaliser ce code afin qu'un utilisateur puisse spécifier un URI au lieu d'un fichier de modèle comme conteneur cible de la transformation. Le fichier désigné par l'URI n'a pas besoin d'exister déjà au moment où la transformation est exécutée ; cette dernière le crée s'il n'existe pas.

Cet exemple contient un modèle de mappage de transformation simple, qui définit un seul mappage entre un modèle UML et un autre modèle UML ; le mappage attribue un nom au modèle cible généré et ce nom est dérivé de celui du modèle source.
Remarque : Il n'est pas nécessaire que le nom interne d'un modèle soit identique à celui du fichier qui contient ce modèle dans le système de fichiers.
De par la simplicité du modèle de mappage, la transformation générée dans cet exemple ne fait qu'illustrer les étapes de personnalisation visant à permettre à l'utilisateur de désigner un conteneur cible au moyen d'un URI. Elle ne copie pas d'éléments du modèle source vers le modèle cible.
Cet exemple montre comment personnaliser les éléments suivants dans la transformation générée :
  • Le point d'extension de la transformation dans le fichier plugin.xml
  • La méthode isTargetElementValid dans la classe du valideur de la transformation générée
  • La méthode createRootTransformation dans la classe Uri4targetTransformationProvider, fournisseur de la transformation générée

Personnalisation du fichier plugin.xml

Une fois que le code source de la transformation a été généré, dans le point d'extension de la transformation (fichier plugin.xml), la propriété targetModelType spécifie le type de modèle qu'un utilisateur peut désigner comme conteneur cible. Par défaut, la valeur de cette propriété est resource, ce qui signifie que, dans la configuration de transformation, l'utilisateur doit spécifier un fichier existant dans son espace de travail. Dans le fichier plugin.xml personnalisé, la propriété targetModelType a pour valeur none (néant).

Dans le fichier plugin.xml, l'élément d'extension de transformation généré contient une nouvelle propriété de transformation nommée Target Model URI (URI du modèle cible). Ici, dans l'assistant et l'éditeur de configuration de transformation, sous l'onglet Propriétés, l'utilisateur doit spécifier une valeur de chaîne pour cette propriété dans la zone Target Model URI.

Personnalisation de la classe du valideur de transformation

L'assistant et l'éditeur de configuration de transformation utilisent la classe générée Uri4targetTransformationValidator pour contrôler la validité des réglages dans la configuration de transformation. Par défaut, l'implémentation de la méthode isTargetElementValid renvoie true uniquement si le conteneur cible configuré est un fichier. Dans cet exemple, l'implémentation par défaut est remplacée par une version personnalisée qui renvoie toujours true, quelle que soit la valeur spécifiée pour le conteneur cible. Un implémentation plus complète pourrait valider l'URI indiqué par l'utilisateur en fonction de caractéristiques propres à la transformation ou au projet.

Le fragment de code suivant montre l'implémentation par défaut de la méthode isTargetElementValid telle qu'elle est générée par la transformation :
    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see com.ibm.xtools.transform.authoring.TransformationValidator#isTargetElementValid(java.lang.Object)
     * @generated
     */
    protected boolean isTargetElementValid(Object target) {
    	//Remove @generated tag to add more target validation checks
    	return super.isTargetElementValid(target);
    }
Le fragment de code suivant montre l'implémentation personnalisée de cette méthode qui, pour les besoins de cet exemple, renvoie toujours true :
    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see com.ibm.xtools.transform.authoring.TransformationValidator#isTargetElementValid(java.lang.Object)
     * @generated NOT
     */
    protected boolean isTargetElementValid(Object target) {
        return true;
    }

Personnalisation du fournisseur de transformation

Dans la classe personnalisée générée Uri4targetTransformationProvider, l'implémentation par défaut de la méthode createRootTransformation instancie un objet de la classe RootTransformation, qui lui-même instancie un objet de la classe ResourceTransform. L'implémentation par défaut de la classe ResourceTransform utilise une implémentation nommée ResourceTargetRule, qui ouvre le fichier représentant le conteneur cible configuré. Dans cet exemple, le conteneur cible configuré est un URI, et non un fichier ; par conséquent, une implémentation personnalisée de ResourceTransform, nommée ResourceFromUriTransform, et une implémentation personnalisée de ResourceTargetRule, nommée ResourceFromUriTargetRule, sont ajoutées à la classe Uri4targetTransformationProvider.

L'implémentation personnalisée ResourceFromUriTargetRule effectue les étapes suivantes :
  • Elle crée le fichier désigné par l'URI, s'il n'existe pas déjà
  • Elle ouvre le fichier spécifié par l'URI
  • Elle associe une ressource de modèle en mémoire au fichier et stocke l'objet fichier dans le contexte de la transformation racine afin que les autres règles de transformation puissent l'obtenir
Le fragment de code suivant montre l'implémentation par défaut de la méthode createRootTransformation telle qu'elle est générée par la transformation :
    /**
     * Creates a root transformation. You may add more rules to the transformation here
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @param transform The root transformation
     * @generated
     */
    protected RootTransformation createRootTransformation(ITransformationDescriptor descriptor) {
        return new RootTransformation(descriptor, new MainTransform());
    }
Le fragment de code suivant montre l'implémentation personnalisée de la méthode createRootTransformation contenue dans cet exemple :
    /**
     * Creates a root transformation. You may add more rules to the transformation here
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @param transform The root transformation
     * @generated NOT
     */
    protected RootTransformation createRootTransformation(ITransformationDescriptor descriptor) {
        return new RootTransformation(descriptor, new MainTransform()) {
            @Override
             protected void addInitialExtractor(Transform mainTransform) {
                add(new ResourceListExtractor(new ResourceFromUriTransform(mainTransform)));
             }};
    }
    
Le fragment de code suivant montre les implémentations personnalisées, nommées ResourceFromUriTransform et ResourceFromUriTargetRule, que la classe Uri4targetTransformationProvider contient :
    protected class ResourceFromUriTransform extends ResourceTransform {
        public ResourceFromUriTransform(Transform mainTransform) {
            super(Uri4targetMessages.ResourceFromUriTransform_id);
            setName(Uri4targetMessages.ResourceFromUriTransform_name);
            add(new ResourceFromUriTargetRule());
            add(new ResourceContentsExtractor(mainTransform));
        }
    }

    protected class ResourceFromUriTargetRule extends ResourceTargetRule {
        @Override
        protected Object createTarget(ITransformContext context) {
            ResourceSet resourceSet = ((EditingDomain) context
.getPropertyValue(TransformAuthoringConstants.TARGET_EDITING_DOMAIN))
.getResourceSet();
            Resource resource = null;
            Object targetModelURIString = context.getPropertyValue("TargetModelURI"); //$NON-NLS-1$
            if (targetModelURIString instanceof String) {
                URI targetModelURI = URI.createURI((String)targetModelURIString);
                IPath targetModelPath = new Path(targetModelURI.path());                
                IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
                IFile targetModelFile = wsRoot.getFile(targetModelPath);
                ValidateEditRule.addAffectedFile(context, targetModelFile);
                resource = resourceSet.createResource(getPlatformURI(targetModelFile));
                ITransformContext rootContext = context;
                while (rootContext.getParentContext() != null)
                    rootContext = rootContext.getParentContext();
                rootContext.setPropertyValue(ITransformContext.TARGET_CONTAINER, targetModelFile);
            }
            return resource;
        }        
    }

Vos commentaires