I'm developing some JavaSE GUI application which has to store and load it's data from/to XML file (source code avaliable here: https://github.com/SP8EBC/MKS_JG)
In some place of the data structure I've a HashMap which bond a base type to Short. In practice this base type is an abstract class, so my software adds object of child classes as a keys. To marshall and unmarshall these types I developed an adapter, but unfortunatelly whatever I did with annotations this adapter is never used, so the output XML file is wrong. I put some breakpoints inside methods and on Debug software newer stops on these breaks.
My questions is: What should I do inside the code to correctly handle this HashMap with my Adapter?
The class where the HashMap with base class exists is like that:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Competition {
// some other fields and methods
@XmlElement
public HashMap<LugerCompetitor, Short> startList;
}
At this point declaration of the base class looks like this
@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();
}
And one of the child classes looks like this
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;
}
}
As You see I wrote an Adapter which should convert totally different child objects to something standarized in the XML file. The adapter looks as follows:
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;
}
}
EDIT (Solution added)
So I made what I want in quite another way. I just made an adapter for whole HashMap, instead of trying do marschall and unmarschall LugerCompetitor itself. My solution is below and it seems to work when I'm generating the XML. Opposite direction still need to be developed.
@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;
}
}