1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xpath.internal.axes;
  22 
  23 import com.sun.org.apache.xml.internal.dtm.DTM;
  24 import com.sun.org.apache.xml.internal.utils.QName;
  25 import com.sun.org.apache.xpath.internal.Expression;
  26 import com.sun.org.apache.xpath.internal.ExpressionOwner;
  27 import com.sun.org.apache.xpath.internal.XPathVisitor;
  28 import com.sun.org.apache.xpath.internal.objects.XNodeSet;
  29 import java.util.List;
  30 
  31 /**
  32  * @LastModified: Oct 2017
  33  */
  34 public class FilterExprIterator extends BasicTestIterator
  35 {
  36     static final long serialVersionUID = 2552176105165737614L;
  37   /** The contained expression. Should be non-null.
  38    *  @serial   */
  39   private Expression m_expr;
  40 
  41   /** The result of executing m_expr.  Needs to be deep cloned on clone op.  */
  42   transient private XNodeSet m_exprObj;
  43 
  44   private boolean m_mustHardReset = false;
  45   private boolean m_canDetachNodeset = true;
  46 
  47   /**
  48    * Create a FilterExprIterator object.
  49    *
  50    */
  51   public FilterExprIterator()
  52   {
  53     super(null);
  54   }
  55 
  56   /**
  57    * Create a FilterExprIterator object.
  58    *
  59    */
  60   public FilterExprIterator(Expression expr)
  61   {
  62     super(null);
  63     m_expr = expr;
  64   }
  65 
  66   /**
  67    * Initialize the context values for this expression
  68    * after it is cloned.
  69    *
  70    * @param context The XPath runtime context for this
  71    * transformation.
  72    */
  73   public void setRoot(int context, Object environment)
  74   {
  75         super.setRoot(context, environment);
  76 
  77         m_exprObj = FilterExprIteratorSimple.executeFilterExpr(context,
  78                           m_execContext, getPrefixResolver(),
  79                           getIsTopLevel(), m_stackFrame, m_expr);
  80    }
  81 
  82 
  83   /**
  84    * Get the next node via getNextXXX.  Bottlenecked for derived class override.
  85    * @return The next node on the axis, or DTM.NULL.
  86    */
  87   protected int getNextNode()
  88   {
  89     if (null != m_exprObj)
  90     {
  91       m_lastFetched = m_exprObj.nextNode();
  92     }
  93     else
  94       m_lastFetched = DTM.NULL;
  95 
  96     return m_lastFetched;
  97   }
  98 
  99   /**
 100    * Detaches the walker from the set which it iterated over, releasing
 101    * any computational resources and placing the iterator in the INVALID
 102    * state.
 103    */
 104   public void detach()
 105   {
 106         super.detach();
 107         m_exprObj.detach();
 108         m_exprObj = null;
 109   }
 110 
 111   /**
 112    * This function is used to fixup variables from QNames to stack frame
 113    * indexes at stylesheet build time.
 114    * @param vars List of QNames that correspond to variables.  This list
 115    * should be searched backwards for the first qualified name that
 116    * corresponds to the variable reference qname.  The position of the
 117    * QName in the vector from the start of the vector will be its position
 118    * in the stack frame (but variables above the globalsTop value will need
 119    * to be offset to the current stack frame).
 120    */
 121   public void fixupVariables(List<QName> vars, int globalsSize)
 122   {
 123     super.fixupVariables(vars, globalsSize);
 124     m_expr.fixupVariables(vars, globalsSize);
 125   }
 126 
 127   /**
 128    * Get the inner contained expression of this filter.
 129    */
 130   public Expression getInnerExpression()
 131   {
 132     return m_expr;
 133   }
 134 
 135   /**
 136    * Set the inner contained expression of this filter.
 137    */
 138   public void setInnerExpression(Expression expr)
 139   {
 140     expr.exprSetParent(this);
 141     m_expr = expr;
 142   }
 143 
 144   /**
 145    * Get the analysis bits for this walker, as defined in the WalkerFactory.
 146    * @return One of WalkerFactory#BIT_DESCENDANT, etc.
 147    */
 148   public int getAnalysisBits()
 149   {
 150     if (null != m_expr && m_expr instanceof PathComponent)
 151     {
 152       return ((PathComponent) m_expr).getAnalysisBits();
 153     }
 154     return WalkerFactory.BIT_FILTER;
 155   }
 156 
 157   /**
 158    * Returns true if all the nodes in the iteration well be returned in document
 159    * order.
 160    * Warning: This can only be called after setRoot has been called!
 161    *
 162    * @return true as a default.
 163    */
 164   public boolean isDocOrdered()
 165   {
 166     return m_exprObj.isDocOrdered();
 167   }
 168 
 169   class filterExprOwner implements ExpressionOwner
 170   {
 171     /**
 172     * @see ExpressionOwner#getExpression()
 173     */
 174     public Expression getExpression()
 175     {
 176       return m_expr;
 177     }
 178 
 179     /**
 180      * @see ExpressionOwner#setExpression(Expression)
 181      */
 182     public void setExpression(Expression exp)
 183     {
 184       exp.exprSetParent(FilterExprIterator.this);
 185       m_expr = exp;
 186     }
 187 
 188   }
 189 
 190   /**
 191    * This will traverse the heararchy, calling the visitor for
 192    * each member.  If the called visitor method returns
 193    * false, the subtree should not be called.
 194    *
 195    * @param visitor The visitor whose appropriate method will be called.
 196    */
 197   public void callPredicateVisitors(XPathVisitor visitor)
 198   {
 199     m_expr.callVisitors(new filterExprOwner(), visitor);
 200 
 201     super.callPredicateVisitors(visitor);
 202   }
 203 
 204   /**
 205    * @see Expression#deepEquals(Expression)
 206    */
 207   public boolean deepEquals(Expression expr)
 208   {
 209     if (!super.deepEquals(expr))
 210       return false;
 211 
 212     FilterExprIterator fet = (FilterExprIterator) expr;
 213     if (!m_expr.deepEquals(fet.m_expr))
 214       return false;
 215 
 216     return true;
 217   }
 218 
 219 }