This method is great for SOAP calls where you have might have a cyclic tree structure, as JAXWS allows for custom wrapper beans.
For this method to work, your nodes must have a unique id that is not only unique for the Node, but unique for the XML document. You will also need to be a bit more flexible in your XML schema, as cyclic data structures might look fine in your xsd, but in practice it does not work.
Here is the Node POJO:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class BidirectionalNode {
@XmlAttribute
@XmlID
private String id;
@XmlTransient
private BidirectionalNode parent;
@XmlElement(name = "child")
@XmlIDREF
private List<BidirectionalNode> children;
public BidirectionalNode() {
super();
}
public BidirectionalNode(String name) {
this();
this.id = name;
}
public void addChild(BidirectionalNode child) {
if (child != null) {
child.parent = this;
this.getChildren().add(child);
}
}
public String getName() {
return id;
}
public void setName(String name) {
this.id = name;
}
public BidirectionalNode getParent() {
return parent;
}
public void setParent(BidirectionalNode parent) {
this.parent = parent;
}
public List<BidirectionalNode> getChildren() {
if (children == null) {
children = new ArrayList<BidirectionalNode>();
}
return children;
}
public void setChildren(List<BidirectionalNode> children) {
this.children = children;
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class NodeWrapper {
@XmlAttribute
@XmlIDREF
private BidirectionalNode root;
@XmlElement(name = "node")
private List<BidirectionalNode> nodes;
public BidirectionalNode getRoot() {
return root;
}
public void setRoot(BidirectionalNode root) {
this.root = root;
}
public List<BidirectionalNode> getNodes() {
return nodes;
}
public void setNodes(List<BidirectionalNode> nodes) {
this.nodes = nodes;
}
public void wrap(BidirectionalNode root) {
this.root = root;
this.nodes = parseNode(root, new HashSet<String>());
}
private List<BidirectionalNode> parseNode(BidirectionalNode node,
HashSet<String> visited) {
if (!visited.contains(node.getName())) {
ArrayList<BidirectionalNode> results = new ArrayList<BidirectionalNode>();
visited.add(node.getName());
results.add(node);
for (BidirectionalNode child : node.getChildren()) {
results.addAll(parseNode(child, visited));
}
return results;
}
return Collections.emptyList();
}
}
This will result in the following XML:<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <nodeWrapper root="rootNode"> <node id="rootNode"> <child>child1</child> </node> <node id="child1"> <child>child2</child> </node> <node id="child2"> <child>child3</child> <child>child1</child> </node> <node id="child3"> <child>child1</child> </node> </nodeWrapper>
No comments:
Post a Comment