2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 * $Id: MatchPatternIterator.java 469314 2006-10-30 23:31:59Z minchau $
21 package org.apache.xpath.axes;
23 import org.apache.xml.dtm.Axis;
24 import org.apache.xml.dtm.DTM;
25 import org.apache.xml.dtm.DTMAxisTraverser;
26 import org.apache.xml.dtm.DTMIterator;
27 import org.apache.xpath.XPathContext;
28 import org.apache.xpath.compiler.Compiler;
29 import org.apache.xpath.compiler.OpMap;
30 import org.apache.xpath.objects.XObject;
31 import org.apache.xpath.patterns.NodeTest;
32 import org.apache.xpath.patterns.StepPattern;
36 * <a href="http://www.w3.org/TR/xpath#location-paths">LocationPath</a> as a
37 * filtered iteration over the tree, evaluating each node in a super axis
38 * traversal against the LocationPath interpreted as a match pattern. This
39 * class is useful to find nodes in document order that are complex paths
40 * whose steps probably criss-cross each other.
42 public class MatchPatternIterator extends LocPathIterator
44 static final long serialVersionUID = -5201153767396296474L;
46 /** This is the select pattern, translated into a match pattern. */
47 protected StepPattern m_pattern;
49 /** The traversal axis from where the nodes will be filtered. */
50 protected int m_superAxis = -1;
52 /** The DTM inner traversal class, that corresponds to the super axis. */
53 protected DTMAxisTraverser m_traverser;
55 /** DEBUG flag for diagnostic dumps. */
56 private static final boolean DEBUG = false;
58 // protected int m_nsElemBase = DTM.NULL;
61 * Create a LocPathIterator object, including creation
62 * of step walkers from the opcode list, and call back
63 * into the Compiler to create predicate expressions.
65 * @param compiler The Compiler which is creating
67 * @param opPos The position of this iterator in the
68 * opcode list from the compiler.
69 * @param analysis Analysis bits that give general information about the
72 * @throws javax.xml.transform.TransformerException
74 MatchPatternIterator(Compiler compiler, int opPos, int analysis)
75 throws javax.xml.transform.TransformerException
78 super(compiler, opPos, analysis, false);
80 int firstStepPos = OpMap.getFirstChildPos(opPos);
82 m_pattern = WalkerFactory.loadSteps(this, compiler, firstStepPos, 0);
84 boolean fromRoot = false;
85 boolean walkBack = false;
86 boolean walkDescendants = false;
87 boolean walkAttributes = false;
89 if (0 != (analysis & (WalkerFactory.BIT_ROOT |
90 WalkerFactory.BIT_ANY_DESCENDANT_FROM_ROOT)))
94 & (WalkerFactory.BIT_ANCESTOR
95 | WalkerFactory.BIT_ANCESTOR_OR_SELF
96 | WalkerFactory.BIT_PRECEDING
97 | WalkerFactory.BIT_PRECEDING_SIBLING
98 | WalkerFactory.BIT_FOLLOWING
99 | WalkerFactory.BIT_FOLLOWING_SIBLING
100 | WalkerFactory.BIT_PARENT | WalkerFactory.BIT_FILTER)))
104 & (WalkerFactory.BIT_DESCENDANT_OR_SELF
105 | WalkerFactory.BIT_DESCENDANT
106 | WalkerFactory.BIT_CHILD)))
107 walkDescendants = true;
110 & (WalkerFactory.BIT_ATTRIBUTE | WalkerFactory.BIT_NAMESPACE)))
111 walkAttributes = true;
115 System.out.print("analysis: "+Integer.toBinaryString(analysis));
116 System.out.println(", "+WalkerFactory.getAnalysisString(analysis));
119 if(fromRoot || walkBack)
123 m_superAxis = Axis.ALL;
127 m_superAxis = Axis.DESCENDANTSFROMROOT;
130 else if(walkDescendants)
134 m_superAxis = Axis.ALLFROMNODE;
138 m_superAxis = Axis.DESCENDANTORSELF;
143 m_superAxis = Axis.ALL;
147 System.out.println("axis: "+Axis.getNames(m_superAxis));
154 * Initialize the context values for this expression
155 * after it is cloned.
157 * @param context The XPath runtime context for this
160 public void setRoot(int context, Object environment)
162 super.setRoot(context, environment);
163 m_traverser = m_cdtm.getAxisTraverser(m_superAxis);
167 * Detaches the iterator from the set which it iterated over, releasing
168 * any computational resources and placing the iterator in the INVALID
169 * state. After<code>detach</code> has been invoked, calls to
170 * <code>nextNode</code> or<code>previousNode</code> will raise the
171 * exception INVALID_STATE_ERR.
179 // Always call the superclass detach last!
185 * Get the next node via getNextXXX. Bottlenecked for derived class override.
186 * @return The next node on the axis, or DTM.NULL.
188 protected int getNextNode()
190 m_lastFetched = (DTM.NULL == m_lastFetched)
191 ? m_traverser.first(m_context)
192 : m_traverser.next(m_context, m_lastFetched);
193 return m_lastFetched;
197 * Returns the next node in the set and advances the position of the
198 * iterator in the set. After a NodeIterator is created, the first call
199 * to nextNode() returns the first node in the set.
200 * @return The next <code>Node</code> in the set being iterated over, or
201 * <code>null</code> if there are no more members in that set.
203 public int nextNode()
210 org.apache.xpath.VariableStack vars;
212 if (-1 != m_stackFrame)
214 vars = m_execContext.getVarStack();
216 // These three statements need to be combined into one operation.
217 savedStart = vars.getStackFrame();
219 vars.setStackFrame(m_stackFrame);
223 // Yuck. Just to shut up the compiler!
231 System.out.println("m_pattern"+m_pattern.toString());
235 next = getNextNode();
237 if (DTM.NULL != next)
239 if(DTMIterator.FILTER_ACCEPT == acceptNode(next, m_execContext))
247 while (next != DTM.NULL);
249 if (DTM.NULL != next)
253 System.out.println("next: "+next);
254 System.out.println("name: "+m_cdtm.getNodeName(next));
256 incrementCurrentPos();
269 if (-1 != m_stackFrame)
271 // These two statements need to be combined into one operation.
272 vars.setStackFrame(savedStart);
279 * Test whether a specified node is visible in the logical view of a
280 * TreeWalker or NodeIterator. This function will be called by the
281 * implementation of TreeWalker and NodeIterator; it is not intended to
282 * be called directly from user code.
283 * @param n The node to check to see if it passes the filter or not.
284 * @return a constant to determine whether the node is accepted,
285 * rejected, or skipped, as defined above .
287 public short acceptNode(int n, XPathContext xctxt)
292 xctxt.pushCurrentNode(n);
293 xctxt.pushIteratorRoot(m_context);
296 System.out.println("traverser: "+m_traverser);
297 System.out.print("node: "+n);
298 System.out.println(", "+m_cdtm.getNodeName(n));
299 // if(m_cdtm.getNodeName(n).equals("near-east"))
300 System.out.println("pattern: "+m_pattern.toString());
301 m_pattern.debugWhatToShow(m_pattern.getWhatToShow());
304 XObject score = m_pattern.execute(xctxt);
308 // System.out.println("analysis: "+Integer.toBinaryString(m_analysis));
309 System.out.println("score: "+score);
310 System.out.println("skip: "+(score == NodeTest.SCORE_NONE));
313 // System.out.println("\n::acceptNode - score: "+score.num()+"::");
314 return (score == NodeTest.SCORE_NONE) ? DTMIterator.FILTER_SKIP
315 : DTMIterator.FILTER_ACCEPT;
317 catch (javax.xml.transform.TransformerException se)
321 throw new RuntimeException(se.getMessage());
325 xctxt.popCurrentNode();
326 xctxt.popIteratorRoot();