package org.tigris.juxy;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.TreeWalker;
import org.w3c.dom.traversal.NodeFilter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* A proxy for any empty org.w3c.dom.Document object which behaves like if Document
* has all the nodes from the specified DocumentFragment as its direct children.
* I.e. this proxy will append all DocumentFragment child nodes to the Document itself
* thus avoiding the constraint that Document object must have only one child node.
*/
public class ResultDocumentProxy implements InvocationHandler {
private Document adaptedDocument;
private DocumentFragment fragment;
private ResultDocumentProxy(Document adaptedDocument, DocumentFragment fragment) {
this.adaptedDocument = adaptedDocument;
this.fragment = fragment;
}
public static Object newInstance(Document adaptedDocument, DocumentFragment fragment) {
return java.lang.reflect.Proxy.newProxyInstance(
adaptedDocument.getClass().getClassLoader(),
new Class[]{Document.class, DocumentTraversal.class},
new ResultDocumentProxy(adaptedDocument, fragment));
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//noinspection EmptyCatchBlock
try {
Method proxiedMethod = ResultDocumentProxy.class.getMethod(method.getName(), method.getParameterTypes());
return proxiedMethod.invoke(this, args);
} catch (NoSuchMethodException e) {
}
return method.invoke(adaptedDocument, args);
}
public NodeList getChildNodes() {
return fragment.getChildNodes();
}
public Node getFirstChild() {
return fragment.getFirstChild();
}
public Node getLastChild() {
return fragment.getLastChild();
}
public boolean hasChildNodes() {
return fragment.hasChildNodes();
}
public TreeWalker createTreeWalker(Node node, int i, NodeFilter filter, boolean b) throws org.w3c.dom.DOMException {
// if passed node is Document node then we will substituite it with actual document
Node startNode = node instanceof Document ? adaptedDocument : node;
return ((DocumentTraversal)adaptedDocument).createTreeWalker(startNode, i, filter, b);
}
public void normalize() {
fragment.normalize();
}
}