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 10:18  |
Eclipse User |
|
|
|
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 11:42   |
Eclipse User |
|
|
|
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 #755662 is a reply to message #755641] |
Wed, 09 November 2011 04:04   |
Eclipse User |
|
|
|
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 #755706 is a reply to message #755690] |
Wed, 09 November 2011 05:50   |
Eclipse User |
|
|
|
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 05:51] by Moderator
|
|
| | |
Re: [acceleo 3.2] queries and nested Sequence of model objects [message #755826 is a reply to message #755762] |
Wed, 09 November 2011 12:15  |
Eclipse User |
|
|
|
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
|
|
|
Goto Forum:
Current Time: Wed Jul 23 08:51:37 EDT 2025
Powered by FUDForum. Page generated in 0.24638 seconds
|