Detalhes para uma Transformação de Modelo em Modelo que Especifica um Projeto como sua Origem

É possível modificar o código-fonte gerado para uma transformação de modelo em modelo, de forma que usuários possam especificar um projeto que contém diversos modelos como a origem da transformação.
Geralmente, um usuário de transformação especifica um modelo como a origem de uma transformação de modelo em modelo, pois, por padrão, uma transformação de modelo em modelo aceita um modelo como entrada. Esta amostra mostra como customizar o código de transformação gerado, de forma que usuários da transformação possam especificar um projeto Eclipse em vez de um arquivo de modelo como a origem da transformação e o código customizado determina quais modelos do projeto transformar. Os modelos UML que têm .emx como uma extensão do nome do arquivo no projeto designado são coletados no tempo de execução da transformação, em vez de quando o usuário configura a transformação, e são utilizados como entrada para a transformação.
Nota: Nesta amostra, a ordem na qual a transformação processa os modelos de origem não interessa. Para processar os modelos em uma ordem específica, inclua o código correspondente em sua implementação da classe denominada ProjectContentsExtractor.

Esta amostra contém um modelo de mapeamento de transformação que define mapeamentos básicos para modelos UML, pacotes e classes. A transformação gerada cria um modelo UML que tem o mesmo nome que o projeto de origem e, nesse modelo, cria um pacote para cada modelo UML que o projeto de origem contém. Para cada classe no modelo de origem UML correspondente, a transformação também cria uma classe em cada pacote. Apesar de esse modelo de mapeamento ser simples, a transformação gerada mostra como você deve customizar o código para suportar a especificação de modelos de origem, especificando um projeto de origem.

Esta amostra mostra como customizar os itens a seguir na transformação gerada:
  • O ponto de extensão da transformação no arquivo plugin.xml gerado
  • O método isSourceElementValid no validador da transformação gerada
  • O método createRootTransformation no provedor da transformação gerada

Customização do Arquivo plugin.xml Gerado

No arquivo plugin.xml, no ponto de extensão da transformação, a propriedade denominada sourceModelType especifica o tipo de objetos que um usuário da transformação pode especificar como a origem da transformação. Ao criar um projeto de transformação de modelo em modelo, por padrão, esse valor de propriedade é configurado para recurso, o que significa que no assistente no editor de configuração da transformação, um usuário da transformação deve especificar um arquivo existente no espaço de trabalho como a origem da transformação. Ao configurar o valor da propriedade sourceModelType para projeto, um usuário da transformação pode especificar um projeto Eclipse, em vez de um arquivo, como a origem da transformação.

Customização da Classe do Validador da Transformação

O assistente e editor de configuração da transformação utilizam a classe do validador da transformação para verificar se a transformação pode ser executada corretamente com as configurações que o usuário especifica. Na classe do validador da transformação, a implementação padrão do método denominado isSourceElementValid retorna verdadeiro somente se a origem da transformação especificada for um arquivo.

Nesta amostra, a classe do validador da transformação denominada Project4sourceTransformationValidator verifica se a transformação pode ser executada corretamente com as configurações especificadas pelo usuário. Para esta amostra, o código dessa classe substitui a implementação padrão do método denominado isSourceElementValid e o método retorna verdadeiro somente se a origem da transformação for um projeto. Uma implementação mais robusta pode verificar se o usuário selecionou um projeto UML.

O fragmento do código a seguir mostra a versão padrão do método isSourceElementValid que uma transformação gera:

    /**
     * <!-- 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);
    }
O fragmento de código a seguir mostra uma versão customizada desse método, que, para as finalidades desta amostra, sempre retorna verdadeiro:
    /**
     * <!-- 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;
    }

Customização da Classe do Provedor da Transformação

Na classe do provedor da transformação denominada Project4sourceTransformationProvider, a implementação padrão do método denominado createRootTransformation instancia um objeto denominado RootTransformation, que instancia a implementação padrão da classe denominada ResourceTransform. A implementação padrão da classe denominada ResourceTransform contém os itens a seguir:
  • Uma implementação do método denominado ResourceContentsExtractor que abre um arquivo modelo e carrega seu conteúdo na memória
  • Uma regra denominada ResourceTargetRule que inicializa o modelo de destino que a transformação gera
    Nota: Essa regra depende da propriedade sourceModelType no contexto da transformação: se você alterar o valor padrão da propriedade denominada sourceModelType, então, você também deve customizar a regra denominada ResourceTargetRule e a implementação do método denominado ResourceContentsExtractor.
Esta amostra define uma classe denominada ResourcesFromProjectTransform, que é uma versão customizada da classe denominada ResourceTransform. Essa classe customizada instancia as seguintes classes:
  • Uma classe denominada ProjectContentsExtractor, que é uma versão customizada da classe denominada ResourceContentsExtractor
  • Uma classe denominada Project4sourceTargetRule, que é uma versão customizada da classe denominada ResourceTargetRule

O fragmento de código a seguir mostra a versão padrão do método denominado createRootTransformation que uma transformação gera:

    /**
     * Creates a root transformation. É possível incluir mais regras na transformação aqui
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @param transform The root transformation
     * @generated
     */
    protected RootTransformation createRootTransformation(ITransformationDescriptor descriptor) {
        return new RootTransformation(descriptor, new MainTransform());
    }
O fragmento de código a seguir mostra a versão customizada do método denominado createRootTransformation:
    /**
     * Creates a root transformation. É possível incluir mais regras na transformação aqui
     * <!-- 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)));
             }};
    }

O fragmento de código a seguir mostra o código-fonte para a transformação denominada ResourcesFromProjectTransform, que contém um extrator denominado ProjectContentsExtractor, e uma regra denominada 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);
        }
        
    }

Feedback