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