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