Home » Modeling » M2T (model-to-text transformation) » [acceleo 3.2] queries and nested Sequence of model objects
|
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   |
Ed Willink Messages: 7635 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 #755662 is a reply to message #755641] |
Wed, 09 November 2011 09:04   |
Ed Willink Messages: 7635 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   |
Marc Missing name Messages: 38 Registered: March 2011 |
Member |
|
|
Edward Willink wrote on Wed, 09 November 2011 04:04Hi 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 #755706 is a reply to message #755690] |
Wed, 09 November 2011 10:50   |
|
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 #755762 is a reply to message #755756] |
Wed, 09 November 2011 14:08   |
|
Marc,
You're welcome .
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 
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" .
Laurent Goubet
Obeo
|
|
| |
Goto Forum:
Current Time: Sat Dec 09 15:03:58 GMT 2023
Powered by FUDForum. Page generated in 0.02664 seconds
|