Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » M2T (model-to-text transformation) » Acceleo : How to cast in a Collection ?(Impossible to cast an OclAny typed object in a Sequence)
Acceleo : How to cast in a Collection ? [message #1766897] Wed, 28 June 2017 15:47 Go to next message
Mad Vin is currently offline Mad VinFriend
Messages: 23
Registered: September 2013
Junior Member
Hello,

Here is a simple extract of code to show easily the problem (so replace OclAny by Sequence(OclAny) is not the answer i want :p, because i have this kind of problem for a much more complex architecture) :

[let seq : OclAny = Sequence{1, 'str', Set(OclAny), null}] ... [/let]


How to retrieve seq->at(1) ? seq->at(2) ? seq->at(3) ? seq->at(4) ? How to cast seq into a Sequence(OclAny) ?
I've found nothing on the internet. Without this cast, it's impossible to retrieve the elements of the sequence, because the 'at' method cannot be called on an OclAny typed variable, "->oclAsType" cannot be called on an OclAny typed variable, and the oclAsType method refuses Sequence(OclAny) argument. Same problem in the queries.

Thank you for your help.

Acceleo version : 3.4.1
Eclipse version : Helios Service Release 2
Re: Acceleo : How to cast in a Collection ? [message #1766905 is a reply to message #1766897] Wed, 28 June 2017 16:33 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5585
Registered: July 2009
Senior Member
Hi

(oclAsType(Sequence(OclAny) works with the newer PIvot-based OCL, but that doesn't help you with Acceleo.)

The correct answer is the one you don't want. seq is a Sequence(OclAny) so you must declare it as such. You'll need to provide the real problem so that the real problem can be addressed.

Regards

Ed Willink
Re: Acceleo : How to cast in a Collection ? [message #1766947 is a reply to message #1766905] Wed, 28 June 2017 23:35 Go to previous messageGo to next message
Mad Vin is currently offline Mad VinFriend
Messages: 23
Registered: September 2013
Junior Member
Ok, that's what i thought... it's particularly weird for a typed language to not allow to cast a type into a subtype, especially when the subtype is a type defined by the language... :/

Aren't the Sequence instances typed by a subtype of EObject that we could use to do the cast ? Aren't there a solution to retrieve these Sequences and their contents by using a Java services class that i could implement ?

I'm going to try to explain what i want to do : I need to use several internal structures in Acceleo to store some settings (a setting is implemented by storing a setting's id associated to a specific value described in the documentation) about some elements (some of them can be extracted from an emx model, and others can be specified by the Acceleo developers). So it's a kind of Acceleo queries API that will be used by the other Acceleo developers. This API defines queries for creating these structures with the specified settings values, for enabling to access to the values of these settings in a simple way, and for generating the expected code according to the values of the specified settings of a structure.
But i want to hide the internal implementation of these structures from the callers because i want that these structures can be extended by new features later without modifying the already existing calls. It's too long to explain exactly how i do it, but to be brief, the API queries creating structures return an OclAny object (the internal implementation is hidden because it is too complex, and this implementation is done by a Sequence of several kind of objects more or less complex that the developers don't need to know), and the API queries accessing to the structures and generating the expected code take these structures instances as parameter. My problem is that the caller gives to the queries generating code an OclAny typed parameter that i know it is a Sequence of several objects in a specific order (the hidden internal implementation that i'm the only one who needs to know), but i can't specify to Acceleo that this OclAny parameter is a Sequence... This is my problem.

Sorry if it's hard to understand... I know a better solution to do that is to create a new ECore defining these structures, to generate this Ecore code, to import in the Acceleo project this metamodel, and to create the instances in a java services class called by Accelo queries. but for the moment i would like to find a simple solution without adding any external dependency to the Acceleo projects because i've got several Acceleo projects executed in standalone outside Eclipse and depending from each others, and i prefer to avoid to lose time for the moment by trying to fix the dependencies errors.

Thank you for your patience. ;)

[Updated on: Thu, 29 June 2017 03:32]

Report message to a moderator

Re: Acceleo : How to cast in a Collection ? [message #1766957 is a reply to message #1766947] Thu, 29 June 2017 06:21 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5585
Registered: July 2009
Senior Member
Hi

You give me very little to work with. I can debug code, I cannot debug vague aspirations.

In OCL 2.0 on which the Classic Eclipse OCL that Acceleo is based, Collection did not conform to OclAny (OCL 2.2 introduced the change). However there is some polymorphism so sometimes it works, but there are problems when behind the scenes it is not clear whether an eGet() return is an EList or EObject.

Acceleo provides some helper functions such as filter that might do something useful.

But I'm afraid that until you convince me you need to use OclAny rather than Collection, I can only urge you to consider your design more carefully. I'm sure your problem is solvable but you must provide something that can be debugged.

Regards

Ed Willink
Re: Acceleo : How to cast in a Collection ? [message #1766968 is a reply to message #1766957] Thu, 29 June 2017 07:55 Go to previous messageGo to next message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1843
Registered: July 2009
Senior Member
Hi,

You will encounter issues with the OCL implementation we rely on not considering that Sequences (collections, in general) are instances of OclAny so what you plan to achieve is at first sight impossible in Acceleo.

It seems extremely strange, however, that you're basically saying "my user will send me an object that I know is a Sequence, but I don't want to type my parameter as a Sequence". By default, I consider that APIs that take "Object" as parameter without telling me exactly what they want are a bad design. I really agree with Ed here in that it seems, from the explanation you've given, that you should really reconsider the design of your APIs. Do you really want to obfuscate your APIs with OclAny parameters?

Nevertheless, if you're really stuck on this design decision for any reason, you will have to work around the limitations of the underlying OCL implementation. That will have to be done either in Java (through a service call) or with quirky workarounds in your acceleo template such as casting into a set then flattening it... And I'm not even sure that would work, especially if your initial sequence can contain other sequences. You haven't given us much to work with but off the top of my head, these are the only things I can think of that might help:

myOclAny->flatten() (the "->" operator on an object that is not typed as a sequence is an implicit cast into a set, but you'll likely end up with a Set containing your Sequence)
myOclAny->asSequence() (same deal here, that will likely be a Sequence containing your initial sequence as sole object, but it's still typed as oclAny so you likely won't be able to use it)

Laurent Goubet
Obeo
Re: Acceleo : How to cast in a Collection ? [message #1766984 is a reply to message #1766968] Thu, 29 June 2017 09:27 Go to previous messageGo to next message
Mad Vin is currently offline Mad VinFriend
Messages: 23
Registered: September 2013
Junior Member
Thank you for your answers.

I know such a design is not perfect because the structures i create are not typed clearly, and i suppose that the only way to create properly new typed complex structures usable in Acceleo is to create a new metamodel only for this task. But like i said, for the moment i prefer to avoid this solution.

I can't explain to you easily the architecture of my API, the only thing to know is that it should work like i wanted, but the only problem i have is this problem of cast of OclAny objects into Collections.

But after having tested several things, i've finally found a solution by using a Java services method that is simple. It only needs to create a query calling a Java services method casting the OclAny object into Sequence, like this :

@SuppressWarnings("unchecked")
    public static List<Object> castObjectIntoSequence(Object obj) {
        return (List<Object>) obj;
    }


[query public castObjectIntoSequence(contextObject : OclAny, obj : OclAny) : Sequence(OclAny) =
invoke('package1.MyJavaServicesClass', 'castObjectIntoSequence(java.lang.Object)', Sequence{obj})
/]


We have to do the same kind of solution for Set instances and other Collections types.

And it works ! I can easily retrieve like this the contents of the Sequence. And if one of the element of the Sequence is another Sequence or a Set, it only needs to call the corresponding cast query on this element. Ex :
castObjectIntoSet(castObjectIntoSequence(myObject)->at(2))
if the second element of the Sequence is a Set.


Thank you for your support.

Best regards.
Re: Acceleo : How to cast in a Collection ? [message #1767010 is a reply to message #1766984] Thu, 29 June 2017 13:47 Go to previous message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1843
Registered: July 2009
Senior Member
Good to know you found a solution!

Laurent Goubet
Obeo
Previous Topic:Vhdl code generation from UML model using acceleo
Next Topic:Stereotypes
Goto Forum:
  


Current Time: Mon Jan 22 12:46:35 GMT 2018

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

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