[SOLVED] Transforming an element twice (or more) [message #871059] |
Thu, 10 May 2012 17:12 |
|
Hello,
The ETL engine (and I guess all other model transformation engines) work on the principle that each element is transformed once. It can be transformed to many output elements, but each rule that has an input type of the same type of the element is only executed once for it. Is there any way that his can be changed so that the rule is executed twice (or more times?).
In my case, working with the eclipse uml metamodel, I have a class that has two elements of another class, lets say ClassA has cX and cY of type ClassB. Hence, ClassA has two owneAttributes that are typed with ClassB. If I do a transformation, lets say I have an output metamodel with a Block type and a block can have a nested Block, from Class to Block, I would like to have BlockA to have two nested blocks: BlockcY and BlockcX. However, if the rule is from Class to Block, ClassB only is transformed once. Hence,
rule Class2Block
transform c: Class
to b : Block {
...
b.block.addAll(c.ownedAttribute.collect(oa | oa.type).equivalent());
...
}
Will result in BlockA having only one nested block: BlockB.
If I change the approach and add a rule to transform an ownedAttribute to a block.
rule Class2Block
transform c: Class
to b : Block {
...
b.block.addAll(c.ownedAttribute.equivalent());
...
}
rule oA2Block
transform a : attribute
to b : Block {
...
b.port.addAll(a.type.ownedConnecter.equivalent());
}
This time BlockA will have two nested blocks: BlockcY and BlockcX. However, since the connectors are transformed from ClassB, only either BlockcY or BlockcX will have the equivalent ports (connectors are transformed once).
I have tried using the clone() method, but since cloned elements have the same xmi:id for the engine they are the same element and still only are transformed once. I have also tried using extended properties, but since ClassB can have additional nested classes and so on it comes a point where it is to complex to keep track of all the relations and equivalents and such.
After much thought it seems using eol to create the output elements would be the easier solution... but I just dislike the fact of doing model 2 model transformations with eol plus I loose the power of the equivalent(s) trace to "paste" realted elements.
Horacio Hoyos Rodriguez
Kinori Tech
Need professional support for Epsilon, EMF?
Go to: https://kinori.tech
[Updated on: Wed, 16 May 2012 15:09] Report message to a moderator
|
|
|
Re: Transforming an element twice (or more) [message #871324 is a reply to message #871059] |
Fri, 11 May 2012 23:37 |
|
Hello Horacio,
From reading the ETL source code, it appears that transformed elements are cached on a rule-by-rule basis. You could do something like this:
- Duplicate the connectors -> ports transformation as two lazy rules, named "Class2BlockConnectors" and "oA2BlockConnectors".
- In Class2Block, use .equivalents("Class2BlockConnectors") to transform the ports.
- In oA2Block, use .equivalents("oA2BlockConnectors") to transform the ports.
I haven't been able to test anything like this, though .
Cheers,
Antonio
[Updated on: Fri, 11 May 2012 23:37] Report message to a moderator
|
|
|
Re: Transforming an element twice (or more) [message #872278 is a reply to message #871324] |
Tue, 15 May 2012 20:26 |
|
Hello Antonio,
After some more testing I ended up with a duplication approach. However as stated earlier the clone() method is no good. I ended up using extended properties to make a copy of the elements I need to have transformed multiple times and use the equivalents with specific rule call.
The following code example is what i am doing in the case of ports (similar problem as the class/attribute I mentioned in the OP):
// Since a property references the Class in its type, we clone all the
// class attributes of interest so that they can be generated from
// transformations
var ports = new Set;
// Since he flow port may have been cloned previously, make sure that
// we only clone the correct flow ports.
var flowPorts = new Set(SysML!FlowPort);
for (a in property.type.ownedAttribute.select(oa | oa.isTypeOf(SysML!Port)))
{
flowPorts.add(SysML!FlowPort.all().selectOne(fp | fp.base_Port = a));
}
for (port in flowPorts)
{
var cp = new SysML!FlowPort;
cp.base_Port = port.base_Port;
//cp.isAtomic = port.isAtomic; // isAtomic is derived
cp.isConjugated = port.isConjugated;
cp.direction = port.direction;
cp.~partWithPort = property;
ports.add(cp);
}
property.~port = ports;
However this approach turns to be a bit overwhelming if you have to copy many elements and/or if the elements have a lot of properties.
Maybe one could have a @multiple annotation that would allow a @lazy rule to be executed multiple times. However I don't know if there is a universal model transformation restriction that goes against this.
Regards,
Horacio Hoyos Rodriguez
Kinori Tech
Need professional support for Epsilon, EMF?
Go to: https://kinori.tech
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.07823 seconds