An interesting feature in QVT Operational Mapping language (QVTo) is mapping reuse. Differently from QVT Relations (QVTr), the QVTo language has some concepts that allow reusing mappings easily, and, more importantly, in an organized way. One of these concepts is mapping inheritance.
When I first saw this concept, I expected (or hoped) it would allow specializing an existing mapping similar to what happens in a object-oriented language – maybe because I am an OO programmer/designer. To my frustration, it does not… Moreover, I think it has a strange semantics that is more similar to an “include”. Yet, a truly “inheritance” can be an interesting and useful concept to allow mapping reuse in QVTo.
Before discussing what I think would be a more interesting semantics, let me explain how it works in QVTo. When a mapping
x inherits a mapping
y, the version 1.1 of the standard specifies (in page 75) that:
xinitialization section (init) is invoked – including its implicit instantiation section;
- the mapping
yis fully executed; and
- the rest of mapping
The parameters in
x must comply to the parameters in
y (just as the parameters of a caller and a callee must comply). Graphically, what happens is:
(I used the same representation used by this presentation.)
So, an inheritance is just calling a mapping after the init section? Well… yes. But there is more. What happens if the “when” (or “where”) section in the inherited mapping does not hold? Well, I don’t know… I did not find any explanation of the expected behavior in the specification. Nevertheless, if this happens using the Eclipse QVTo implementation, the inherited mapping (
y, in the example) does not execute, but the mapping (
x, in the example) is executed (what can be very confusing). In my opinion, the specified semantics makes it more similar to an “include”, instead of an inheritance – especially as the inherited mapping might not be executed in Eclipse QVTo semantics.
When a mapping inherits another mapping, I would expect it behaves like a specialization of the parent mapping. In other words, the mapping would behave as the parent mapping, but with additional constraints – thus, it would be a special case of the original mapping. A possible semantics could be:
- The “when” and “where” constraints of the parent should apply to the mapping itself.
- The “init”, “population”, and “end” sections should be executed first in the parent mapping and then in the mapping.
- Regarding to the “init” section, the mapping could “redefine” an initialization made by the parent. Therefore, the parent’s initialization for some elements would not be executed. This would avoid creating objects in the parent mapping that would be not used by the mapping.
Graphically, this means (notice I’ve inverted the order of the mappings in the diagram):
(The order of the calls is represented by the numbers in the circles.)
There are probably some details to be corrected in the proposed semantics, or some other improvements to make it more useful (for instance, maybe it would be interesting to allow a redefinition of other sections). Anyhow, I think this semantics would make much more sense, and would allow specializing a mapping. The current semantics could be used as an “include” relationship.
As usual, if you have a different opinion – or if you have a suggestion – please comment. I would be happy to discuss this idea.