2

Alright here is what happens when I do the following:

Entities.java: All of those classes whose names start with "E" (e.g. EStudent, ETeacher etc.) extends EntityWithId class.

public class Entities {

  Map<Integer,EStudent> students;
  Map<Integer,ETeacher> teachers;
  Map<Integer,ECourse> courses;
  Map<Integer,EQuiz> quizzes;
  Map<Integer,EQuestion> questions;
  Map<Integer,EAnswer> answers;
  Map<Integer,ETimeslot> timeslots;
  Map<Integer,ESharedFile> sharedFiles;

  ...
}

entities-xml-bindings.xml: I set xml-java-type-adapter for all properties. Omitted for clarity.

<?xml version="1.0" encoding="US-ASCII"?>
  <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="com.pest.esinif.common.entity">

<java-types>
    <java-type name="Entities">
        <java-attributes>
            <xml-element java-attribute="students" >
                <xml-java-type-adapter value="com.pest.esinif.common.entity.adapters.MapToCollectionAdapter" />
            </xml-element>
            ...
        </java-attributes>
    </java-type>
</java-types>
</xml-bindings>

MapToCollectionAdapter.java: Intends to convert Maps to Collections.

public class MapToCollectionAdapter extends XmlAdapter<MyCollection, Map<Integer,EntityWithId>> {

@Override
public Map<Integer, EntityWithId> unmarshal(MyCollection v) throws Exception {
    Map<Integer, EntityWithId> m = new TreeMap<>();

    for (Iterator<EntityWithId> it = v.list.iterator(); it.hasNext();) {
        EntityWithId i = it.next();
        m.put(i.getId(), i);
    }

    return m;
}

@Override
public MyCollection marshal(Map<Integer, EntityWithId> v) throws Exception {
    if(v == null) {
        return null;
    }
    MyCollection mc = new MyCollection();
    mc.list = v.values();
    return mc;
}

class MyCollection {

  @XmlElement(name="entry")
  public Collection<EntityWithId> list;

  public MyCollection() {}
}

When I marshal this, output is as below.

<?xml version="1.0" encoding="UTF-8"?>
<entities>
   <courses>
      <entry id="4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="eCourse">
         <name>English</name>
         <timetable>5</timetable>
         <timetable>6</timetable>
      </entry>
   </courses>
   <students>
      <entry id="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="eStudent">
         <name>Anil Anar</name>
      </entry>
   </students>
   <timeslots>
      <entry id="12" course="4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="eTimeslot">
         <attendances>1</attendances>
         <day>1970-01-01T02:00:00.0</day>
         <slot>0</slot>
      </entry>
   </timeslots>
</entities>

Have you noticed those xsi:types? When I omit them, unmarshaller obviously fails. But I don't want all <entry> tags to have that. I would prefer it as follows:

<courses child-xsi-type="eCourse">
    <entry> ... </entry>
    <entry> ... </entry>
</courses>

Thanks for help.

mostruash
  • 4,169
  • 1
  • 23
  • 40
  • This question seems like its related to mine but its answer is not clear enough: http://stackoverflow.com/questions/8912925/jaxb-elipselink-xmljavatypeadapter-and-the-type-attribute?rq=1 – mostruash Apr 12 '13 at 19:14

1 Answers1

0

I solved the problem thanks to Blaise Doughan's blogs. The trick is to use @XmlAnyElement(lax=true) and is to annotate child classes of EntityWithId with @XmlRootElement.

class MyCollection {

  @XmlAnyElement(lax=true)
  public Collection<EntityWithId> list;

  public MyCollection() {}
}

Output I get:

<?xml version="1.0" encoding="UTF-8"?>
<entities>
   <courses>
      <course id="4">
         <name>English</name>
         <timetable>5</timetable>
         <timetable>6</timetable>
      </course>
   </courses>
   <students>
      <student id="1">
         <name>Anil Anar</name>
      </student>
   </students>
   <timeslots>
      <timeslot id="12">
         <attendances>1</attendances>
         <day>1970-01-01T02:00:00.0</day>
         <slot>0</slot>
      </timeslot>
   </timeslots>
</entities>
mostruash
  • 4,169
  • 1
  • 23
  • 40