OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / org / apache / xpath / axes / MatchPatternIterator.java
1 /*
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18 /*
19  * $Id: MatchPatternIterator.java 469314 2006-10-30 23:31:59Z minchau $
20  */
21 package org.apache.xpath.axes;
22
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;
33
34 /**
35  * This class treats a 
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.
41  */
42 public class MatchPatternIterator extends LocPathIterator
43 {
44     static final long serialVersionUID = -5201153767396296474L;
45
46   /** This is the select pattern, translated into a match pattern. */
47   protected StepPattern m_pattern;
48
49   /** The traversal axis from where the nodes will be filtered. */
50   protected int m_superAxis = -1;
51
52   /** The DTM inner traversal class, that corresponds to the super axis. */
53   protected DTMAxisTraverser m_traverser;
54   
55   /** DEBUG flag for diagnostic dumps. */
56   private static final boolean DEBUG = false;
57   
58 //  protected int m_nsElemBase = DTM.NULL;
59
60   /**
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.
64    *
65    * @param compiler The Compiler which is creating
66    * this expression.
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 
70    * LocationPath.
71    *
72    * @throws javax.xml.transform.TransformerException
73    */
74   MatchPatternIterator(Compiler compiler, int opPos, int analysis)
75           throws javax.xml.transform.TransformerException
76   {
77
78     super(compiler, opPos, analysis, false);
79
80     int firstStepPos = OpMap.getFirstChildPos(opPos);
81
82     m_pattern = WalkerFactory.loadSteps(this, compiler, firstStepPos, 0); 
83
84     boolean fromRoot = false;
85     boolean walkBack = false;
86     boolean walkDescendants = false;
87     boolean walkAttributes = false;
88
89     if (0 != (analysis & (WalkerFactory.BIT_ROOT | 
90                           WalkerFactory.BIT_ANY_DESCENDANT_FROM_ROOT)))
91       fromRoot = true;
92       
93     if (0 != (analysis
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)))
101       walkBack = true;
102
103     if (0 != (analysis
104               & (WalkerFactory.BIT_DESCENDANT_OR_SELF
105                  | WalkerFactory.BIT_DESCENDANT
106                  | WalkerFactory.BIT_CHILD)))
107       walkDescendants = true;
108
109     if (0 != (analysis
110               & (WalkerFactory.BIT_ATTRIBUTE | WalkerFactory.BIT_NAMESPACE)))
111       walkAttributes = true;
112       
113     if(false || DEBUG)
114     {
115       System.out.print("analysis: "+Integer.toBinaryString(analysis));
116       System.out.println(", "+WalkerFactory.getAnalysisString(analysis));
117     }
118       
119     if(fromRoot || walkBack)
120     {
121       if(walkAttributes)
122       {
123         m_superAxis = Axis.ALL;
124       }
125       else
126       {
127         m_superAxis = Axis.DESCENDANTSFROMROOT;
128       }
129     }
130     else if(walkDescendants)
131     {
132       if(walkAttributes)
133       {
134         m_superAxis = Axis.ALLFROMNODE;
135       }
136       else
137       {
138         m_superAxis = Axis.DESCENDANTORSELF;
139       }
140     }
141     else
142     {
143       m_superAxis = Axis.ALL;
144     }
145     if(false || DEBUG)
146     {
147       System.out.println("axis: "+Axis.getNames(m_superAxis));
148     }
149     
150   }
151   
152   
153   /**
154    * Initialize the context values for this expression
155    * after it is cloned.
156    *
157    * @param context The XPath runtime context for this
158    * transformation.
159    */
160   public void setRoot(int context, Object environment)
161   {
162     super.setRoot(context, environment);
163     m_traverser = m_cdtm.getAxisTraverser(m_superAxis);
164   }
165
166   /**
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.
172    */
173   public void detach()
174   {    
175     if(m_allowDetach)
176     {
177       m_traverser = null;
178       
179       // Always call the superclass detach last!
180       super.detach();
181     }
182   }
183   
184   /**
185    * Get the next node via getNextXXX.  Bottlenecked for derived class override.
186    * @return The next node on the axis, or DTM.NULL.
187    */
188   protected int getNextNode()
189   {
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;
194   }
195
196   /**
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.
202    */
203   public int nextNode()
204   {      
205         if(m_foundLast)
206                 return DTM.NULL;
207
208     int next;
209     
210     org.apache.xpath.VariableStack vars;
211     int savedStart;
212     if (-1 != m_stackFrame)
213     {
214       vars = m_execContext.getVarStack();
215
216       // These three statements need to be combined into one operation.
217       savedStart = vars.getStackFrame();
218
219       vars.setStackFrame(m_stackFrame);
220     }
221     else
222     {
223       // Yuck.  Just to shut up the compiler!
224       vars = null;
225       savedStart = 0;
226     }
227     
228     try
229     {
230       if(DEBUG)
231         System.out.println("m_pattern"+m_pattern.toString());
232
233       do
234       {
235         next = getNextNode();
236   
237         if (DTM.NULL != next)
238         {
239           if(DTMIterator.FILTER_ACCEPT == acceptNode(next, m_execContext))
240             break;
241           else
242             continue;
243         }
244         else
245           break;
246       }
247       while (next != DTM.NULL);
248       
249       if (DTM.NULL != next)
250       {
251         if(DEBUG)
252         {
253           System.out.println("next: "+next);
254           System.out.println("name: "+m_cdtm.getNodeName(next));
255         }
256         incrementCurrentPos();
257   
258         return next;
259       }
260       else
261       {
262         m_foundLast = true;
263   
264         return DTM.NULL;
265       }
266     }
267     finally
268     {
269       if (-1 != m_stackFrame)
270       {
271         // These two statements need to be combined into one operation.
272         vars.setStackFrame(savedStart);
273       }
274     }
275
276   }
277   
278   /**
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 .
286    */
287   public short acceptNode(int n, XPathContext xctxt)
288   {
289
290     try
291     {
292       xctxt.pushCurrentNode(n);
293       xctxt.pushIteratorRoot(m_context);
294       if(DEBUG)
295       {
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());
302       }
303       
304       XObject score = m_pattern.execute(xctxt);
305       
306       if(DEBUG)
307       {
308         // System.out.println("analysis: "+Integer.toBinaryString(m_analysis));
309         System.out.println("score: "+score);
310         System.out.println("skip: "+(score == NodeTest.SCORE_NONE));
311       }
312
313       // System.out.println("\n::acceptNode - score: "+score.num()+"::");
314       return (score == NodeTest.SCORE_NONE) ? DTMIterator.FILTER_SKIP 
315                     : DTMIterator.FILTER_ACCEPT;
316     }
317     catch (javax.xml.transform.TransformerException se)
318     {
319
320       // TODO: Fix this.
321       throw new RuntimeException(se.getMessage());
322     }
323     finally
324     {
325       xctxt.popCurrentNode();
326       xctxt.popIteratorRoot();
327     }
328
329   }
330
331 }