Home » Archived » M2M (model-to-model transformation) » [QVTo] How to attach intermediate data that is valid only within the scope of a mapping?
[QVTo] How to attach intermediate data that is valid only within the scope of a mapping? [message #550054] |
Wed, 28 July 2010 23:02 |
Ryan Messages: 74 Registered: July 2009 Location: Indiana |
Member |
|
|
The title is the best I could come up with, but I've got a transform that I'm not quite sure how to approach.
Example first model (also not sure of best way to represent model):
Class Color
-attribute red (int)
-attribute green (int)
-attribute blue (int)
Class Item
-attribute itemName (String)
-reference itemColor (type Color)
and the second model is
Class Pair:
-attribute name (String)
-attribute value (String)
And example instance of model 1 would be
Color Red (255,0,0)
Color Green (0, 255, 0)
Item GreenApple (with reference to Green)
Item RedApple (with reference to Red)
Item Cherry (with reference to Red)
and the transform would be
name value
color[0].red 255
color[0].green 0
color[0].blue 0
color[1].red 0
color[1].green 255
color[1].blue 0
item[0].name RedApple
item[0].color 0
item[1].name GreenApple
item[1].color 1
item[2].name Cherry
item[2].color 0
So as I iterate over the items, I'll map the color (which i assume I'll need a variable to hold the index I'm at), but I don't want to map red twice, so I want to be able the next time I see red, to just get the index, and not map it to color[2]. I know the string string model is not very good, but that's what I've got to generate. I don't know enough about QVTO and it may be something I just end up coding in Java.
Thanks,
Ryan
[Updated on: Fri, 30 July 2010 20:14] Report message to a moderator
|
|
| |
Re: [QVTo] How to avoid mapping the same object twice? [message #550209 is a reply to message #550054] |
Thu, 29 July 2010 14:23 |
Ryan Messages: 74 Registered: July 2009 Location: Indiana |
Member |
|
|
Thanks Ed,
I read through that and have also read through 13.5.6 of the DSL book, and must admit, I still am not sure how to apply those tools to this scenario. I realized after I posted that it is a bit more complex as there are times when I do want to remap and times I don't. The original model has a list of items that will map to a collection of pairs called itemdata, and the colors for each set of items needs to be mapped into that itemdata.
Revised example below.
Class Color
-attribute red (int)
-attribute green (int)
-attribute blue (int)
Class ColorList
-reference colors (Color) 0..*
Class Item
-attribute itemName (String)
-reference itemColor (type Color)
Class ItemList
-reference items (Item) 0..*
Class Pair:
-attribute name (String)
-attribute value (String)
Class ItemData
-reference data (Pair) 0..*
ColorList myColorList
-Color Red (255,0,0)
-Color Green (0, 255, 0)
ItemList list1
-Item RedApple (with reference to Red)
-Item GreenApple (with reference to Green)
-Item Cherry (with reference to Red)
ItemList list2
-Item Pear (with reference to Green)
-Item Strawberry (with reference to Red)
ItemData datalist1
name value
color[0].red 255
color[0].green 0
color[0].blue 0
color[1].red 0
color[1].green 255
color[1].blue 0
item[0].name RedApple
item[0].color 0
item[1].name GreenApple
item[1].color 1
item[2].name Cherry
item[2].color 0
ItemData datalist2
name value
color[0].red 0
color[0].green 255
color[0].blue 0
color[1].red 255
color[1].green 0
color[1].blue 0
item[0].name Pear
item[0].color 0
item[1].name Strawberry
item[1].color 1
I planned on having a mapping
mapping Model1::ItemList::itemList2itemData() : Model2::ItemData
and I assume that I'll somehow use the resolve within that mapping to get previously mapped colors within that mapping. But after I map list 1 (which would skip the second mapping of red), mapping list2 needs to also map the colors again into the second itemdata.
Also, the resolve would get me a reference to the object Pairs, but to get the index that I really need, I'd need to parse that string, or add an attribute index to Pairs to hold the index.
Thanks,
Ryan
|
|
|
Re: [QVTo] How to avoid mapping the same object twice? [message #550259 is a reply to message #550209] |
Thu, 29 July 2010 16:13 |
Ed Willink Messages: 7680 Registered: July 2009 |
Senior Member |
|
|
Hi Ryan
I'm really only beginning to learn QVTo myself. I've been surprised how
well it does simple mappings and how badly it does even slightly complex
pattern conversions. QVTr wouldn't have been much better. I found that
it was only once I drew UMLX diagrams that I could see what I was trying
to do and then decompose it into what QVTo could do. I found the
explicit UMLX traceability conversion operator invaluable, but since I
defined it, perhaps that's not surprising;
http://www.eclipse.org/gmt/umlx/doc/index.html
Until you know what you want to do you can't expect the tool to do it
for you.
If what you want to do is too complex, you may find it easier to use
multiple passes, or a side analysis.
Regards
Ed Willink
On 29/07/2010 15:23, Ryan wrote:
> Thanks Ed,
> I read through that and have also read through 13.5.6 of the DSL book,
> and must admit, I still am not sure how to apply those tools to this
> scenario. I realized after I posted that it is a bit more complex as
> there are times when I do want to remap and times I don't. The original
> model has a list of items that will map to a collection of pairs called
> itemdata, and the colors for each set of items needs to be mapped into
> that itemdata.
>
> Revised example below.
> Class Color
> -attribute red (int)
> -attribute green (int)
> -attribute blue (int)
> Class ColorList
> -reference colors (Color) 0..*
> Class Item
> -attribute itemName (String)
> -reference itemColor (type Color)
> Class ItemList
> -reference items (Item) 0..*
>
>
> Class Pair:
> -attribute name (String)
> -attribute value (String)
> Class ItemData
> -reference data (Pair) 0..*
>
>
> ColorList myColorList
> -Color Red (255,0,0)
> -Color Green (0, 255, 0)
>
> ItemList list1
> -Item RedApple (with reference to Red)
> -Item GreenApple (with reference to Green)
> -Item Cherry (with reference to Red)
>
> ItemList list2
> -Item Pear (with reference to Green)
> -Item Strawberry (with reference to Red)
>
>
>
> ItemData datalist1
> name value
> color[0].red 255
> color[0].green 0
> color[0].blue 0
> color[1].red 0
> color[1].green 255
> color[1].blue 0
> item[0].name RedApple
> item[0].color 0
> item[1].name GreenApple
> item[1].color 1
> item[2].name Cherry
> item[2].color 0
>
> ItemData datalist2
> name value
> color[0].red 0
> color[0].green 255
> color[0].blue 0
> color[1].red 255
> color[1].green 0
> color[1].blue 0
> item[0].name Pear
> item[0].color 0
> item[1].name Strawberry
> item[1].color 1
>
> I planned on having a mapping
> mapping Model1::ItemList::itemList2itemData() : Model2::ItemData
> and I assume that I'll somehow use the resolve within that mapping to
> get previously mapped colors within that mapping. But after I map list 1
> (which would skip the second mapping of red), mapping list2 needs to
> also map the colors again into the second itemdata.
> Also, the resolve would get me a reference to the object Pairs, but to
> get the index that I really need, I'd need to parse that string, or add
> an attribute index to Pairs to hold the index.
>
> Thanks,
> Ryan
|
|
|
Re: [QVTo] How to avoid mapping the same object twice? [message #550272 is a reply to message #550259] |
Thu, 29 July 2010 17:15 |
Ryan Messages: 74 Registered: July 2009 Location: Indiana |
Member |
|
|
Here is a quick bit of java pseudo code for doing this in Java.
public int mappingColor(ItemData data, Color color) {
if (/*color has not been mapped in data*/){
int nextInt = /* get total number of colors mapped in this ItemData */
data.addPair("color[" + nextInt + "].red", color.getRed().toString());
// add green
// add blue
// save nextInt for this color/data combo
}
return intForColor;
}
public ItemData mappingItemList(ItemList list) {
ItemData retVal = new ItemData();
int index = 0;
for (Item i : list) {
retVal.addPair("item[" + index + "].name", i.getName());
retVal.addPair("item[" + index + "].color", mappingColor(retVal, i.getColor());
index++;
}
return retVal;
}
Basically, I'd call the mapping for the color and if it has not been mapped for a particular ItemData, add that color to the itemdata and save the int in some data structure that will be used to look up next time that the mappingColor is called with the same itemdata and color object, so that the int will just be returned.
I took a look at the doc "UMLX - A Graphical Transformation Language for MDA" from your page. Do you have an eclipse plugin for creating these transform diagrams? I could sketch one out on pencil/paper, but that doesn't help for conveying via a forum.
|
|
| |
Re: [QVTo] How to avoid mapping the same object twice? [message #550303 is a reply to message #550054] |
Thu, 29 July 2010 20:39 |
Sergey Boyko Messages: 171 Registered: July 2009 |
Senior Member |
|
|
Hi Ryan,
Single mapping invocation is the fundamental QVTo behavior (see 8.2.1.15
MappingOperation, section Execution Semantics).
In short:
- all the 'in' and 'inout' parameters of the mapping are ordered as a tuple
- mapping guard (when clause) is checked. if failed then 'null' is returned
- trace records for the mapping are checked to match parameters tuple.
if matched then all 'out' parameters of the mapping are filled from the
found trace record and mapping exists
- mapping is executed and new trace record is created (mapping in/inout
parameters tuple to out parameters)
For example consider the following:
transformation transf();
intermediate class MyInClass { name : String; }
intermediate class MyOutClass { value : Integer; }
main() {
var s := Sequence{
object MyInClass{name := '11'},
object MyInClass{name := '21'},
object MyInClass{name := '11'}
};
var s1 := s->collect(i|i.name.map name2value());
assert fatal (s1->size() = 3);
assert fatal (s1->at(1) = s1->at(3));
}
mapping String::name2value() : MyOutClass {
value := self.toInteger();
}
Also look at thread
http://www.eclipse.org/forums/index.php?t=msg&goto=91769 &
There singleton pattern is described using single mapping invocation
behavior.
Regards,
Sergey
Ryan wrote:
> The title is the best I could come up with, but I've got a transform
> that I'm not quite sure how to approach.
>
> Example first model (also not sure of best way to represent model):
> Class Color
> -attribute red (int)
> -attribute green (int)
> -attribute blue (int)
> Class Item
> -attribute itemName (String)
> -reference itemColor (type Color)
>
> and the second model is Class Pair:
> -attribute name (String)
> -attribute value (String)
>
> And example instance of model 1 would be Color Red (255,0,0)
> Color Green (0, 255, 0)
>
> Item GreenApple (with reference to Green)
> Item RedApple (with reference to Red)
> Item Cherry (with reference to Red)
>
> and the transform would be
>
> name value
> color[0].red 255
> color[0].green 0
> color[0].blue 0
> color[1].red 0
> color[1].green 255
> color[1].blue 0
> item[0].name RedApple
> item[0].color 0
> item[1].name GreenApple
> item[1].color 1
> item[2].name Cherry
> item[2].color 0
>
>
> So as I iterate over the items, I'll map the color (which i assume I'll
> need a variable to hold the index I'm at), but I don't want to map red
> twice, so I want to be able the next time I see red, to just get the
> index, and not map it to color[2]. I know the string string model is
> not very good, but that's what I've got to generate. I don't know
> enough about QVTO and it may be something I just end up coding in Java.
>
> Thanks,
> Ryan
|
|
|
Re: [QVTo] How to avoid mapping the same object twice? [message #550305 is a reply to message #550303] |
Thu, 29 July 2010 20:45 |
Sergey Boyko Messages: 171 Registered: July 2009 |
Senior Member |
|
|
So the answer on the title question (How to avoid mapping the same
object twice?) - it's done automatically according to the mapping
specification.
Sergey Boyko wrote:
> Hi Ryan,
>
> Single mapping invocation is the fundamental QVTo behavior (see 8.2.1.15
> MappingOperation, section Execution Semantics).
>
> In short:
> - all the 'in' and 'inout' parameters of the mapping are ordered as a tuple
> - mapping guard (when clause) is checked. if failed then 'null' is returned
> - trace records for the mapping are checked to match parameters tuple.
> if matched then all 'out' parameters of the mapping are filled from the
> found trace record and mapping exists
> - mapping is executed and new trace record is created (mapping in/inout
> parameters tuple to out parameters)
>
>
> For example consider the following:
>
> transformation transf();
> intermediate class MyInClass { name : String; }
> intermediate class MyOutClass { value : Integer; }
>
> main() {
> var s := Sequence{
> object MyInClass{name := '11'},
> object MyInClass{name := '21'},
> object MyInClass{name := '11'}
> };
>
> var s1 := s->collect(i|i.name.map name2value());
> assert fatal (s1->size() = 3);
> assert fatal (s1->at(1) = s1->at(3));
> }
>
> mapping String::name2value() : MyOutClass {
> value := self.toInteger();
> }
>
>
> Also look at thread
> http://www.eclipse.org/forums/index.php?t=msg&goto=91769 &
> There singleton pattern is described using single mapping invocation
> behavior.
>
>
> Regards,
> Sergey
>
>
> Ryan wrote:
>> The title is the best I could come up with, but I've got a transform
>> that I'm not quite sure how to approach.
>>
>> Example first model (also not sure of best way to represent model):
>> Class Color
>> -attribute red (int)
>> -attribute green (int)
>> -attribute blue (int)
>> Class Item
>> -attribute itemName (String)
>> -reference itemColor (type Color)
>>
>> and the second model is Class Pair:
>> -attribute name (String)
>> -attribute value (String)
>>
>> And example instance of model 1 would be Color Red (255,0,0)
>> Color Green (0, 255, 0)
>>
>> Item GreenApple (with reference to Green)
>> Item RedApple (with reference to Red)
>> Item Cherry (with reference to Red)
>>
>> and the transform would be
>>
>> name value
>> color[0].red 255
>> color[0].green 0
>> color[0].blue 0
>> color[1].red 0
>> color[1].green 255
>> color[1].blue 0
>> item[0].name RedApple
>> item[0].color 0
>> item[1].name GreenApple
>> item[1].color 1
>> item[2].name Cherry
>> item[2].color 0
>>
>>
>> So as I iterate over the items, I'll map the color (which i assume
>> I'll need a variable to hold the index I'm at), but I don't want to
>> map red twice, so I want to be able the next time I see red, to just
>> get the index, and not map it to color[2]. I know the string string
>> model is not very good, but that's what I've got to generate. I don't
>> know enough about QVTO and it may be something I just end up coding in
>> Java.
>>
>> Thanks,
>> Ryan
|
|
|
Re: [QVTo] How to avoid mapping the same object twice? [message #550318 is a reply to message #550303] |
Thu, 29 July 2010 21:28 |
Ryan Messages: 74 Registered: July 2009 Location: Indiana |
Member |
|
|
Thanks Sergey for the insight into how mappings really work.
Ok, I think I may have figured out a way to accomplish what I want, but I'll run it by you guys first.
So it seems like what I need to do is attach intermediate data with the int value to the colors object (from model 1) when i do the mapping for the color. In the mapping for the itemList2itemData(), first check that intermediate data for the int, and use it if it is set. Otherwise go ahead with the mapping and save the int in the intermediate data. Then clean out the intermediate data for all the colors just before leaving the itemList2itemData().
Sergey, thanks also for the eclipsecon 09 pdf on qvto, that helped clear up a few things that the DSL book didn't quite explain clearly.
Edit:
After thinking it through, I'm not sure that would work. I would somehow need to set that those mappings for colors are valid only in the scope of the mapping of the itemList2itemData(), not the entire transform. Is there a way to rescope a mapping from the transform level down to a mapping within the transform level?
Edit 2:
Perhaps as a way to sort out the mapping, for the mapping Model1::Color::color2pairs() : Sequence(Model1::Pair) have it take as an in parameter the itemData object that is created in the itemList2itemData() mapping.
[Updated on: Thu, 29 July 2010 21:46] Report message to a moderator
|
|
| |
Re: [QVTo] How to avoid mapping the same object twice? [message #550407 is a reply to message #550054] |
Fri, 30 July 2010 09:36 |
Eclipse User |
|
|
|
Originally posted by: koen.yskout.cs.kuleuven.be
Ryan,
I think something along the following works (for your extended models
given somewhere else in this thread). By using a mapping to generate the
index of the color for a certain ItemList, you can re-use the result of
that mapping. (The index is an integer and needs to be wrapped in an
object, otherwise it cannot be used as the result from a mapping).
You can look at the code below for details (I tested it on your
examples, and it does what I understand you want to achieve :p)
Kind regards,
Koen
modeltype MODEL1 "strict" uses "http://firstmodel";
modeltype MODEL2 "strict" uses "http://secondmodel";
transformation First2Second(in model1 : MODEL1, out model2 : MODEL2);
// Wrapper object for an integer
intermediate class Index {
indexValue : Integer;
}
intermediate property ItemList::nextColorIndex : Integer;
intermediate property ItemList::nextItemIndex : Integer;
main() {
model1.rootObjects()[FirstModel]->map first2Second();
}
mapping FirstModel::first2Second() : SecondModel {
itemData := self.itemList.map itemList2ItemData(self.colorList);
}
mapping ItemList::itemList2ItemData(colorList : ColorList) : ItemData {
init {
self.nextColorIndex := 0;
self.nextItemIndex := 0;
}
name := self.name + 'data';
data := colorList.colors->color2Pairs(self)->flatten();
data += self.items->item2Pairs(self)->flatten();
}
// Map a color to an index in the context of a given ItemList.
// Always returns same Index object when called using the same (Color,
ItemList) pair.
mapping Color::color2Index(list : ItemList) : Index {
indexValue := list.nextColorIndex;
list.nextColorIndex := list.nextColorIndex + 1;
}
mapping Item::item2Index(list : ItemList) : Index {
indexValue := list.nextItemIndex;
list.nextItemIndex := list.nextItemIndex + 1;
}
helper Color::color2PairAttributeName(list: ItemList, attribute :
String) : String {
var index := self.map color2Index(list).indexValue;
return indexedNameAttribute('color', index, attribute);
}
helper Item::item2PairAttributeName(list: ItemList, attribute : String)
: String {
var index := self.map item2Index(list).indexValue;
return indexedNameAttribute('item', index, attribute);
}
helper indexedNameAttribute(name : String, index : Integer, attribute :
String) : String {
return name + '[' + index.toString() + '].' + attribute;
}
helper Color::color2Pairs(list : ItemList) : Sequence(Pair) {
return Sequence {
object Pair {
name := self.color2PairAttributeName(list, 'red');
value := self.red.toString();
},
object Pair {
name := self.color2PairAttributeName(list, 'green');
value := self.green.toString();
},
object Pair {
name := self.color2PairAttributeName(list, 'blue');
value := self.blue.toString();
}
}
}
helper Item::item2Pairs(list : ItemList) : Sequence(Pair) {
return Sequence {
object Pair {
name := self.item2PairAttributeName(list, 'name');
value := self.itemName;
},
object Pair {
name := self.item2PairAttributeName(list, 'color');
value := self.itemColor.map color2Index(list).indexValue.toString();
}
}
}
|
|
|
Re: [QVTo] How to avoid mapping the same object twice? [message #550533 is a reply to message #550407] |
Fri, 30 July 2010 17:04 |
Ryan Messages: 74 Registered: July 2009 Location: Indiana |
Member |
|
|
Thanks Koen for the sample code. I understand better now how to get qvto to do what I want it to do. I got it to pretty much work how I want (I only have one color list, and only colors for a given item list should end up in an item data set), but can't seem to figure out why all the pairs end up at the root of model 2 instead of within each ItemData. The mapping itemList2itemData() stores the pairs returned from item2pairs() in it's data field, but when this gets run, they end up as children of the root of the model. Any thoughs? I have a feeling I'm overlooking something simple here.
Here is the modified code:
modeltype Model1 "strict" uses "http://org.example/models/1.0/model1";
modeltype Model2 "strict" uses "http://org.example/models/1.0/model2";
transformation First2Second(in model1 : Model1, out model2 : Model2);
// Wrapper object for an integer
intermediate class Index {
indexValue : Integer;
}
intermediate property ItemList::nextColorIndex : Integer;
intermediate property ItemList::nextItemIndex : Integer;
main() {
model1.objectsOfType(Model1Root)->map first2Second();
}
mapping Model1::Model1Root::first2Second() : Model2::Model2Root {
dataLists := self.products.map itemList2ItemData()->asOrderedSet();
}
mapping ItemList::itemList2ItemData() : ItemData {
init {
self.nextColorIndex := 0;
self.nextItemIndex := 0;
}
name := self.name + 'data';
data := self.items.map item2Pairs(self)->asOrderedSet();
}
// Map a color to an index in the context of a given ItemList.
// Always returns same Index object when called using the same (Color,ItemList) pair.
mapping Color::color2Index(list : ItemList) : Index {
indexValue := list.nextColorIndex;
list.nextColorIndex := list.nextColorIndex + 1;
}
mapping Item::item2Index(list : ItemList) : Index {
indexValue := list.nextItemIndex;
list.nextItemIndex := list.nextItemIndex + 1;
}
helper Color::color2PairAttributeName(list: ItemList, attribute : String) : String {
var index := self.map color2Index(list).indexValue;
return indexedNameAttribute('color', index, attribute);
}
helper Item::item2PairAttributeName(list: ItemList, attribute : String) : String {
var index := self.map item2Index(list).indexValue;
return indexedNameAttribute('item', index, attribute);
}
helper indexedNameAttribute(name : String, index : Integer, attribute : String) : String {
return name + '[' + index.toString() + '].' + attribute;
}
mapping Color::color2Pairs(list : ItemList) : Sequence(Pair) {
result := Sequence {
object Pair {
name := self.color2PairAttributeName(list, 'red');
value := self.red.toString();
},
object Pair {
name := self.color2PairAttributeName(list, 'green');
value := self.green.toString();
},
object Pair {
name := self.color2PairAttributeName(list, 'blue');
value := self.blue.toString();
}
}
}
mapping Item::item2Pairs(list : ItemList) : Sequence(Pair) {
result := Sequence {
object Pair {
name := self.item2PairAttributeName(list, 'name');
value := self.itemName;
},
object Pair {
name := self.item2PairAttributeName(list, 'color');
value := self.itemColor.map color2Index(list).indexValue.toString();
}
};
result += self.itemColor.map color2Pairs(list)->asOrderedSet();
}
And I couldn't figure out how to attach files to this post, so here are my Model1.ecore
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model1"
nsURI="http://org.example/models/1.0/model1" nsPrefix="org.example.models">
<eClassifiers xsi:type="ecore:EClass" name="Color">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="red" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="green" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="blue" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Item">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="itemName" lowerBound="1"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="itemColor" lowerBound="1"
eType="#//Color"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="ColorList">
<eStructuralFeatures xsi:type="ecore:EReference" name="colors" upperBound="-1"
eType="#//Color" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="ItemList">
<eStructuralFeatures xsi:type="ecore:EReference" name="items" upperBound="-1"
eType="#//Item" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Model1Root">
<eStructuralFeatures xsi:type="ecore:EReference" name="products" upperBound="-1"
eType="#//ItemList" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="colorData" lowerBound="1"
eType="#//ColorList" containment="true"/>
</eClassifiers>
</ecore:EPackage>
And my Model2.ecore:
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model2"
nsURI="http://org.example/models/1.0/model2" nsPrefix="org.example.models">
<eClassifiers xsi:type="ecore:EClass" name="Model2Root">
<eStructuralFeatures xsi:type="ecore:EReference" name="dataLists" upperBound="-1"
eType="#//ItemData" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="ItemData">
<eStructuralFeatures xsi:type="ecore:EReference" name="data" upperBound="-1" eType="#//Pair"
containment="true"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Pair">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="value" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
</ecore:EPackage>
[Updated on: Fri, 30 July 2010 17:05] Report message to a moderator
|
|
|
Re: [QVTo] How to avoid mapping the same object twice? [message #550550 is a reply to message #550533] |
Fri, 30 July 2010 18:38 |
Ed Willink Messages: 7680 Registered: July 2009 |
Senior Member |
|
|
Hi Ryan
All the created elements that have no container are contained by the root.
Mapping compositions is easy. Mapping aggregations is much harder.
You'll probably need something like this:
mapping Base::TemplateBindingCS::decorateTemplateBinding(inout dict :
Dict(String,Pivot::Element)) : Pivot::TemplateBinding {
init {
result := self.resolveone(Pivot::TemplateBinding);
if result->isEmpty() then { -- should never happen
result := invalid;
}
else if result.parameterSubstitution->isEmpty() then {
result.parameterSubstitution := self.ownedParameterSubstitution->map
decorateTemplateParameterSubstitution(dict);
}
endif endif;
}
}
To cope with the three cases and workaround the lack of return support.
Target does not exist and needs creating.
Target exists but is not configured.
Target already exists and needs configuring.
You are currently creating new targets for the last two cases.
Regards
Ed Willink
On 30/07/2010 18:04, Ryan wrote:
> Thanks Koen for the sample code. I understand better now how to get
> qvto to do what I want it to do. I got it to pretty much work how I
> want, but can't seem to figure out why all the pairs end up at the root
> of model 2 instead of within each ItemData. The mapping
> itemList2itemData() stores the pairs returned from item2pairs() in it's
> data field, but when this gets run, they end up as children of the root
> of the model. Any thoughs? I have a feeling I'm overlooking something
> simple here.
>
> Here is the modified code:
>
> modeltype Model1 "strict" uses "http://org.example/models/1.0/model1";
> modeltype Model2 "strict" uses "http://org.example/models/1.0/model2";
>
> transformation First2Second(in model1 : Model1, out model2 : Model2);
>
> // Wrapper object for an integer
> intermediate class Index {
> indexValue : Integer;
> }
> intermediate property ItemList::nextColorIndex : Integer;
> intermediate property ItemList::nextItemIndex : Integer;
>
> main() {
> model1.objectsOfType(Model1Root)->map first2Second();
> }
>
> mapping Model1::Model1Root::first2Second() : Model2::Model2Root {
> dataLists := self.products.map itemList2ItemData()->asOrderedSet();
> }
>
> mapping ItemList::itemList2ItemData() : ItemData {
> init {
> self.nextColorIndex := 0;
> self.nextItemIndex := 0;
> }
> name := self.name + 'data';
> data := self.items.map item2Pairs(self)->asOrderedSet();
> }
>
> // Map a color to an index in the context of a given ItemList.
> // Always returns same Index object when called using the same
> (Color,ItemList) pair.
> mapping Color::color2Index(list : ItemList) : Index {
> indexValue := list.nextColorIndex;
> list.nextColorIndex := list.nextColorIndex + 1;
> }
>
> mapping Item::item2Index(list : ItemList) : Index {
> indexValue := list.nextItemIndex;
> list.nextItemIndex := list.nextItemIndex + 1;
> }
>
> helper Color::color2PairAttributeName(list: ItemList, attribute :
> String) : String {
> var index := self.map color2Index(list).indexValue;
> return indexedNameAttribute('color', index, attribute);
> }
>
> helper Item::item2PairAttributeName(list: ItemList, attribute : String)
> : String {
> var index := self.map item2Index(list).indexValue;
> return indexedNameAttribute('item', index, attribute);
> }
>
> helper indexedNameAttribute(name : String, index : Integer, attribute :
> String) : String {
> return name + '[' + index.toString() + '].' + attribute;
> }
>
> mapping Color::color2Pairs(list : ItemList) : Sequence(Pair) {
> result := Sequence {
> object Pair {
> name := self.color2PairAttributeName(list, 'red');
> value := self.red.toString();
> },
> object Pair {
> name := self.color2PairAttributeName(list, 'green');
> value := self.green.toString();
> },
> object Pair {
> name := self.color2PairAttributeName(list, 'blue');
> value := self.blue.toString();
> }
> }
> }
>
> mapping Item::item2Pairs(list : ItemList) : Sequence(Pair) {
> result := Sequence {
> object Pair {
> name := self.item2PairAttributeName(list, 'name');
> value := self.itemName;
> },
> object Pair {
> name := self.item2PairAttributeName(list, 'color');
> value := self.itemColor.map color2Index(list).indexValue.toString();
> }
> };
> result += self.itemColor.map color2Pairs(list)->asOrderedSet();
> }
>
> And I couldn't figure out how to attach files to this post, so here are
> my Model1.ecore
> <?xml version="1.0" encoding="UTF-8"?>
> <ecore:EPackage xmi:version="2.0"
> xmlns:xmi="http://www.omg.org/XMI"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model1"
> nsURI="http://org.example/models/1.0/model1" nsPrefix="org.example.models">
> <eClassifiers xsi:type="ecore:EClass" name="Color">
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="red"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="green"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="blue"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="Item">
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="itemName"
> lowerBound="1"
> eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> <eStructuralFeatures xsi:type="ecore:EReference" name="itemColor"
> lowerBound="1"
> eType="#//Color"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="ColorList">
> <eStructuralFeatures xsi:type="ecore:EReference" name="colors"
> upperBound="-1"
> eType="#//Color" containment="true"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="ItemList">
> <eStructuralFeatures xsi:type="ecore:EReference" name="items"
> upperBound="-1"
> eType="#//Item" containment="true"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="Model1Root">
> <eStructuralFeatures xsi:type="ecore:EReference" name="products"
> upperBound="-1"
> eType="#//ItemList" containment="true"/>
> <eStructuralFeatures xsi:type="ecore:EReference" name="colorData"
> lowerBound="1"
> eType="#//ColorList" containment="true"/>
> </eClassifiers>
> </ecore:EPackage>
>
>
> And my Model2.ecore:
> <?xml version="1.0" encoding="UTF-8"?>
> <ecore:EPackage xmi:version="2.0"
> xmlns:xmi="http://www.omg.org/XMI"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model2"
> nsURI="http://org.example/models/1.0/model2" nsPrefix="org.example.models">
> <eClassifiers xsi:type="ecore:EClass" name="Model2Root">
> <eStructuralFeatures xsi:type="ecore:EReference" name="dataLists"
> upperBound="-1"
> eType="#//ItemData" containment="true"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="ItemData">
> <eStructuralFeatures xsi:type="ecore:EReference" name="data"
> upperBound="-1" eType="#//Pair"
> containment="true"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="Pair">
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="value"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> </eClassifiers>
> </ecore:EPackage>
>
|
|
| |
Re: [QVTo] How to avoid mapping the same object twice? [message #550560 is a reply to message #550558] |
Fri, 30 July 2010 19:37 |
Ryan Messages: 74 Registered: July 2009 Location: Indiana |
Member |
|
|
Well, I got it working. After posting about init and population, I realized I just needed to move the creation of the result object into the init section on my mappings:
mapping Color::color2Pairs(list : ItemList) : Collection(Pair) {
init {
result := Sequence {
object Pair {
name := self.color2PairAttributeName(list, 'red');
value := self.red.toString();
},
object Pair {
name := self.color2PairAttributeName(list, 'green');
value := self.green.toString();
},
object Pair {
name := self.color2PairAttributeName(list, 'blue');
value := self.blue.toString();
}
}
}
}
mapping Item::item2Pairs(list : ItemList) : Collection(Pair) {
init {
result := Sequence {
object Pair {
name := self.item2PairAttributeName(list, 'name');
value := self.itemName;
},
object Pair {
name := self.item2PairAttributeName(list, 'color');
value := self.itemColor.map color2Index(list).indexValue.toString();
}
};
result += self.itemColor.map color2Pairs(list);
}
}
Now the second model is created with all pairs below the intended itemdata list, and and each color is mapped only once for each itemdata list, and the index saved. Thanks to all who helped me arrive at this solution. A deadline was looming and had I not got it working by today, I would have had to code it in java.
Edit:
Even though this works, I'm a bit confused as to why the second time
result += self.itemColor.map color2Pairs(list); is called (with the same color and list parameters), even though the mapping doesn't take place, shouldn't the original set of pairs be returned from the first time the mapping took place? I guess I would assume I should have two sets of identical color[0].red .... if two items were associated with red.
Edit2:
Examining the qvtotrace file for a transform shows that for an item that has a color that has already been mapped, the mapping for that color is not called, but the result of the item mapping still has 5 pairs in the collection, but the resultant output model only has the 2 for the item, not the additional 3 for the (duplicate) color. Is the qvto transform smart enough to know that the color pairs have already been added to the list of pairs and skips adding them?
[Updated on: Fri, 30 July 2010 20:12] Report message to a moderator
|
|
|
Re: [QVTo] How to avoid mapping the same object twice? [message #550695 is a reply to message #550533] |
Wed, 04 August 2010 07:33 |
Eclipse User |
|
|
|
Originally posted by: koen.yskout.cs.kuleuven.be
Ryan,
Note that item2Pairs returns a collection of Pairs for each item, and
you call the mapping for each item in the itemlist. You thus end up with
a collection of a collection of pairs, which you need to flatten to be
able to add them to the data as a single collection of pairs. (I made
exactly the same error when creating the sample code at first, giving
the same strange result ;))
Koen
On 30/07/10 19:04, Ryan wrote:
> Thanks Koen for the sample code. I understand better now how to get
> qvto to do what I want it to do. I got it to pretty much work how I
> want, but can't seem to figure out why all the pairs end up at the root
> of model 2 instead of within each ItemData. The mapping
> itemList2itemData() stores the pairs returned from item2pairs() in it's
> data field, but when this gets run, they end up as children of the root
> of the model. Any thoughs? I have a feeling I'm overlooking something
> simple here.
>
> Here is the modified code:
>
> modeltype Model1 "strict" uses "http://org.example/models/1.0/model1";
> modeltype Model2 "strict" uses "http://org.example/models/1.0/model2";
>
> transformation First2Second(in model1 : Model1, out model2 : Model2);
>
> // Wrapper object for an integer
> intermediate class Index {
> indexValue : Integer;
> }
> intermediate property ItemList::nextColorIndex : Integer;
> intermediate property ItemList::nextItemIndex : Integer;
>
> main() {
> model1.objectsOfType(Model1Root)->map first2Second();
> }
>
> mapping Model1::Model1Root::first2Second() : Model2::Model2Root {
> dataLists := self.products.map itemList2ItemData()->asOrderedSet();
> }
>
> mapping ItemList::itemList2ItemData() : ItemData {
> init {
> self.nextColorIndex := 0;
> self.nextItemIndex := 0;
> }
> name := self.name + 'data';
> data := self.items.map item2Pairs(self)->asOrderedSet();
> }
>
> // Map a color to an index in the context of a given ItemList.
> // Always returns same Index object when called using the same
> (Color,ItemList) pair.
> mapping Color::color2Index(list : ItemList) : Index {
> indexValue := list.nextColorIndex;
> list.nextColorIndex := list.nextColorIndex + 1;
> }
>
> mapping Item::item2Index(list : ItemList) : Index {
> indexValue := list.nextItemIndex;
> list.nextItemIndex := list.nextItemIndex + 1;
> }
>
> helper Color::color2PairAttributeName(list: ItemList, attribute :
> String) : String {
> var index := self.map color2Index(list).indexValue;
> return indexedNameAttribute('color', index, attribute);
> }
>
> helper Item::item2PairAttributeName(list: ItemList, attribute :
> String) : String {
> var index := self.map item2Index(list).indexValue;
> return indexedNameAttribute('item', index, attribute);
> }
>
> helper indexedNameAttribute(name : String, index : Integer, attribute
> : String) : String {
> return name + '[' + index.toString() + '].' + attribute;
> }
>
> mapping Color::color2Pairs(list : ItemList) : Sequence(Pair) {
> result := Sequence {
> object Pair {
> name := self.color2PairAttributeName(list, 'red');
> value := self.red.toString();
> },
> object Pair {
> name := self.color2PairAttributeName(list, 'green');
> value := self.green.toString();
> },
> object Pair {
> name := self.color2PairAttributeName(list, 'blue');
> value := self.blue.toString();
> }
> }
> }
>
> mapping Item::item2Pairs(list : ItemList) : Sequence(Pair) {
> result := Sequence {
> object Pair {
> name := self.item2PairAttributeName(list, 'name');
> value := self.itemName;
> },
> object Pair {
> name := self.item2PairAttributeName(list, 'color');
> value := self.itemColor.map
> color2Index(list).indexValue.toString();
> }
> };
> result += self.itemColor.map color2Pairs(list)->asOrderedSet();
> }
>
> And I couldn't figure out how to attach files to this post, so here are
> my Model1.ecore
> <?xml version="1.0" encoding="UTF-8"?>
> <ecore:EPackage xmi:version="2.0"
> xmlns:xmi="http://www.omg.org/XMI"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model1"
> nsURI="http://org.example/models/1.0/model1"
> nsPrefix="org.example.models">
> <eClassifiers xsi:type="ecore:EClass" name="Color">
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="red"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="green"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="blue"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="Item">
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="itemName"
> lowerBound="1"
> eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> <eStructuralFeatures xsi:type="ecore:EReference" name="itemColor"
> lowerBound="1"
> eType="#//Color"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="ColorList">
> <eStructuralFeatures xsi:type="ecore:EReference" name="colors"
> upperBound="-1"
> eType="#//Color" containment="true"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="ItemList">
> <eStructuralFeatures xsi:type="ecore:EReference" name="items"
> upperBound="-1"
> eType="#//Item" containment="true"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="Model1Root">
> <eStructuralFeatures xsi:type="ecore:EReference" name="products"
> upperBound="-1"
> eType="#//ItemList" containment="true"/>
> <eStructuralFeatures xsi:type="ecore:EReference" name="colorData"
> lowerBound="1"
> eType="#//ColorList" containment="true"/>
> </eClassifiers>
> </ecore:EPackage>
>
>
> And my Model2.ecore:
> <?xml version="1.0" encoding="UTF-8"?>
> <ecore:EPackage xmi:version="2.0"
> xmlns:xmi="http://www.omg.org/XMI"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model2"
> nsURI="http://org.example/models/1.0/model2"
> nsPrefix="org.example.models">
> <eClassifiers xsi:type="ecore:EClass" name="Model2Root">
> <eStructuralFeatures xsi:type="ecore:EReference" name="dataLists"
> upperBound="-1"
> eType="#//ItemData" containment="true"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="ItemData">
> <eStructuralFeatures xsi:type="ecore:EReference" name="data"
> upperBound="-1" eType="#//Pair"
> containment="true"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EClass" name="Pair">
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="value"
> lowerBound="1" eType="ecore:EDataType
> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
> </eClassifiers>
> </ecore:EPackage>
>
|
|
|
Re: [QVTo] How to avoid mapping the same object twice? [message #550700 is a reply to message #550695] |
Wed, 04 August 2010 07:40 |
Eclipse User |
|
|
|
Originally posted by: koen.yskout.cs.kuleuven.be
Oops, never mind...
I see that my explanation is incorrect (the QVT parser catches the
faulty assignment, as should be expected), and you found the cause of
your result (which was another error I also made at some point, hence
the confusion :p)
Koen
On 04/08/10 09:33, Koen Yskout wrote:
> Ryan,
>
> Note that item2Pairs returns a collection of Pairs for each item, and
> you call the mapping for each item in the itemlist. You thus end up with
> a collection of a collection of pairs, which you need to flatten to be
> able to add them to the data as a single collection of pairs. (I made
> exactly the same error when creating the sample code at first, giving
> the same strange result ;))
>
> Koen
>
>
> On 30/07/10 19:04, Ryan wrote:
>> Thanks Koen for the sample code. I understand better now how to get
>> qvto to do what I want it to do. I got it to pretty much work how I
>> want, but can't seem to figure out why all the pairs end up at the root
>> of model 2 instead of within each ItemData. The mapping
>> itemList2itemData() stores the pairs returned from item2pairs() in it's
>> data field, but when this gets run, they end up as children of the root
>> of the model. Any thoughs? I have a feeling I'm overlooking something
>> simple here.
>>
>> Here is the modified code:
>>
>> modeltype Model1 "strict" uses "http://org.example/models/1.0/model1";
>> modeltype Model2 "strict" uses "http://org.example/models/1.0/model2";
>>
>> transformation First2Second(in model1 : Model1, out model2 : Model2);
>>
>> // Wrapper object for an integer
>> intermediate class Index {
>> indexValue : Integer;
>> }
>> intermediate property ItemList::nextColorIndex : Integer;
>> intermediate property ItemList::nextItemIndex : Integer;
>>
>> main() {
>> model1.objectsOfType(Model1Root)->map first2Second();
>> }
>>
>> mapping Model1::Model1Root::first2Second() : Model2::Model2Root {
>> dataLists := self.products.map itemList2ItemData()->asOrderedSet();
>> }
>>
>> mapping ItemList::itemList2ItemData() : ItemData {
>> init {
>> self.nextColorIndex := 0;
>> self.nextItemIndex := 0;
>> }
>> name := self.name + 'data';
>> data := self.items.map item2Pairs(self)->asOrderedSet();
>> }
>>
>> // Map a color to an index in the context of a given ItemList.
>> // Always returns same Index object when called using the same
>> (Color,ItemList) pair.
>> mapping Color::color2Index(list : ItemList) : Index {
>> indexValue := list.nextColorIndex;
>> list.nextColorIndex := list.nextColorIndex + 1;
>> }
>>
>> mapping Item::item2Index(list : ItemList) : Index {
>> indexValue := list.nextItemIndex;
>> list.nextItemIndex := list.nextItemIndex + 1;
>> }
>>
>> helper Color::color2PairAttributeName(list: ItemList, attribute :
>> String) : String {
>> var index := self.map color2Index(list).indexValue;
>> return indexedNameAttribute('color', index, attribute);
>> }
>>
>> helper Item::item2PairAttributeName(list: ItemList, attribute :
>> String) : String {
>> var index := self.map item2Index(list).indexValue;
>> return indexedNameAttribute('item', index, attribute);
>> }
>>
>> helper indexedNameAttribute(name : String, index : Integer, attribute
>> : String) : String {
>> return name + '[' + index.toString() + '].' + attribute;
>> }
>>
>> mapping Color::color2Pairs(list : ItemList) : Sequence(Pair) {
>> result := Sequence {
>> object Pair {
>> name := self.color2PairAttributeName(list, 'red');
>> value := self.red.toString();
>> },
>> object Pair {
>> name := self.color2PairAttributeName(list, 'green');
>> value := self.green.toString();
>> },
>> object Pair {
>> name := self.color2PairAttributeName(list, 'blue');
>> value := self.blue.toString();
>> }
>> }
>> }
>>
>> mapping Item::item2Pairs(list : ItemList) : Sequence(Pair) {
>> result := Sequence {
>> object Pair {
>> name := self.item2PairAttributeName(list, 'name');
>> value := self.itemName;
>> },
>> object Pair {
>> name := self.item2PairAttributeName(list, 'color');
>> value := self.itemColor.map
>> color2Index(list).indexValue.toString();
>> }
>> };
>> result += self.itemColor.map color2Pairs(list)->asOrderedSet();
>> }
>>
>> And I couldn't figure out how to attach files to this post, so here are
>> my Model1.ecore
>> <?xml version="1.0" encoding="UTF-8"?>
>> <ecore:EPackage xmi:version="2.0"
>> xmlns:xmi="http://www.omg.org/XMI"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model1"
>> nsURI="http://org.example/models/1.0/model1"
>> nsPrefix="org.example.models">
>> <eClassifiers xsi:type="ecore:EClass" name="Color">
>> <eStructuralFeatures xsi:type="ecore:EAttribute" name="red"
>> lowerBound="1" eType="ecore:EDataType
>> http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
>> <eStructuralFeatures xsi:type="ecore:EAttribute" name="green"
>> lowerBound="1" eType="ecore:EDataType
>> http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
>> <eStructuralFeatures xsi:type="ecore:EAttribute" name="blue"
>> lowerBound="1" eType="ecore:EDataType
>> http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
>> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
>> lowerBound="1" eType="ecore:EDataType
>> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
>> </eClassifiers>
>> <eClassifiers xsi:type="ecore:EClass" name="Item">
>> <eStructuralFeatures xsi:type="ecore:EAttribute" name="itemName"
>> lowerBound="1"
>> eType="ecore:EDataType
>> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
>> <eStructuralFeatures xsi:type="ecore:EReference" name="itemColor"
>> lowerBound="1"
>> eType="#//Color"/>
>> </eClassifiers>
>> <eClassifiers xsi:type="ecore:EClass" name="ColorList">
>> <eStructuralFeatures xsi:type="ecore:EReference" name="colors"
>> upperBound="-1"
>> eType="#//Color" containment="true"/>
>> </eClassifiers>
>> <eClassifiers xsi:type="ecore:EClass" name="ItemList">
>> <eStructuralFeatures xsi:type="ecore:EReference" name="items"
>> upperBound="-1"
>> eType="#//Item" containment="true"/>
>> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
>> lowerBound="1" eType="ecore:EDataType
>> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
>> </eClassifiers>
>> <eClassifiers xsi:type="ecore:EClass" name="Model1Root">
>> <eStructuralFeatures xsi:type="ecore:EReference" name="products"
>> upperBound="-1"
>> eType="#//ItemList" containment="true"/>
>> <eStructuralFeatures xsi:type="ecore:EReference" name="colorData"
>> lowerBound="1"
>> eType="#//ColorList" containment="true"/>
>> </eClassifiers>
>> </ecore:EPackage>
>>
>>
>> And my Model2.ecore:
>> <?xml version="1.0" encoding="UTF-8"?>
>> <ecore:EPackage xmi:version="2.0"
>> xmlns:xmi="http://www.omg.org/XMI"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="model2"
>> nsURI="http://org.example/models/1.0/model2"
>> nsPrefix="org.example.models">
>> <eClassifiers xsi:type="ecore:EClass" name="Model2Root">
>> <eStructuralFeatures xsi:type="ecore:EReference" name="dataLists"
>> upperBound="-1"
>> eType="#//ItemData" containment="true"/>
>> </eClassifiers>
>> <eClassifiers xsi:type="ecore:EClass" name="ItemData">
>> <eStructuralFeatures xsi:type="ecore:EReference" name="data"
>> upperBound="-1" eType="#//Pair"
>> containment="true"/>
>> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
>> lowerBound="1" eType="ecore:EDataType
>> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
>> </eClassifiers>
>> <eClassifiers xsi:type="ecore:EClass" name="Pair">
>> <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
>> lowerBound="1" eType="ecore:EDataType
>> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
>> <eStructuralFeatures xsi:type="ecore:EAttribute" name="value"
>> lowerBound="1" eType="ecore:EDataType
>> http://www.eclipse.org/emf/2002/Ecore#//EString"/>
>> </eClassifiers>
>> </ecore:EPackage>
>>
>
|
|
| |
Re: [QVTo] How to attach intermediate data that is valid only within the scope of a mapping? [message #550929 is a reply to message #550845] |
Wed, 04 August 2010 15:48 |
Eclipse User |
|
|
|
Originally posted by: koen.yskout.cs.kuleuven.be
If you want to include only the colors from the list that are actually
used by your items into the ItemData, you can also do something like the
following:
// map used colors only
data := self.items->itemColor->asOrderedSet()->color2Pairs(self).flatten();
// map items
data += self.items->item2Pairs(self).flatten();
It will select the colors from the items, weed out duplicates by
converting it to a set, and then doing the conversion to pairs for each
color.
As far as I know (but people that know the QVT spec better might have a
better answer), in the population section you set values for the
attributes of the object that you return.
Returning a collection is something special, because Collection is not
really a class from one of the models, but a built-in type. Therefore
you can't set its contents in the population section, because it doesn't
have user-settable attributes. (Imagine for a moment a collection would
have a 'elements' attribute, then 'elements := self.map someMapping'
would make more sense in the population section, I guess).
I have the impression that QVT became quite liberal with its syntax
since version 2, so a lot more is allowed now than before, making the
distinction between the init section and the population section more
difficult to notice now than before, except in some cases like this.
Koen
On 04/08/10 15:44, Ryan wrote:
> Thanks Koen for following up on this thread.
>
> My last question was why no duplicates ended up in the list, even though
> the qvto trace files show that there should be (based on the return from
> each mapping). The answer to that is that each many mapping in the
> ecore model is by default set to ordered and unique, which make the ocl
> representation an orderedset that doesn't allow duplicates.
>
> However, I've got one other question about how the init section works,
> basically, why do the assignment statements for the pairs need to go in
> the init section, isn't that populating the result object (which seems
> like it should go in the population section).
|
|
|
Goto Forum:
Current Time: Wed Dec 11 20:21:53 GMT 2024
Powered by FUDForum. Page generated in 0.04226 seconds
|