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

QVT Tutorial - 6

Each Edge needs to be transformed to a Transition. The Action to Event transformation is not a problem, however the sourceMode and targetMode are.
The sourceMode of the Transition is the Parent of the Edge (i.e. the Location), because the Location Class contains the Edges. The function "container()" returns the parent object, however as a general type. We have to add "oclAsType(Location)".

We are not yet finished, because we only have the Location that is the "source Location" of the Edge we are transforming.
According to the transformation of the Automaton (previous page), the Locations have already been transformed to Modes (but we've yet to implement this, see next page).
Because of this, we don't need to transform the obtained Location (the parent of the Edge). We just have to point to the already transformed version of this Location, the Mode. This is called resolving.

Summarized, when you have already transformed an object and later on there is a reference to that already transformed object, you have to resolve this reference.

There are a few types of resolving:
  • "resolve", which returns a list of target objects (i.e. when a source object would be transformed into multiple target objects)
  • "resolveone", this returns the first target object. In our case, the first also means the only one because each Location is only transformed to one Mode.
  • "resolveIn": like "resolve", but the source object was mapped to the target object(s) in a specific mapping.
  • "resolveoneIn": like "resolveone", also with a specific mapping.
However, what if we had chosen to transform the Edges first (instead of the Locations first)? The targetLocation of the Edge would of course still be a Location, but this Location wouldn't have been transformed yet. To anticipate, the keyword "late" can be added in front of a resolve command. QVT remembers these resolvings, and in the end of the transformation it uses the transformation trace to resolve the "late" resolvings.

An example of the Edge to Transition mapping looks like this:

mapping Edge::toTransition() : Transition {
 Event := self.Action;
 sourceMode := self.container().oclAsType(Location).resolveone(Mode);
 targetMode := self.targetLocation.resolveone(Mode); 

Again, both "self.container().oclAsType(Location)" and "self.targetLocation" return a Location, i.e. a source object. Earlier on, these objects have been transformed to Modes, the target objects. Because of this, we don't transform them again but resolve the reference by using resolve functions.

Instead of "targetMode := self.targetLocation.resolveone(Mode);" I could have used other resolvings which would yield the same result, but look more difficult:
  • targetMode := self.targetLocation.late resolveone(Mode);
  • targetMode := self.targetLocation.resolveoneIn(Location::toMode,Mode);
  • targetMode := self.targetLocation.resolve(Mode)->at(1);
Of course there are more combinations, like "late resolve" or "late resolveIn", etc.

It is also possible to inverse resolve, i.e. find the source object(s) which was/were transformed in the target object. To use these commands, simply prefix a resolving command with "inv".

I hope the idea behind resolving is a bit clear. If not, please send me an e-mail.
Let's continue with the toMode() mapping.