Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » M2T (model-to-text transformation) » [Acceleo] Map data type?
[Acceleo] Map data type? [message #1840367] Tue, 13 April 2021 09:50 Go to next message
Denis Nikiforov is currently offline Denis NikiforovFriend
Messages: 283
Registered: August 2013
Senior Member
Hi

What is a preferred way to work with maps in Acceleo?

For example, I have a Java service returning Map<String, String> or List<Map.Entry<String, String>>, etc.

Is it possible to get all keys from the map or to get a value by a key?

Actually my Java service can return any data structure. The problem is that I don't understand how to handle it in Acceleo. For now, it seems that the only way is to simulate maps by List<List<String>>. Is it right?
Re: [Acceleo] Map data type? [message #1840368 is a reply to message #1840367] Tue, 13 April 2021 11:18 Go to previous messageGo to next message
Denis Nikiforov is currently offline Denis NikiforovFriend
Messages: 283
Registered: August 2013
Senior Member
Sequence(Sequence(String)) is not very handy replacement for maps.

I think Sequence(Tuple(key : String, value : String)) would be better. However it seems that it's not supported: https://www.eclipse.org/forums/index.php/t/1098323/
Re: [Acceleo] Map data type? [message #1840369 is a reply to message #1840368] Tue, 13 April 2021 11:42 Go to previous messageGo to next message
Denis Nikiforov is currently offline Denis NikiforovFriend
Messages: 283
Registered: August 2013
Senior Member
Sequence(EStringToStringMapEntry) would be great too. But I don't understand how to create them in a Java service.
Re: [Acceleo] Map data type? [message #1840370 is a reply to message #1840369] Tue, 13 April 2021 12:01 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7127
Registered: July 2009
Senior Member
Hi

Map is not supported by OCL and so not by Acceleo that leverages OCL.

Set<Tuple<Key,Value>> is often considered to be equivalent but isn't. See [1] for my paper on the Map type support in the Pivot-based Eclipse OCL, which makes Maps available in QVTc and QVTr. QVTo has a Dict type.

I have never tried, but it might be possible to use Acceleo's Java escapes to access the Pivot OCL Map, Java Map, or EMF's EMap. But beware that EMap is actually just an EList with some map-like operations.

Experience has shown me that, in Java at least, after using a Map for a while, I need to reify the Map.Entry as a genuine class. Once you do this you only need a Set. Reifying a Map Entry is almost certainly easier and cleaner than tricking Acceleo into doing something unnatural. (Similarly an Operation with a long parameter list is often hiding a hidden user class.)

Regards

Ed Willink

[1] http://www.eclipse.org/modeling/mdt/ocl/docs/publications/OCL2019MapType/OCLMapType.pdf
Re: [Acceleo] Map data type? [message #1840371 is a reply to message #1840370] Tue, 13 April 2021 12:12 Go to previous messageGo to next message
Denis Nikiforov is currently offline Denis NikiforovFriend
Messages: 283
Registered: August 2013
Senior Member
Thanks for answer!

The problem is that the only data structure I was able to return from my Java service is List<List<String>> treated as Sequence(Sequence(String)) in Acceleo.

I don't understand how to return Tuple, EStringToStringMapEntry, etc. And how to work with these data types in Acceleo. It seems that only collections and plain data types are fully supported. I can't even define a query returning a Tuple. I get the error: "Invalid Type: Sequence(Tuple(key : String, value : String))"

It seems for me that the only representation for maps supported by Acceleo is Sequence(Sequence(String)).
Re: [Acceleo] Map data type? [message #1840373 is a reply to message #1840371] Tue, 13 April 2021 13:01 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7127
Registered: July 2009
Senior Member
Hi

As explained in my paper Sequence(Sequence(String)) cannot be equivalent since a Map is unique wrt the key but multi-valued. Sequence(Sequence(String)) is unique wrt key+value.

As per my previous answer, short of non-standard Acceleo heroics, your only solution is to reify Map.Entry as a user class. Personally I find Xtend much more satisfactory since it is layered on Java so any limitation can be resolved by natural Java.

Regards

Ed Willink
Re: [Acceleo] Map data type? [message #1840379 is a reply to message #1840373] Tue, 13 April 2021 13:49 Go to previous messageGo to next message
Denis Nikiforov is currently offline Denis NikiforovFriend
Messages: 283
Registered: August 2013
Senior Member
I've found a satisfactory solution!

My Java-service returns Map<String, String>:
public Map<String, String> getProperties(EObject eObject) {
     // ...
}


Which is treated as EMap:
[query public getProperties(obj : OclAny) : EMap =
  invoke(
    '...service.CommonService',
    'getProperties(org.eclipse.emf.ecore.EObject)',
    Sequence{obj})/]


And here are some helper methods:

[query public keys(arg : EMap) : Set(String) =
  invoke('...service.CommonService',
    'getStringMapKeys(java.util.Map)',
    Sequence{arg})/]

[query public get(arg : EMap, key : String) : String =
  invoke('...service.CommonService',
    'getStringMapValue(java.util.Map, java.lang.String)',
    Sequence{arg, key})/]

[query public merge(arg : Sequence(EMap)) : EMap =
  invoke('...service.CommonService',
    'mergeStringMaps(java.util.List)',
    Sequence{arg})/]


And their implementation:
    public Set<String> getStringMapKeys(Map<String, String> obj) {
        return obj.keySet();
    }

    public String getStringMapValue(Map<String, String> obj, String key) {
        return obj.get(key);
    }
    
    public Map<String, String> mergeStringMaps(List<Map<String, String>> objs) {
        Map<String, String> result = new HashMap<>();
        for (Map<String, String> obj : objs) {
            obj.forEach(result::putIfAbsent);
        }
        return result;
    }


It seems to work for me.
Re: [Acceleo] Map data type? [message #1840738 is a reply to message #1840379] Fri, 23 April 2021 06:27 Go to previous message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7127
Registered: July 2009
Senior Member
Hi

Sorry. Retraction

Quote:
reify Map.Entry as a user class


Rubbish. This has the same key+value rather than key uniqueness problems as the Set<Tuple> 'solution'.

Regards

Ed Willink
Previous Topic:java.lang.ClassCastException while transforming source EReference to Target ERefernce.
Next Topic:[Xtend] M2T transformation examples
Goto Forum:
  


Current Time: Sat May 08 22:12:27 GMT 2021

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

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

Back to the top