FileDocCategorySizeDatePackage
AxesWalker.javaAPI DocJava SE 6 API15386Tue Jun 10 00:23:14 BST 2008com.sun.org.apache.xpath.internal.axes

AxesWalker

public class AxesWalker extends PredicatedNodeTest implements PathComponent, Cloneable, ExpressionOwner
Serves as common interface for axes Walkers, and stores common state variables.

Fields Summary
static final long
serialVersionUID
private DTM
m_dtm
The DTM for the root. This can not be used, or must be changed, for the filter walker, or any walker that can have nodes from multiple documents. Never, ever, access this value without going through getDTM(int node).
transient int
m_root
The root node of the TreeWalker, as specified when it was created.
private transient int
m_currentNode
The node at which the TreeWalker is currently positioned.
transient boolean
m_isFresh
True if an itteration has not begun.
protected AxesWalker
m_nextWalker
The next walker in the location step chain.
AxesWalker
m_prevWalker
The previous walker in the location step chain, or null.
protected int
m_axis
The traversal axis from where the nodes will be filtered.
protected DTMAxisTraverser
m_traverser
The DTM inner traversal class, that corresponds to the super axis.
Constructors Summary
public AxesWalker(LocPathIterator locPathIterator, int axis)
Construct an AxesWalker using a LocPathIterator.

param
locPathIterator non-null reference to the parent iterator.

  
                   
      
  
    super( locPathIterator );
    m_axis = axis;
  
Methods Summary
public voidcallVisitors(com.sun.org.apache.xpath.internal.ExpressionOwner owner, com.sun.org.apache.xpath.internal.XPathVisitor visitor)
This will traverse the heararchy, calling the visitor for each member. If the called visitor method returns false, the subtree should not be called.

param
owner The owner of the visitor, where that path may be rewritten if needed.
param
visitor The visitor whose appropriate method will be called.

  	if(visitor.visitStep(owner, this))
  	{
  		callPredicateVisitors(visitor);
  		if(null != m_nextWalker)
  		{
  			m_nextWalker.callVisitors(this, visitor);
  		}
  	}
  
public java.lang.Objectclone()
Get a cloned AxesWalker.

return
A new AxesWalker that can be used without mutating this one.
throws
CloneNotSupportedException

    // Do not access the location path itterator during this operation!
    
    AxesWalker clone = (AxesWalker) super.clone();

    //clone.setCurrentNode(clone.m_root);

    // clone.m_isFresh = true;

    return clone;
  
com.sun.org.apache.xpath.internal.axes.AxesWalkercloneDeep(com.sun.org.apache.xpath.internal.axes.WalkingIterator cloneOwner, java.util.Vector cloneList)
Do a deep clone of this walker, including next and previous walkers. If the this AxesWalker is on the clone list, don't clone but return the already cloned version.

param
cloneOwner non-null reference to the cloned location path iterator to which this clone will be added.
param
cloneList non-null vector of sources in odd elements, and the corresponding clones in even vectors.
return
non-null clone, which may be a new clone, or may be a clone contained on the cloneList.

    AxesWalker clone = findClone(this, cloneList);
    if(null != clone)
      return clone;
    clone = (AxesWalker)this.clone();
    clone.setLocPathIterator(cloneOwner);
    if(null != cloneList)
    {
      cloneList.addElement(this);
      cloneList.addElement(clone);
    }
    
    if(wi().m_lastUsedWalker == this)
      cloneOwner.m_lastUsedWalker = clone;
      
    if(null != m_nextWalker)
      clone.m_nextWalker = m_nextWalker.cloneDeep(cloneOwner, cloneList);
      
    // If you don't check for the cloneList here, you'll go into an 
    // recursive infinate loop.  
    if(null != cloneList)
    {
      if(null != m_prevWalker)
        clone.m_prevWalker = m_prevWalker.cloneDeep(cloneOwner, cloneList);
    }
    else
    {
      if(null != m_nextWalker)
        clone.m_nextWalker.m_prevWalker = clone;
    }
    return clone;
  
public booleandeepEquals(com.sun.org.apache.xpath.internal.Expression expr)

see
Expression#deepEquals(Expression)

      if (!super.deepEquals(expr))
                return false;

      AxesWalker walker = (AxesWalker)expr;
      if(this.m_axis != walker.m_axis)
      	return false;

      return true;
    
public voiddetach()
Detaches the walker from the set which it iterated over, releasing any computational resources and placing the iterator in the INVALID state.

 
  	m_currentNode = DTM.NULL;
  	m_dtm = null;
  	m_traverser = null;
  	m_isFresh = true;
  	m_root = DTM.NULL;
  
static com.sun.org.apache.xpath.internal.axes.AxesWalkerfindClone(com.sun.org.apache.xpath.internal.axes.AxesWalker key, java.util.Vector cloneList)
Find a clone that corresponds to the key argument.

param
key The original AxesWalker for which there may be a clone.
param
cloneList vector of sources in odd elements, and the corresponding clones in even vectors, may be null.
return
A clone that corresponds to the key, or null if key not found.

    if(null != cloneList)
    {
      // First, look for clone on list.
      int n = cloneList.size();
      for (int i = 0; i < n; i+=2) 
      {
        if(key == cloneList.elementAt(i))
          return (AxesWalker)cloneList.elementAt(i+1);
      }
    }
    return null;    
  
public intgetAnalysisBits()
Get the analysis bits for this walker, as defined in the WalkerFactory.

return
One of WalkerFactory#BIT_DESCENDANT, etc.

  	int axis = getAxis();
  	int bit = WalkerFactory.getAnalysisBitFromAxes(axis);
  	return bit;
  
public intgetAxis()
Returns the axis being iterated, if it is known.

return
Axis.CHILD, etc., or -1 if the axis is not known or is of multiple types.

    return m_axis;
  
public final intgetCurrentNode()
The node at which the TreeWalker is currently positioned.
The value must not be null. Alterations to the DOM tree may cause the current node to no longer be accepted by the TreeWalker's associated filter. currentNode may also be explicitly set to any node, whether or not it is within the subtree specified by the root node or would be accepted by the filter and whatToShow flags. Further traversal occurs relative to currentNode even if it is not part of the current view by applying the filters in the requested direction (not changing currentNode where no traversal is possible).

return
The node at which the TreeWalker is currently positioned, only null if setRoot has not yet been called.

    return m_currentNode;
  
public com.sun.org.apache.xml.internal.dtm.DTMgetDTM(int node)
Get the DTM for this walker.

return
Non-null reference to a DTM.

    //
    return wi().getXPathContext().getDTM(node);
  
public com.sun.org.apache.xpath.internal.ExpressiongetExpression()

see
ExpressionOwner#getExpression()

    return m_nextWalker;
  
public intgetLastPos(com.sun.org.apache.xpath.internal.XPathContext xctxt)
Get the index of the last node that can be itterated to.

param
xctxt XPath runtime context.
return
the index of the last node that can be itterated to.


    int pos = getProximityPosition();
    
    AxesWalker walker;

    try
    {
      walker = (AxesWalker) clone();
    }
    catch (CloneNotSupportedException cnse)
    {
      return -1;
    }

    walker.setPredicateCount(walker.getPredicateCount() - 1);
    walker.setNextWalker(null);
    walker.setPrevWalker(null);

    WalkingIterator lpi = wi();
    AxesWalker savedWalker = lpi.getLastUsedWalker();

    try
    {
      lpi.setLastUsedWalker(walker);

      int next;

      while (DTM.NULL != (next = walker.nextNode()))
      {
        pos++;
      }

      // TODO: Should probably save this in the iterator.
    }
    finally
    {
      lpi.setLastUsedWalker(savedWalker);
    }

    // System.out.println("pos: "+pos);
    return pos;
  
protected intgetNextNode()
Get the next node in document order on the axes.

return
the next node in document order on the axes, or null.

    if (m_foundLast)
      return DTM.NULL;

    if (m_isFresh)
    {
      m_currentNode = m_traverser.first(m_root);
      m_isFresh = false;
    }
    // I shouldn't have to do this the check for current node, I think.
    // numbering\numbering24.xsl fails if I don't do this.  I think 
    // it occurs as the walkers are backing up. -sb
    else if(DTM.NULL != m_currentNode) 
    {
      m_currentNode = m_traverser.next(m_root, m_currentNode);
    }

    if (DTM.NULL == m_currentNode)
      this.m_foundLast = true;

    return m_currentNode;
  
public com.sun.org.apache.xpath.internal.axes.AxesWalkergetNextWalker()
Get the next walker in the location step chain.

return
Reference to AxesWalker derivative, or null.

    return m_nextWalker;
  
public com.sun.org.apache.xpath.internal.axes.AxesWalkergetPrevWalker()
Get the previous walker reference in the location step chain.

return
Reference to previous walker reference in the location step chain, or null.

    return m_prevWalker;
  
public intgetRoot()
The root node of the TreeWalker, as specified in setRoot(int root). Note that this may actually be below the current node.

return
The context node of the step.

    return m_root;
  
public voidinit(com.sun.org.apache.xpath.internal.compiler.Compiler compiler, int opPos, int stepType)
Initialize an AxesWalker during the parse of the XPath expression.

param
compiler The Compiler object that has information about this walker in the op map.
param
opPos The op code position of this location step.
param
stepType The type of location step.
throws
javax.xml.transform.TransformerException


    initPredicateInfo(compiler, opPos);

    // int testType = compiler.getOp(nodeTestOpPos);
  
public booleanisDocOrdered()
Returns true if all the nodes in the iteration well be returned in document order. Warning: This can only be called after setRoot has been called!

return
true as a default.

    return true;
  
public intnextNode()
Moves the TreeWalker to the next visible node in document order relative to the current node, and returns the new node. If the current node has no next node, or if the search for nextNode attempts to step upward from the TreeWalker's root node, returns null , and retains the current node.

return
The new node, or null if the current node has no next node in the TreeWalker's logical view.

    int nextNode = DTM.NULL;
    AxesWalker walker = wi().getLastUsedWalker();

    while (true)
    {
      if (null == walker)
        break;

      nextNode = walker.getNextNode();

      if (DTM.NULL == nextNode)
      {

        walker = walker.m_prevWalker;
      }
      else
      {
        if (walker.acceptNode(nextNode) != DTMIterator.FILTER_ACCEPT)
        {
          continue;
        }

        if (null == walker.m_nextWalker)
        {
          wi().setLastUsedWalker(walker);

          // return walker.returnNextNode(nextNode);
          break;
        }
        else
        {
          AxesWalker prev = walker;

          walker = walker.m_nextWalker;

          walker.setRoot(nextNode);

          walker.m_prevWalker = prev;

          continue;
        }
      }  // if(null != nextNode)
    }  // while(null != walker)

    return nextNode;
  
private intreturnNextNode(int n)
This is simply a way to bottle-neck the return of the next node, for diagnostic purposes.

param
n Node to return, or null.
return
The argument.


    return n;
  
public voidsetDefaultDTM(com.sun.org.apache.xml.internal.dtm.DTM dtm)
Set the DTM for this walker.

param
dtm Non-null reference to a DTM.

    m_dtm = dtm;
  
public voidsetExpression(com.sun.org.apache.xpath.internal.Expression exp)

see
ExpressionOwner#setExpression(Expression)

  	exp.exprSetParent(this);
  	m_nextWalker = (AxesWalker)exp;
  
public voidsetNextWalker(com.sun.org.apache.xpath.internal.axes.AxesWalker walker)
Set the next walker in the location step chain.

param
walker Reference to AxesWalker derivative, or may be null.

    m_nextWalker = walker;
  
public voidsetPrevWalker(com.sun.org.apache.xpath.internal.axes.AxesWalker walker)
Set or clear the previous walker reference in the location step chain.

param
walker Reference to previous walker reference in the location step chain, or null.

    m_prevWalker = walker;
  
public voidsetRoot(int root)
Set the root node of the TreeWalker. (Not part of the DOM2 TreeWalker interface).

param
root The context node of this step.

    // %OPT% Get this directly from the lpi.
    XPathContext xctxt = wi().getXPathContext();
    m_dtm = xctxt.getDTM(root);
    m_traverser = m_dtm.getAxisTraverser(m_axis);
    m_isFresh = true;
    m_foundLast = false;
    m_root = root;
    m_currentNode = root;

    if (DTM.NULL == root)
    {
      throw new RuntimeException(
        XSLMessages.createXPATHMessage(XPATHErrorResources.ER_SETTING_WALKER_ROOT_TO_NULL, null)); //"\n !!!! Error! Setting the root of a walker to null!!!");
    }

    resetProximityPositions();
  
public final com.sun.org.apache.xpath.internal.axes.WalkingIteratorwi()

    return (WalkingIterator)m_lpi;