blob: 40638e6e6937f67dcec5858741862a97ca0bac20 [file] [log] [blame]
ohair6c320662012-03-04 11:55:34 -08001/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Copyright 1999-2004 The Apache Software Foundation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * 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 * $Id: FilterExprWalker.java,v 1.2.4.2 2005/09/14 19:45:23 jeffsuttor Exp $
22 */
23package com.sun.org.apache.xpath.internal.axes;
24
25import com.sun.org.apache.xml.internal.dtm.Axis;
26import com.sun.org.apache.xml.internal.dtm.DTM;
27import com.sun.org.apache.xml.internal.dtm.DTMIterator;
28import com.sun.org.apache.xpath.internal.Expression;
29import com.sun.org.apache.xpath.internal.ExpressionOwner;
30import com.sun.org.apache.xpath.internal.XPathContext;
31import com.sun.org.apache.xpath.internal.XPathVisitor;
32import com.sun.org.apache.xpath.internal.compiler.Compiler;
33import com.sun.org.apache.xpath.internal.compiler.OpCodes;
34import com.sun.org.apache.xpath.internal.objects.XNodeSet;
35
36/**
37 * Walker for the OP_VARIABLE, or OP_EXTFUNCTION, or OP_FUNCTION, or OP_GROUP,
38 * op codes.
39 * @see <a href="http://www.w3.org/TR/xpath#NT-FilterExpr">XPath FilterExpr descriptions</a>
40 */
41public class FilterExprWalker extends AxesWalker
42{
43 static final long serialVersionUID = 5457182471424488375L;
44
45 /**
46 * Construct a FilterExprWalker using a LocPathIterator.
47 *
48 * @param locPathIterator non-null reference to the parent iterator.
49 */
50 public FilterExprWalker(WalkingIterator locPathIterator)
51 {
52 super(locPathIterator, Axis.FILTEREDLIST);
53 }
54
55 /**
56 * Init a FilterExprWalker.
57 *
58 * @param compiler non-null reference to the Compiler that is constructing.
59 * @param opPos positive opcode position for this step.
60 * @param stepType The type of step.
61 *
62 * @throws javax.xml.transform.TransformerException
63 */
64 public void init(Compiler compiler, int opPos, int stepType)
65 throws javax.xml.transform.TransformerException
66 {
67
68 super.init(compiler, opPos, stepType);
69
70 // Smooth over an anomily in the opcode map...
71 switch (stepType)
72 {
73 case OpCodes.OP_FUNCTION :
74 case OpCodes.OP_EXTFUNCTION :
75 m_mustHardReset = true;
76 case OpCodes.OP_GROUP :
77 case OpCodes.OP_VARIABLE :
78 m_expr = compiler.compile(opPos);
79 m_expr.exprSetParent(this);
80 //if((OpCodes.OP_FUNCTION == stepType) && (m_expr instanceof com.sun.org.apache.xalan.internal.templates.FuncKey))
81 if(m_expr instanceof com.sun.org.apache.xpath.internal.operations.Variable)
82 {
83 // hack/temp workaround
84 m_canDetachNodeset = false;
85 }
86 break;
87 default :
88 m_expr = compiler.compile(opPos + 2);
89 m_expr.exprSetParent(this);
90 }
91// if(m_expr instanceof WalkingIterator)
92// {
93// WalkingIterator wi = (WalkingIterator)m_expr;
94// if(wi.getFirstWalker() instanceof FilterExprWalker)
95// {
96// FilterExprWalker fw = (FilterExprWalker)wi.getFirstWalker();
97// if(null == fw.getNextWalker())
98// {
99// m_expr = fw.m_expr;
100// m_expr.exprSetParent(this);
101// }
102// }
103//
104// }
105 }
106
107 /**
108 * Detaches the walker from the set which it iterated over, releasing
109 * any computational resources and placing the iterator in the INVALID
110 * state.
111 */
112 public void detach()
113 {
114 super.detach();
115 if (m_canDetachNodeset)
116 {
117 m_exprObj.detach();
118 }
119 m_exprObj = null;
120 }
121
122 /**
123 * Set the root node of the TreeWalker.
124 *
125 * @param root non-null reference to the root, or starting point of
126 * the query.
127 */
128 public void setRoot(int root)
129 {
130
131 super.setRoot(root);
132
133 m_exprObj = FilterExprIteratorSimple.executeFilterExpr(root,
134 m_lpi.getXPathContext(), m_lpi.getPrefixResolver(),
135 m_lpi.getIsTopLevel(), m_lpi.m_stackFrame, m_expr);
136
137 }
138
139 /**
140 * Get a cloned FilterExprWalker.
141 *
142 * @return A new FilterExprWalker that can be used without mutating this one.
143 *
144 * @throws CloneNotSupportedException
145 */
146 public Object clone() throws CloneNotSupportedException
147 {
148
149 FilterExprWalker clone = (FilterExprWalker) super.clone();
150
151 // clone.m_expr = (Expression)((Expression)m_expr).clone();
152 if (null != m_exprObj)
153 clone.m_exprObj = (XNodeSet) m_exprObj.clone();
154
155 return clone;
156 }
157
158 /**
159 * This method needs to override AxesWalker.acceptNode because FilterExprWalkers
160 * don't need to, and shouldn't, do a node test.
161 * @param n The node to check to see if it passes the filter or not.
162 * @return a constant to determine whether the node is accepted,
163 * rejected, or skipped, as defined above .
164 */
165 public short acceptNode(int n)
166 {
167
168 try
169 {
170 if (getPredicateCount() > 0)
171 {
172 countProximityPosition(0);
173
174 if (!executePredicates(n, m_lpi.getXPathContext()))
175 return DTMIterator.FILTER_SKIP;
176 }
177
178 return DTMIterator.FILTER_ACCEPT;
179 }
180 catch (javax.xml.transform.TransformerException se)
181 {
182 throw new RuntimeException(se.getMessage());
183 }
184 }
185
186 /**
187 * Moves the <code>TreeWalker</code> to the next visible node in document
188 * order relative to the current node, and returns the new node. If the
189 * current node has no next node, or if the search for nextNode attempts
190 * to step upward from the TreeWalker's root node, returns
191 * <code>null</code> , and retains the current node.
192 * @return The new node, or <code>null</code> if the current node has no
193 * next node in the TreeWalker's logical view.
194 */
195 public int getNextNode()
196 {
197
198 if (null != m_exprObj)
199 {
200 int next = m_exprObj.nextNode();
201 return next;
202 }
203 else
204 return DTM.NULL;
205 }
206
207 /**
208 * Get the index of the last node that can be itterated to.
209 *
210 *
211 * @param xctxt XPath runtime context.
212 *
213 * @return the index of the last node that can be itterated to.
214 */
215 public int getLastPos(XPathContext xctxt)
216 {
217 return m_exprObj.getLength();
218 }
219
220 /** The contained expression. Should be non-null.
221 * @serial */
222 private Expression m_expr;
223
224 /** The result of executing m_expr. Needs to be deep cloned on clone op. */
225 transient private XNodeSet m_exprObj;
226
227 private boolean m_mustHardReset = false;
228 private boolean m_canDetachNodeset = true;
229
230 /**
231 * This function is used to fixup variables from QNames to stack frame
232 * indexes at stylesheet build time.
233 * @param vars List of QNames that correspond to variables. This list
234 * should be searched backwards for the first qualified name that
235 * corresponds to the variable reference qname. The position of the
236 * QName in the vector from the start of the vector will be its position
237 * in the stack frame (but variables above the globalsTop value will need
238 * to be offset to the current stack frame).
239 */
240 public void fixupVariables(java.util.Vector vars, int globalsSize)
241 {
242 super.fixupVariables(vars, globalsSize);
243 m_expr.fixupVariables(vars, globalsSize);
244 }
245
246 /**
247 * Get the inner contained expression of this filter.
248 */
249 public Expression getInnerExpression()
250 {
251 return m_expr;
252 }
253
254 /**
255 * Set the inner contained expression of this filter.
256 */
257 public void setInnerExpression(Expression expr)
258 {
259 expr.exprSetParent(this);
260 m_expr = expr;
261 }
262
263
264 /**
265 * Get the analysis bits for this walker, as defined in the WalkerFactory.
266 * @return One of WalkerFactory#BIT_DESCENDANT, etc.
267 */
268 public int getAnalysisBits()
269 {
270 if (null != m_expr && m_expr instanceof PathComponent)
271 {
272 return ((PathComponent) m_expr).getAnalysisBits();
273 }
274 return WalkerFactory.BIT_FILTER;
275 }
276
277 /**
278 * Returns true if all the nodes in the iteration well be returned in document
279 * order.
280 * Warning: This can only be called after setRoot has been called!
281 *
282 * @return true as a default.
283 */
284 public boolean isDocOrdered()
285 {
286 return m_exprObj.isDocOrdered();
287 }
288
289 /**
290 * Returns the axis being iterated, if it is known.
291 *
292 * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
293 * types.
294 */
295 public int getAxis()
296 {
297 return m_exprObj.getAxis();
298 }
299
300 class filterExprOwner implements ExpressionOwner
301 {
302 /**
303 * @see ExpressionOwner#getExpression()
304 */
305 public Expression getExpression()
306 {
307 return m_expr;
308 }
309
310 /**
311 * @see ExpressionOwner#setExpression(Expression)
312 */
313 public void setExpression(Expression exp)
314 {
315 exp.exprSetParent(FilterExprWalker.this);
316 m_expr = exp;
317 }
318 }
319
320 /**
321 * This will traverse the heararchy, calling the visitor for
322 * each member. If the called visitor method returns
323 * false, the subtree should not be called.
324 *
325 * @param visitor The visitor whose appropriate method will be called.
326 */
327 public void callPredicateVisitors(XPathVisitor visitor)
328 {
329 m_expr.callVisitors(new filterExprOwner(), visitor);
330
331 super.callPredicateVisitors(visitor);
332 }
333
334
335 /**
336 * @see Expression#deepEquals(Expression)
337 */
338 public boolean deepEquals(Expression expr)
339 {
340 if (!super.deepEquals(expr))
341 return false;
342
343 FilterExprWalker walker = (FilterExprWalker)expr;
344 if(!m_expr.deepEquals(walker.m_expr))
345 return false;
346
347 return true;
348 }
349
350
351
352}