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

Vous pouvez modifier le code source généré pour une transformation de modèle à modèle afin que les utilisateurs puisse spécifier, comme source de cette transformation, un projet contenant plusieurs modèles.
Par défaut, l'entrée d'une transformation de modèle à modèle est un modèle et, par conséquent, l'utilisateur spécifie généralement un modèle comme source d'une telle transformation. Cet exemple montre comment personnaliser le code généré d'une d'une transformation de modèle à modèle afin que les utilisateurs puissent spécifier un projet Eclipse comme source de la transformation et que ce code détermine lui-même à quels modèles de ce projet appliquer la transformation. Les modèles UML portant l'extension de nom de fichier .emx dans le projet désigné sont collectés à l'exécution de la transformation, et non lorsque celle-ci est configurée par l'utilisateur, et sont utilisés comme entrée de la transformation.
Remarque : Dans cet exemple, l'ordre dans lequel la transformation traite les modèles source n'a pas d'importance. Pour les traiter dans un ordre précis, ajoutez le code correspondant à votre implémentation de la classe ProjectContentsExtractor.

Cet exemple contient un modèle de mappage de transformation qui définit des mappages élémentaires pour les modèles, les packages et les classes UML. La transformation générée crée un modèle UML qui porte le même nom que le projet source ; à l'intérieur de ce modèle, elle crée un package pour chaque modèle UML contenu dans le projet source. Pour chaque classe contenue dans un modèle source UML, la transformation crée également une classe dans chaque package. Bien que ce modèle de mappage soit simple, la transformation générée montre comment vous devez personnaliser le code pour qu'un utilisateur puisse spécifier les modèles source en désignant un projet source.

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 généré
  • La méthode isSourceElementValid dans le valideur de la transformation générée
  • La méthode createRootTransformation dans le fournisseur de la transformation générée

Personnalisation du fichier plugin.xml généré

Dans le point d'extension de la transformation (fichier plugin.xml), la propriété sourceModelType spécifie le type d'objet qu'un utilisateur peut désigner comme source de la transformation. Par défaut, lorsque vous créez un projet de transformation de modèle à modèle, la valeur de cette propriété est resource, ce qui signifie que, dans l'assistant et l'éditeur de configuration de transformation, l'utilisateur doit spécifier un fichier existant dans son espace de travail comme source de la transformation. Lorsque vous attribuez la valeur project à la propriété sourceModelType, l'utilisateur peut spécifier un projet Eclipse au lieu d'un fichier comme source de la transformation.

Personnalisation de la classe du valideur de transformation

L'assistant et l'éditeur de configuration de transformation utilisent la classe du valideur de transformation pour vérifier que la transformation peut s'exécuter correctement avec les réglages spécifiés par l'utilisateur. Dans cette classe, l'implémentation par défaut de la méthode isSourceElementValid renvoie true uniquement si la source spécifiée pour la transformation est un fichier.

Dans cet exemple, la classe du valideur de transformation nommée Project4sourceTransformationValidator vérifie que la transformation peut s'exécuter correctement avec les réglages définis par l'utilisateur. Ici, le code dans cette classe remplace l'implémentation par défaut de la méthode isSourceElementValid de sorte que celle-ci renvoie true uniquement si la source de la transformation est un projet. Une implémentation plus complète pourrait vérifier que l'utilisateur a sélectionné un projet UML.

Le fragment de code suivant montre la version par défaut de la méthode isSourceElementValid telle qu'elle est générée par une transformation :

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see com.ibm.xtools.transform.authoring.TransformationValidator#isSourceElementValid(java.lang.Object)
     * @generated
     */
    protected boolean isSourceElementValid(Object source) {
    	//Remove @generated tag to add more source validation checks
    	return super.isSourceElementValid(source);
    }
Le fragment de code suivant montre une version 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#isSourceElementValid(java.lang.Object)
     * @generated NOT
     */
    protected boolean isSourceElementValid(Object source) {
    	return source instanceof IProject;
    }

Personnalisation de la classe du fournisseur de transformation

Dans la classe du fournisseur de transformation nommée Project4sourceTransformationProvider, l'implémentation par défaut de la méthode createRootTransformation instancie un objet appelé RootTransformation, qui lui-même instancie l'implémentation par défaut de la classe ResourceTransform. L'implémentation par défaut de la classe ResourceTransform contient les éléments suivants :
  • Une implémentation de la méthode nommée ResourceContentsExtractor, qui ouvre un fichier de modèle et charge son contenu en mémoire
  • Une règle nommée ResourceTargetRule, qui initialise le modèle cible que la transformation génère
    Remarque : Cette règle est tributaire de la propriété sourceModelType dans le contexte de la transformation ; par conséquent, si vous changez la valeur par défaut de cette propriété, vous devez également personnaliser la règle ResourceTargetRule et l'implémentation de la méthode ResourceContentsExtractor.
Cet exemple définit une classe nommée ResourcesFromProjectTransform, qui est une version personnalisée de la classe ResourceTransform. Cette classe personnalisée instancie les classes suivantes :
  • Une classe nommée ProjectContentsExtractor, qui est une version personnalisée de la classe ResourceContentsExtractor
  • Une classe nommée Project4sourceTargetRule, qui est une version personnalisée de la classe ResourceTargetRule

Le fragment de code suivant montre la version par défaut de la méthode createRootTransformation telle qu'elle est générée par une 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 la version personnalisée de la méthode createRootTransformation :
    /**
     * 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 ResourcesFromProjectTransform(mainTransform)));
             }};
    }

Le fragment de code suivant montre le code source de la transformée ResourcesFromProjectTransform, qui contient un extracteur nommé ProjectContentsExtractor et une règle nommée Project4sourceTargetRule.

    protected class ResourcesFromProjectTransform extends ResourceTransform {
        public ResourcesFromProjectTransform(Transform mainTransform) {
            super(Project4sourceMessages.ResourcesFromProjectTransform_id);
            setName(Project4sourceMessages.ResourcesFromProjectTransform_name);
            add(new Project4sourceTargetRule());
            add(new ProjectContentsExtractor(mainTransform));
        }
    }
    
    protected class ProjectContentsExtractor extends ResourceContentsExtractor {
        
        public static final String UML_MODEL_FILE_TYPE = "emx"; //$NON-NLS-1$
        
        public ProjectContentsExtractor(AbstractTransform transform) {
            super(transform);
            setName(Project4sourceMessages.ProjectContentsExtractor_name);
        }

        @Override
        public Collection<Model> execute(ITransformContext context) {
            final ResourceSet resourceSet = ((EditingDomain) context
.getPropertyValue(TransformAuthoringConstants.SOURCE_EDITING_DOMAIN)).getResourceSet();
            final Collection<Model> models = new BasicEList();
            Object source = context.getSource();
            if (source instanceof IProject) {
                IProject project = (IProject)source;
                IResourceVisitor visitor = new IResourceVisitor() {
                    @Override
                    public boolean visit(IResource resource) throws CoreException {
                        if (resource instanceof IProject || resource instanceof IFolder)
                            return true;
                        if (resource instanceof IFile) {
                            IFile file = (IFile)resource;
                            if (UML_MODEL_FILE_TYPE.equals(file.getFileExtension())) {
                                Resource modelResource = resourceSet.getResource(getPlatformURI(file), true);
                                for (Iterator<EObject> i = modelResource.getContents().iterator(); i.hasNext();) {
                                    EObject content = i.next();
                                    if (content instanceof Model)
                                        models.add((Model)content);
                                }
                            }
                        }
                        return false;
                    }                    
                };
                try {
                    project.accept(visitor);
                } catch (CoreException ce) {
                    Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
Project4sourceMessages.ProjectContentsExtractor_name, ce));
                }                   
            }
            return models;
        }

    }
    
    protected class Project4sourceTargetRule extends ResourceTargetRule {

        @Override
        protected Object createTarget(ITransformContext context) {
            if (context.getSource() instanceof IProject) {        
                Object targetContainer = context.getTargetContainer();        
                if (targetContainer instanceof Resource) {
                    return targetContainer;
                } else if (targetContainer instanceof IFile){
                    IFile targetFile = (IFile)targetContainer;
                    ValidateEditRule.addAffectedFile(context, targetFile);
                    ResourceSet resourceSet = ((EditingDomain) context
.getPropertyValue(TransformAuthoringConstants.TARGET_EDITING_DOMAIN)).getResourceSet();
                    return resourceSet.createResource(getPlatformURI(targetFile));
                }
            }
            return super.createTarget(context);
        }
        
    }

Vos commentaires