public Document build(Document doc, NodeFactory factory) {
if (doc == null)
throw new IllegalArgumentException("doc must not be null");
if (factory == null || factory.getClass() == NodeFactory.class) {
return new Document(doc); // no need to pipe through the default factory
}
Document result = factory.startMakingDocument();
boolean hasRootElement = false;
int k = 0;
for (int i=0; i < doc.getChildCount(); i++) {
Node child = doc.getChild(i);
Nodes nodes;
if (child instanceof Element) {
Element elem = (Element) child;
Element root = factory.makeRootElement(
elem.getQualifiedName(), elem.getNamespaceURI());
if (root == null) {
throw new NullPointerException("Factory failed to create root element.");
}
result.setRootElement(root);
appendNamespaces(elem, root);
appendAttributes(elem, factory, root);
build(elem, factory, root);
nodes = factory.finishMakingElement(root);
} else if (child instanceof Comment) {
nodes = factory.makeComment(child.getValue());
} else if (child instanceof ProcessingInstruction) {
ProcessingInstruction pi = (ProcessingInstruction) child;
nodes = factory.makeProcessingInstruction(
pi.getTarget(), pi.getValue());
} else if (child instanceof DocType) {
DocType docType = (DocType) child;
nodes = factory.makeDocType(
docType.getRootElementName(),
docType.getPublicID(),
docType.getSystemID());
} else {
throw new IllegalArgumentException("Unrecognized node type");
}
// append nodes:
for (int j=0; j < nodes.size(); j++) {
Node node = nodes.get(j);
if (node instanceof Element) { // replace fake root with real root
if (hasRootElement) {
throw new IllegalAddException(
"Factory returned multiple root elements");
}
result.setRootElement((Element) node);
hasRootElement = true;
} else {
result.insertChild(node, k);
}
k++;
}
}