Model-to-model transformation mapping projects, also called mapping projects, are Eclipse plug-ins that extend the extension point named com.ibm.xtools.transform.core.transformationProviders. By creating model-to-model transformations in transformation mapping projects, you can specify how elements in the selected source and target models, or metamodels, are related, instead of creating code that represents the implementation details of the transformation.
A mapping project can contain more than one mapping file, which is also called a mapping model. You can iteratively generate transformation source code when you modify the mapping model. When you generate the transformation source code, one externally visible transform, called MainTransform, is registered automatically, and the Java source code for a transform is generated for each mapping declaration in the mapping model.
You can specify one or more source and target metamodels when you create a mapping project. You can specify metamodels, which have .ecore as a file name extension, or UML profiles, which have .epx or .uml as a file name extension. If you specify source and target metamodels when you create a project, the necessary dependencies are added to the plug-in manifest file automatically. If you add the metamodels by using the commands in the editor area after you create the mapping project, you must add any new required dependencies to the plug-in manifest file.
Mapping models, also called mapping files, are instances of Eclipse Modeling Framework (EMF) metamodels, also called Ecore models, that contain references to the metamodels that are being mapped. When you create a mapping project, the authoring tools create a mapping model in the project by using the input and output model or models that you specify. A mapping project contains at least one mapping model. A mapping model has .mapping as a file name extension. Creating multiple mapping models in a project encourages the reuse of maps in other mapping projects. This functionality is useful for large-scale mapping solutions, where multiple mapping models exist in multiple mapping projects.
Mapping models are stored and serialized as XML files. The Problems view displays detailed error information about mapping models. In this view, double-click an item to open the mapping model in a text editor and view the line that contains the error. This method of troubleshooting is often easier than troubleshooting by viewing the mapping model in the editor area.
A mapping declaration, also called a map, specifies how to create or update an output object for a given input object. Each mapping declaration specifies an input type and an output type, which you select from the metamodels that you add to the mapping model. A mapping model can contain multiple mapping declarations.
The purpose of creating a map is to assign values to a target, based on the values in a source. A map between elements establishes the correspondence between their attributes, which permits the exchange of data between them. Most maps provide the ability to further manipulate the data between the source and target. For example, you might choose to specify calculations or make other modifications to the data by creating custom code, which enables you to assign values to the target.
Mapping declarations can contain abstract output objects. Such mapping declarations can only be inherited, extended, or referenced in a submap mapping rule whose target attribute contains a containment property that is set to false. Such target attributes might be populated with references to objects that are created by a mapping declaration that inherits from the mapping declaration that is specified in the submap mapping rule. You might use a mapping declaration that specifies an abstract output object to simplify the creation of object references.
Mapping declarations typically follow a naming convention of x2y, where x represents the input object type and y represents the output object type. For example, a mapping declaration named Package2EPackage specifies a mapping declaration that has Package as an input object, and EPackage as an output object.
When you generate the transformation source code, the transformation service generates a Java source file for each mapping declaration in a mapping model, which implements a transform.
Mapping declarations contain one or more mapping rules.
Mapping declarations can inherit from other mapping declarations. The inherited and inheriting mapping declarations do not have to be defined in the same mapping model. The inheriting input and output objects must be subtypes, but not necessarily proper subtypes, of the input and output objects in the inherited mapping declaration. The inheriting mapping declaration inherits all the mappings defined in, or inherited by, the inherited mapping declaration. The mapping rules in the inherited mapping declaration become part of the inheriting mapping declaration; however, you can create custom mapping rules to override those in the inherited mapping declaration. You can also create additional mapping rules in the inheriting mapping declaration. The transform that is generated from an inheriting mapping declaration extends the transform that is generated from the inherited mapping declaration.
Mapping rules, also called mappings, specify how to assign a value to an attribute of an output object, according to the values of the attributes of an input object.
You can also create submap mapping rules between the input objects and output objects in a mapping declaration.
For each submap in a mapping declaration, an extractor named getInputFeatureToOutputFeature_UsingMap_Extractor is generated in the containing transform, where InputFeature represents the name of the input attribute, OutputFeature represents the name of the output attribute, and Map represents the name of the mapping declaration.
You can specify semantic refinements by using the Object Constraint Language (OCL) API that Eclipse provides.
An inherited mapping rule, and the rule or extractor generated from that mapping, maintains the same relative position in the processing order as the overridden mapping rule and its generated rule or extractor.
For each move or custom mapping rule in a mapping declaration, a rule is added to the generated transformation source code. For each submap mapping rule, a content extractor is generated in the transformation source code.
When you create a mapping rule, its type is determined by the input and output attributes that you select. For example, if the input and output attributes are compatible primitive types, such as strings or integers, a move mapping rule is specified. If the input and output attributes are complex types, a submap rule is specified. If neither move nor submap are appropriate mapping rule types, a custom mapping rule is specified.
You can also create a submap, custom, or inherited maps mapping rule between an input object and an output object.
The characteristics of output objects and the containment properties of attributes in an output object determine the behavior of submap mapping rules.
| Item | Representation |
|---|---|
| InputFeature | The compartment in the input object that is connected to the submap element |
| OutputFeature | The compartment in the output object that is connected to the submap element |
| Map | The mapping declaration that the submap applies when the generated transform runs |
| InputElement | The input object that the Map mapping declaration specifies |
| OutputElement | The output object that the Map mapping declaration specifies |
When you generate transformation source code for a mapping model, for each mapping declaration, the authoring tools generate a transform named MapTransform. For each submap in a mapping declaration, the authoring tools generate a content extractor named getInputFeatureToOutputFeature_UsingMap_Extractor in the transform.
When a model-to-model transformation runs, it generates either objects or references to generated objects, depending on the feature settings in the metamodel. If the transformation generates objects, it records identifying information about those objects in a hash map. The transformation resolves references to objects during post-processing, based on the hash map.
The Ecore or UML metamodel element that you specify as the output object in a mapping declaration can be abstract or concrete. You can instantiate concrete elements, but not abstract elements.
The features, also known as attributes, of an output object can contain or refer to other Ecore or UML objects. If an object contains another object, the contained object is deleted when the containing object is deleted. If an object references another object, deleting the reference or deleting the owner of the reference does not delete the referenced object.
The following table lists the behavior of submap mapping rules depending on the characteristics of the output object and output attributes.
| Type of output object | Type of containment or reference in the output attribute | Submap behavior |
|---|---|---|
| Abstract | Abstract or concrete containment | This type of submap is not supported because the MapTransform transform cannot create objects and, therefore, cannot insert objects into the OutputFeature collection. |
| Abstract or concrete | Abstract or concrete reference | After processing all other rules and extractors,
the transformation processes this type of submap by completing the
following steps:
|
| Concrete | Abstract or concrete containment | For each object InputItem in
the InputFeature collection, the transformation
completes the following steps:
|
The following example explains how a transformation resolves references to output objects during post-processing.
This mapping declaration defines an inherited maps mapping rule between the input and output object. The mapping rule specifies that this mapping declaration inherits from the Classifier2Classifier mapping declaration.
public class Class2ClassTransform extends Classifier2ClassifierTransform {
...
}
Because a classifier is an abstract type, the Classifier2ClassifierTransform transform cannot create objects. However, the Class2ClassTransform transform can create objects, even though a class inherits from a classifier.
If you run the transformation on a source model that contains an input class named ClassA, the Class2ClassTransform transform generates an output class named ClassB. To record the creation of ClassB, the Class2ClassTransform transform creates a hash map record whose key equals (Class2ClassTransform+ClassA->ClassB).
If the transformation searches the hash map for a record whose key equals (Classifier2ClassifierTransform+ClassA), the record whose key equals (Class2ClassTransform+ClassA) is returned in the search results because the Class2ClassTransform transform inherits from the Classifier2ClassifierTransform transform.
For example, consider a mapping model called OriginalMappingModel that contains a mapping declaration called Package2Package. The input object in the mapping declaration is in an input metamodel called MyPackageDefinition, and the output object in the mapping declaration belongs to an output metamodel called MyOtherPackageDefinition. The mapping declaration contains a move mapping rule that connects two String attributes that are both called PackageName. If the URI of the MyPackageDefinition metamodel changes, the Package2Package mapping rule becomes invalid. The next time that you open the mapping model, the Problems view displays error messages, and in the mapping editor area, an error adornment is displayed on the invalid mapping declaration. You must specify a correct input object and specify how the mapping editor should refactor the existing mapping rules.
After you refactor the mapping rules, you can continue to refine the mapping model and regenerate transformation code.
If you plan to merge the transformation output into an existing model, the target metamodel must declare a CompareMerge content type extension. If the transformation output is a UML model, the content type extension is defined by default, and you do not have to configure merge support. If the metamodel of the target model does not declare a CompareMerge extension, the transformation overwrites the target model.
When you generate transformation code, the @generated tag is added to the comments of Java elements such as classes, attributes, and operations. The tag informs the code generator that a specific code element is under its control, which enables the code generator to update the code for the Java element if changes occur to the mapping model. You can modify and extend the transformation code by editing or removing the @generated tag of the Java element that you want to change.