package org.basex.build.xml;
import static org.basex.core.Text.*;
import static org.basex.util.Token.*;
import java.io.IOException;
import java.util.Stack;
import org.basex.build.Builder;
import org.basex.build.Parser;
import org.basex.util.Util;
import org.w3c.dom.Attr;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
/**
* This class converts an DOM document instance to a database representation.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class DOMWrapper extends Parser {
/** Name of the document. */
private final String filename;
/** Root document. */
private final Node root;
/** Element counter. */
private int nodes;
/**
* Constructor.
* @param doc document instance
* @param fn filename
*/
public DOMWrapper(final Document doc, final String fn) {
super(fn);
root = doc;
filename = fn;
}
@Override
public void parse(final Builder builder) throws IOException {
builder.startDoc(token(filename));
final Stack<NodeIterator> stack = new Stack<NodeIterator>();
stack.push(new NodeIterator(root));
while(!stack.empty()) {
final NodeIterator ni = stack.peek();
if(ni.more()) {
final Node n = ni.curr();
if(n instanceof Element) {
stack.push(new NodeIterator(n));
atts.reset();
final NamedNodeMap at = n.getAttributes();
for(int a = 0, as = at.getLength(); a < as; ++a) {
final Attr att = (Attr) at.item(a);
final byte[] k = token(att.getName()), v = token(att.getValue());
if(eq(k, XMLNS)) {
builder.startNS(EMPTY, v);
} else if(startsWith(k, XMLNSC)) {
builder.startNS(local(k), v);
} else {
atts.add(k, v);
}
}
builder.startElem(token(n.getNodeName()), atts);
} else if(n instanceof Text) {
builder.text(token(n.getNodeValue()));
} else if(n instanceof Comment) {
builder.comment(token(n.getNodeValue()));
} else if(n instanceof ProcessingInstruction) {
builder.pi(token(n.getNodeName() + ' ' + n.getNodeValue()));
}
++nodes;
} else {
stack.pop();
if(stack.empty()) break;
builder.endElem();
}
}
builder.endDoc();
}
@Override
public String det() {
return Util.info(NODES_PARSED_X, filename, nodes);
}
@Override
public double prog() {
return nodes / 1000000d % 1;
}
/** Node iterator. */
private static final class NodeIterator {
/** Node list. */
private final NodeList nl;
/** Position. */
private int i = -1;
/**
* Constructor.
* @param n input node
*/
NodeIterator(final Node n) {
nl = n.getChildNodes();
}
/**
* Checks if more nodes are found.
* @return result of check
*/
boolean more() {
return ++i < nl.getLength();
}
/**
* Returns the current node.
* @return current node
*/
Node curr() {
return nl.item(i);
}
}
}