EMF and XSD – How to add values to a Feature Map

Eclipse provides a nice feature to create ECore metamodels based on an XML Schema. While it is fairly simple to create a metamodel and subsequently generate Java code from the metamodel with a genmodel, there are some obstacles when using this Java implementation on code level. One prominent problem are features of a class which are realized with a FeatureMap. In this article I explain how to add instances to a FeatureMap.

Foundation

Usually, an XSD attribute is mapped to class EAttribute and XSD content is mapped to an EReference. However, it is possible in an XSD to allow multiple different types as content of an xsd:element. In those cases EMF realizes this mixed typed reference with a FeatureMap.

There is a lot of documentation available on how to read from such FeatureMap. For example:

However, these sources do not describe how to insert values into the map programmatically. Therefore, I investigated the issue and found one hint in a forum post. However, it is hard to understand when you do not understand a lot about feature maps. In an effort to document my solution, I decided to also post it on my blog, hoping some can benefit from it (and I certainly will, as I can now look it up for any place on this lovely planet).

Solution

Lets assume you have an XSD with an element data.

<xsd:element name="data" minOccurs="0" maxOccurs="unbounded">
   <xsd:complexType>
      
         
      
   

Based on this XSD you generated a metamodel, created a genmodel for this model, and generated the Java classes for the metamodel. In this case the there will by a Java class DataType with an attribute any of type <a href="http://download.eclipse.org/modeling/emf/emf/javadoc/2.5.0/org/eclipse/emf/ecore/util/FeatureMap.html">FeatureMap. Apart from the EClasses realizing the different element declarations, the generated Java code also contains a class YourPackageNameFactory and YourPackageNamePackage, where YourPackageName is (usually) the name of the root package of the metamodel plus some package prefix you defined.

Now you can implement code to create model elements. First, lets create a data element:

DataType data = YourPackageNameFactory.eINSTANCE.createDataType;
data.name = "Some name";
// This is only an example, you might use another option from the enumeration.
data.handleUnknown = HandleUnknownType.IMPLEMENTATION;

Second, lets create some content for the data element:

SomeOtherType other = YourPackageNameFactory.eINSTANCE.createSomeOtherType
// Here set all attributes of 'other'

And third, assign the other element to the data element:

data.any.add(YourPackageNamePackage.eINSTANCE.getDataType_Any(), other);

YourPackageNamePackage provides accessors for classes, features, operations, enumerations, and data types. The signature of the add method of the FeatureMap any requires as first parameter a structural feature. They are named getFeatureName_AttributeName.

Hope that helps. Any comments welcome.