Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » M2T (model-to-text transformation) » [Acceleo] Difficulties with variables
[Acceleo] Difficulties with variables [message #633900] Tue, 19 October 2010 18:11 Go to next message
Simone Franzini is currently offline Simone Franzini
Messages: 3
Registered: October 2010
Junior Member
Hi,
I am pretty new to Acceleo, but after some initial difficulties I have been able to use it quite successfully so far.
However, the fact that all variables in Acceleo are final, i.e. cannot be modified after they are declared, is giving me quite a hard time. I understand that part of my problem is that I am new to OCL as well, but I hope you will be able to help. Despite I looked quite thoroughly through Acceleo and OCL documentation and MTL specification, I couldn't find anything similar to this.

Even something as simple as a counter is not so simple in Acceleo; I have tried what is described here:
http://www.eclipse.org/forums/index.php?t=msg&&th=19 986&goto=64949
but I couldn't get it working. Even the suggested solution of using the let statement inside the for loop does not seem to have the side effect of incrementing the general variable. Moreover, I don't see how this could work, given that variables are final.

Now, on to my specific problem. Let's say I have a Collection and I need to do something with each member of the Collection and store the result in a different variable in order to reuse it later. E.g. let's say I have a UML model of a Java class, with the list of getters and setters. I want to store the names of all the operations in a different variable Set(String). I have been able to retrieve all the setters, for example like this:
setters : Set(Operation) = (c.getOperations()->select(name.startsWith('set')));
but now how do I assign their names to a Set(String)?

A slightly more complicated thing would be if I also need to check some condition on the names. Or, if I need to compute something that depends on the value of each variable: a counter or something similar would be of use here, but values of variables cannot be modified...

Any ideas?
Thank you!

[Updated on: Tue, 19 October 2010 20:58]

Report message to a moderator

Re: [Acceleo] Difficulties with variables [message #633978 is a reply to message #633900] Wed, 20 October 2010 07:03 Go to previous messageGo to next message
Stephane Begaudeau is currently offline Stephane Begaudeau
Messages: 406
Registered: April 2010
Location: Nantes (France)
Senior Member

Hi Simone,

>> c.getOperations()->select(name.startsWith('set'))
>> but now how do I assign their names to a Set(String)?

If you want to collect all their names, you can do this:
c.getOperations()->select(name.startsWith('set'))->collect(oper | oper.name)
or
c.getOperations()->select(name.startsWith('set')).name

(both are the same since ".name" is here applied on a collection)

If you need a counter, you can iterate on your collection with a for and inside of that for you have access to a counter with a variable named "i".

Finally, I would advise you to use a query for something like "c.getOperations()->select(name.startsWith('set')).name" because a query would store the result in a cache and if you call it again with the same parameters we won't have to compute the result again. This query would looks like this:
[query public collectNameOfSetters(c : Class) : Set(String) = c.getOperations()->select(name.startsWith('set')).name/]

You could also store all your utility queries in a utility module in order to be able to easily access your queries from all your modules. You can see an example here: http://www.eclipse.org/forums/index.php?t=msg&goto=54763 2&S=54f46cd8651eb190524163fe9c3c70ca#msg_547632

Stephane Begaudeau, Obeo



Re: [Acceleo] Difficulties with variables [message #634642 is a reply to message #633978] Fri, 22 October 2010 14:39 Go to previous messageGo to next message
Simone Franzini is currently offline Simone Franzini
Messages: 3
Registered: October 2010
Junior Member
Hi Stephane,
first of all, thank for your quick reply. I couldn't test this until today. So, I had tried what you say before, i.e.:
c.getOperations()->select(name.startsWith('set'))->collect(oper | oper.name)
or
c.getOperations()->select(name.startsWith('set')).name
and it works.
However, I finally found my problem: there seem to be something wrong when I try to assign the result of that function to a Set(String), through a "let" statement or an initialization statement.

In the case of the let statement, I don't get any compile-time or run-time error but the code inside the let statement is never executed:
[let attributes : Set(String) = c.getOperations()->select(name.startsWith('set')).name]
This statement is never entered.
[for (s : String | attributes)]
[s/]
[/for]
[/let]

In the case of the initialization statement:
[template public generatePropertySourceWoAttributeNames(c : Class){
getters : Set(Operation) = (c.getOperations()->select(name.startsWith('get') or name.startsWith('is')));
setters : Set(Operation) = (c.getOperations()->select(name.startsWith('set')));
attributes : Set(String) = c.getOperations()->select(name.startsWith('get')).name;
}]
[for (s : String | attributes)]
[s/]
[/for]
I get an error on "attributes": "Init expression type does not conform to type of variable (attributes)."
However, a for loop on "getters" or "setters" above works perfectly.

Finally, putting the code in a query as you suggested works, unless I try to assign the result of the query to a Set(String) variable. It seems to be some issue with the Set(String) type, or the way the attribute is collected. I am a little unclear of why this happens, could you please explain? I am quite sure I am missing something.

Thank you.

[Updated on: Fri, 22 October 2010 15:38]

Report message to a moderator

Re: [Acceleo] Difficulties with variables [message #634953 is a reply to message #633900] Mon, 25 October 2010 08:21 Go to previous message
Stephane Begaudeau is currently offline Stephane Begaudeau
Messages: 406
Registered: April 2010
Location: Nantes (France)
Senior Member

Hi,

I'm sorry I've made a small mistake, c.getOperations()->select(name.startsWith('set'))->collect(oper | oper.name) or c.getOperations()->select(name.startsWith('set')).name would not return a set, here is why:

myCollection->collect(...) returns a collection with the same type as myCollection, here myCollection is the return type of the select, and the return type of the select is like the type of the collection on which the select is applied. And here the return type of c.getOperations()->select(name.startsWith('set'))->collect(oper | oper.name) is the type of c.getOperations(), which should be a Sequence.

Stephane Begaudeau, Obeo



Previous Topic:[Acceleo 3 / MTL] Variables in MTL?
Next Topic:[Acceleo] Can Acceleo support @text-explicit syntax ?
Goto Forum:
  


Current Time: Mon Sep 22 08:29:57 GMT 2014

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

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