KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xpath > internal > axes > MatchPatternIterator


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: MatchPatternIterator.java,v 1.8 2004/02/17 04:32:08 minchau Exp $
18  */

19 package com.sun.org.apache.xpath.internal.axes;
20
21 import com.sun.org.apache.xml.internal.dtm.Axis;
22 import com.sun.org.apache.xml.internal.dtm.DTM;
23 import com.sun.org.apache.xml.internal.dtm.DTMAxisTraverser;
24 import com.sun.org.apache.xml.internal.dtm.DTMIterator;
25 import com.sun.org.apache.xpath.internal.XPathContext;
26 import com.sun.org.apache.xpath.internal.compiler.Compiler;
27 import com.sun.org.apache.xpath.internal.objects.XObject;
28 import com.sun.org.apache.xpath.internal.patterns.NodeTest;
29 import com.sun.org.apache.xpath.internal.patterns.StepPattern;
30
31 /**
32  * This class treats a
33  * <a HREF="http://www.w3.org/TR/xpath#location-paths">LocationPath</a> as a
34  * filtered iteration over the tree, evaluating each node in a super axis
35  * traversal against the LocationPath interpreted as a match pattern. This
36  * class is useful to find nodes in document order that are complex paths
37  * whose steps probably criss-cross each other.
38  */

39 public class MatchPatternIterator extends LocPathIterator
40 {
41
42   /** This is the select pattern, translated into a match pattern. */
43   protected StepPattern m_pattern;
44
45   /** The traversal axis from where the nodes will be filtered. */
46   protected int m_superAxis = -1;
47
48   /** The DTM inner traversal class, that corresponds to the super axis. */
49   protected DTMAxisTraverser m_traverser;
50   
51   /** DEBUG flag for diagnostic dumps. */
52   private static final boolean DEBUG = false;
53   
54 // protected int m_nsElemBase = DTM.NULL;
55

56   /**
57    * Create a LocPathIterator object, including creation
58    * of step walkers from the opcode list, and call back
59    * into the Compiler to create predicate expressions.
60    *
61    * @param compiler The Compiler which is creating
62    * this expression.
63    * @param opPos The position of this iterator in the
64    * opcode list from the compiler.
65    * @param analysis Analysis bits that give general information about the
66    * LocationPath.
67    *
68    * @throws javax.xml.transform.TransformerException
69    */

70   MatchPatternIterator(Compiler JavaDoc compiler, int opPos, int analysis)
71           throws javax.xml.transform.TransformerException JavaDoc
72   {
73
74     super(compiler, opPos, analysis, false);
75
76     int firstStepPos = compiler.getFirstChildPos(opPos);
77
78     m_pattern = WalkerFactory.loadSteps(this, compiler, firstStepPos, 0);
79
80     boolean fromRoot = false;
81     boolean walkBack = false;
82     boolean walkDescendants = false;
83     boolean walkAttributes = false;
84
85     if (0 != (analysis & (WalkerFactory.BIT_ROOT |
86                           WalkerFactory.BIT_ANY_DESCENDANT_FROM_ROOT)))
87       fromRoot = true;
88       
89     if (0 != (analysis
90               & (WalkerFactory.BIT_ANCESTOR
91                  | WalkerFactory.BIT_ANCESTOR_OR_SELF
92                  | WalkerFactory.BIT_PRECEDING
93                  | WalkerFactory.BIT_PRECEDING_SIBLING
94                  | WalkerFactory.BIT_FOLLOWING
95                  | WalkerFactory.BIT_FOLLOWING_SIBLING
96                  | WalkerFactory.BIT_PARENT | WalkerFactory.BIT_FILTER)))
97       walkBack = true;
98
99     if (0 != (analysis
100               & (WalkerFactory.BIT_DESCENDANT_OR_SELF
101                  | WalkerFactory.BIT_DESCENDANT
102                  | WalkerFactory.BIT_CHILD)))
103       walkDescendants = true;
104
105     if (0 != (analysis
106               & (WalkerFactory.BIT_ATTRIBUTE | WalkerFactory.BIT_NAMESPACE)))
107       walkAttributes = true;
108       
109     if(false || DEBUG)
110     {
111       System.out.print("analysis: "+Integer.toBinaryString(analysis));
112       System.out.println(", "+WalkerFactory.getAnalysisString(analysis));
113     }
114       
115     if(fromRoot || walkBack)
116     {
117       if(walkAttributes)
118       {
119         m_superAxis = Axis.ALL;
120       }
121       else
122       {
123         m_superAxis = Axis.DESCENDANTSFROMROOT;
124       }
125     }
126     else if(walkDescendants)
127     {
128       if(walkAttributes)
129       {
130         m_superAxis = Axis.ALLFROMNODE;
131       }
132       else
133       {
134         m_superAxis = Axis.DESCENDANTORSELF;
135       }
136     }
137     else
138     {
139       m_superAxis = Axis.ALL;
140     }
141     if(false || DEBUG)
142     {
143       System.out.println("axis: "+Axis.names[m_superAxis]);
144     }
145     
146   }
147   
148   
149   /**
150    * Initialize the context values for this expression
151    * after it is cloned.
152    *
153    * @param execContext The XPath runtime context for this
154    * transformation.
155    */

156   public void setRoot(int context, Object JavaDoc environment)
157   {
158     super.setRoot(context, environment);
159     m_traverser = m_cdtm.getAxisTraverser(m_superAxis);
160   }
161
162   /**
163    * Detaches the iterator from the set which it iterated over, releasing
164    * any computational resources and placing the iterator in the INVALID
165    * state. After<code>detach</code> has been invoked, calls to
166    * <code>nextNode</code> or<code>previousNode</code> will raise the
167    * exception INVALID_STATE_ERR.
168    */

169   public void detach()
170   {
171     if(m_allowDetach)
172     {
173       m_traverser = null;
174       
175       // Always call the superclass detach last!
176
super.detach();
177     }
178   }
179   
180   /**
181    * Get the next node via getNextXXX. Bottlenecked for derived class override.
182    * @return The next node on the axis, or DTM.NULL.
183    */

184   protected int getNextNode()
185   {
186     m_lastFetched = (DTM.NULL == m_lastFetched)
187                      ? m_traverser.first(m_context)
188                      : m_traverser.next(m_context, m_lastFetched);
189     return m_lastFetched;
190   }
191
192   /**
193    * Returns the next node in the set and advances the position of the
194    * iterator in the set. After a NodeIterator is created, the first call
195    * to nextNode() returns the first node in the set.
196    * @return The next <code>Node</code> in the set being iterated over, or
197    * <code>null</code> if there are no more members in that set.
198    */

199   public int nextNode()
200   {
201     if(m_foundLast)
202         return DTM.NULL;
203
204     int next;
205     
206     com.sun.org.apache.xpath.internal.VariableStack vars;
207     int savedStart;
208     if (-1 != m_stackFrame)
209     {
210       vars = m_execContext.getVarStack();
211
212       // These three statements need to be combined into one operation.
213
savedStart = vars.getStackFrame();
214
215       vars.setStackFrame(m_stackFrame);
216     }
217     else
218     {
219       // Yuck. Just to shut up the compiler!
220
vars = null;
221       savedStart = 0;
222     }
223     
224     try
225     {
226       if(DEBUG)
227         System.out.println("m_pattern"+m_pattern.toString());
228
229       do
230       {
231         next = getNextNode();
232   
233         if (DTM.NULL != next)
234         {
235           if(DTMIterator.FILTER_ACCEPT == acceptNode(next, m_execContext))
236             break;
237           else
238             continue;
239         }
240         else
241           break;
242       }
243       while (next != DTM.NULL);
244       
245       if (DTM.NULL != next)
246       {
247         if(DEBUG)
248         {
249           System.out.println("next: "+next);
250           System.out.println("name: "+m_cdtm.getNodeName(next));
251         }
252         incrementCurrentPos();
253   
254         return next;
255       }
256       else
257       {
258         m_foundLast = true;
259   
260         return DTM.NULL;
261       }
262     }
263     finally
264     {
265       if (-1 != m_stackFrame)
266       {
267         // These two statements need to be combined into one operation.
268
vars.setStackFrame(savedStart);
269       }
270     }
271
272   }
273   
274   /**
275    * Test whether a specified node is visible in the logical view of a
276    * TreeWalker or NodeIterator. This function will be called by the
277    * implementation of TreeWalker and NodeIterator; it is not intended to
278    * be called directly from user code.
279    * @param n The node to check to see if it passes the filter or not.
280    * @return a constant to determine whether the node is accepted,
281    * rejected, or skipped, as defined above .
282    */

283   public short acceptNode(int n, XPathContext xctxt)
284   {
285
286     try
287     {
288       xctxt.pushCurrentNode(n);
289       xctxt.pushIteratorRoot(m_context);
290       if(DEBUG)
291       {
292         System.out.println("traverser: "+m_traverser);
293         System.out.print("node: "+n);
294         System.out.println(", "+m_cdtm.getNodeName(n));
295         // if(m_cdtm.getNodeName(n).equals("near-east"))
296
System.out.println("pattern: "+m_pattern.toString());
297         m_pattern.debugWhatToShow(m_pattern.getWhatToShow());
298       }
299       
300       XObject score = m_pattern.execute(xctxt);
301       
302       if(DEBUG)
303       {
304         // System.out.println("analysis: "+Integer.toBinaryString(m_analysis));
305
System.out.println("score: "+score);
306         System.out.println("skip: "+(score == NodeTest.SCORE_NONE));
307       }
308
309       // System.out.println("\n::acceptNode - score: "+score.num()+"::");
310
return (score == NodeTest.SCORE_NONE) ? DTMIterator.FILTER_SKIP
311                     : DTMIterator.FILTER_ACCEPT;
312     }
313     catch (javax.xml.transform.TransformerException JavaDoc se)
314     {
315
316       // TODO: Fix this.
317
throw new RuntimeException JavaDoc(se.getMessage());
318     }
319     finally
320     {
321       xctxt.popCurrentNode();
322       xctxt.popIteratorRoot();
323     }
324
325   }
326
327 }
328
Popular Tags