@XmlJavaTypeAdapter, наследование и xsi:тип

Хорошо, вот что происходит, когда я делаю следующее:

Entities.java: все те классы, имена которых начинаются с «E» (например, EStudent, ETeacher и т. д.), расширяют класс EntityWithId.

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;

  ...
}

entity-xml-bindings.xml: я установил xml-java-type-adapter для всех свойств. Опущено для ясности.

<?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: предназначен для преобразования карт в коллекции.

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() {}
}

Когда я упорядочиваю это, вывод выглядит следующим образом.

<?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>

Вы заметили эти xsi:type? Когда я опускаю их, unmarshaller явно терпит неудачу. Но я не хочу, чтобы все теги <entry> имели это. Я бы предпочел следующее:

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

Спасибо за помощь.


person mostruash    schedule 12.04.2013    source источник
comment
Этот вопрос кажется связанным с моим, но его ответ недостаточно ясен: stackoverflow.com/questions/8912925/   -  person mostruash    schedule 12.04.2013


Ответы (1)


Я решил эту проблему благодаря блогам Блейза Догана. Хитрость заключается в том, чтобы использовать @XmlAnyElement(lax=true) и аннотировать дочерние классы EntityWithId с помощью @XmlRootElement.

class MyCollection {

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

  public MyCollection() {}
}

Вывод, который я получаю:

<?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>
person mostruash    schedule 12.04.2013