Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Archived » M2M (model-to-model transformation) » [QVTo] 1-to-* transformation does only result in one deeper transformationtree(Transforming one element to many (e.g. two) others let to only on of the resulting items generated with deeper transformation logic)
[QVTo] 1-to-* transformation does only result in one deeper transformationtree [message #538672] Tue, 08 June 2010 11:52 Go to next message
C. Kopf is currently offline C. Kopf
Messages: 37
Registered: November 2009
Member
Hi everybody.

I got the following issue:

Doing my one-to-many transformation, as shown below, all eof the "many" elements are generated, but somehow only for one of them a deeper transformation is done.

Description:
I want to map a single SRInterface to two MessagePortTypes. Both of these MessagePortTypes shall have the same ComSpec and so on (this will be changed later on, but now it is necessary).
Runing the script with the code below, the result is that for each SRInterface two MessagePortTypes are generated but only one of them has ComSpecs at all (the one with isProvided=false).
I expect this maybe is some trouble with tracing objects or so on. Does anybody see what I made wrong or got any idea how to solve the issue?

Thanks a lot!

Chris




mapping AUTOSARGenIA::ARPackage::arpackage2module() : Module {
-- ...
self.elements[SenderReceiverInterface]->forEach(SRInterface) {declarations += generateMessagePortTypes(SRInterface)->asOrderedSet()};
--...
}

query generateMessagePortTypes(in interface:AUTOSARSwcPorti::SenderReceiverInterface) : Set(MessagePortType){
	var resultPorts:Set(MessagePortType);
	resultPorts += interface.map senderReceiverInterface2messagePortType(true);
	resultPorts += interface.map senderReceiverInterface2messagePortType(false);
	return resultPorts;
}

mapping AUTOSARSwcPorti::SenderReceiverInterface::senderReceiverInterface2messagePortType(in isProvided:Boolean) : MessagePortType{
	var direction:String;
	if (isProvided)
		then direction := "OUT"
		else direction := "IN"
		endif;
	name := self.shortName+direction;
	comSpec := self.dataElements.map dataElementProtoType2messageAndStreamComSpec()->asOrderedSet();
}

mapping DataElementPrototype::dataElementProtoType2messageAndStreamComSpec() : MessageAndStreamComSpec
	{
	var foundtype:TTCN3::PrimitiveType := getPrimitiveType(self.type.repr()); 
	types := foundtype;
}

-- and so on ...
Re: [QVTo] 1-to-* transformation does only result in one deeper transformationtree [message #538698 is a reply to message #538672] Tue, 08 June 2010 12:52 Go to previous messageGo to next message
C. Kopf is currently offline C. Kopf
Messages: 37
Registered: November 2009
Member
Dennis Hendriks [dhendriksREMOVE_THIS@tueremove.this.nl] wrote:

Quote:

> resultPorts += interface.map
> senderReceiverInterface2messagePortType(true);
> resultPorts += interface.map
> senderReceiverInterface2messagePortType(false);

You map twice using senderReceiverInterface2messagePortType on the same object, but with different parameters. Therefore, two target objects are created. However, in the body of senderReceiverInterface2messagePortType, you do this:

> comSpec := self.dataElements.map
> dataElementProtoType2messageAndStreamComSpec()->asOrderedSet();

You apply a parameterless mapping to the self.dataElements. You will end up doing this twice. The first time you do it, a new object is created.
The second time you apply the same mapping to the same object, you get (because of tracing) the same element back. Since you can only have the same target element contained once, only one of them will have that element.

I think the last one always gets it. I assume this is because the parent attribute is set upon containment assignment. The second time you assign the same element, the parent is overwritten. Therefore, the last one 'sticks'. But this is just guessing.

A solution would be to do this:

comSpec := self.dataElements.map
dataElementProtoType2messageAndStreamComSpec()
.deepclone().oclAsType(???)->asOrderedSet();

This way you assign unique copies. (I didn't really know what type to cast it to.)

Note however, that if you deepclone them always, the original uncloned one is not contained anywhere, so it ends up a root target object. I got around this by filtering the output model extend root objects as the last thing in the main function. I remove everything that is not of the type of the top level class. It seems like hacking to me, and I would really like a better way to do this, but I haven't found one...

Dennis



Thanks Dennis,

you helped me a lot.
I expected something like this. I will try out the workaround with the deepclone()-methode soon. A filtering of the poutput model is needed due to a lot of conditions, so this is done anyway in my case. As a last question: How do you filter your output models? (I did not yet focus on it).

Thanks a lot!

Cheers

Chris
Re: [QVTo] 1-to-* transformation does only result in one deeper transformationtree [message #538703 is a reply to message #538672] Tue, 08 June 2010 12:43 Go to previous messageGo to next message
Eclipse User
Originally posted by: dhendriksREMOVE_THIS.tueREMOVE.THIS.nl

> resultPorts += interface.map
> senderReceiverInterface2messagePortType(true);
> resultPorts += interface.map
> senderReceiverInterface2messagePortType(false);

You map twice using senderReceiverInterface2messagePortType on the same
object, but with different parameters. Therefore, two target objects are
created. However, in the body of
senderReceiverInterface2messagePortType, you do this:

> comSpec := self.dataElements.map
> dataElementProtoType2messageAndStreamComSpec()->asOrderedSet();

You apply a parameterless mapping to the self.dataElements. You will end
up doing this twice. The first time you do it, a new object is created.
The second time you apply the same mapping to the same object, you get
(because of tracing) the same element back. Since you can only have the
same target element contained once, only one of them will have that element.

I think the last one always gets it. I assume this is because the parent
attribute is set upon containment assignment. The second time you assign
the same element, the parent is overwritten. Therefore, the last one
'sticks'. But this is just guessing.

A solution would be to do this:

comSpec := self.dataElements.map
dataElementProtoType2messageAndStreamComSpec()
.deepclone().oclAsType(???)->asOrderedSet();

This way you assign unique copies. (I didn't really know what type to
cast it to.)

Note however, that if you deepclone them always, the original uncloned
one is not contained anywhere, so it ends up a root target object. I got
around this by filtering the output model extend root objects as the
last thing in the main function. I remove everything that is not of the
type of the top level class. It seems like hacking to me, and I would
really like a better way to do this, but I haven't found one...

Dennis



C. Kopf wrote:
> Hi everybody.
>
> I got the following issue:
>
> Doing my one-to-many transformation, as shown below, all eof the "many"
> elements are generated, but somehow only for one of them a deeper
> transformation is done.
>
> Description:
> I want to map a single SRInterface to two MessagePortTypes. Both of
> these MessagePortTypes shall have the same ComSpec and so on (this will
> be changed later on, but now it is necessary).
> Runing the script with the code below, the result is that for each
> SRInterface two MessagePortTypes are generated but only one of them has
> ComSpecs at all (the one with isProvided=false).
> I expect this maybe is some trouble with tracing objects or so on. Does
> anybody see what I made wrong or got any idea how to solve the issue?
>
> Thanks a lot!
>
> Chris
>
>
>
>
>
> mapping AUTOSARGenIA::ARPackage::arpackage2module() : Module {
> -- ...
> self.elements[SenderReceiverInterface]->forEach(SRInterface)
> {declarations += generateMessagePortTypes(SRInterface)->asOrderedSet()};
> --...
> }
>
> query generateMessagePortTypes(in
> interface:AUTOSARSwcPorti::SenderReceiverInterface) : Set(MessagePortType){
> var resultPorts:Set(MessagePortType);
> resultPorts += interface.map
> senderReceiverInterface2messagePortType(true);
> resultPorts += interface.map
> senderReceiverInterface2messagePortType(false);
> return resultPorts;
> }
>
> mapping
> AUTOSARSwcPorti::SenderReceiverInterface::senderReceiverInte rface2messagePortType(in
> isProvided:Boolean) : MessagePortType{
> var direction:String;
> if (isProvided)
> then direction := "OUT"
> else direction := "IN"
> endif;
> name := self.shortName+direction;
> comSpec := self.dataElements.map
> dataElementProtoType2messageAndStreamComSpec()->asOrderedSet();
> }
>
> mapping
> DataElementPrototype::dataElementProtoType2messageAndStreamC omSpec() :
> MessageAndStreamComSpec
> {
> var foundtype:TTCN3::PrimitiveType :=
> getPrimitiveType(self.type.repr()); types := foundtype;
> }
>
> -- and so on ...
>
Re: [QVTo] 1-to-* transformation does only result in one deeper transformationtree [message #538741 is a reply to message #538698] Tue, 08 June 2010 14:16 Go to previous messageGo to next message
Eclipse User
Originally posted by: dhendriksREMOVE_THIS.tueREMOVE.THIS.nl

> as a last question: How do you filter your output models? (I did not
> yet focus on it).

I have a helper (cif_helpers.qvto) which looks like this:

modeltype mm_annotations "strict" uses 
'http://cif.tue.nl/cif-2.1.1/annotations';
modeltype mm_cif "strict" uses 'http://cif.tue.nl/cif-2.1.1';
modeltype mm_expressions "strict" uses 
'http://cif.tue.nl/cif-2.1.1/expressions';
modeltype mm_types "strict" uses 'http://cif.tue.nl/cif-2.1.1/types';

library cif_helpers;

// Enable this property to enable to debug output.
property DEBUG: Boolean = false;

// Removes all root objects from an (output) model, except for 
specifications,
// and asserts that there is exactly one root object left.
helper Stdlib::Model::cleanOutput()
{
     if DEBUG then log('DEBUG: Root object count:', 
self.rootObjects()->size())
     endif;

     // Remove all root objects that are not cif specifications.
     self.rootObjects()->select(ro | not ro.oclIsTypeOf(Specification))
                       ->forEach(ro)
     {
         if DEBUG then log('DEBUG: Removing root object:', ro) endif;
         self.removeElement(ro);
     };

     if DEBUG then log('DEBUG: Root object count:', 
self.rootObjects()->size())
     endif;

     // Make sure we have exactly one root object.
     assert fatal (self.rootObjects()->size() = 1);
}



then in my transformation I have:

import logging;
import cifcopy;
import cif_helpers;

modeltype (...)
(...)
transformation initpreds(in inModel : mm_cif, out outModel : mm_cif)
     extends transformation cifcopy(in mm_cif, out mm_cif)
     extends logging
     access cif_helpers;

main() {
     inModel.rootObjects()[Specification]->xmap transSpecification();
     outModel.cleanOutput();
}

(...)


Hope this helps.

Dennis


C. Kopf wrote:
> Dennis Hendriks [mailto:dhendriksREMOVE_THIS@tueremove.this.nl] wrote:
>
> Quote:
>> > resultPorts += interface.map
>> > senderReceiverInterface2messagePortType(true);
>> > resultPorts += interface.map
>> > senderReceiverInterface2messagePortType(false);
>>
>> You map twice using senderReceiverInterface2messagePortType on the
>> same object, but with different parameters. Therefore, two target
>> objects are created. However, in the body of
>> senderReceiverInterface2messagePortType, you do this:
>>
>> > comSpec := self.dataElements.map
>> > dataElementProtoType2messageAndStreamComSpec()->asOrderedSet();
>>
>> You apply a parameterless mapping to the self.dataElements. You will
>> end up doing this twice. The first time you do it, a new object is
>> created. The second time you apply the same mapping to the same
>> object, you get (because of tracing) the same element back. Since you
>> can only have the same target element contained once, only one of them
>> will have that element.
>>
>> I think the last one always gets it. I assume this is because the
>> parent attribute is set upon containment assignment. The second time
>> you assign the same element, the parent is overwritten. Therefore, the
>> last one 'sticks'. But this is just guessing.
>>
>> A solution would be to do this:
>>
>> comSpec := self.dataElements.map
>> dataElementProtoType2messageAndStreamComSpec()
>> .deepclone().oclAsType(???)->asOrderedSet();
>>
>> This way you assign unique copies. (I didn't really know what type to
>> cast it to.)
>>
>> Note however, that if you deepclone them always, the original uncloned
>> one is not contained anywhere, so it ends up a root target object. I
>> got around this by filtering the output model extend root objects as
>> the last thing in the main function. I remove everything that is not
>> of the type of the top level class. It seems like hacking to me, and I
>> would really like a better way to do this, but I haven't found one...
>>
>> Dennis
>
>
> Thanks Dennis,
>
> you helped me a lot.
> I expected something like this. I will try out the workaround with the
> deepclone()-methode soon. A filtering of the poutput model is needed due
> to a lot of conditions, so this is done anyway in my case. As a last
> question: How do you filter your output models? (I did not yet focus on
> it).
>
> Thanks a lot!
>
> Cheers
>
> Chris
>
Re: [QVTo] 1-to-* transformation does only result in one deeper transformationtree [message #538750 is a reply to message #538672] Tue, 08 June 2010 14:37 Go to previous message
C. Kopf is currently offline C. Kopf
Messages: 37
Registered: November 2009
Member
Wow, thanks a lot Dennis,

good idea to use a debug property, I will do so too.

My filter will be somewhat more complex, but that is not a big deal at all.

Doing it in a helper-library is much better than my way (i used to do it 'hard-wired' in the main) thanks a lot, you gave me several ideas how to improve my transformation script.

Thanks and greetings


Chris
Previous Topic:[ATL] one to many Transformation
Next Topic:Unique Matched Rule !
Goto Forum:
  


Current Time: Tue Sep 16 11:41:37 GMT 2014

Powered by FUDForum. Page generated in 0.74701 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software