/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.ast.xpath;
import java.util.ArrayList;
import java.util.Iterator;
import org.jaxen.DefaultNavigator;
import org.jaxen.XPath;
import org.jaxen.util.SingleObjectIterator;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.ast.RootNode;
/**
* @author daniels
*/
public class DocumentNavigator extends DefaultNavigator {
private static final Iterator<Node> EMPTY_ITERATOR = new ArrayList<Node>().iterator();
@Override
public String getAttributeName(Object arg0) {
return ((Attribute) arg0).getName();
}
@Override
public String getAttributeNamespaceUri(Object arg0) {
return "";
}
@Override
public String getAttributeQName(Object arg0) {
return ((Attribute) arg0).getName();
}
@Override
public String getAttributeStringValue(Object arg0) {
return ((Attribute) arg0).getStringValue();
}
@Override
public String getCommentStringValue(Object arg0) {
return "";
}
@Override
public String getElementName(Object node) {
return node.toString();
}
@Override
public String getElementNamespaceUri(Object arg0) {
return "";
}
@Override
public String getElementQName(Object arg0) {
return getElementName(arg0);
}
@Override
public String getElementStringValue(Object arg0) {
return "";
}
@Override
public String getNamespacePrefix(Object arg0) {
return "";
}
@Override
public String getNamespaceStringValue(Object arg0) {
return "";
}
@Override
public String getTextStringValue(Object arg0) {
return "";
}
@Override
public boolean isAttribute(Object arg0) {
return arg0 instanceof Attribute;
}
@Override
public boolean isComment(Object arg0) {
return false;
}
@Override
public boolean isDocument(Object arg0) {
return arg0 instanceof RootNode;
}
@Override
public boolean isElement(Object arg0) {
return arg0 instanceof Node;
}
@Override
public boolean isNamespace(Object arg0) {
return false;
}
@Override
public boolean isProcessingInstruction(Object arg0) {
return false;
}
@Override
public boolean isText(Object arg0) {
return false;
}
@Override
public XPath parseXPath(String arg0) {
return null;
}
@Override
public Object getParentNode(Object arg0) {
if (arg0 instanceof Node) {
return ((Node) arg0).jjtGetParent();
}
if (arg0 instanceof Attribute) {
return ((Attribute) arg0).getParent();
}
// can't navigate to parent node...
return null;
}
@Override
public Iterator<Attribute> getAttributeAxisIterator(Object arg0) {
if (arg0 instanceof AttributeNode) {
return ((AttributeNode) arg0).getAttributeIterator();
} else {
return new AttributeAxisIterator((Node) arg0);
}
}
/**
* Get an iterator over all of this node's children.
*
* @param contextNode
* The context node for the child axis.
* @return A possibly-empty iterator (not null).
*/
@Override
public Iterator<Node> getChildAxisIterator(Object contextNode) {
return new NodeIterator((Node) contextNode) {
@Override
protected Node getFirstNode(Node node) {
return getFirstChild(node);
}
@Override
protected Node getNextNode(Node node) {
return getNextSibling(node);
}
};
}
/**
* Get a (single-member) iterator over this node's parent.
*
* @param contextNode
* the context node for the parent axis.
* @return A possibly-empty iterator (not null).
*/
@Override
public Iterator<Node> getParentAxisIterator(Object contextNode) {
if (isAttribute(contextNode)) {
return new SingleObjectIterator(((Attribute) contextNode).getParent());
}
Node parent = ((Node) contextNode).jjtGetParent();
if (parent != null) {
return new SingleObjectIterator(parent);
} else {
return EMPTY_ITERATOR;
}
}
/**
* Get an iterator over all following siblings.
*
* @param contextNode
* the context node for the sibling iterator.
* @return A possibly-empty iterator (not null).
*/
@Override
public Iterator<Node> getFollowingSiblingAxisIterator(Object contextNode) {
return new NodeIterator((Node) contextNode) {
@Override
protected Node getFirstNode(Node node) {
return getNextNode(node);
}
@Override
protected Node getNextNode(Node node) {
return getNextSibling(node);
}
};
}
/**
* Get an iterator over all preceding siblings.
*
* @param contextNode
* The context node for the preceding sibling axis.
* @return A possibly-empty iterator (not null).
*/
@Override
public Iterator<Node> getPrecedingSiblingAxisIterator(Object contextNode) {
return new NodeIterator((Node) contextNode) {
@Override
protected Node getFirstNode(Node node) {
return getNextNode(node);
}
@Override
protected Node getNextNode(Node node) {
return getPreviousSibling(node);
}
};
}
/**
* Get an iterator over all following nodes, depth-first.
*
* @param contextNode
* The context node for the following axis.
* @return A possibly-empty iterator (not null).
*/
@Override
public Iterator<Node> getFollowingAxisIterator(Object contextNode) {
return new NodeIterator((Node) contextNode) {
@Override
protected Node getFirstNode(Node node) {
if (node == null) {
return null;
} else {
Node sibling = getNextSibling(node);
if (sibling == null) {
return getFirstNode(node.jjtGetParent());
} else {
return sibling;
}
}
}
@Override
protected Node getNextNode(Node node) {
if (node == null) {
return null;
} else {
Node n = getFirstChild(node);
if (n == null) {
n = getNextSibling(node);
}
if (n == null) {
return getFirstNode(node.jjtGetParent());
} else {
return n;
}
}
}
};
}
/**
* Get an iterator over all preceding nodes, depth-first.
*
* @param contextNode
* The context node for the preceding axis.
* @return A possibly-empty iterator (not null).
*/
@Override
public Iterator<Node> getPrecedingAxisIterator(Object contextNode) {
return new NodeIterator((Node) contextNode) {
@Override
protected Node getFirstNode(Node node) {
if (node == null) {
return null;
} else {
Node sibling = getPreviousSibling(node);
if (sibling == null) {
return getFirstNode(node.jjtGetParent());
} else {
return sibling;
}
}
}
@Override
protected Node getNextNode(Node node) {
if (node == null) {
return null;
} else {
Node n = getLastChild(node);
if (n == null) {
n = getPreviousSibling(node);
}
if (n == null) {
return getFirstNode(node.jjtGetParent());
} else {
return n;
}
}
}
};
}
@Override
public Object getDocumentNode(Object contextNode) {
if (isDocument(contextNode)) {
return contextNode;
}
if (null == contextNode) {
throw new RuntimeException("contextNode may not be null");
}
return getDocumentNode(getParentNode(contextNode));
}
}