Dettagli relativi a una trasformazione modello-a-modello che specifica un progetto come origine

È possibile modificare il codice sorgente generato per una trasformazione modello-a-modello in modo che gli utenti possano specificare come origine della trasformazione un progetto che contiene più modelli.
Di solito, l'utente di una trasformazione specifica un modello come origine di una trasformazione modello-a-modello perché, per impostazione predefinita, una trasformazione modello-a-modello accetta un modello come input. Questo esempio mostra come personalizzare il codice della trasformazione generato in modo che gli utenti della trasformazione possano specificare un progetto Eclipse anziché un file di modello come origine della trasformazione; il codice personalizzato determinerà quali modelli del progetto trasformare. I modelli UML che hanno .emx come estensione nome file nel progetto designato vengono raccolti al momento del runtime della trasformazione e non quando l'utente configura la trasformazione e vengono utilizzati come input per la trasformazione.
Nota: in questo esempio, l'ordine in cui la trasformazione elabora i modelli di origine non è importante. Per elaborare i modelli in un ordine specifico, aggiungere il corrispondente codice alla propria implementazione della classe ProjectContentsExtractor.

Questo esempio contiene un modello di associazione di trasformazione che definisce le associazioni di base per le classi, i package e i modelli UML. La trasformazione generata crea un modello UML che ha lo stesso nome del progetto di origine e, in quel modello, crea un package per ciascun modello UML contenuto nel progetto di origine. Per ciascuna classe nel modello di origine UML corrispondente, la trasformazione crea anche una classe in ciascun package. Sebbene questo modello di associazione sia semplice, la trasformazione generata mostra come personalizzare il codice per supportare la specifica di modelli di origine indicando un progetto di origine.

Questo esempio mostra come personalizzare i seguenti elementi della trasformazione generata:
  • Il punto di estensione della trasformazione nel file plugin.xml generato
  • Il metodo isSourceElementValid nel validator della trasformazione generata
  • Il metodo createRootTransformation nel fornitore della trasformazione generata

Personalizzazione del file plugin.xml generato

Nel file plugin.xml, nel punto di estensione della trasformazione, la proprietà denominata sourceModelType specifica il tipo di oggetti che gli utenti di una trasformazione possono specificare come origine della trasformazione. Quando si crea un progetto di trasformazione modello-a-modello, per impostazione predefinita, il valore di questa proprietà è impostato su resource, pertanto nell'editor e nella procedura guidata configurazione di trasformazione, gli utenti della trasformazione devono specificare un file presente nello spazio di lavoro come origine della trasformazione. Quando si imposta il valore della proprietà sourceModelType su project, gli utenti della trasformazione possono specificare un progetto Eclipse, anziché un file, come origine della trasformazione.

Personalizzazione della classe validator della trasformazione

La procedura guidata e l'editor configurazione di trasformazione utilizzano la classe validator della trasformazione per verificare che la trasformazione possa essere eseguita correttamente con le impostazioni specificate dall'utente. Nella classe validator della trasformazione, l'implementazione predefinita del metodo isSourceElementValid restituisce true solo se l'origine della trasformazione specificata è un file.

In questo esempio, la classe validator della trasformazione denominata Project4sourceTransformationValidator verifica che la trasformazione possa essere eseguita correttamente con le impostazioni specificate dall'utente. Per questo esempio, il codice presente in questa classe sovrascrive l'implementazione predefinita del metodo isSourceElementValid e il metodo restituisce true solo se l'origine della trasformazione è un progetto. Una implementazione più efficace potrebbe verificare che l'utente ha selezionato un progetto UML.

Il seguente frammento di codice mostra la versione predefinita del metodo isSourceElementValid che una trasformazione genera:

    /**
     * <!-- 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);
    }
Il seguente frammento di codice mostra una versione personalizzata di questo metodo che, ai fini di questo esempio, restituisce sempre 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;
    }

Personalizzazione della classe fornitore della trasformazione

Nella classe fornitore della trasformazione denominata Project4sourceTransformationProvider, l'implementazione predefinita del metodo createRootTransformation crea una istanza di un oggetto denominato RootTransformation, che crea un'istanza dell'implementazione predefinita della classe denominata ResourceTransform. L'implementazione predefinita della classe denominata ResourceTransform contiene i seguenti elementi:
  • Un'implementazione del metodo ResourceContentsExtractor che apre un file di modello e ne carica il contenuto in memoria
  • Una regola denominata ResourceTargetRule che inizializza il modello di destinazione che la trasformazione genera
    Nota: questa regola dipende dalla proprietà sourceModelType nel contesto di trasformazione: se si modifica il valore predefinito della proprietà denominata sourceModelType, occorre personalizzare anche la regola denominata ResourceTargetRule e l'implementazione del metodo ResourceContentsExtractor.
Questo esempio definisce una classe denominata ResourcesFromProjectTransform, che è una versione personalizzata della classe denominata ResourceTransform. Questa classe personalizzata crea un'istanza delle seguenti classi:
  • Una classe denominata ProjectContentsExtractor, che è una versione personalizzata della classe ResourceContentsExtractor
  • Una classe denominata Project4sourceTargetRule, che è una versione personalizzata della classe ResourceTargetRule

Il seguente frammento di codice mostra la versione predefinita del metodo createRootTransformation che una trasformazione genera:

    /**
     * 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());
    }
Il seguente frammento di codice mostra la versione personalizzata del metodo 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)));
             }};
    }

Il seguente frammento di codice mostra il codice sorgente per la trasformazione denominata ResourcesFromProjectTransform, che contiene un estrattore denominato ProjectContentsExtractor e una regola denominata 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);
        }
        
    }
Argomento principale: Trasformazione modello-a-modello che specifica un progetto come origine

Feedback