Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Adding AnyType to AnyType Feature Map
Adding AnyType to AnyType Feature Map [message #1747339] Sat, 12 November 2016 15:14 Go to next message
Benjamin Alt is currently offline Benjamin AltFriend
Messages: 1
Registered: November 2016
Junior Member
I already posted this question on Stack Overflow some time ago but did not get an answer, so now I hope one of you might be able to help me out...

I am building an XML importer using the EMF. To that end, I had EMF generate me an Ecore model from my XSD metamodel and generate the corresponding Java classes from the Ecore model. Now I am reading in an XML file conforming to my XSD schema and got stuck at the following issue: Creating object instances for all types defined in the XSD schema works perfectly well and I get a nice Java object (instance) hierarchy, but I can't manage to create instances of "AnyType" Elements.

The (simplified) XSD schema is attached.

So say I have the following XML conforming to my XSD:
<XMLFile xsi:noNamespaceSchemaLocation="My_xsd_file.xsd" FileName="Example.xml" SchemaVersion="1.10" xmlns:xsi="http://www.w3 dot org/2001/XMLSchema-instance">
    	<Version>2.1</Version>
    	<AdditionalInformation someAttribute="someValue" />
    	<AdditionalInformation>
    		<SomeChildElement>
    			<ChildA>Some content</ChildA>
    			<ChildB>Some content</ChildB>
    		</SomeChildElement>
        </AdditionalInformation>
</XMLFile>

XMLFile and Version are types defined in the XSD schema; I can instantiate the generated XMLFile Java object, it has a reference to a Version object which I can instantiate as well. It even has a reference to AdditionalInformation, but because AdditionalInformation has been declared of type xs:anyType in the XSD schema, the reference AdditionalInformation of XMLFile points to an EObject which itself has no references (so I cannot add its children to it) and one cannot add references to EObject. Here is my code to set these references:
    for (EReference reference : object.eClass().getEAllReferences()) {
    	if (reference.getName().toLowerCase().equals(childNode.getNodeName().toLowerCase())) {
    	EClass type = Utils.getInstantiableEClass(reference.getEReferenceType());
    	    if (type != null && reference.isChangeable()) {
    			if (reference.isMany()) {
    				EList list = (EList)object.eGet(reference);
    				EObject obj = EcoreUtil.create(type);
    				if(obj.getClass().equals(EObjectImpl.class)) {
    					obj = xmlFactory.createAnyType();
    				}
    				//recursiveImport(childNode, obj);
    				list.add(obj);
                    ...

So when I noticed this doesn't work with EObjects, I create an AnyType object instead (see code above), as (theserverside dot com)/news/1364302/Binding-XML-to-Java (I'm not allowed to link to sites outside of eclipse.org yet) says that's what AnyType objects are for.
However, I cannot set the AnyType object's references either:

    if (object instanceof AnyType) {
    	NodeList children = node.getChildNodes();
    	for (int i = 0; i < children.getLength(); i++) {
    		Node childNode = children.item(i);
    		switch (childNode.getNodeType()) {
    		case Node.ELEMENT_NODE:
    			AnyType childObj = xmlFactory.createAnyType();
    			recursiveImport(childNode, childObj);
    			Entry entry = FeatureMapUtil.createEntry(xmlPackage.getAnyType_Any(), childObj);
    			((FeatureMap) object.eGet(xmlPackage.getAnyType_Any())).add(entry); // throws exception
    			((AnyType) object).getAny().add(entry); // throws exception
    			...

This throws an exception:
    Exception in thread "main" java.lang.ClassCastException: The feature 'any's type 'EFeatureMapEntry' does not permit a value of type 'AnyType'
    	at org.eclipse.emf.ecore.impl.EStructuralFeatureImpl$BasicFeatureMapEntry.validate(EStructuralFeatureImpl.java:3213)
    	at org.eclipse.emf.ecore.util.FeatureMapUtil.createEntry(FeatureMapUtil.java:174)

I am confused. Isn't the AnyType object supposed to do exactly that? Allow an arbitrary number of AnyType children?

Do you know how to dynamically add a reference/feature map entry of an arbitrary type (AnyType OR one of the classes I had EMF generate from my XSD) to an AnyType object instance?

P.S.: I read https://www.eclipse.org/forums/index.php/t/536670/ and http://www.eclipse.org/modeling/emf/docs/presentations/EclipseCon/EclipseCon2006_EMF_XML_Binding.pdf, to no avail. I also tried to do what is recommended at (theserverside dot com)/news/1364302/Binding-XML-to-Java (the forum lets me link only to eclipse.org sites) but it did not really help me, as I ran into another error ("Feature 'XMLFile' not found" exception, even though XMLFile is clearly defined in my XSD)...
  • Attachment: demo.xsd
    (Size: 3.30KB, Downloaded 59 times)
Re: Adding AnyType to AnyType Feature Map [message #1747464 is a reply to message #1747339] Tue, 15 November 2016 08:06 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 31900
Registered: July 2009
Senior Member
It's a very long question...

So when you're converting the XML content for some element of type anyType, you're creating an AnyType instance rather than an EObject because an EObject instance has no features and therefore can't capture any other information in the XML you're converting. Of course I'm not sure why you're writing such conversion logic when EMF already does all this automatically, e.g., org.eclipse.emf.ecore.xmi.XMLResource.load(Node, Map<?, ?>) if you have a Node as input as opposed to parsing the XML directly...

In any case, then you recursively need to process the contents for this AnyType instance at which point you need to deal with attributes and elements (and white space) for that nested XML which can have arbitrary content. At this point you really need to start using ExtendedMetadata and demand create the attributes and elements from the namespace and name you see in the XML, i.e., org.eclipse.emf.ecore.util.ExtendedMetaData.getAttribute(String, String) and org.eclipse.emf.ecore.util.ExtendedMetaData.getElement(String, String). The feature of the feature map entry you create should be such a demand-created feature with the right namespace and name.


Ed Merks
Professional Support: https://www.macromodeling.com/
Previous Topic:Setting Single Containment Reference of A Model Element's using EMF Reflective API
Next Topic:CamelCase in EMF generated Getter/Setter names
Goto Forum:
  


Current Time: Tue Jun 15 17:31:21 GMT 2021

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

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

Back to the top