Our preceding example mapped an analysis model to a design model, but there are other scenarios for mappings and for mapping functions.
We've shown a mapping from an analysis to a design model that changes the level of abstraction at which things are expressed, because the design metamodel has additional language elements. We call such mappings refining mappings.
A refining mapping function may create everything needed by the target model, just as a compiler does with C++ or Java programs; in this case, the source model is complete in respect to this mapping function. There's no need to examine the target model before executing it or mapping it to the next more detailed model.
There are also scenarios where the mapping function is incomplete and it cannot construct everything needed in the target model. This can be overcome in one of two ways: Fill in the blanks in the target model, or associate additional input with the source model in a manner that doesn't pollute it. These techniques may be combined as well. (Chapter 8 discusses how to elaborate models in ways such as these.)
When we can't see the forest for the trees, it's helpful to abstract stuff away that doesn't add to our understanding of the model or source code. So we can be sure that the abstract view is in synch with the detailed model, we'd like to do it automatically with mappings. Such mappings are called abstracting mappings.
Besides providing abstract views on models, abstracting mappings come in handy when moving an existing model to a different platform. An abstracting mapping pulls the contents of the detailed model into a more abstract model whence it can be mapped to other more detailed models for other platforms.
Abstracting and refining mappings are vertical mappings, so named because they change the level of abstraction.
Sometimes a metamodel is not supported by readily available notations, and sometimes a plethora of metamodels each requires its own notation and tool support. In these cases, we can define a mapping to an existing metamodel for which notations and tool support exist. Such a mapping allows us to create models in one metamodel that stand for models in another metamodel. We call such mappings representing mappings.
Representing mappings are most useful when they're reversible. This means that whenever we change the representation, this change is reflected in the represented model, ideally in real time without substantial delay. The reverse is also true: A change in the represented model is reflected in the representation.
An example of a reversible representing mapping is the graphical notation of the UML itself. Any time you change the name label in a class shape of a UML class diagram, a representing mapping running in the background ensures that the name change is reflected in the underlying UML model in the repository. Conversely, if someone changes that class's name using the UML repository's programming interfaces, we'd want this name change to be reflected in all diagrams currently showing this class.
In some cases, porting existing models to other platforms using an abstracting mapping and a refining mapping isn't appropriate because the changes are not substantial. Think, for example, about a migration from one version of a data model to another. Lightweight migrating mapping functions can be defined to implement the necessary conversions.
These mappings reformat and regroup existing information to make it amenable to other mappings. Like representing mappings, they don't change the level of abstraction. To contrast these mappings from those that do change the level of abstraction, we call them horizontal mappings. Other examples of horizontal mappings are optimizations (typically to improve some computational quality like speed, small memory consumption, bandwidth, and so forth) and refactorings (typically to improve some "ility" such as maintainability, readability, and so forth).
If a mapping function weaves together aspects of multiple source models to combine them into a single target model, that mapping is called a merging mapping. Merging mappings create links between model elements from different models that don't make explicit reference to each other. Figure 5-1 illustrates the concept.
Figure 5-1. Merging mapping
This concept of weaving also appears in the programming language community in aspect-oriented programming. Each aspect is a cross-cutting concern, similar to a problem domain, and each aspect is woven together with others by defining a set of merging mappings. We describe how these mappings can be used to weave together Executable UML models in Chapter 9, and we illustrate the mappings in more detail in the next section.