Home » Archived » M2M (model-to-model transformation) » [ATL] how to match rules only once
[ATL] how to match rules only once [message #36003] |
Fri, 04 May 2007 07:57 |
Eclipse User |
|
|
|
Originally posted by: r.c.ladan.tue.nl
Hi,
to transform something like
<comp name="1"/>
<comp name="2"/>
to
<comp name="1"/>
<comp name="2"/>
<comp name="3"/>
I came up with this rule (atl2006):
rule R {
from c1 : mm!component, c2 : mm!component(c1 <> c2)
to c3(...), c4(...), c5(...)
}
where c3 and c4 are copies of c1 and c2, and c5 is new
This works, but it matches and transforms both (<comp name="1"/> , <comp
name="2"/>) and (<comp name="2"> , <comp name="1"> ), so the output
consists of 6 component elements.
Is there any way to tell the interpreter that it should transform only once?
Regards,
Rene
|
|
|
Re: [ATL] how to match rules only once [message #36732 is a reply to message #36003] |
Thu, 10 May 2007 08:00 |
Eclipse User |
|
|
|
Originally posted by: rchevrel.sodius.com
This is a multi-part message in MIME format.
--------------080906060405090506060205
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit
Hi Rene,
You could use Maps, Sequences or other Collections to retrieve the
already treated elements.
e.g. for your example (and many other):
*helper* *def*: assoMap : Map(mm!component, *Sequence*(mm!component)) = Map{};
*rule* isAlreadyConsidered(ref1 : mm!component, ref2 : mm!component) {
*do* {
*if* (not thisModule.assoMap.get(ref2).oclIsUndefined()) {
*if* (thisModule.assoMap.get(ref2)->includes(ref1)) {
true;
}
*else* {
thisModule.assoMap <- thisModule.assoMap.including(ref1, *Sequence*{ref2});
false;
}
}
*else* {
thisModule.assoMap <- thisModule.assoMap.including(ref1, *Sequence*{ref2});
false;
}
}
}
best regard,
*R
|
|
|
Re: [ATL] how to match rules only once [message #36766 is a reply to message #36732] |
Thu, 10 May 2007 08:05 |
Eclipse User |
|
|
|
Originally posted by: rchevrel.sodius.com
This is a multi-part message in MIME format.
--------------070004020300040308020708
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit
You have to lock your match filter:
rule R {
from c1 : mm!component, c2 : mm!component(
c1 <> c2
and not thisModule.isAlreadyConsidered(c1, c2)
)
to c3(...), c4(...), c5(...)
}
You could prefer used an helper
*helper def:* isAlreadyConsidered(ref1 : mm!component, ref2 : mm!component) : Boolean =
*if* (not thisModule.assoMap.get(ref2).oclIsUndefined()) {
*if* (thisModule.assoMap.get(ref2)->includes(ref1)) {
true;
}
*else* {
thisModule.assoMap <- thisModule.assoMap.including(ref1, *Sequence*{ref2});
false;
}
}
*else* {
thisModule.assoMap <- thisModule.assoMap.including(ref1, *Sequence*{ref2});
false;
}
;
best regard,
*R
|
|
|
Re: [ATL] how to match rules only once [message #36936 is a reply to message #36766] |
Fri, 11 May 2007 08:44 |
Eclipse User |
|
|
|
Originally posted by: r.c.ladan.tue.nl
Régis wrote:
> You have to lock your match filter:
> rule R {
> from c1 : mm!component, c2 : mm!component(
> c1 <> c2
> and not thisModule.isAlreadyConsidered(c1, c2)
> )
> to c3(...), c4(...), c5(...)
> }
>
>
> You could prefer used an helper
>
> *helper def:* isAlreadyConsidered(ref1 : mm!component, ref2 : mm!component) : Boolean =
> *if* (not thisModule.assoMap.get(ref2).oclIsUndefined()) {
> *if* (thisModule.assoMap.get(ref2)->includes(ref1)) {
> true;
> }
> *else* {
> thisModule.assoMap <- thisModule.assoMap.including(ref1, *Sequence*{ref2});
> false;
> }
> }
> *else* {
> thisModule.assoMap <- thisModule.assoMap.including(ref1, *Sequence*{ref2});
> false;
> }
> ;
>
Uhm, this doesn't work, the output is still duplicated (i.e. c21, ...,
are duplicated). Your code doesn't compile either.
Code (simplified):
--@atlcompiler atl2006
module add_module;
create OUT : deploymentView from IN : deploymentView;
-- from rchevrel@sodius.com on newsgroup eclipse.modeling.m2m on
news.eclipse.org
helper def : assoMap : Map(deploymentView!Component,
Sequence(deploymentView!Component)) =
Map{};
helper def : isAlreadyConsidered(ref1 : deploymentView!Component, ref2 :
deploymentView!Component) : Boolean =
if (not thisModule.assoMap.get(ref2).oclIsUndefined()) then
thisModule.assoMap.get(ref2)->includes(ref1)
else
false
endif ;
rule add_module {
from
c11 : deploymentView!Component,
c12 : deploymentView!Component(c12 <> c11 and not
thisModule.isAlreadyConsidered(c11, c12))
to
-- skeleton output code for newsgroup
c21 : deploymentView!Component,
-- more output elements ...
-- register as considered, the parser doesn't allow this in the helper
do {
thisModule.assoMap <- thisModule.assoMap.including(c11, Sequence{c12}) ;
}
} -- add_module
Debugging this shows that assoMap stays empty/undefined? It isn't shown
in any view, since it isn't a variable.
An alternative would be to write some post-processing script that merges
elements with equal types and names.
Regards,
Rene
|
|
|
Re: [ATL] how to match rules only once [message #37037 is a reply to message #36936] |
Fri, 11 May 2007 10:30 |
Eclipse User |
|
|
|
Originally posted by: rchevrel.sodius.com
Hi Rene,
I know why the code does not compile, it must be a called rule, not an
helper because helpers don't support "map <- map", sorry for my last post ;)
I have worked again on this code, it work very fine now ! (thanks to
Eric Vépa)
------------------------------------------------------------ --------------------------
helper def: assoMap : Map(deploymentView!Component,
Sequence(deploymentView!Component)) = Map{};
------------------------------------------------------------ --------------------------
rule isAlreadyConsidered(ref1 : deploymentView!Component, ref2 :
deploymentView!Component) {
using {
seq : Sequence(deploymentView!Component) =
if thisModule.assoMap.get(ref1).oclIsUndefined()
then Sequence{}
else thisModule.assoMap.get(ref1)
endif;
}
do {
if (not thisModule.assoMap.get(ref2).oclIsUndefined()) {
if (thisModule.assoMap.get(ref2)->includes(ref1)) {
true;
}
else {
thisModule.assoMap <-
thisModule.assoMap.including(ref1, seq->including(ref2));
false;
}
}
else {
thisModule.assoMap <- thisModule.assoMap.including(ref1,
seq->including(ref2));
false;
}
}
}
------------------------------------------------------------ --------------------------
rule add_module {
from
c11 : deploymentView!Component,
c12 : deploymentView!Component (
c12 <> c11 and
not thisModule.isAlreadyConsidered(c11, c12)
)
to
c21 : deploymentView!Component ...
}
------------------------------------------------------------ --------------------------
I hope that this code will be useful for many people ;)
*Régis CHEVREL* <mailto:rchevrel@sodius.com>
SODIUS*
*6, rue Cornouaille
44319 Nantes - France
Phone: +33 (0)2 28 23 54 34
***www.mdworkbench.com* <http://www.mdworkbench.com/>* *
Draw more value from your model
|
|
|
Re: [ATL] how to match rules only once [message #37142 is a reply to message #37037] |
Fri, 11 May 2007 11:18 |
Eclipse User |
|
|
|
Originally posted by: r.c.ladan.tue.nl
Régis wrote:
> Hi Rene,
>
> I know why the code does not compile, it must be a called rule, not an
> helper because helpers don't support "map <- map", sorry for my last
> post ;)
>
> I have worked again on this code, it work very fine now ! (thanks to
> Eric Vépa)
>
Confirmed :)
>
> I hope that this code will be useful for many people ;)
>
> *Régis CHEVREL* <mailto:rchevrel@sodius.com>
>
>
> SODIUS*
> *6, rue Cornouaille
> 44319 Nantes - France
>
> Phone: +33 (0)2 28 23 54 34
>
> ***www.mdworkbench.com* <http://www.mdworkbench.com/>* *
> Draw more value from your model
>
>
>
>
>
|
|
|
Re: [ATL] how to match rules only once [message #37703 is a reply to message #37142] |
Tue, 15 May 2007 05:30 |
Frédéric Jouault Messages: 572 Registered: July 2009 |
Senior Member |
|
|
Hello all,
Thank you very much for sorting out this problem ;-).
However, may I suggest an alternative, and possibly simpler solution? I
need to do this to feel useful on this one ;-).
Moreover, I usually prefer to stick with declarative style when
imperative code is not *absolutely* necessary.
It seems to me that no two classes should have the same name in your
source model. If this is really the case, then you may use the fact that
strings are totally ordered, and use the following guard in your rule:
c1.name < c2.name
This should work (please confirm!), requires less code, memory, and
cycles, and is fully declarative!
Regards,
Frédéric Jouault
|
|
|
Re: [ATL] how to match rules only once [message #59754 is a reply to message #37703] |
Wed, 29 August 2007 09:05 |
Eclipse User |
|
|
|
Originally posted by: r.c.ladan.tue.nl
Frédéric Jouault wrote:
> Hello all,
>
> Thank you very much for sorting out this problem ;-).
>
>
> However, may I suggest an alternative, and possibly simpler solution? I
> need to do this to feel useful on this one ;-).
>
> Moreover, I usually prefer to stick with declarative style when
> imperative code is not *absolutely* necessary.
>
>
> It seems to me that no two classes should have the same name in your
> source model. If this is really the case, then you may use the fact that
> strings are totally ordered, and use the following guard in your rule:
>
> c1.name < c2.name
>
>
> This should work (please confirm!), requires less code, memory, and
> cycles, and is fully declarative!
>
Just tested this using c1.id < c2.id, it indeed works ;-) (i.e. no duplicates in the output).
id is an attribute with the EMF isID option set.
Regards,
Rene
|
|
|
Goto Forum:
Current Time: Fri Mar 29 13:47:38 GMT 2024
Powered by FUDForum. Page generated in 0.04816 seconds
|