• No results found

3.2 The Simple Transformer

3.2.1 Capturing Rule and Transformation Dependencies

We have already discussed the initialisation and binding phases within M2M transformation engines. In SiTra the initialisation phase is synonymous to the buildmethod, and binding is the setProperties method; however the scheduling differs from more declarative engines as they are called explicitly rather than phased.

For instance, if EtoT were to iterate through a collection of attributes to generate columns then each of them would be transformed on demand. If one were to call a transformation, which was dependent on itself, its destination objects need to be available to the lower stack frames. The conversion of an Attribute, from an object orientated (OO) model, to a Column, from a relational database view, would require access to the newly transformed Table to set its owner. Without this, we would have an infinite loop. We illustrate this inter-rule dependency with our EtoT and AtoC rules shown in Figure 3.6. Both rules call upon each other to set references.

caller 0..1

Figure 3.7: A new meta-model for a traceable model transformation.

While exploring this, we also found that SiTra would only transform a source object once. SiTra uses a cache as not to repeat a transformation more than once.

This cache uses the source object as the key (s → r(s)). The map (r, s) → r(s) uses both the input and the rule as the key; this allowed us to request any transformation of a particular source given a rule with ease. A similar behaviour was found in ETL as well. Using the equivalent() method or ::= operator seemed to return the first item within the trace. It is possible to transform a source object using multiple rules, however, if the user requires the results from a rule defined later in the transformation script, they need to specify which.

The largest issue we have found within transformation traces is the verbosity of the trace itself. The tracking structure does not represent what happens during execution. The current state-of-the-art provides a chronological list of rules; we

never get to see the dependencies between those and invocations of them. ETL uses an equivalent structure as SiTra’s ITrace interface (Shah, Anastasakis, and Bordbar 2010), inferred from the QVT standard (Object Management Group, Inc.

2016a). In which is contained the map as described above. This tuple does not take into consideration the nested nature of a transformation, and only concerns the instantiation phase on the first run. It may also be important to see what calls the buildmethod and which have the object returned from the cache. Figure 3.7 shows the new transformation trace within SiTra. Here we have introduced new trace elements to aid in retaining structural information. Invocation is the equivalent of the previous ITrace; it contains the source, target and the rule responsible for the transformation. This object alone can provide the current state-of-the-art in traceability within rule-based engines. We have introduced two more types of trace-able elements within SiTra: a) NestedInvocation; and b) RecalledInvocation.

These provide more detail to the actual internals of the transformation. The former provides the same information as the standard, however, contains two more elements: a) the calling transformation trace element (if applicable); and b) the trace elements generated because of the current transformation. The latter is an indicator that the current execution required the results of a previously transformed set of sources. To maintain this list, and to reduce the effect on performance by traversing it, we amended the internal cache once more: (r, s) → (r(s), t) such that t ∈ T . Using this latest implementation, we can now see that a source element, s, and a rule, r, returns the target object r(s) and is referenced by the TraceableElement t. This map can be further simplified as the traceable element includes r(s): (r, s) → t.

Algorithm 1 demonstrates the execution of transforming an object within SiTra.

This process is a general algorithm allowing it to be used within a plethora of other transformation engines to retain structural information about its internal workings. The two phases, instantiation and binding, can be found at Line 12 and Line 20 respectively. Before either of these, we check the cache to see if the transformation has been completed already (lines 5-9). A cache hit is indicative of a recalled invocation. Likewise, lines 14-18 is where the first attempt of transforming a given set of sources by a rule and therefore is where they must be instantiated and then bound. In both cases, they depend on an execution stack to determine what invocation is dependent on another. The stack is pushed (Line 19) and popped (Line 21), before and after the binding phase (Line 20) as this method can induce recursion. The recursion of transformations will increase and decrease the size of the stack; however, the top will always be the invocation that is directly related to the current.

Our meta-model provides solutions to retain the order of execution of transfor-mation rules and the ability to recreate the transfortransfor-mation. This is provided by the nested nature of our meta-model as it explains what rules are completed and what invoked them. The capability to find the actual binding phase, opposed to a recollection, is provided by the new recalled invocation type. Allowing the user to recreate the situation at the time of creation. This recalled invocation aids in providing a graph of rule dependencies.