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 03: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 #36936 is a reply to message #36766] |
Fri, 11 May 2007 04: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 06: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 #37703 is a reply to message #37142] |
Tue, 15 May 2007 01:30   |
Eclipse User |
|
|
|
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 05: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: Wed Jul 09 08:16:42 EDT 2025
Powered by FUDForum. Page generated in 0.05528 seconds
|