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    */
FilterExprIterator()51   public FilterExprIterator()
52   {
53     super(null);
54   }
55 
56   /**
57    * Create a FilterExprIterator object.
58    *
59    */
FilterExprIterator(Expression expr)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    */
setRoot(int context, Object environment)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    */
getNextNode()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    */
detach()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    */
fixupVariables(List<QName> vars, int globalsSize)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    */
getInnerExpression()130   public Expression getInnerExpression()
131   {
132     return m_expr;
133   }
134 
135   /**
136    * Set the inner contained expression of this filter.
137    */
setInnerExpression(Expression expr)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    */
getAnalysisBits()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    */
isDocOrdered()164   public boolean isDocOrdered()
165   {
166     return m_exprObj.isDocOrdered();
167   }
168 
169   class filterExprOwner implements ExpressionOwner
170   {
171     /**
172     * @see ExpressionOwner#getExpression()
173     */
getExpression()174     public Expression getExpression()
175     {
176       return m_expr;
177     }
178 
179     /**
180      * @see ExpressionOwner#setExpression(Expression)
181      */
setExpression(Expression exp)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    */
callPredicateVisitors(XPathVisitor visitor)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    */
deepEquals(Expression expr)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 }
220