简体   繁体   English

JAXB和用于基础类型的XmlAdapter映射在Hash Map中

[英]JAXB and an XmlAdapter for base type mapped inside the Hash Map

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 ) 我正在开发一些JavaSE GUI应用程序,该应用程序必须将数据存储到XML文件中或从XML文件中加载数据(源代码可在此处获取: https : //github.com/SP8EBC/MKS_JG

In some place of the data structure I've a HashMap which bond a base type to Short. 在数据结构的某个地方,我有一个HashMap,它将基本类型绑定到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. 为了编组和解组这些类型,我开发了一个适配器,但是很遗憾,我对注释所做的任何操作都从未使用过,因此输出XML文件是错误的。 I put some breakpoints inside methods and on Debug software newer stops on these breaks. 我在方法内部放置了一些断点,在Debug软件上,在这些中断处有了新的停止点。

My questions is: What should I do inside the code to correctly handle this HashMap with my Adapter? 我的问题是:我应该在代码内部做什么以使用适配器正确处理此HashMap?

The class where the HashMap with base class exists is like that: 具有基类的HashMap存在的类是这样的:

@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. 如您所见,我编写了一个适配器,该适配器应该将完全不同的子对象转换为XML文件中标准化的内容。 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. 我只是为整个HashMap制作了一个适配器,而不是尝试进行marschall和unmarschall LugerCompetitor本身。 My solution is below and it seems to work when I'm generating the XML. 我的解决方案在下面,并且在生成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;
    }

}

First, if possible but not necessary, convert LugerCompetitor to an interface. 首先,如果可能但不必要,将LugerCompetitor转换为接口。 You can avoid all public abstract clutter: 您可以避免所有公共抽象混乱:

public interface LugerCompetitor {
    /**
     * .... some commentary in polish 
     */ 
    CompetitionTypes getCompetitorType();

    void setStartNumber(short num);
    @XmlTransient
    short getStartNumber();
}

Then you can define an element to represent LugerCompetitor and Short value: 然后,您可以定义一个表示LugerCompetitor和Short值的元素:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class LugerCompetitorValue {
    @XmlElement
    @XmlJavaTypeAdapter(LugerCompetitorAdapter.class)
    public LugerCompetitor competitor;

    @XmlElement
    public Short value;

}

And add a collection of LugerCompetitorValue to your class: 并将LugerCompetitorValue的集合添加到您的类中:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Competition {
 // some other fields and methods 
    @XmlElement
    public List<LugetCompetitorValue> lugerCompetitorValues;
}

Then adapter should start working. 然后适配器应该开始工作。 The question, however, is how are you expecting to unmarshal the data on the client side? 但是,问题是,您如何期望在客户端解组数据?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM