Monday, February 16, 2009

Create Maps in EMF - the other way

EMF wiki on Eclipsepedia has a post which shows you one method of creating maps in EMF.
I feel that the suggested method in wiki will not exactly allow you to access a map as it should be.
like say - myMap.put("key", value); Instead you'll have to do:

myMap.eSet(keyFeature,
"key");
myMap.eSet(valueFeature, valueObj);

After some trails here's the second method summarized in terms of steps.
To create a map using Reflective Ecore Editor:
  • create an EAttribute and set a name (let's say _map) to it.
  • set _map's EType as EMap [java.util.Map]
  • create an ETypedParameter for key and set EType accordingly
  • crate another ETypedParameter for value and set EType accordingly.

here is a snap shot of how a map looks in the Ecore Editor.

what happens behind the scenes of the editor ?
well, these lines of code are executed.


EAttribute _map = EcoreFactory.eINSTANCE.createEAttribute();
_map.setName("_map");
EGenericType _mapType = EcoreFactory.
eINSTANCE.createEGenericType();
_mapType.setEClassifier(EcorePackage.
eINSTANCE.getEMap());
// set key
EGenericType key = EcoreFactory.
eINSTANCE.createEGenericType();
key.setEClassifier(EcorePackage.
eINSTANCE.getEString());
// set key
EGenericType value = EcoreFactory.
eINSTANCE.createEGenericType();
value.setEClassifier(EcorePackage.
eINSTANCE.getEObject());
// add them
_mapType.getETypeArguments().add(key);
_mapType.getETypeArguments().add(value);
_map.setEGenericType(_mapType);


You have to use it like this:

Map _map = (Map) instance
.eGet(_mapFeature); // this is now java.util.Map
// don't forget to set the changes on _map back to instance!

Happy mapping!

4 comments:

Hendy said...

Your method seems complicated.

The one in the EMF Wiki works fine and I can access them as generic Map just fine...

Here's what it generated:

/**
* Returns the value of the '<em><b>Costs</b></em>' map.
* The key is of type {@link java.lang.String},
* and the value is of type {@link java.math.BigDecimal},
* <!-- begin-user-doc -->
* <p>
* If the meaning of the '<em>Costs</em>' map isn't clear,
* there really should be more of a description here...
* </p>
* <!-- end-user-doc -->
* @return the value of the '<em>Costs</em>' map.
* @see com.abispulsa.dealer.DealerPackage#getCostsResponse_Costs()
* @model mapType="com.abispulsa.dealer.StringToBigDecimal<org.eclipse.emf.ecore.EString, org.eclipse.emf.ecore.EBigDecimal>"
* @generated
*/
EMap<String, BigDecimal> getCosts();

B said...

hi chetan, how do you suggest we create a HashMap> with EMF?

thanks

Chetan said...

Hello Amrita,

In order to use Java collections instead of EMF types, you have to set "Supress EMF Types" to true in the genmodel properties.

+ Chetan

roza.gh said...

Hi cheta,
What if we need a linkedhashmap? If we need to keep the order of insertion? Do we have anything for this in EMF?