A model compiler takes a set of marked Executable UML models and weaves them together according to a consistent set of rules, thus normalizing all of the models to a single common infrastructure. This task involves executing the mapping functions between the various source and target models to produce a single all-encompassing model repository that includes all of the structure, behavior, and logic everything in the system.
The final mappings from a model into code can be performed using archetypes, which are especially suited to manipulating text. The archetype-based approach is explained in Query, Views, and Transformations (QVT) in Chapter 5. It remains to be seen whether the adopted QVT standard will be sufficiently general to cover this special case of metamodel-to-text as well as metamodel-to-metamodel. If not, a new MDA standard will have to be proposed.
Whatever the standard proposes, archetype languages must be able to traverse the repository and generate text. The text can be anything at all, including natural language or graphic instructions, but most likely it will be text that can be compiled, such as Java, C++, VHDL, or COBOL.
Marks (see Chapter 6) may be used to provide for point optimization. A mapping function may be defined to provide a different implementation when a particular (marked) region of the model requires it. Moreover, marks can be used to direct the invocation of a mapping function that copies hand-written code, and so incorporate it when required.
A marking model defines a projection on a (source) metamodel. Archetypes and marks that operate on a combination of source models can then be written without any need to determine which archetypes to run, because the projection will have selected the correct model elements. Archetypes can also explicitly refer to the APIs for libraries or legacy code; this provides a way to incorporate these code elements into the overall MDA architecture.
In addition to mapping all of the source models, the model compiler must also incorporate elements required to execute the models, such as ways to store instances, generate calls and signals across task and processor boundaries, and traverse state machines. These elements, taken together, constitute an Executable UML execution engine targeted to a selected software platform. The execution engine is therefore an implementation of a virtual machine.
The overall scheme (without the additional complexities of marks) is shown in Figure 9-3.
Figure 9-3. Relation between application and model compiler
A model compiler imposes a single architectural structure on the system as a whole. Because each executable model is a PIM, and the model compiler compiles the models to make code, you might ask what happened to the PSM. The PSM is there alright it's the code. Code is a weaving together of the elements of the PIM and of the required platforms, and it executes, too. Using executable models, there's no need to manipulate the PSM or to visualize it as a model. We can go straight to the code, the Mother of All PSMs.