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: FilterExprWalker.java,v 1.2.4.2 2005/09/14 19:45:23 jeffsuttor Exp $
   */
  package jaxp.sun.org.apache.xpath.internal.axes;
  
  import jaxp.sun.org.apache.xml.internal.dtm.Axis;
  import jaxp.sun.org.apache.xml.internal.dtm.DTM;
  import jaxp.sun.org.apache.xml.internal.dtm.DTMIterator;
  import jaxp.sun.org.apache.xpath.internal.Expression;
  import jaxp.sun.org.apache.xpath.internal.ExpressionOwner;
  import jaxp.sun.org.apache.xpath.internal.XPathContext;
  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.OpCodes;
  import jaxp.sun.org.apache.xpath.internal.objects.XNodeSet;
  import jaxp.sun.org.apache.xpath.internal.operations.Variable;
  import jaxp.xml.transform.TransformerException;
  
  /**
   * Walker for the OP_VARIABLE, or OP_EXTFUNCTION, or OP_FUNCTION, or OP_GROUP,
   * op codes.
   * @see <a href="http://www.w3.org/TR/xpath#NT-FilterExpr">XPath FilterExpr descriptions</a>
   */
  public class FilterExprWalker extends AxesWalker
  {
      static final long serialVersionUID = 5457182471424488375L;
  
    /**
     * Construct a FilterExprWalker using a LocPathIterator.
     *
     * @param locPathIterator non-null reference to the parent iterator.
     */
    public FilterExprWalker(WalkingIterator locPathIterator)
    {
      super(locPathIterator, Axis.FILTEREDLIST);
    }
  
    /**
     * Init a FilterExprWalker.
     *
     * @param compiler non-null reference to the Compiler that is constructing.
     * @param opPos positive opcode position for this step.
     * @param stepType The type of step.
     *
     * @throws TransformerException
     */
    public void init(Compiler compiler, int opPos, int stepType)
            throws TransformerException
    {
  
      super.init(compiler, opPos, stepType);
  
      // Smooth over an anomily in the opcode map...
      switch (stepType)
      {
      case OpCodes.OP_FUNCTION :
      case OpCodes.OP_EXTFUNCTION :
          m_mustHardReset = true;
      case OpCodes.OP_GROUP :
      case OpCodes.OP_VARIABLE :
        m_expr = compiler.compile(opPos);
        m_expr.exprSetParent(this);
        //if((OpCodes.OP_FUNCTION == stepType) && (m_expr instanceof com.sun.org.apache.xalan.internal.templates.FuncKey))
        if(m_expr instanceof Variable)
        {
          // hack/temp workaround
          m_canDetachNodeset = false;
        }
        break;
      default :
        m_expr = compiler.compile(opPos + 2);
        m_expr.exprSetParent(this);
      }
  //    if(m_expr instanceof WalkingIterator)
  //    {
  //      WalkingIterator wi = (WalkingIterator)m_expr;
  //      if(wi.getFirstWalker() instanceof FilterExprWalker)
  //      {
  //              FilterExprWalker fw = (FilterExprWalker)wi.getFirstWalker();
  //              if(null == fw.getNextWalker())
  //              {
  //                      m_expr = fw.m_expr;
  //                      m_expr.exprSetParent(this);
  //              }
  //      }
  //
  //    }
    }
  
    /**
     * Detaches the walker from the set which it iterated over, releasing
     * any computational resources and placing the iterator in the INVALID
     * state.
     */
    public void detach()
    {
          super.detach();
          if (m_canDetachNodeset)
          {
            m_exprObj.detach();
          }
          m_exprObj = null;
    }
  
    /**
     *  Set the root node of the TreeWalker.
     *
     * @param root non-null reference to the root, or starting point of
     *        the query.
     */
    public void setRoot(int root)
    {
  
      super.setRoot(root);
  
          m_exprObj = FilterExprIteratorSimple.executeFilterExpr(root,
                            m_lpi.getXPathContext(), m_lpi.getPrefixResolver(),
                            m_lpi.getIsTopLevel(), m_lpi.m_stackFrame, m_expr);
  
    }
  
    /**
     * Get a cloned FilterExprWalker.
     *
     * @return A new FilterExprWalker that can be used without mutating this one.
     *
     * @throws CloneNotSupportedException
     */
    public Object clone() throws CloneNotSupportedException
    {
  
      FilterExprWalker clone = (FilterExprWalker) super.clone();
  
      // clone.m_expr = (Expression)((Expression)m_expr).clone();
      if (null != m_exprObj)
        clone.m_exprObj = (XNodeSet) m_exprObj.clone();
  
      return clone;
    }
  
    /**
     * This method needs to override AxesWalker.acceptNode because FilterExprWalkers
     * don't need to, and shouldn't, do a node test.
     * @param n  The node to check to see if it passes the filter or not.
     * @return  a constant to determine whether the node is accepted,
     *   rejected, or skipped, as defined  above .
     */
    public short acceptNode(int n)
    {
  
      try
      {
        if (getPredicateCount() > 0)
        {
          countProximityPosition(0);
  
          if (!executePredicates(n, m_lpi.getXPathContext()))
            return DTMIterator.FILTER_SKIP;
        }
  
        return DTMIterator.FILTER_ACCEPT;
      }
      catch (TransformerException se)
      {
        throw new RuntimeException(se.getMessage());
      }
    }
  
    /**
     *  Moves the <code>TreeWalker</code> 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
     * <code>null</code> , and retains the current node.
     * @return  The new node, or <code>null</code> if the current node has no
     *   next node  in the TreeWalker's logical view.
     */
    public int getNextNode()
    {
  
      if (null != m_exprObj)
      {
         int next = m_exprObj.nextNode();
         return next;
      }
      else
        return DTM.NULL;
    }
  
    /**
     * 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.
     */
    public int getLastPos(XPathContext xctxt)
    {
      return m_exprObj.getLength();
    }
  
    /** The contained expression. Should be non-null.
     *  @serial   */
    private Expression m_expr;
  
    /** The result of executing m_expr.  Needs to be deep cloned on clone op.  */
    transient private XNodeSet m_exprObj;
  
    private boolean m_mustHardReset = false;
    private boolean m_canDetachNodeset = true;
  
    /**
     * 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)
    {
      super.fixupVariables(vars, globalsSize);
      m_expr.fixupVariables(vars, globalsSize);
    }
  
    /**
     * Get the inner contained expression of this filter.
     */
    public Expression getInnerExpression()
    {
          return m_expr;
    }
  
    /**
     * Set the inner contained expression of this filter.
     */
    public void setInnerExpression(Expression expr)
    {
          expr.exprSetParent(this);
          m_expr = expr;
    }
  
  
    /**
     * Get the analysis bits for this walker, as defined in the WalkerFactory.
     * @return One of WalkerFactory#BIT_DESCENDANT, etc.
     */
    public int getAnalysisBits()
    {
        if (null != m_expr && m_expr instanceof PathComponent)
        {
          return ((PathComponent) m_expr).getAnalysisBits();
        }
        return WalkerFactory.BIT_FILTER;
    }
  
    /**
     * 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.
     */
    public boolean isDocOrdered()
    {
      return m_exprObj.isDocOrdered();
    }
  
    /**
     * 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.
     */
    public int getAxis()
    {
      return m_exprObj.getAxis();
    }
  
    class filterExprOwner implements ExpressionOwner
    {
        /**
       * @see ExpressionOwner#getExpression()
       */
      public Expression getExpression()
      {
        return m_expr;
      }
  
      /**
       * @see ExpressionOwner#setExpression(Expression)
       */
      public void setExpression(Expression exp)
      {
          exp.exprSetParent(FilterExprWalker.this);
          m_expr = exp;
      }
    }
  
          /**
           * 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 visitor The visitor whose appropriate method will be called.
           */
          public void callPredicateVisitors(XPathVisitor visitor)
          {
            m_expr.callVisitors(new filterExprOwner(), visitor);
  
            super.callPredicateVisitors(visitor);
          }
  
  
      /**
       * @see Expression#deepEquals(Expression)
       */
      public boolean deepEquals(Expression expr)
      {
        if (!super.deepEquals(expr))
                  return false;
  
        FilterExprWalker walker = (FilterExprWalker)expr;
        if(!m_expr.deepEquals(walker.m_expr))
          return false;
  
        return true;
      }
  
  
  
  }
  