/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.ast.xpath.saxon;
import net.sourceforge.pmd.lang.ast.Node;
import net.sf.saxon.om.Axis;
import net.sf.saxon.om.AxisIterator;
import net.sf.saxon.om.DocumentInfo;
import net.sf.saxon.om.EmptyIterator;
import net.sf.saxon.om.Navigator;
import net.sf.saxon.om.NodeArrayIterator;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.om.SingleNodeIterator;
import net.sf.saxon.type.Type;
/**
* A Saxon OM Element type node for an AST Node.
*/
public class ElementNode extends AbstractNodeInfo {
protected final DocumentNode document;
protected final ElementNode parent;
protected final Node node;
protected final int id;
protected final int siblingPosition;
protected final NodeInfo[] children;
public ElementNode(DocumentNode document, IdGenerator idGenerator, ElementNode parent, Node node,
int siblingPosition) {
this.document = document;
this.parent = parent;
this.node = node;
this.id = idGenerator.getNextId();
this.siblingPosition = siblingPosition;
if (node.jjtGetNumChildren() > 0) {
this.children = new NodeInfo[node.jjtGetNumChildren()];
for (int i = 0; i < children.length; i++) {
children[i] = new ElementNode(document, idGenerator, this, node.jjtGetChild(i), i);
}
} else {
this.children = null;
}
document.nodeToElementNode.put(node, this);
}
@Override
public Object getUnderlyingNode() {
return node;
}
@Override
public int getSiblingPosition() {
return siblingPosition;
}
@Override
public int getColumnNumber() {
return node.getBeginColumn();
}
@Override
public int getLineNumber() {
return node.getBeginLine();
}
@Override
public boolean hasChildNodes() {
return children != null;
}
@Override
public int getNodeKind() {
return Type.ELEMENT;
}
@Override
public DocumentInfo getDocumentRoot() {
return document;
}
@Override
public String getLocalPart() {
return node.toString();
}
@Override
public String getURI() {
return "";
}
@Override
public NodeInfo getParent() {
return parent;
}
@Override
public int compareOrder(NodeInfo other) {
return Integer.signum(this.node.jjtGetId() - ((ElementNode) other).node.jjtGetId());
}
@SuppressWarnings("PMD.MissingBreakInSwitch")
@Override
public AxisIterator iterateAxis(byte axisNumber) {
switch (axisNumber) {
case Axis.ANCESTOR:
return new Navigator.AncestorEnumeration(this, false);
case Axis.ANCESTOR_OR_SELF:
return new Navigator.AncestorEnumeration(this, true);
case Axis.ATTRIBUTE:
return new AttributeAxisIterator(this);
case Axis.CHILD:
if (children == null) {
return EmptyIterator.getInstance();
} else {
return new NodeArrayIterator(children);
}
case Axis.DESCENDANT:
return new Navigator.DescendantEnumeration(this, false, true);
case Axis.DESCENDANT_OR_SELF:
return new Navigator.DescendantEnumeration(this, true, true);
case Axis.FOLLOWING:
return new Navigator.FollowingEnumeration(this);
case Axis.FOLLOWING_SIBLING:
if (parent == null || siblingPosition == parent.children.length - 1) {
return EmptyIterator.getInstance();
} else {
return new NodeArrayIterator(parent.children, siblingPosition + 1, parent.children.length);
}
case Axis.NAMESPACE:
return super.iterateAxis(axisNumber);
case Axis.PARENT:
return SingleNodeIterator.makeIterator(parent);
case Axis.PRECEDING:
return new Navigator.PrecedingEnumeration(this, false);
case Axis.PRECEDING_SIBLING:
if (parent == null || siblingPosition == 0) {
return EmptyIterator.getInstance();
} else {
return new NodeArrayIterator(parent.children, 0, siblingPosition);
}
case Axis.SELF:
return SingleNodeIterator.makeIterator(this);
case Axis.PRECEDING_OR_ANCESTOR:
return new Navigator.PrecedingEnumeration(this, true);
default:
return super.iterateAxis(axisNumber);
}
}
}