Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
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 Go to next message
Eclipse UserFriend
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 Go to previous messageGo to next message
Eclipse UserFriend
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 Go to previous messageGo to next message
Eclipse UserFriend
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 Go to previous messageGo to next message
Eclipse UserFriend
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 Go to previous messageGo to next message
Eclipse UserFriend
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 Go to previous messageGo to next message
Eclipse UserFriend
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 Go to previous messageGo to next message
Frédéric Jouault is currently offline Frédéric JouaultFriend
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 Go to previous message
Eclipse UserFriend
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
Previous Topic:[ATL] Model checking with ATL
Next Topic:Stereotype property with defined type
Goto Forum:
  


Current Time: Sun Apr 11 02:30:42 GMT 2021

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

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

Back to the top