Projetos de mapeamento de transformações de modelo em modelo, também chamados de projetos de mapeamento, são plug-ins do Eclipse que estendem o ponto de extensão denominado com.ibm.xtools.transform.core.transformationProviders. Ao criar transformações de modelo em modelo em projetos de mapeamento de transformação, você especifica como os elementos nos modelos selecionados de origem e destino, ou metamodelos, estão relacionados, em vez de criar um código que represente os detalhes de implementação da transformação.
Um projeto de mapeamento pode conter mais de um arquivo de mapeamento, que também é chamado de modelo de mapeamento. Você pode gerar iterativamente um código-fonte quando modificar o modelo de mapeamento. Quando você gera o código-fonte da transformação, uma transfiguração externamente visível, chamada MainTransform, é registrada automaticamente, e o código-fonte Java de uma transfiguração é gerado para cada declaração de mapeamento no modelo de mapeamento.
É possível especificar um ou mais metamodelos de origem e destino ao criar um projeto de mapeamento. É possível especificar metamodelos, que possuem .ecore como extensão de nome de arquivo, ou perfis UML, que possuem .epx ou .uml como extensão de nome de arquivo. Se você especificar metamodelos de origem e destino ao criar um projeto, as dependências necessárias serão incluídas no arquivo de manifesto de plug-ins automaticamente. Se você incluir os metamodelos utilizando os comandos na área do editor depois de criar o projeto de mapeamento, deverá incluir quaisquer novas dependências necessárias ao arquivo de manifesto de plug-ins.
Modelos de mapeamento, também chamados de arquivos de mapeamento, são instâncias de metamodelos Eclipse Modeling Framework (EMF), também chamados de modelos Ecore, que contêm referências aos metamodelos que estão sendo mapeados. Quando você cria um projeto de mapeamento, as ferramentas de criação cria um modelo de mapeamento no projeto utilizando um ou mais modelos de entrada e saída que forem especificados. Um projeto de mapeamento contém pelo menos um modelo de mapeamento. Um modelo de mapeamento tem .mapping como extensão de nome de arquivo. A criação de vários modelos de mapeamento em um projeto incentiva a reutilização de mapas em outros projetos de mapeamento. Essa funcionalidade é útil para soluções de mapeamento em grande escala, na qual existe vários modelos de mapeamento em diversos projetos de mapeamento.
Modelos de mapeamento são armazenados e serializados como arquivos XML. A visualização Problemas exibe informações de erro detalhadas sobre modelos de mapeamento. Nessa visualização, dê um clique duplo em um item para abrir o modelo de mapeamento em um editor de texto e visualize a linha que contém o erro. Esse método de resolução de problemas costuma ser mais fácil do que a resolução de problemas por meio da visualização do modelo de mapeamento na área do editor.
Uma declaração de mapeamento, também chamada de mapa, especifica como criar ou atualizar um objeto de saída para um determinado objeto de entrada. Cada declaração de mapeamento especifica um tipo de entrada e um tipo de saída, que você seleciona a partir dos metamodelos que inclui no modelo de mapeamento. Um modelo de mapeamento pode conter várias declarações de mapeamento.
A finalidade da criação de um mapa é designar valores a um destino, com base nos valores em uma origem. Um mapa entre elementos estabelece a correspondência entre seus atributos, o que permite a troca de dados entre eles. A maioria dos mapas oferece a capacidade de manipular ainda mais os dados entre a origem e o destino. Por exemplo, você pode optar por especificar cálculos ou fazer outras modificações nos dados criando um código customizado, que possibilita designar valores ao destino.
Declarações de mapeamento podem conter objetos de saída abstratos. Essas declarações de mapeamento podem apenas ser herdadas, estendidas ou referenciadas em uma regra de mapeamento de submapa cujo atributo de destino contenha uma propriedade de contenção definida como false. Esses atributos de destino podem ser preenchidos com referências a objetos que são criados por uma declaração de mapeamento que é herdada a partir da declaração de mapeamento especificada na regra de mapeamento de submapa. Você pode utilizar uma declaração de mapeamento que especifique um objeto de saída abstrato para simplificar a criação de referências de objeto.
Em geral, declarações de mapeamento seguem uma convenção de nomenclatura de x2y, em que x representa o tipo de objeto de entrada e y representa o tipo de objeto de saída. Por exemplo, uma declaração de mapeamento denominada Package2EPackage especifica uma declaração de mapeamento que possui Package como objeto de entrada e EPackage como objeto de saída.
Quando você gera o código-fonte da transformação, o serviço de transformação gera um arquivo de origem Java para cada declaração de mapeamento em um modelo de mapeamento, que implementa uma transformação.
Declarações de mapeamento contêm uma ou mais regras de mapeamento.
Declarações de mapeamento podem herdar de outras declarações de mapeamento. As declarações de mapeamento herdadas e hereditárias não precisam ser definidas no mesmo modelo de mapeamento. Os objetos de entrada e saída hereditários devem ser subtipos, mas não necessariamente subtipos característicos, dos objetos de entrada e saída na declaração de mapeamento herdada. A declaração de mapeamento hereditária herda todos os mapeamentos definidos na declaração de mapeamento herdada ou por ela herdados. As regras de mapeamento na declaração de mapeamento herdada se tornam parte da declaração de mapeamento hereditária; entretanto, você pode criar regras de mapeamento customizadas para substituir as que se encontram na declaração de mapeamento herdada. Você também pode criar regras de mapeamento adicionais na declaração de mapeamento hereditária. A transfiguração gerada a partir de uma declaração de mapeamento hereditária estende a transfiguração gerada a partir da declaração de mapeamento herdada.
Regras de mapeamento, também chamadas de mapeamentos, especificam como designar um valor a um atributo de um objeto de saída, de acordo com os valores dos atributos de um objeto de entrada.
Você também pode criar regras de mapeamento de submapas entre os objetos de entrada e os objetos de saída em uma declaração de mapeamento.
Para cada submapa em uma declaração de mapeamento, um extrator denominado getInputFeatureToOutputFeature_UsingMap_Extractor é gerado na transformação de inclusão, em que InputFeature representa o nome do atributo de entrada e OutputFeature representa o nome do atributo de saída, enquanto Map representa o nome da declaração de mapeamento.
Você pode especificar refinamentos semânticos utilizando a API Object Constraint Language (OCL) fornecida pelo Eclipse.
Uma regra de mapeamento herdada, e a regra ou o extrator gerado a partir desse mapeamento, mantêm a mesma posição relativa na ordem de processamento que a regra de mapeamento e sua regra ou seu extrator gerado.
Para cada regra de mapeamento de movimentação ou customizada em uma declaração de mapeamento, é incluída uma regra no código-fonte de transformação gerado. Para cada regra de mapeamento de submapa, é gerado um extrator de conteúdo no código-fonte da transformação.
Quando você cria uma regra de mapeamento, seu tipo é determinado pelos atributos de entrada e saída que são selecionados. Por exemplo, se os atributos de entrada e saída forem tipos primitivos compatíveis, como cadeias ou inteiros, uma regra de mapeamento de movimentação será especificada. Se os atributos de entrada e saída forem tipos complexos, uma regra de submapa será especificada. Se movimentação e submapa não forem tipos de regras de mapeamento apropriados, uma regra de mapeamento customizada será especificada.
Você também pode criar uma regra de mapeamento de mapas herdada, customizada ou de submapa entre um objeto de entrada e um objeto de saída.
As características de objetos de saída e as propriedades de contenção de atributos em um objeto de saída determinam o comportamento das regras de mapeamento de submapa.
| Item | Representação |
|---|---|
| InputFeature | O compartimento no objeto de entrada que é conectado ao elemento de submapa |
| OutputFeature | O compartimento no objeto de saída que é conectado ao elemento de submapa |
| Map | A declaração de mapeamento que o submapa aplica quando a transfiguração gerada é executada |
| InputElement | O objeto de entrada especificado pela declaração de mapeamento Map |
| OutputElement | O objeto de saída especificado pela declaração de mapeamento Map |
Quando você gerar o código-fonte de transformação para um modelo de mapeamento, para cada declaração de mapeamento, as ferramentas de criação irão gerar uma transfiguração denominada MapTransform. Para cada submapa em uma declaração de mapeamento, as ferramentas de criação geram um extrator de conteúdo denominado getInputFeatureToOutputFeature_UsingMap_Extractor na transformação.
Quando uma transformação de modelo em modelo é executada, ela gera outros objetos ou referências aos objetos gerados, dependendo das configurações de recursos nesse metamodelo. Se a transformação gerar objetos, ela registrará informações de identificação sobre esses objetos em um mapa de hash. A transformação resolve referências em objetos durante o pós-processamento com base nesse mapa de hash.
O elemento de metamodelo Ecore ou UML que você especifica como objeto de saída em uma declaração de mapeamento pode ser abstrato ou concreto. É possível instanciar elementos concretos, mas não elementos abstratos.
Os recursos, também conhecidos como atributos, de um objeto de saída podem conter outros objetos Ecore ou UML ou podem fazer referência e esses objetos. Se um objeto contiver outro objeto, o objeto contido será excluído quando o objeto de inclusão for excluído. Se um objeto fizer referência a outro objeto, a exclusão da referência ou a exclusão do proprietário dessa referência não irá excluir o objeto referenciado.
A tabela a seguir lista o comportamento das regras de mapeamento de submapa, dependendo das características do objeto de saída e dos atributos de saída.
| Tipo de objeto de saída | Tipo de contenção ou referência no atributo de saída | Comportamento do submapa |
|---|---|---|
| Abstrato | Contenção abstrata ou concreta | Esse tipo de submapa não é suportado porque a transfiguração MapTransform não pode criar objetos e, portanto, não pode inserir objetos na coleta OutputFeature. |
| Abstrato ou concreto | Referência abstrata ou concreta | Após o processamento de todas as outras regras e extratores, a transformação processa esse tipo de submapa concluindo as etapas a seguir:
|
| Concreto | Contenção abstrata ou concreta | Para cada objeto InputItem na coleta InputFeature, a transformação conclui as seguintes etapas:
|
O exemplo a seguir explica como uma transformação resolve referências para objetos de saída durante o pós-processamento.
Essa declaração de mapeamento define uma regra de mapeamento de mapas herdada entre o objeto de entrada e o objeto de saída. A regra de mapeamento especifica que essa declaração de mapeamento herda da declaração de mapeamento Classifier2Classifier.
public class Class2ClassTransform extends Classifier2ClassifierTransform {
...
}
Como um classificador é um tipo abstrato, a transfiguração Classifier2ClassifierTransform não pode criar objetos. Entretanto, a transfiguração Class2ClassTransform pode criar objetos, mesmo que uma classe herde a partir de um classificador.
Se você executar a transformação em um modelo de origem que contém uma classe de entrada ClassA, a transfiguração Class2ClassTransform irá gerar uma classe de saída ClassB. Para registrar a criação de ClassB, a transfiguração Class2ClassTransform cria um registro de mapa de hash cuja chave é igual a (Class2ClassTransform+ClassA->ClassB).
Se a transformação procurar no mapa de hash um registro cuja chave seja igual a (Classifier2ClassifierTransform+ClassA), o registro cuja chave for igual a (Class2ClassTransform+ClassA) será retornado nos resultados da procura, uma vez que a transfiguração Class2ClassTransform herda a partir da transfiguração Classifier2ClassifierTransform.
Por exemplo, considere um modelo de mapeamento OriginalMappingModel que contém uma declaração de mapeamento Package2Package. O objeto de entrada na declaração de mapeamento está em um metamodelo de entrada denominado MyPackageDefinition, enquanto o objeto de saída na declaração de mapeamento pertence a um metamodelo de saída denominado MyOtherPackageDefinition. A declaração de mapeamento contém uma regra de mapeamento de movimentação que conecta dois atributos de Cadeia, ambos denominados PackageName. Se o URI do metamodelo MyPackageDefinition for alterado, a regra de mapeamento Package2Package se tornará inválida. Da próxima vez que você abrir o modelo de mapeamento, a visualização Problemas exibirá mensagens de erro e, na área do editor de mapeamentos, uma indicação de erro aparecerá na declaração de mapeamento inválida. É necessário especificar um objeto de entrada correto e determinar como o editor de mapeamentos deve refatorar as regras de mapeamento existentes.
Depois de refatorar as regras de mapeamento, você poderá continuar a refinar o modelo de mapeamento e gerar novamente o código de transformação.
Se você planeja fundir a saída da transformação em um modelo existente, é necessário que o metamodelo de destino declare uma extensão de tipo de conteúdo CompareMerge. Se a saída da transformação for um modelo UML, a extensão do tipo de conteúdo será definida por padrão, e você não precisará configurar o suporte a fusões. Se o metamodelo do modelo de destino não declarar uma extensão CompareMerge, a transformação irá sobrescrever o modelo de destino.
Quando o código de transformação é gerado, a tag @generated é incluída nos comentários de elementos Java, como classes, atributos e operações. A tag informa o gerador do código que um elemento de código específico está sob o seu controle, o que permite ao gerador do código atualizar o código referente ao elemento Java no caso de ocorrerem alterações no modelo de mapeamento. Você pode modificar e estender o código de transformação editando ou removendo a tag @generated do elemento Java que deseja alterar.