Я разрабатываю некоторое приложение JavaSE GUI, которое должно хранить и загружать свои данные из / в XML-файл (исходный код доступен здесь: https://github.com/SP8EBC/MKS_JG)
В некотором месте структуры данных у меня естьHashMap, который связывает базовый тип с Short. На практике этот базовый тип является абстрактным классом, поэтому мое программное обеспечение добавляет объект дочерних классов в качестве ключей. Для маршалинга и демаршаллинга этих типов я разработал адаптер, но, к сожалению, все, что я сделал с аннотациями, этоадаптер никогда не используется, поэтому выходной XML-файл неправильный. Я поставил некоторые точки останова в методах и в программном обеспечении отладки новые остановки на этих перерывах.
Мои вопросы: что я должен делать внутри кода, чтобы правильно обрабатывать этоHashMap с моим адаптером?
Класс, в котором существует HashMap с базовым классом, выглядит следующим образом:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Competition {
// some other fields and methods
@XmlElement
public HashMap<LugerCompetitor, Short> startList;
}
На этом этапе объявление базового класса выглядит следующим образом
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
@XmlJavaTypeAdapter(value = LugerCompetitorAdapter.class)
public abstract class LugerCompetitor {
/**
* .... some commentary in polish
*/
public abstract CompetitionTypes getCompetitorType();
public abstract void setStartNumber(short num);
@XmlTransient
public abstract short getStartNumber();
public abstract String toString();
}
И один из дочерних классов выглядит следующим образом
public class LugerDouble extends LugerCompetitor {
/**
* Saneczkarz na górze
*/
public Luger upper;
/**
* Saneczkarz na dole
*/
public Luger lower;
short startNum;
@Override
public CompetitionTypes getCompetitorType() {
// TODO Auto-generated method stub
return null;
}
public String toString() {
String out;
out = upper.surname + " / " + lower.surname;
return out;
}
@Override
public short getStartNumber() {
return this.startNum;
}
@Override
public void setStartNumber(short num) {
this.startNum = num;
}
}
Как видите, я написал адаптер, который долженпреобразовать совершенно разные дочерние объекты во что-то стандартизированное в XML-файле.Адаптер выглядит следующим образом:
public class LugerCompetitorAdapter extends XmlAdapter<LugerCompetitorAdapter.AdaptedCompetitorLuger, LugerCompetitor> {
public static class AdaptedCompetitorLuger {
@XmlAttribute
public long lugerSystemId; // LugerSingle
@XmlAttribute
public long bottomLugerSystemId; // Dwójka sankowa - dół
@XmlAttribute
public long upperLugerSystemId; // Dwójka sankowa - góra
@XmlAttribute
public long maleLugerSystemId; // Sztafeta albo drużyna
@XmlAttribute
public long femaleSystemId; // jw
@XmlAttribute
public long doubleSystemId; // jw
}
@Override
public AdaptedCompetitorLuger marshal(LugerCompetitor v) throws Exception {
AdaptedCompetitorLuger adaptedCompetitorLuger = new AdaptedCompetitorLuger();
if (v instanceof LugerSingle) {
adaptedCompetitorLuger.lugerSystemId = ((LugerSingle)v).single.getSystemId();
return adaptedCompetitorLuger;
}
if (v instanceof LugerDouble) {
adaptedCompetitorLuger.bottomLugerSystemId = ((LugerDouble)v).lower.getSystemId();
adaptedCompetitorLuger.upperLugerSystemId = ((LugerDouble)v).upper.getSystemId();
return adaptedCompetitorLuger;
}
return null;
}
@Override
public LugerCompetitor unmarshal(AdaptedCompetitorLuger v) throws Exception {
return null;
}
}
РЕДАКТИРОВАТЬ (добавлено решение)
Так что я сделал то, что хочу, совершенно другим способом.Я только что сделал адаптер для всей HashMap, вместо того, чтобы пытаться сделать маршалл и демаршалл самого LugerCompetitor.Мое решение ниже, и, кажется, оно работает, когда я генерирую XML.Противоположное направление еще нужно развивать.
@Component
public class StartListAdapter extends XmlAdapter<StartListAdapter.AdaptedStartList, Map<LugerCompetitor, Short>> {
RTE_ST rte_st;
@Autowired
@Lazy
public void setRTE(RTE_ST rte) {
rte_st = rte;
}
public static class AdaptedStartList {
@XmlElement(name="startListEntry")
public List<AdaptedEntry> adaptedList = new ArrayList<AdaptedEntry>();
}
public static class AdaptedEntry {
@XmlElement(required = false, nillable = true )
public Long lugerSystemId; // konkurencja pojedyncza K albo M
@XmlElement(required = false, nillable = true )
public Long lowerLugerSystemId; // dwójki sankowe - sankarz na dole
@XmlElement(required = false, nillable = true )
public Long upperLugerSystemId; // j/w ale sankarz na górze
@XmlElement(required = false, nillable = true )
public Long maleLugerSystemId; // M podczas sztafety albo konkurencji drużynowej
@XmlElement(required = false, nillable = true )
public Long femaleLugerSystemId; // K j/w
@XmlElement(required = true)
public short startNumber;
}
@Override
public AdaptedStartList marshal(Map<LugerCompetitor, Short> arg0) throws Exception {
AdaptedStartList out = new AdaptedStartList();
for (Entry<LugerCompetitor, Short> e : arg0.entrySet()) {
AdaptedEntry adaptedEntry = new AdaptedEntry();
LugerCompetitor k = e.getKey();
if (k instanceof LugerSingle) {
adaptedEntry.lugerSystemId = ((LugerSingle)k).single.getSystemId();
adaptedEntry.startNumber = e.getValue();
}
else if (k instanceof LugerDouble) {
adaptedEntry.lowerLugerSystemId = ((LugerDouble)k).lower.getSystemId();
adaptedEntry.upperLugerSystemId = ((LugerDouble)k).upper.getSystemId();
adaptedEntry.startNumber = e.getValue();
}
out.adaptedList.add(adaptedEntry);
}
return out;
}
@Override
public Map<LugerCompetitor, Short> unmarshal(AdaptedStartList arg0) throws Exception {
return null;
}
}