开发者

how to handle references between elements in JAXB

开发者 https://www.devze.com 2023-02-16 05:14 出处:网络
There is next problem, i have similar class structure: class A { public String a; } class B extends A {

There is next problem, i have similar class structure:

class A {
 public String a;
}

class B extends A {
 public String b; 
}

class C {
  public List<A> alist;
  public A current;
}

Structure of this classes can not be changed. I.e. i can not add id attribute. I need to create xsd schema for those classes. current element is one from alist element. So I wa开发者_运维知识库nt some kind of references here. But I don't see how @XmlID, @XmlIREF can be used. Then base on schema xml files will be generated and loaded via JAXB to objects. Are there any way to do this? May be somehow use xpointer or whatever, that JAXB can understand?


Ok, I end up with such solution:

Using custom impl of RuntimeAnnotationReader, i embed two type of adater to alist and current elements.

public class ABeanAdapterList extends XmlAdapter<ABeanWrapper, Abean> {

    public int i = 0;

    private Map<Abean, String> unmarshall = new HashMap<Abean, String>();
    private Map<String, Abean> marshall = new HashMap<String, Abean>();


    @Override
    public Abean unmarshal(ABeanWrapper v) throws Exception {
        marshall.put(v.id, v.abean);
        return v.abean;
    }

    @Override
    public ABeanWrapper marshal(Abean v) throws Exception {
        ABeanWrapper beanWrapper = new ABeanWrapper();
        beanWrapper.abean = v;
        beanWrapper.id = String.valueOf(i++);
        unmarshall.put(beanWrapper.abean , beanWrapper.id);
        return beanWrapper;
    }

    public String getId(Abean abean) {
        return unmarshall.get(abean);
    }

    public Abean getAbean(String id) {
        return marshall.get(id);
    }
}

where ABeanWrapper contains two field: id and ABean for alist, and for current:

public class ABeanAdapterImpl extends XmlAdapter<ABeanRef, Abean> {

        private ABeanAdapterList listAdapter;

        public ABeanAdapterImpl(ABeanAdapterList list) {
            listAdapter = list;
        }

        @Override
        public Abean unmarshal(ABeanRef wrapper) throws Exception {
            return listAdapter.getAbean(wrapper.refId);
        }

        @Override
        public ABeanRef marshal(Abean abean) throws Exception {
            ABeanRef ref = new ABeanRef();
            ref.refId = listAdapter.getId(abean);
            return ref;

        }
    }

And ABeanRef contains only one ref field. Invoke it such way:

Marshaller marshaller = context.createMarshaller();
ABeanAdapterList adapterList = new ABeanAdapterList();
marshaller.setAdapter(adapterList);
ABeanAdapterImpl beanAdapter = new ABeanAdapterImpl(adapterList);
marshaller.setAdapter(beanAdapter);
marshaller.marshal(sBean, new File("testSBean.xml"));

May by there is a better way, but this approach works...

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号