content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *   along with AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * reserved comment block
   * DO NOT REMOVE OR ALTER!
   */
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  /*
   * $Id: WalkingIterator.java,v 1.2.4.2 2005/09/14 19:45:19 jeffsuttor Exp $
   */
  package jaxp.sun.org.apache.xpath.internal.axes;
  
  import jaxp.sun.org.apache.xml.internal.dtm.DTM;
  import jaxp.sun.org.apache.xml.internal.utils.PrefixResolver;
  import jaxp.sun.org.apache.xpath.internal.Expression;
  import jaxp.sun.org.apache.xpath.internal.ExpressionOwner;
  import jaxp.sun.org.apache.xpath.internal.VariableStack;
  import jaxp.sun.org.apache.xpath.internal.XPathVisitable;
  import jaxp.sun.org.apache.xpath.internal.XPathVisitor;
  import jaxp.sun.org.apache.xpath.internal.compiler.Compiler;
  import jaxp.sun.org.apache.xpath.internal.compiler.OpMap;
  import jaxp.xml.transform.TransformerException;
  
  /**
   * Location path iterator that uses Walkers.
   */
  
  public class WalkingIterator extends LocPathIterator implements ExpressionOwner
  {
      static final long serialVersionUID = 9110225941815665906L;
    /**
     * Create a WalkingIterator iterator, including creation
     * of step walkers from the opcode list, and call back
     * into the Compiler to create predicate expressions.
     *
     * @param compiler The Compiler which is creating
     * this expression.
     * @param opPos The position of this iterator in the
     * opcode list from the compiler.
     * @param shouldLoadWalkers True if walkers should be
     * loaded, or false if this is a derived iterator and
     * it doesn't wish to load child walkers.
     *
     * @throws TransformerException
     */
    WalkingIterator(
            Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers)
              throws TransformerException
    {
      super(compiler, opPos, analysis, shouldLoadWalkers);
  
      int firstStepPos = OpMap.getFirstChildPos(opPos);
  
      if (shouldLoadWalkers)
      {
        m_firstWalker = WalkerFactory.loadWalkers(this, compiler, firstStepPos, 0);
        m_lastUsedWalker = m_firstWalker;
      }
    }
  
    /**
     * Create a WalkingIterator object.
     *
     * @param nscontext The namespace context for this iterator,
     * should be OK if null.
     */
    public WalkingIterator(PrefixResolver nscontext)
    {
  
      super(nscontext);
    }
  
  
    /**
     * Get the analysis bits for this walker, as defined in the WalkerFactory.
     * @return One of WalkerFactory#BIT_DESCENDANT, etc.
     */
    public int getAnalysisBits()
    {
      int bits = 0;
      if (null != m_firstWalker)
      {
        AxesWalker walker = m_firstWalker;
  
        while (null != walker)
        {
          int bit = walker.getAnalysisBits();
          bits |= bit;
          walker = walker.getNextWalker();
        }
      }
      return bits;
    }
  
    /**
     * Get a cloned WalkingIterator that holds the same
     * position as this iterator.
     *
     * @return A clone of this iterator that holds the same node position.
     *
     * @throws CloneNotSupportedException
     */
    public Object clone() throws CloneNotSupportedException
    {
  
      WalkingIterator clone = (WalkingIterator) super.clone();
  
      //    clone.m_varStackPos = this.m_varStackPos;
      //    clone.m_varStackContext = this.m_varStackContext;
      if (null != m_firstWalker)
      {
        clone.m_firstWalker = m_firstWalker.cloneDeep(clone, null);
      }
  
      return clone;
    }
  
    /**
     * Reset the iterator.
     */
    public void reset()
    {
  
      super.reset();
  
      if (null != m_firstWalker)
      {
        m_lastUsedWalker = m_firstWalker;
  
        m_firstWalker.setRoot(m_context);
      }
  
    }
  
    /**
     * Initialize the context values for this expression
     * after it is cloned.
     *
     * @param context The XPath runtime context for this
     * transformation.
     */
    public void setRoot(int context, Object environment)
    {
  
      super.setRoot(context, environment);
  
      if(null != m_firstWalker)
      {
        m_firstWalker.setRoot(context);
        m_lastUsedWalker = m_firstWalker;
      }
    }
  
    /**
     *  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 <code>Node</code> in the set being iterated over, or
     *   <code>null</code> if there are no more members in that set.
     */
    public int nextNode()
    {
          if(m_foundLast)
                  return DTM.NULL;
  
      // If the variable stack position is not -1, we'll have to
      // set our position in the variable stack, so our variable access
      // will be correct.  Iterators that are at the top level of the
      // expression need to reset the variable stack, while iterators
      // in predicates do not need to, and should not, since their execution
      // may be much later than top-level iterators.
      // m_varStackPos is set in setRoot, which is called
      // from the execute method.
      if (-1 == m_stackFrame)
      {
        return returnNextNode(m_firstWalker.nextNode());
      }
      else
      {
        VariableStack vars = m_execContext.getVarStack();
  
        // These three statements need to be combined into one operation.
        int savedStart = vars.getStackFrame();
  
        vars.setStackFrame(m_stackFrame);
  
        int n = returnNextNode(m_firstWalker.nextNode());
  
        // These two statements need to be combined into one operation.
        vars.setStackFrame(savedStart);
  
        return n;
      }
    }
  
  
    /**
     * Get the head of the walker list.
     *
     * @return The head of the walker list, or null
     * if this iterator does not implement walkers.
     * @xsl.usage advanced
     */
    public final AxesWalker getFirstWalker()
    {
      return m_firstWalker;
    }
  
    /**
     * Set the head of the walker list.
     *
     * @param walker Should be a valid AxesWalker.
     * @xsl.usage advanced
     */
    public final void setFirstWalker(AxesWalker walker)
    {
      m_firstWalker = walker;
    }
  
  
    /**
     * Set the last used walker.
     *
     * @param walker The last used walker, or null.
     * @xsl.usage advanced
     */
    public final void setLastUsedWalker(AxesWalker walker)
    {
      m_lastUsedWalker = walker;
    }
  
    /**
     * Get the last used walker.
     *
     * @return The last used walker, or null.
     * @xsl.usage advanced
     */
    public final AxesWalker getLastUsedWalker()
    {
      return m_lastUsedWalker;
    }
  
    /**
     *  Detaches the iterator from the set which it iterated over, releasing
     * any computational resources and placing the iterator in the INVALID
     * state. After<code>detach</code> has been invoked, calls to
     * <code>nextNode</code> or<code>previousNode</code> will raise the
     * exception INVALID_STATE_ERR.
     */
    public void detach()
    {
      if(m_allowDetach)
      {
                  AxesWalker walker = m_firstWalker;
              while (null != walker)
              {
                walker.detach();
                walker = walker.getNextWalker();
              }
  
              m_lastUsedWalker = null;
  
              // Always call the superclass detach last!
              super.detach();
      }
    }
  
    /**
     * This function is used to fixup variables from QNames to stack frame
     * indexes at stylesheet build time.
     * @param vars List of QNames that correspond to variables.  This list
     * should be searched backwards for the first qualified name that
     * corresponds to the variable reference qname.  The position of the
     * QName in the vector from the start of the vector will be its position
     * in the stack frame (but variables above the globalsTop value will need
     * to be offset to the current stack frame).
     */
    public void fixupVariables(java.util.Vector vars, int globalsSize)
    {
      m_predicateIndex = -1;
  
      AxesWalker walker = m_firstWalker;
  
      while (null != walker)
      {
        walker.fixupVariables(vars, globalsSize);
        walker = walker.getNextWalker();
      }
    }
  
    /**
     * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
     */
    public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
    {
                  if(visitor.visitLocationPath(owner, this))
                  {
                          if(null != m_firstWalker)
                          {
                                  m_firstWalker.callVisitors(this, visitor);
                          }
                  }
    }
  
  
    /** The last used step walker in the walker list.
     *  @serial */
    protected AxesWalker m_lastUsedWalker;
  
    /** The head of the step walker list.
     *  @serial */
    protected AxesWalker m_firstWalker;
  
    /**
     * @see ExpressionOwner#getExpression()
     */
    public Expression getExpression()
    {
      return m_firstWalker;
    }
  
    /**
     * @see ExpressionOwner#setExpression(Expression)
     */
    public void setExpression(Expression exp)
    {
          exp.exprSetParent(this);
          m_firstWalker = (AxesWalker)exp;
    }
  
      /**
       * @see Expression#deepEquals(Expression)
       */
      public boolean deepEquals(Expression expr)
      {
        if (!super.deepEquals(expr))
                  return false;
  
        AxesWalker walker1 = m_firstWalker;
        AxesWalker walker2 = ((WalkingIterator)expr).m_firstWalker;
        while ((null != walker1) && (null != walker2))
        {
          if(!walker1.deepEquals(walker2))
                  return false;
          walker1 = walker1.getNextWalker();
          walker2 = walker2.getNextWalker();
        }
  
        if((null != walker1) || (null != walker2))
          return false;
  
        return true;
      }
  
  }
  