Reputation: 449
I'm trying to use JAXB to unmarshal a data (Polygon) with two @XmlJavaTypeAdapter annotations (Subscriber, Tag) to and from an XML file. Each object has it's own XML file, and the objects are related thus:
I'm trying to unmarshall the Polygon XML file back to its class object, with its Subscribers and Tags in tact, but can't work out how to do it.
== Subscriber.java ==
@XmlRootElement(name = "Subscriber")
@XmlAccessorType(XmlAccessType.FIELD)
public class Subscriber {
private String ID;
private Set<Polygon> polygons;
@XmlAttribute(name = "ID")
public String getID() {
return this.ID;
}
public void setID(String ID) {
this.ID = ID;
}
@XmlJavaAdapter(PolygonXmlAdapter.class)
@XmlElementWrapper(name = "Polygons")
@XmlElement(name = "Polygon")
public set<Polygon> getPolygons() {
return this.polygons;
}
public void setPolygons(Set<Polygon> polygons) {
this.polygons = polygons;
}
}
== Polygon.java ==
@XmlRootElement(name = "{Polygon}")
@XmlAccessorType(XmlAccessType.FIELD)
public class Polygon {
private String ID;
private Set<Subscriber> subscribers;
private Set<Tag> tags
@XmlAttribute(name = "ID")
public String getID() {
return this.ID;
}
public void setID(String ID) {
this.ID = ID;
}
@XmlJavaAdapter(SubscriberXmlAdapter.class)
@XmlElementWrapper(name = "Subscribers")
@XmlElement(Subscriber)
public Set<Subscriber> getSubscribers() {
return this.subscribers;
}
@XmlJavaAdapter(TagXmlAdapter.class)
@XmlElementWrapper(name = "Tags")
@XmlElement(name = "Tag")
public Set<Tag> getTags() {
return this.tags
}
public void setTags(Set<Tag> tags) {
this.tags = tags;
}
}
== Tag.java ==
@XmlRootElement(name = "Tag")
@XmlAccessorType(XmlAccessType.FIELD)
public class Tag {
private String ID;
@XmlAttribute(name = "ID")
public String getID() {
return this.ID;
}
public void setID(String ID) {
this.ID = ID;
}
}
== SubscriberXmlAdapter.java ==
public class SubscriberXmlAdapter extends XmlAdapter<String, Subscriber> {
private Map<String, Subscriber> subscribers = new HashMap<>();
private Map<String, Subscriber> getSubscribers() {
return subscribers;
}
@Override
public Subscriber unmarshal(String v) throws Exception {
return subscribers.get(v);
}
@Override
public String marshal(Subscriber v) throws Exception {
return v.getID();
}
}
== TagXmlAdapter.java ==
public class TagXmlAdapter extends XmlAdapter<String, Tag> {
private Map<String, Tag> tags = new HashMap<>();
private Map<String, Tag> getTags() {
return tags;
}
@Override
public String unmarshal(String v) throws Exception {
return tags.get(v);
}
@Override
public String marshal(Tag v) throws Exception {
reutrn v.getID();
}
}
== SubscriberCollection.java ==
@XmlRootElement(name = "Subscribers")
@XmlAccessorType(XmlAccessType.FIELD)
public class SubscriberCollection {
private Collection<Subscriber> collection;
@XmlElement(name = "Subscriber")
public Collection<Subscriber> getSubscribers() {
return this.collection;
}
public void setCollection(Collection<Subscriber> collection) {
this.collection = collection;
}
}
== TagCollection.java ==
@XmlRootElement(name = "Tags")
@XmlAccessorType(XmlAccessType.FIELD)
public class TagCollection {
private Collection<Subscriber> collection;
@XmlElement(name="Tag")
public Collection<Tag> getSubscribers() {
return this.collection;
}
public void setCollection(Collection<Subscriber> collection) {
this.collection = collection;
}
}
And to execute the unmarshalling, three xml files - for subscribers, polygons, and tags - containing their respective data are used:
JAXBContext jaxbContext = JAXBContext.newInstance(SubscriberCollection.class, PolygonTagCollection.class, Polygon.class);
unmarshaller subUnmarshaller = jaxbContext.createunmarshaller();
SubscriberCollection subCollection = (SubscriberCollection) subUnmarshaller.unmarshal(new ByteArrayInputStream(subscribersXml.getBytes(StandardCharset.UTF_8.name())));
Unmarshaller tagUnmarshaller = jaxbContext.createUnmarshaller();
TagCollection tagCollectino = (TagCollection) tagUnmarshaller.un,arshal(new ByteArrayInputStream(tagXml.getBytes(StandardCharsets.UTF_8.name())));
Unmarshaller polUnmarshaller = jaxbContext.createUnmarshaller();
SubscriberXmlAdapter subAdapter = new SubscriberXmlAdapter();
for (Subscriber sub : subscriberCollection.getCollection()) {
subAdapter.getCollection().put(sub.getID(), sub);
}
TagXmlAdapter tagAdapter = new TagXmlAdapter();
for (Tag tag : tagCollection.getCollection()) {
tagAdapter.getCollection().put(tag.getID(), tag);
}
polUnmarshaller.setAdapter(SubscriberXmlAdapter.class subAdapter);
polUnmarshaller.unmarshal(new ByteArrayInputStream(polygonXml.getBytes(StandardCharsets.UTF_8.name())));
This unmarshalls the Polygon with the correct subscribers, but not with the correct tags.
I can only set one XmlAdapter to the unmarshaller, so it can only populate the subscribers or the tags within the polygon being unmarshalled.
Is there a way to combine these adapters? Or is there a better way of doing things altogether.
Thanks!
Upvotes: 0
Views: 427