Home » Modeling » Epsilon » Mapping of abstract types
Mapping of abstract types [message #1841968] |
Fri, 04 June 2021 16:21 |
Tomas Wall Messages: 53 Registered: April 2021 |
Member |
|
|
Hello,
I am currently trying to learn ETL, and I am using a simple example. I want to map between two Ecore metamodels that contain the same object and relationships (I know this is not ideal, but it is just for learning purposes).
In the photo I have attached the image of the metamodel.
Up until now I have been able to write the following rules.
rule Forest2Forest
transform s: model1!Forest
to t: model2!Forest
{
t.name=s.name;
t.house::=s.getHouses();
t.tree::=s.getTrees();
t.river::=s.getRivers();
}
rule House2House
transform s: model1!House
to t: model2!House
{
t.name=s.name;
}
rule Tree2Tree
transform s: model1!Tree
to t: model2!Tree
{
t.name=s.name;
}
rule River2River
transform s: model1!River
to t: model2!River
{
t.name=s.name;
}
rule Path2Path
transform s: model1!Path
to t: model2!Path
{
t.name=s.name;
t.sourceObject ...?
t.targetObject ...?
}
operation model1!Forest getHouses() {
return model1!House.all;
}
operation model1!Forest getRivers() {
return model1!River.all;
}
operation model1!Forest getTress() {
return model1!Tree.all;
}
However, I am a bit stuck when it comes to the relation between the path and the object. The idea is that a path has one sourceObject that can be a House, a Tree, or a River, and one targetObject that can be a House, a Tree, or a River. I am not sure how the transformation rules in such relationship should be. Should I create a transformation rule for the Object too? If so how to show that an object can either be a house, a tree, or a river?
Hope I was clear :)
Best,
Tomas
|
|
| | |
Re: Mapping of abstract types [message #1841982 is a reply to message #1841975] |
Sat, 05 June 2021 19:44 |
Tomas Wall Messages: 53 Registered: April 2021 |
Member |
|
|
Hi Dimistris,
Thank you for your answer. I am trying to learn how the relationship between components is translated into transformation rules and I have encountered some issues with the metamodels I have uploaded here.
This is the input and this is the output .
I mapped region to region and neighbourhood to zone and they work fine. However, now I want to map park2zone, and zone2zone. So the park, zone, and neighbourhood in the input model should be transformed into a zone in the output model. I wrote the rules, but there is something missing, and I cannot seem to find how to transform them.
The second thing I want to do is transform BigHouseArea2BigHouseArea. Now in the input model, the big house area is contained in the neighbourhood that will be transformed into a zone in the output model. Howeveer, the big house area in the output model , only has a reference with the region and big house, and this is where I get confused and cannot continue further with the transformation rules.
I am not sure how to proceed in this cases therefore your help would be deeply appreciated. These are the transformation rules I have written so far.
rule Region2Region
transform s: input!Region
to t: output!Region
{
t.name=s.name;
t.zone ::= s.neighbourhood;
}
rule Neighbourhood2Zone
transform s: input!Neighbourhood
to t:output!Zone
{
t.name=s.name;
}
rule Park2Zone
transform s: input!Park
to t:Zone
{
t.name=s.name;
//not sure what else should be added here or in some other tranformation for this to take place
}
rule Zone2Zone
transform s: input!Zone
to t: output!Zone
{
t.name=s.name;
//not complete
}
rule BigHouseArea2BigHouseArea
transform s: input!BigHouseArea
to t: output!BigHouseArea
{
t.name=s.name;
//in the input file there is a containment between the BigHouseArea and the Neighbourhood, while in the output, there is a reference between Region and BigHouseArea, and BigHouse and BigHouseArea.Should I add anything anywhere else to show these relationships?
}
Note: The concepts and the relationships might look a bit weird, but this is just for learning purposes.
Thank you in advance,
Tomas!
|
|
| |
Re: Mapping of abstract types [message #1842014 is a reply to message #1842004] |
Mon, 07 June 2021 09:20 |
Tomas Wall Messages: 53 Registered: April 2021 |
Member |
|
|
Hi Dimitris,
This is the Epsilon version I currently have 2.2.0.202009032353
And these are the files.
Another issue that I also have, besides the one mentioned above is that i also want to map House to Houses, and Furniture to Furniture, but in the output model I also have HouseObjects, therefore when I transform from the input model to the output model, I also need to create the HouseObjects and Furniture should be contained in the HouseObjects, and I am not quite sure how to make that happen.
Many many thanks!
[Updated on: Mon, 07 June 2021 20:30] Report message to a moderator
|
|
|
Re: Mapping of abstract types [message #1842040 is a reply to message #1842014] |
Tue, 08 June 2021 05:23 |
|
Hi Tomas,
Could you please try to reduce your example to the bare minimum I'd need to understand (i.e. remove unrelated classes/references/attributes/rules) and also include a hand-crafted copy of your expected target model in your zip file? It'd be great if you could also try to rationalise what remains of your metamodels (e.g. why would a SmallHouse have from/to references to a Block? why would a Region have a direct reference to one MansionGarden?).
Best,
Dimitris
|
|
|
Re: Mapping of abstract types [message #1842105 is a reply to message #1842040] |
Wed, 09 June 2021 11:24 |
Tomas Wall Messages: 53 Registered: April 2021 |
Member |
|
|
Hi Dimitris,
I tried some other metamodels, as they are probably more comprehensible.
However, I cannot reduce them, as some of the issues I have include multiple elements and the relationship between them.
The metamodels have a similar logic, they have locations (of different kinds), and paths that connect the locations. Paths can also contain components.
So I have two metamodels, forestEcore and forestTextual. They contain more or less the same concepts with slight differences, and also some differences in the relationships.
My first goal is to transform from forestEcore to forestTextual.
In the following is the mapping I want to achieve:
These are done:
--------------------------------------------------------------
Forest -> Forest
SimpleLocation -> Location
CompoundLocation -> Location
EntryPosition -> EntryPosition
Crossroad -> Crossroad
These are not:
--------------------------------------------------------------
//for these two the issue I have is that in forestEcore they are contained in the Compound Location, while in the forextTextual, special position is contained in special position path which is contained in location, while start position is contained in initial path which is contained in the location. So when I make the transformations StartPosition2StartPosition I have to first create the path in the forestTextual and then place the StartPosition that is transformed, in that path.
StartPosition -> StartPosition
SpecialPosition -> SpecialPosition
// when I transform ComponentA2ComponentA, in forestEcore, ComponentA is contained in Path, while in forestTextual it is contained in ComponentCollection that does not exist at all in forestEcore, therefore I believe that when I transform them I have to create the ComponentCollection, which should be contained in the InternalPath, or Path, and it should contain ComponentA. How can I do that in Epsilon?
Component A -> ComponentA
// in forestEcore there is only one kind of path, while in forestTextual there are four which are subcategories of the path that is in forestEcore, depending on what they connect. So when I transform a path from forestEcore I need to check what they connect , so I can transform them accordingly. In the following I am also describing some pseudocode for each rule, but not sure how to write them in Epsilon
//when the paths are transformed, I should also make sure to include in the attributes the locations they connect.
Path -> Path // if (sourceArea== (simplelocation || compundlocation) && targetArea== (simplelocation || compundlocation) )
Path -> InitialPath // if (sourceArea==StartPosition)
Path -> SpecialPositionPath // if (targetArea==SpecialPosition)
Path -> InternalPath // if (sourceArea== null && targetArea== null )
--------------------------------------------------------------------------------
There are my main issues. As I mentioned sorry that I can have a more minimal example as the concepts are related to one another. In the zip file you can find the metamodels, the models and the transformation. The ecore model is the source model, and based on that source model, I have attached a handcrafted target model, that the transformation should output.
Would really appreciate your help.
Many thanks,
Tomas!
|
|
|
Re: Mapping of abstract types [message #1842109 is a reply to message #1842105] |
Wed, 09 June 2021 11:48 |
|
Hi Tomas,
I'm very sorry but I'm finding it difficult to follow this example too. You shouldn't really need a metamodel that contains 10+ classes and more than a dozen features to demonstrate the issue you're encountering. I'd encourage you to give this another go and simplify your metamodels so that they contain no more than 4-5 classes each, with self-evident semantics (e.g. it's not clear to me what a CompoundLocation, a ComponentA or a SpecialPosition represents in the real world).
If you're struggling to come up with suitable metamodels, perhaps you could draw some inspiration from [1].
Best,
Dimitris
[1] https://www.eclipse.org/epsilon/live/?etl
[Updated on: Wed, 09 June 2021 11:50] Report message to a moderator
|
|
| | | |
Re: Mapping of abstract types [message #1842118 is a reply to message #1842117] |
Wed, 09 June 2021 14:59 |
Tomas Wall Messages: 53 Registered: April 2021 |
Member |
|
|
Hi Dimitris,
Thanks a lot, it works perfectly fine. Now I extended the metamodel a bit to show another issue I have, presented in this link https://www.eclipse.org/epsilon/live/?f32e2091 .
I want to transform Tree2Tree, but in the source metamodel the tree is contained in the area, while in the target metamodel in TreeGroup, which does not exist as a concept in the source metamodel. So to do this transformation, I believe I should first create the TreeGroup which should be contained in the area and forest, and then transform tree to tree, where the tree should be contained in the TreeGroup. But I am not really sure on how to create these new elements that do not exist and specify their containers. Hope this is clear enough!
Many thanks,
Tomas!
|
|
|
Re: Mapping of abstract types [message #1842119 is a reply to message #1842118] |
Wed, 09 June 2021 15:06 |
|
Two options here. You could update your Area2Area rule to the following
rule Area2Area
transform s : Source!Area
to t : Target!Area,
tg : Target!TreeGroup {
t.name = s.name;
t.treegroup = tg;
tg.tree ::= s.tree;
}
or (more imperatively)
rule Area2Area
transform s : Source!Area
to t : Target!Area {
t.name = s.name;
var tg : new Target!TreeGroup;
t.treegroup = tg;
tg.tree ::= s.tree;
}
Best,
Dimitris
|
|
| | | |
Re: Mapping of abstract types [message #1842173 is a reply to message #1842169] |
Thu, 10 June 2021 18:12 |
|
You can achieve this by adding guards to your two rules as shown below.
rule highway2capitalhighway
transform s: Source!Highway
to t: Target!CapitalHighway {
guard: s.targetLocation.isTypeOf(Source!Capital) or
s.sourceLocation.isTypeOf(Source!Capital)
t.name=s.name;
}
rule highway2highway
transform s: Source!Highway
to t: Target!Highway {
guard: not s.targetLocation.isTypeOf(Source!Capital) and
not s.sourceLocation.isTypeOf(Source!Capital)
t.name=s.name;
}
Best,
Dimitris
|
|
|
Re: Mapping of abstract types [message #1842176 is a reply to message #1842173] |
Thu, 10 June 2021 19:37 |
Tomas Wall Messages: 53 Registered: April 2021 |
Member |
|
|
Hi Dimiris,
Thanks for the answer! However, I have a question in this case. Why when I try the following guards:
rule highway2capitalhighway
transform s: Source!Highway
to t: Target!CapitalHighway
{
guard: s.sourceLocation.isTypeOf(Source!Capital)
t.name=s.name;
}
//highway2highway
//this should happen only when the highway
//in the source model connects a city
//to a city
rule highway2highway
transform s: Source!Highway
to t: Target!Highway
{
guard: s.sourceLocation.isTypeOf(Source!City)
t.name=s.name;
}
With these guards I am checking just the source location as that is what I am actually interested about and I am not using the keyword "not".
I just say that the source Location should be a city and the highway can be transformed into a highway. But that transformation never happens. Would you mind explaining why does this happen?
________________________________________________________
Another issue that I encounter (using the guards that you suggested, which work perfectly fine), is when I add this line
t.capitalhighway::=s.highways;
to the Region2City rule. I do it in the same way as I did for
but I get an error which you can see here
https://www.eclipse.org/epsilon/live/?3638b011
Many thanks,
Tomas
[Updated on: Thu, 10 June 2021 20:28] Report message to a moderator
|
|
|
Re: Mapping of abstract types [message #1842180 is a reply to message #1842176] |
Fri, 11 June 2021 05:02 |
|
> I just say that the source Location should be a city and the highway can be transformed into a highway. But that transformation never happens. Would you mind explaining why does this happen?
This works fine if you fix the model by replacing the reference to "jp1" which doesn't exist to a city that exists e.g. "s2"
> but I get an error which you can see here https://www.eclipse.org/epsilon/live/?3638b011
This happens because you are attempting to assign a collection of values (s.highways is multi-valued) to a single-valued feature.
Best,
Dimitris
|
|
| |
Re: Mapping of abstract types [message #1842213 is a reply to message #1842203] |
Sat, 12 June 2021 04:53 |
|
One option would be to select the first value of the multi-valued feature using the first() operation [1] and assign it to the single-valued feature i.e.
t.highway ::= s.highways.first();
Just to note that the metamodels have started growing/losing relevance to the real world (e.g. "class Highway extends Highways") so my suggestion would be to tidy them up a bit if you are to use them in further questions.
Also, please note that opposite references are not specified correctly (see [2]):
ref Highway[*]#incomingHighway incomingHighway ;
...
ref Location[1]#targetLocation targetLocation;
should instead be:
ref Highway[*]#targetLocation incomingHighway ;
...
ref Location[1]#incomingHighway targetLocation;
The Eclipse-based Emfatic editor should report this problem.
Best,
Dimitris
[1] https://www.eclipse.org/epsilon/doc/eol/#collections-and-maps
[2] https://www.eclipse.org/emfatic/#references
[Updated on: Sat, 12 June 2021 05:06] Report message to a moderator
|
|
| |
Re: Mapping of abstract types [message #1842265 is a reply to message #1842257] |
Tue, 15 June 2021 04:56 |
|
Hi Tomas,
As the "states" feature is multi-valued, you should use "s.states.isEmpty()" instead of "s.states == null" to check this (and "not s.states.isEmpty()" instead of "s.states.isDefined()" further down).
Best,
Dimitris
|
|
|
Goto Forum:
Current Time: Sat Apr 27 06:21:59 GMT 2024
Powered by FUDForum. Page generated in 0.03317 seconds
|