FileDocCategorySizeDatePackage
DescendantIterator.javaAPI DocJava SE 5 API10570Fri Aug 26 14:56:06 BST 2005com.sun.org.apache.xpath.internal.axes

DescendantIterator

public class DescendantIterator extends LocPathIterator
This class implements an optimized iterator for descendant, descendant-or-self, or "//foo" patterns.
see
com.sun.org.apache.xpath.internal.axes.LocPathIterator
xsl.usage
advanced

Fields Summary
protected transient DTMAxisTraverser
m_traverser
The traverser to use to navigate over the descendants.
protected int
m_axis
The axis that we are traversing.
protected int
m_extendedTypeID
The extended type ID, not set until setRoot.
Constructors Summary
DescendantIterator(Compiler compiler, int opPos, int analysis)
Create a DescendantIterator object.

param
compiler A reference to the Compiler that contains the op map.
param
opPos The position within the op map, which contains the location path expression for this itterator.
throws
javax.xml.transform.TransformerException


    super(compiler, opPos, analysis, false);

    int firstStepPos = compiler.getFirstChildPos(opPos);
    int stepType = compiler.getOp(firstStepPos);

    boolean orSelf = (OpCodes.FROM_DESCENDANTS_OR_SELF == stepType);
    boolean fromRoot = false;
    if (OpCodes.FROM_SELF == stepType)
    {
      orSelf = true;
      // firstStepPos += 8;
    }
    else if(OpCodes.FROM_ROOT == stepType)
    {
      fromRoot = true;
      // Ugly code... will go away when AST work is done.
      int nextStepPos = compiler.getNextStepPos(firstStepPos);
      if(compiler.getOp(nextStepPos) == OpCodes.FROM_DESCENDANTS_OR_SELF)
        orSelf = true;
      // firstStepPos += 8;
    }
    
    // Find the position of the last step.
    int nextStepPos = firstStepPos;
    while(true)
    {
      nextStepPos = compiler.getNextStepPos(nextStepPos);
      if(nextStepPos > 0)
      {
        int stepOp = compiler.getOp(nextStepPos);
        if(OpCodes.ENDOP != stepOp)
          firstStepPos = nextStepPos;
        else
          break;
      }
      else
        break;
      
    }
    
    // Fix for http://nagoya.apache.org/bugzilla/show_bug.cgi?id=1336
    if((analysis & WalkerFactory.BIT_CHILD) != 0)
      orSelf = false;
      
    if(fromRoot)
    {
      if(orSelf)
        m_axis = Axis.DESCENDANTSORSELFFROMROOT;
      else
        m_axis = Axis.DESCENDANTSFROMROOT;
    }
    else if(orSelf)
      m_axis = Axis.DESCENDANTORSELF;
    else
      m_axis = Axis.DESCENDANT;

    int whatToShow = compiler.getWhatToShow(firstStepPos);

    if ((0 == (whatToShow
               & (DTMFilter.SHOW_ATTRIBUTE | DTMFilter.SHOW_ELEMENT
                  | DTMFilter.SHOW_PROCESSING_INSTRUCTION))) || 
                   (whatToShow == DTMFilter.SHOW_ALL))
      initNodeTest(whatToShow);
    else
    {
      initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
                              compiler.getStepLocalName(firstStepPos));
    }
    initPredicateInfo(compiler, firstStepPos);
  
public DescendantIterator()
Create a DescendantIterator object.

param
compiler A reference to the Compiler that contains the op map.
param
opPos The position within the op map, which contains the location path expression for this itterator.
throws
javax.xml.transform.TransformerException

    super(null);
    m_axis = Axis.DESCENDANTSORSELFFROMROOT;
    int whatToShow = DTMFilter.SHOW_ALL;
    initNodeTest(whatToShow);
  
Methods Summary
public intasNode(com.sun.org.apache.xpath.internal.XPathContext xctxt)
Return the first node out of the nodeset, if this expression is a nodeset expression. This is the default implementation for nodesets.

WARNING: Do not mutate this class from this function!

param
xctxt The XPath runtime context.
return
the first node out of the nodeset, or DTM.NULL.

    if(getPredicateCount() > 0)
      return super.asNode(xctxt);

    int current = xctxt.getCurrentNode();
    
    DTM dtm = xctxt.getDTM(current);
    DTMAxisTraverser traverser = dtm.getAxisTraverser(m_axis);
    
    String localName = getLocalName();
    String namespace = getNamespace();
    int what = m_whatToShow;
    
    // System.out.print(" (DescendantIterator) ");
    
    // System.out.println("what: ");
    // NodeTest.debugWhatToShow(what);
    if(DTMFilter.SHOW_ALL == what
       || localName == NodeTest.WILD
       || namespace == NodeTest.WILD)
    {
      return traverser.first(current);
    }
    else
    {
      int type = getNodeTypeTest(what);
      int extendedType = dtm.getExpandedTypeID(namespace, localName, type);
      return traverser.first(current, extendedType);
    }
  
public com.sun.org.apache.xml.internal.dtm.DTMIteratorcloneWithReset()
Get a cloned Iterator that is reset to the beginning of the query.

return
A cloned NodeIterator set of the start of the query.
throws
CloneNotSupportedException


    DescendantIterator clone = (DescendantIterator) super.cloneWithReset();
    clone.m_traverser = m_traverser;

    clone.resetProximityPositions();

    return clone;
  
public booleandeepEquals(com.sun.org.apache.xpath.internal.Expression expr)

see
Expression#deepEquals(Expression)

  	if(!super.deepEquals(expr))
  		return false;
  		
  	if(m_axis != ((DescendantIterator)expr).m_axis)
  		return false;
  		
  	return true;
  
public voiddetach()
Detaches the iterator from the set which it iterated over, releasing any computational resources and placing the iterator in the INVALID state. Afterdetach has been invoked, calls to nextNode orpreviousNode will raise the exception INVALID_STATE_ERR.

    if (m_allowDetach) {
      m_traverser = null;    
      m_extendedTypeID = 0;

      // Always call the superclass detach last!
      super.detach();
    }
  
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 intnextNode()
Returns the next node in the set and advances the position of the iterator in the set. After a NodeIterator is created, the first call to nextNode() returns the first node in the set.

return
The next Node in the set being iterated over, or null if there are no more members in that set.
throws
DOMException INVALID_STATE_ERR: Raised if this method is called after the detach method was invoked.

   	if(m_foundLast)
  		return DTM.NULL;

    if(DTM.NULL == m_lastFetched)
    {
      resetProximityPositions();
    }

    int next;
    
    com.sun.org.apache.xpath.internal.VariableStack vars;
    int savedStart;
    if (-1 != m_stackFrame)
    {
      vars = m_execContext.getVarStack();

      // These three statements need to be combined into one operation.
      savedStart = vars.getStackFrame();

      vars.setStackFrame(m_stackFrame);
    }
    else
    {
      // Yuck.  Just to shut up the compiler!
      vars = null;
      savedStart = 0;
    }
    
    try
    {
      do
      {
        if(0 == m_extendedTypeID)
        {
          next = m_lastFetched = (DTM.NULL == m_lastFetched)
                       ? m_traverser.first(m_context)
                       : m_traverser.next(m_context, m_lastFetched);
        }
        else
        {
          next = m_lastFetched = (DTM.NULL == m_lastFetched)
                       ? m_traverser.first(m_context, m_extendedTypeID)
                       : m_traverser.next(m_context, m_lastFetched, 
                                          m_extendedTypeID);
        }
  
        if (DTM.NULL != next)
        {
          if(DTMIterator.FILTER_ACCEPT == acceptNode(next))
            break;
          else
            continue;
        }
        else
          break;
      }
      while (next != DTM.NULL);
  
      if (DTM.NULL != next)
      {
      	m_pos++;
        return next;
      }
      else
      {
        m_foundLast = true;
  
        return DTM.NULL;
      }
    }
    finally
    {
      if (-1 != m_stackFrame)
      {
        // These two statements need to be combined into one operation.
        vars.setStackFrame(savedStart);
      }
    }
  
public voidsetRoot(int context, java.lang.Object environment)
Initialize the context values for this expression after it is cloned.

param
execContext The XPath runtime context for this transformation.

    super.setRoot(context, environment);
    m_traverser = m_cdtm.getAxisTraverser(m_axis);
    
    String localName = getLocalName();
    String namespace = getNamespace();
    int what = m_whatToShow;
    // System.out.println("what: ");
    // NodeTest.debugWhatToShow(what);
    if(DTMFilter.SHOW_ALL == what
       || localName == NodeTest.WILD
       || namespace == NodeTest.WILD)
    {
      m_extendedTypeID = 0;
    }
    else
    {
      int type = getNodeTypeTest(what);
      m_extendedTypeID = m_cdtm.getExpandedTypeID(namespace, localName, type);
    }