Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » M2T (model-to-text transformation) » [acceleo 3.2] queries and nested Sequence of model objects
[acceleo 3.2] queries and nested Sequence of model objects [message #755460] Tue, 08 November 2011 15:18 Go to next message
Marc Missing name is currently offline Marc Missing nameFriend
Messages: 38
Registered: March 2011
Member
Hello,

I'm really trying hard to figure out what I'm doing wrong, but without any success.

I have these 2 queries. Basically, the first one gives direct 'successors' of a node (prio), and the second one will trigger recursive calls to build lists of all successors (direct & indirect).

[query private upper(aPrio : PriorityDeclaration) : Sequence(PriorityDeclaration) =
    let at : AType = aPrio.eContainer(AType) in 
        at.priorities->select(e:PriorityDeclaration | aPrio.high = e.low)->asSequence()
/]

[query private uppers(aPrio : PriorityDeclaration) : Sequence(Sequence(PriorityDeclaration)) =
    aPrio.upper()->collectNested(uppers()->union(Sequence{aPrio}))
/]


Problem is that when calling the second query, I get «strange» results: I can call it, but I can't iterate over its result:
[for (it : Sequence(PriorityDeclaration) | prio.uppers())]
[for (u : PriorityDeclaration | it)]
[u.name/]
[/for]
[/for]


Invalid type for iteration at line 172 in Module generateAtomType for block for (it). java.util.ArrayList was not an instanceof PriorityDeclaration.


but if I simply "print" the result:

[for (it : Sequence(PriorityDeclaration) | prio.uppers())]
[it/]
[/for]


I get:

 bla.impl.PriorityDeclarationImpl@8eae04 (name: P2)bla.impl.PriorityDeclarationImpl@a86d12 (name: P1)


So, the objects are here, but I don't really understand what's happening.

Any help greatly appreciated !
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755508 is a reply to message #755460] Tue, 08 November 2011 16:42 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 4188
Registered: July 2009
Senior Member
Hi Marc

OCL did not originally support nested collections, hence the need for
collectNested() to fix the dubious behaviour of collect(). I'm not
convinced that this is sufficient to make nested collections sound
specification-wise.

It is not until OCL 2.3 that will find a hint that
Sequence(Sequence(PriorityDeclaration)) might be valid. There's
certainly insufficient specification to make it consistently valid.

The new pivot binding of Eclipse OCL supports the nested declarations,
but Acceleo is using the Ecore binding where you may find nested
collections a bit suspect, unless Acceleo has worked around bugs.

I recommend using Collections of single part Tuples rather than
Collections of Collections to work around the limitations and perhaps
get better diagnostics when your code rather than the tool is at fault.

Regards

Ed Willink

On 08/11/2011 15:18, Marc wrote:
> Hello,
>
> I'm really trying hard to figure out what I'm doing wrong, but without
> any success.
>
> I have these 2 queries. Basically, the first one gives direct
> 'successors' of a node (prio), and the second one will trigger
> recursive calls to build lists of all successors (direct & indirect).
>
>
> [query private upper(aPrio : PriorityDeclaration) :
> Sequence(PriorityDeclaration) =
> let at : AType = aPrio.eContainer(AType) in
> at.priorities->select(e:PriorityDeclaration | aPrio.high =
> e.low)->asSequence()
> /]
>
> [query private uppers(aPrio : PriorityDeclaration) :
> Sequence(Sequence(PriorityDeclaration)) =
> aPrio.upper()->collectNested(uppers()->union(Sequence{aPrio}))
> /]
>
> Problem is that when calling the second query, I get «strange»
> results: I can call it, but I can't iterate over its result:
>
> [for (it : Sequence(PriorityDeclaration) | prio.uppers())]
> [for (u : PriorityDeclaration | it)]
> [u.name/]
> [/for]
> [/for]
>
> Invalid type for iteration at line 172 in Module generateAtomType for
> block for (it). java.util.ArrayList was not an instanceof
> PriorityDeclaration.
>
> but if I simply "print" the result:
>
>
> [for (it : Sequence(PriorityDeclaration) | prio.uppers())]
> [it/]
> [/for]
>
> I get:
>
>
> bla.impl.PriorityDeclarationImpl@8eae04 (name:
> P2)bla.impl.PriorityDeclarationImpl@a86d12 (name: P1)
>
> So, the objects are here, but I don't really understand what's happening.
>
> Any help greatly appreciated !
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755641 is a reply to message #755508] Wed, 09 November 2011 08:17 Go to previous messageGo to next message
Marc Missing name is currently offline Marc Missing nameFriend
Messages: 38
Registered: March 2011
Member
Edward Willink wrote on Tue, 08 November 2011 11:42
Hi Marc

I recommend using Collections of single part Tuples rather than
Collections of Collections to work around the limitations and perhaps
get better diagnostics when your code rather than the tool is at fault.



Thanks very much for the explanation and the tip.
I'm now trying to understand how to use Tuple inside acceleo, but can't find any example using Tuple and I'm having a hard time understand the various docs... How am I supposed to modify my current queries ? I can't even find how to specify my return type correctly...

[query private uppers(aPrio : PriorityDeclaration) : Sequence(Tuple(Sequence(PriorityDeclaration))) =
...
/]
[query private uppers(aPrio : PriorityDeclaration) : Sequence(Tuple(n:Sequence(PriorityDeclaration))) =
...
/]

...


All combinations found in various documentation won't please acceleo.

Thanks!
Marc
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755661 is a reply to message #755641] Wed, 09 November 2011 09:04 Go to previous messageGo to next message
Marc Missing name is currently offline Marc Missing nameFriend
Messages: 38
Registered: March 2011
Member
I can't use syntax defined in http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.ocl.doc%2Fhelp%2Findex.html
In fact, acceleo doesn't know the 'Tuple' type (it won't autocomplete it as it would with Set, Sequence, etc). I checked that I was really using OCL 3.1. I've even reinstalled completely eclipse.

I'm really confused here Sad. Which "OCL reference" should be used while using acceleo 3.2 ? This one:
http://help.eclipse.org/helios/topic/org.eclipse.acceleo.doc/doc/html/ocl_operation_reference.html

does reference 'Tuple', but never explains how to use it (or even declare a Tuple type).
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755662 is a reply to message #755641] Wed, 09 November 2011 09:04 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 4188
Registered: July 2009
Senior Member
Hi Marc

The following OCLinEcore test code has some tuples in it that may
inspire you

class Company
{
attribute name : String { ordered };
property employees#company : Employee[*] { ordered composes };
attribute size : CompanySizeKind { ordered derived readonly
transient volatile }
{
derivation:
let table : Set(Tuple(range : Sequence(Integer), size :
CompanySizeKind)) =
Set{Tuple{range = Sequence{0..49}, size =
CompanySizeKind::small},
Tuple{range = Sequence{50..999}, size =
CompanySizeKind::medium},
Tuple{range = Sequence{1000..1000000}, size =
CompanySizeKind::large}}
in table->any(range->includes(employees->size())).size;
}
}

Regards

Ed Willink


On 09/11/2011 08:17, Marc wrote:
> Edward Willink wrote on Tue, 08 November 2011 11:42
>> Hi Marc
>>
>> I recommend using Collections of single part Tuples rather than
>> Collections of Collections to work around the limitations and
>> perhaps get better diagnostics when your code rather than the tool is
>> at fault.
>
>
> Thanks very much for the explanation and the tip.
> I'm now trying to understand how to use Tuple inside acceleo, but
> can't find any example using Tuple and I'm having a hard time
> understand the various docs... How am I supposed to modify my current
> queries ? I can't even find how to specify my return type correctly...
>
>
> [query private uppers(aPrio : PriorityDeclaration) :
> Sequence(Tuple(Sequence(PriorityDeclaration))) =
> ..
> /]
> [query private uppers(aPrio : PriorityDeclaration) :
> Sequence(Tuple(n:Sequence(PriorityDeclaration))) =
> ..
> /]
>
> ..
>
>
> All combinations found in various documentation won't please acceleo.
>
> Thanks!
> Marc
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755671 is a reply to message #755662] Wed, 09 November 2011 09:17 Go to previous messageGo to next message
Marc Missing name is currently offline Marc Missing nameFriend
Messages: 38
Registered: March 2011
Member
Edward Willink wrote on Wed, 09 November 2011 04:04
Hi Marc

let table : Set(Tuple(range : Sequence(Integer), size :
CompanySizeKind)) =


Thanks very much. Alas, I've already seen such examples (I've been googling non-stop since 8h00 this morning...), but acceleo won't let me use 'Tuple' ...

[Some more tests during redaction]

Ok, looks like I can use Tuple, but not as return type of queries.

This works:
[query public testTuple(aPrio : PriorityDeclaration) : OclAny = 
let table : Tuple(i : Integer) = Tuple{i=1} in
table
/]


This gives me a 'Invalid Type: Tuple(i: Integer)' on the first line :
[query public testTuple(aPrio : PriorityDeclaration) : Tuple(i : Integer) = 
let table : Tuple(i : Integer) = Tuple{i=1} in
table
/]


Is there something special about return types in acceleo queries ?

[Updated on: Wed, 09 November 2011 09:32]

Report message to a moderator

Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755677 is a reply to message #755671] Wed, 09 November 2011 09:47 Go to previous messageGo to next message
Marc Missing name is currently offline Marc Missing nameFriend
Messages: 38
Registered: March 2011
Member
I was so close ! I thought I'd be able to cast my Tuple of sequence to and from OclAny, but doing that raises a new error:

org.eclipse.ocl.cst.impl.TupleTypeCSImpl cannot be cast to org.eclipse.ocl.cst.SimpleNameCS


I'm begining to run out of workaround Smile
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755683 is a reply to message #755677] Wed, 09 November 2011 10:05 Go to previous messageGo to next message
Stephane Begaudeau is currently offline Stephane BegaudeauFriend
Messages: 413
Registered: April 2010
Location: Nantes (France)
Senior Member

Hi,

If you need to handle this:
[for (it : Sequence(PriorityDeclaration) | prio.uppers())]
[for (u : PriorityDeclaration | it)]
[u.name/]
[/for]
[/for]


You may try to call '->flatten' to obtain a single collection like this:
[for (u : PriorityDeclaration | prio.uppers()->flatten())]
[u.name/]
[/for]


Regards,

Stephane Begaudeau, Obeo

--
Twitter: @sbegaudeau
Google+: stephane.begaudeau
Blog: http://stephanebegaudeau.tumblr.com
Acceleo Documentation: http://docs.obeonetwork.com/acceleo



Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755684 is a reply to message #755683] Wed, 09 November 2011 10:09 Go to previous messageGo to next message
Marc Missing name is currently offline Marc Missing nameFriend
Messages: 38
Registered: March 2011
Member
Unfortunately, my example was over-simple. I can't simply flatten everything. But I'll try, and if flatten() works, maybe I can come up with a workdaround !

Thanks!
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755690 is a reply to message #755684] Wed, 09 November 2011 10:22 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 4188
Registered: July 2009
Senior Member
Hi Marc

Your attempts at using Tuple seem to be introducing more problems than
they solve. Do not use oclAsType or OclAny until you've understood the
problems.

Tuple should just work in Acceleo since Acceleo should just be using
underlying OCL functionality that works.

Therefore find out if
a simple Tuple type can be declared.
a simple TupleLiteral can be defined.
a Tuple variable can be initialised
as pure OCL embedded inside a query, then as declarations of [let/],
[query/] arguments and returns.

Then you'll know whether the bugs are in your understanding, OCL,
Acceleo and may be able to compromise.

Regards

Ed Willink

On 09/11/2011 10:09, Marc wrote:
> Unfortunately, my example was over-simple. I can't simply flatten
> everything. But I'll try, and if flatten() works, maybe I can come up
> with a workdaround !
>
> Thanks!
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755706 is a reply to message #755690] Wed, 09 November 2011 10:50 Go to previous messageGo to next message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1639
Registered: July 2009
Senior Member
Ed, Marc,

instead of over-complicating the problem and jumping on Tuples (which are useless in Acceleo as I see it, and have a known bug making them unusable in it), let's try and understand the issue.

Quote:

[query private upper(aPrio : PriorityDeclaration) : Sequence(PriorityDeclaration) =
let at : AType = aPrio.eContainer(AType) in
at.priorities->select(e:PriorityDeclaration | aPrio.high = e.low)->asSequence()
/]

[query private uppers(aPrio : PriorityDeclaration) : Sequence(Sequence(PriorityDeclaration)) =
aPrio.upper()->collectNested(uppers()->union(Sequence{aPrio}))
/]


So "uppers" returns a Collection of Collections, or so the "return type" you define says. Yet I think your return type is wrong :

aPrio.upper() = returns a Sequence. That much is good
aPrio.upper()->collectNested(...) = for each PriorityDeclaration in "aPrio.upper()", call the ... expression. Do not flatten the result.

uppers()->union(Sequence{aPrio}) the "uppers" call returns a Collection of Collection, to which you append a Sequence.

Simplified, here is what you're doing:

Sequence(PriorityDeclaration)->collectNested(Sequence(Sequence(PriorityDeclaration)))


So what you have as a result is :

Sequence(Sequence(Sequence(PriorityDeclaration)))


of course, recursive calls to the "uppers" query will further the nesting level. You potentially get something like

Sequence(Sequence(Sequence(Sequence(Sequence(Sequence(PriorityDeclaration))))))


depending on the number of recursive calls to "uppers". You have to either
1 - re-think what you're doing, or
2 - flatten the result.

Quote:

[for (it : Sequence(PriorityDeclaration) | prio.uppers())]
[for (u : PriorityDeclaration | it)]
[u.name/]
[/for]
[/for]


You can't do that since you have no idea of the actual nesting level of "prio.uppers()". If there was only one recursive call to the "uppers" query, and you actually have a Sequence(Sequence(Sequence()))... Then your code should look like :

[for (it : Sequence(Sequence(PriorityDeclaration)) | prio.uppers())]
[for (u : Sequence(PriorityDeclaration) | it)]
[for (t : PriorityDeclaration | u)]
[t.name/]
[/for]
[/for]
[/for]


Quote:

I get
bla.impl.PriorityDeclarationImpl@8eae04 (name: P2)bla.impl.PriorityDeclarationImpl@a86d12 (name: P1)



Acceleo automatically flattens the collections for the "toString"; this is why you do not "see" the collections here.


Bottom line is : be extra careful when using collectNested. This method does not flatten its result, and you might end up with extraneous levels of nesting within your collection.

Laurent Goubet
Obeo

[Updated on: Wed, 09 November 2011 10:51]

Report message to a moderator

Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755756 is a reply to message #755706] Wed, 09 November 2011 14:01 Go to previous messageGo to next message
Marc Missing name is currently offline Marc Missing nameFriend
Messages: 38
Registered: March 2011
Member
Laurent, I think you are right (again!). After thinking the algo, I've been modifying the OCL code to "get ir right" but I've only been introducing bugs, in particular because of the collectNested() that I've been using without taking extra care Smile

Thank you both for your precious help that helped me better understand acceleo/OCL.

I'm still confused about the state of Tuple in acceleo, so I'll avoid their use Smile

Thanks again !
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755762 is a reply to message #755756] Wed, 09 November 2011 14:08 Go to previous messageGo to next message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1639
Registered: July 2009
Senior Member
Marc,

You're welcome Wink.

Marc wrote on Wed, 09 November 2011 09:01

I'm still confused about the state of Tuple in acceleo, so I'll avoid their use Smile


As I hinted, we have known bugs making Tuples non-functional (https://bugs.eclipse.org/bugs/show_bug.cgi?id=340735). It has been known for a long time, yet we have never considered it a priority : we never had to use Tuples in our generators, and no user has ever encountered it until you. I still think that Tuples are somewhat useless ... I may be proven wrong later when some generation requirements force me to use them, but until then I think it only as a complication of the language.

This is only my opinion, and of course we will consider fixing this issue if a user is bitten ... but until then it remains a "future work" Smile.

Laurent Goubet
Obeo
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755826 is a reply to message #755762] Wed, 09 November 2011 17:15 Go to previous message
Ed Willink is currently offline Ed WillinkFriend
Messages: 4188
Registered: July 2009
Senior Member
On 09/11/2011 14:08, Laurent Goubet wrote:
> I still think that Tuples are somewhat useless ...
I sort of agree; a lot of my usages have ultimately had a better
solution, although they do help disentangling nested Collection
declaration bugs.

My main usages have been in QVTo, where ultimately a Dict can do the job.

In Acceleo, I tend to be forced into custom Java code. Tuples should be
useful for multiple returns, but perhaps this is where the M2T should be
preceeded by a simplifying M2M rather than over-powerful queries and caches.

Tuples will be less useful once OCL supports type constructors.

Regards

Ed Willink
Previous Topic:[Jet] Execute alternative from override template
Next Topic:[Acceleo] Standalone application running error
Goto Forum:
  


Current Time: Sun Dec 21 23:27:03 GMT 2014

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

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