Detalhes para uma Transformação de Modelo em Modelo que Especifica um URI como um Destino

É possível modificar o código-fonte que é gerado para uma transformação de modelo em modelo para possibilitar que usuários especifiquem um Uniform Resource Identifier (URI) como o arquivo modelo de destino.

Executar uma transformação de modelo em modelo gera um modelo em memória. Por padrão, como parte do pós-processamento da transformação, a estrutura da transformação grava o conteúdo do modelo em memória gerado em um arquivo no espaço de trabalho. Quando um usuário cria uma configuração de transformação para a transformação de modelo em modelo, o usuário pode especificar o arquivo como o contêiner de destino da transformação ou criar um novo contêiner de destino. Em uma configuração de transformação, uma propriedade de configuração denominada "contêiner de destino" contém o nome do arquivo do modelo de destino. Esse arquivo deve existir no espaço de trabalho antes de a transformação ser executada.

Este projeto de transformação de amostra mostra como fornecer uma maneira alternativa para que usuários configurem o contêiner de destino, customizando o código-fonte da transformação gerado. Como um autor da transformação, após gerar o código-fonte para uma transformação de modelo em modelo, é possível customizar o código de forma que um usuário da transformação possa especificar um URI, em vez de um arquivo modelo, como o contêiner de destino da transformação. O arquivo identificado pelo URI não precisa existir antes da transformação ser executada; a transformação cria o arquivo se ele não existir.

Esta amostra contém um modelo simples de mapeamento da transformação que define somente um mapeamento de um modelo UML para um modelo UML; o mapeamento designa um nome para o modelo de destino gerado e esse nome é derivado do nome do modelo de origem.
Nota: O nome interno de um modelo não precisa corresponder ao nome do arquivo que contém o modelo no sistema de arquivos.
Como o modelo de mapeamento desta amostra é simples, a transformação gerada demonstra somente a customização necessária para suportar a utilização de um URI para especificar um contêiner de destino. A transformação não copia elementos do modelo de origem para o modelo de destino.
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
  • O método isTargetElementValid na classe do validador da transformação gerada
  • O método createRootTransformation na classe do provedor da transformação gerada denominada Uri4targetTransformationProvider

Customização do Arquivo plugin.xml

Após a geração do código-fonte da transformação, no arquivo plugin.xml, no ponto de extensão da transformação, a propriedade denominada targetModelType lista o tipo de modelos que um usuário de transformação pode especificar como o contêiner de destino. Por padrão, essa propriedade é configurada para recurso, o que significa que na configuração da transformação, o usuário deve especificar um arquivo existente no espaço de trabalho. No arquivo plugin.xml customizado, a propriedade targetModelType é configurada para nenhum.

No arquivo plugin.xml, o elemento de extensão da transformação gerada contém uma nova propriedade da transformação denominada URI do Modelo de Destino. Nesta amostra, no assistente e editor Configuração da Transformação, na guia Propriedades, no campo URI do Modelo de Destino, o usuário especifica um valor de cadeia para a propriedade.

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

O assistente e editor da configuração da transformação utilizam a classe do validador da transformação customizada gerada denominada Uri4targetTransformationValidator para validar as configurações na configuração da transformação. Por padrão, a implementação do método denominado isTargetElementValid retorna verdadeiro somente se o contêiner de destino configurado for um arquivo. Nesta amostra, a implementação padrão é substituída e retorna verdadeiro se um valor for especificado como o contêiner de destino. Uma implementação mais robusta pode executar uma validação específica da transformação ou específica do projeto no URI que o usuário especifica.

O fragmento de código a seguir mostra a implementação padrão do método denominado isTargetElementValid gerado pelo transformação:
    /**
     * <!-- 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);
    }
O fragmento de código a seguir mostra a implementação customizada que a amostra contém, que, para as finalidades desta amostra, sempre retorna verdadeiro:
    /**
     * <!-- 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;
    }

Customização do Provedor da Transformação

Na classe customizada gerada denominada Uri4targetTransformationProvider, a implementação padrão do método denominado createRootTransformation instancia a classe denominada RootTransformation, que, por sua vez, instancia a classe denominada ResourceTransform. A implementação padrão da classe denominada ResourceTransform utiliza uma implementação denominada ResourceTargetRule que abre o arquivo que representa o contêiner de destino configurado. Nesta amostra, o contêiner de destino configurado é um URI em vez de um arquivo; portanto, uma implementação ResourceTransform customizada denominada ResourceFromUriTransform e uma regra ResourceTargetRule customizada denominada ResourceFromUriTargetRule são incluídas na classe Uri4targetTransformationProvider.

A implementação customizada denominada ResourceFromUriTargetRule executa as seguintes etapas:
  • Cria o arquivo especificado pelo URI, se não existir
  • Abre o arquivo especificado pelo URI
  • Associa um recurso do modelo em memória com o arquivo e armazena o objeto do arquivo no contexto da transformação raiz, de forma que outras regras de transformação possa recuperá-lo
O fragmento de código a seguir mostra a implementação padrão do método createRootTransformation que a 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 implementação customizada do método denominado createRootTransformation contido na amostra:
    /**
     * 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 ResourceFromUriTransform(mainTransform)));
             }};
    }
    
O fragmento de código a seguir mostra as implementações customizadas denominadas ResourceFromUriTransform e ResourceFromUriTargetRule que a classe denominada Uri4targetTransformationProvider contém:
    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;
        }        
    }

Feedback