Tutorial | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Downloads

QVT Tutorial - 8

How should we transform the Update with the Variables to Modifications? An option would be transforming each Variable to a Modification because the "Urgent" property doesn't have to be transformed. The mapping call would look like "modifications := self.upates.variables-> map toModification();"
However, in more difficult transformations this might not be the case. Once again I will present two different ways to solve this problem.

The first: creating a mapping that returns a set of Modifications, while the input is a single Update object. This should be possible, however due to an unknown cause it doesn't work properly (it compiles, but the resulting objects are returned to the same level as "Model" instead of children of "Mode").
A (temporary) solution is to use a Query instead of a Mapping. Example:

-- Use "Modifications := ModificationsQuery(self.updates);" to call this Query

query ModificationsQuery( Updates: Update ) : OrderedSet(Modification) {
 var Modifications: OrderedSet(Modification);
 Updates.variables->forEach(Var) {
 Modifications += object Modification { VarName := Var.Name; VarType := Var.Type; };
 return Modifications;

The "forEach" construct loops through all Variable objects, and add them to the set of Modifications. You might think this is the same as the simple solution I provided above, but it isn't. In this query, more attributes can be added to a Modification object (for instance, if we wanted to transform the Urgent attribute).
I'm not sure about one thing: in the OMG specs in section, this is written about Helpers/Queries: "However it is illegal to create or update object instances within a helper operation - except for pre-defined types like sets, tuples and for intermediate properties."

As indicated, we could solve this problem in another way: intermediate classes and properties. My main idea was to create an extra class like "Update" in MMB, called IntermediateMod. Next, add an intermediate attribute to Mode, and map it.
With these intermediate things, the metamodel would look like this (only depicted the relevant part):

One thing to notice are the 0..* bounds w.r.t. the Modification (vars). In MMA, these bounds are 1..*, but as far as I know it is not possible to define a non-empty (ordered)Set?

The general idea works, however the resulting Modification-objects appear on the same level as "Model", instead of children of Mode?

intermediate class IntermediateMod {
 Urgent: Boolean;
 vars: OrderedSet(Modification);

intermediate property Mode::intermediateMods : IntermediateMod;

mapping Location::Updates() : Mode { 
 Name := self.Name;
 InitialState := self.IsInitial;
 --Modifications := ModificationsQuery(self.updates);
 intermediateMods := self.updates.map toIntermediateMod();

mapping Update::toIntermediateMod() : IntermediateMod {
 Urgent := self.Urgent;
 vars := self.variables->VarToMod();

mapping Variable::VarToMod() : Modification {
 VarName := self.Name;
 VarType := self.Type;

If somebody knows why this happens, or has other ideas how to handle this part of the transformation, please let me know!

Ok, the transformation is now finished. In the next part we're going to test it. Continue...