NodeIteratorImplpublic class NodeIteratorImpl extends Object implements NodeIteratorDefaultNodeIterator implements a NodeIterator, which iterates a
DOM tree in the expected depth first way.
The whatToShow and filter functionality is implemented as expected.
This class also has method removeNode to enable iterator "fix-up"
on DOM remove. It is expected that the DOM implementation call removeNode
right before the actual DOM transformation. If not called by the DOM,
the client could call it before doing the removal. |
Fields Summary |
---|
private DocumentImpl | fDocumentThe DocumentImpl which created this iterator, so it can be detached. | private Node | fRootThe root. | private int | fWhatToShowThe whatToShow mask. | private NodeFilter | fNodeFilterThe NodeFilter reference. | private boolean | fDetachIf detach is called, the fDetach flag is true, otherwise flase. | private Node | fCurrentNodeThe last Node returned. | private boolean | fForwardThe direction of the iterator on the fCurrentNode.
nextNode() == fForward = true;
previousNode() == fForward = false;
| private boolean | fEntityReferenceExpansionWhen TRUE, the children of entites references are returned in the iterator. |
Constructors Summary |
---|
public NodeIteratorImpl(DocumentImpl document, Node root, int whatToShow, NodeFilter nodeFilter, boolean entityReferenceExpansion)Public constructor
//
// Constructor
//
fDocument = document;
fRoot = root;
fCurrentNode = null;
fWhatToShow = whatToShow;
fNodeFilter = nodeFilter;
fEntityReferenceExpansion = entityReferenceExpansion;
|
Methods Summary |
---|
boolean | acceptNode(org.w3c.dom.Node node)The node is accepted if it passes the whatToShow and the filter.
if (fNodeFilter == null) {
return ( fWhatToShow & (1 << node.getNodeType()-1)) != 0 ;
} else {
return ((fWhatToShow & (1 << node.getNodeType()-1)) != 0 )
&& fNodeFilter.acceptNode(node) == NodeFilter.FILTER_ACCEPT;
}
| public void | detach()
fDetach = true;
fDocument.removeNodeIterator(this);
| public boolean | getExpandEntityReferences()Return whether children entity references are included in the iterator.
return fEntityReferenceExpansion;
| public org.w3c.dom.traversal.NodeFilter | getFilter()Return the filter
return fNodeFilter;
| public org.w3c.dom.Node | getRoot()
return fRoot;
| public int | getWhatToShow()Return the whatToShow value
return fWhatToShow;
| org.w3c.dom.Node | matchNodeOrParent(org.w3c.dom.Node node)Return node, if matches or any parent if matches.
// Additions and removals in the underlying data structure may occur
// before any iterations, and in this case the reference_node is null.
if (fCurrentNode == null) return null;
// check if the removed node is an _ancestor_ of the
// reference node
for (Node n = fCurrentNode; n != fRoot; n = n.getParentNode()) {
if (node == n) return n;
}
return null;
| org.w3c.dom.Node | nextNode(org.w3c.dom.Node node, boolean visitChildren)The method nextNode(Node, boolean) returns the next node
from the actual DOM tree.
The boolean visitChildren determines whether to visit the children.
The result is the nextNode.
if (node == null) return fRoot;
Node result;
// only check children if we visit children.
if (visitChildren) {
//if hasChildren, return 1st child.
if (node.hasChildNodes()) {
result = node.getFirstChild();
return result;
}
}
if (node == fRoot) { //if Root has no kids
return null;
}
// if hasSibling, return sibling
result = node.getNextSibling();
if (result != null) return result;
// return parent's 1st sibling.
Node parent = node.getParentNode();
while (parent != null && parent != fRoot) {
result = parent.getNextSibling();
if (result != null) {
return result;
} else {
parent = parent.getParentNode();
}
} // while (parent != null && parent != fRoot) {
// end of list, return null
return null;
| public org.w3c.dom.Node | nextNode()Return the next Node in the Iterator. The node is the next node in
depth-first order which also passes the filter, and whatToShow.
If there is no next node which passes these criteria, then return null.
if( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
// if root is null there is no next node.
if (fRoot == null) return null;
Node nextNode = fCurrentNode;
boolean accepted = false; // the next node has not been accepted.
accepted_loop:
while (!accepted) {
// if last direction is not forward, repeat node.
if (!fForward && nextNode!=null) {
//System.out.println("nextNode():!fForward:"+fCurrentNode.getNodeName());
nextNode = fCurrentNode;
} else {
// else get the next node via depth-first
if (!fEntityReferenceExpansion
&& nextNode != null
&& nextNode.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
nextNode = nextNode(nextNode, false);
} else {
nextNode = nextNode(nextNode, true);
}
}
fForward = true; //REVIST: should direction be set forward before null check?
// nothing in the list. return null.
if (nextNode == null) return null;
// does node pass the filters and whatToShow?
accepted = acceptNode(nextNode);
if (accepted) {
// if so, then the node is the current node.
fCurrentNode = nextNode;
return fCurrentNode;
} else
continue accepted_loop;
} // while (!accepted) {
// no nodes, or no accepted nodes.
return null;
| org.w3c.dom.Node | previousNode(org.w3c.dom.Node node)The method previousNode(Node) returns the previous node
from the actual DOM tree.
Node result;
// if we're at the root, return null.
if (node == fRoot) return null;
// get sibling
result = node.getPreviousSibling();
if (result == null) {
//if 1st sibling, return parent
result = node.getParentNode();
return result;
}
// if sibling has children, keep getting last child of child.
if (result.hasChildNodes()
&& !(!fEntityReferenceExpansion
&& result != null
&& result.getNodeType() == Node.ENTITY_REFERENCE_NODE))
{
while (result.hasChildNodes()) {
result = result.getLastChild();
}
}
return result;
| public org.w3c.dom.Node | previousNode()Return the previous Node in the Iterator. The node is the next node in
_backwards_ depth-first order which also passes the filter, and whatToShow.
if( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
// if the root is null, or the current node is null, return null.
if (fRoot == null || fCurrentNode == null) return null;
Node previousNode = fCurrentNode;
boolean accepted = false;
accepted_loop:
while (!accepted) {
if (fForward && previousNode != null) {
//repeat last node.
previousNode = fCurrentNode;
} else {
// get previous node in backwards depth first order.
previousNode = previousNode(previousNode);
}
// we are going backwards
fForward = false;
// if the new previous node is null, we're at head or past the root,
// so return null.
if (previousNode == null) return null;
// check if node passes filters and whatToShow.
accepted = acceptNode(previousNode);
if (accepted) {
// if accepted, update the current node, and return it.
fCurrentNode = previousNode;
return fCurrentNode;
} else
continue accepted_loop;
}
// there are no nodes?
return null;
| public void | removeNode(org.w3c.dom.Node node)Fix-up the iterator on a remove. Called by DOM or otherwise,
before an actual DOM remove.
// Implementation note: Fix-up means setting the current node properly
// after a remove.
if (node == null) return;
Node deleted = matchNodeOrParent(node);
if (deleted == null) return;
if (fForward) {
fCurrentNode = previousNode(deleted);
} else
// if (!fForward)
{
Node next = nextNode(deleted, false);
if (next!=null) {
// normal case: there _are_ nodes following this in the iterator.
fCurrentNode = next;
} else {
// the last node in the iterator is to be removed,
// so we set the current node to be the previous one.
fCurrentNode = previousNode(deleted);
fForward = true;
}
}
|
|