KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xpath > axes > DescendantIterator


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: DescendantIterator.java,v 1.22 2004/02/17 04:32:08 minchau Exp $
18  */

19 package org.apache.xpath.axes;
20
21 import org.apache.xml.dtm.Axis;
22 import org.apache.xml.dtm.DTM;
23 import org.apache.xml.dtm.DTMAxisTraverser;
24 import org.apache.xml.dtm.DTMFilter;
25 import org.apache.xml.dtm.DTMIterator;
26 import org.apache.xpath.Expression;
27 import org.apache.xpath.XPathContext;
28 import org.apache.xpath.compiler.Compiler;
29 import org.apache.xpath.compiler.OpCodes;
30 import org.apache.xpath.patterns.NodeTest;
31
32 /**
33  * This class implements an optimized iterator for
34  * descendant, descendant-or-self, or "//foo" patterns.
35  * @see org.apache.xpath.axes.LocPathIterator
36  * @xsl.usage advanced
37  */

38 public class DescendantIterator extends LocPathIterator
39 {
40   /**
41    * Create a DescendantIterator object.
42    *
43    * @param compiler A reference to the Compiler that contains the op map.
44    * @param opPos The position within the op map, which contains the
45    * location path expression for this itterator.
46    *
47    * @throws javax.xml.transform.TransformerException
48    */

49   DescendantIterator(Compiler JavaDoc compiler, int opPos, int analysis)
50           throws javax.xml.transform.TransformerException JavaDoc
51   {
52
53     super(compiler, opPos, analysis, false);
54
55     int firstStepPos = compiler.getFirstChildPos(opPos);
56     int stepType = compiler.getOp(firstStepPos);
57
58     boolean orSelf = (OpCodes.FROM_DESCENDANTS_OR_SELF == stepType);
59     boolean fromRoot = false;
60     if (OpCodes.FROM_SELF == stepType)
61     {
62       orSelf = true;
63       // firstStepPos += 8;
64
}
65     else if(OpCodes.FROM_ROOT == stepType)
66     {
67       fromRoot = true;
68       // Ugly code... will go away when AST work is done.
69
int nextStepPos = compiler.getNextStepPos(firstStepPos);
70       if(compiler.getOp(nextStepPos) == OpCodes.FROM_DESCENDANTS_OR_SELF)
71         orSelf = true;
72       // firstStepPos += 8;
73
}
74     
75     // Find the position of the last step.
76
int nextStepPos = firstStepPos;
77     while(true)
78     {
79       nextStepPos = compiler.getNextStepPos(nextStepPos);
80       if(nextStepPos > 0)
81       {
82         int stepOp = compiler.getOp(nextStepPos);
83         if(OpCodes.ENDOP != stepOp)
84           firstStepPos = nextStepPos;
85         else
86           break;
87       }
88       else
89         break;
90       
91     }
92     
93     // Fix for http://nagoya.apache.org/bugzilla/show_bug.cgi?id=1336
94
if((analysis & WalkerFactory.BIT_CHILD) != 0)
95       orSelf = false;
96       
97     if(fromRoot)
98     {
99       if(orSelf)
100         m_axis = Axis.DESCENDANTSORSELFFROMROOT;
101       else
102         m_axis = Axis.DESCENDANTSFROMROOT;
103     }
104     else if(orSelf)
105       m_axis = Axis.DESCENDANTORSELF;
106     else
107       m_axis = Axis.DESCENDANT;
108
109     int whatToShow = compiler.getWhatToShow(firstStepPos);
110
111     if ((0 == (whatToShow
112                & (DTMFilter.SHOW_ATTRIBUTE | DTMFilter.SHOW_ELEMENT
113                   | DTMFilter.SHOW_PROCESSING_INSTRUCTION))) ||
114                    (whatToShow == DTMFilter.SHOW_ALL))
115       initNodeTest(whatToShow);
116     else
117     {
118       initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
119                               compiler.getStepLocalName(firstStepPos));
120     }
121     initPredicateInfo(compiler, firstStepPos);
122   }
123   
124   /**
125    * Create a DescendantIterator object.
126    *
127    * @param compiler A reference to the Compiler that contains the op map.
128    * @param opPos The position within the op map, which contains the
129    * location path expression for this itterator.
130    *
131    * @throws javax.xml.transform.TransformerException
132    */

133   public DescendantIterator()
134   {
135     super(null);
136     m_axis = Axis.DESCENDANTSORSELFFROMROOT;
137     int whatToShow = DTMFilter.SHOW_ALL;
138     initNodeTest(whatToShow);
139   }
140
141   
142   /**
143    * Get a cloned Iterator that is reset to the beginning
144    * of the query.
145    *
146    * @return A cloned NodeIterator set of the start of the query.
147    *
148    * @throws CloneNotSupportedException
149    */

150   public DTMIterator cloneWithReset() throws CloneNotSupportedException JavaDoc
151   {
152
153     DescendantIterator clone = (DescendantIterator) super.cloneWithReset();
154     clone.m_traverser = m_traverser;
155
156     clone.resetProximityPositions();
157
158     return clone;
159   }
160
161   /**
162    * Returns the next node in the set and advances the position of the
163    * iterator in the set. After a NodeIterator is created, the first call
164    * to nextNode() returns the first node in the set.
165    *
166    * @return The next <code>Node</code> in the set being iterated over, or
167    * <code>null</code> if there are no more members in that set.
168    *
169    * @throws DOMException
170    * INVALID_STATE_ERR: Raised if this method is called after the
171    * <code>detach</code> method was invoked.
172    */

173   public int nextNode()
174   {
175     if(m_foundLast)
176         return DTM.NULL;
177
178     if(DTM.NULL == m_lastFetched)
179     {
180       resetProximityPositions();
181     }
182
183     int next;
184     
185     org.apache.xpath.VariableStack vars;
186     int savedStart;
187     if (-1 != m_stackFrame)
188     {
189       vars = m_execContext.getVarStack();
190
191       // These three statements need to be combined into one operation.
192
savedStart = vars.getStackFrame();
193
194       vars.setStackFrame(m_stackFrame);
195     }
196     else
197     {
198       // Yuck. Just to shut up the compiler!
199
vars = null;
200       savedStart = 0;
201     }
202     
203     try
204     {
205       do
206       {
207         if(0 == m_extendedTypeID)
208         {
209           next = m_lastFetched = (DTM.NULL == m_lastFetched)
210                        ? m_traverser.first(m_context)
211                        : m_traverser.next(m_context, m_lastFetched);
212         }
213         else
214         {
215           next = m_lastFetched = (DTM.NULL == m_lastFetched)
216                        ? m_traverser.first(m_context, m_extendedTypeID)
217                        : m_traverser.next(m_context, m_lastFetched,
218                                           m_extendedTypeID);
219         }
220   
221         if (DTM.NULL != next)
222         {
223           if(DTMIterator.FILTER_ACCEPT == acceptNode(next))
224             break;
225           else
226             continue;
227         }
228         else
229           break;
230       }
231       while (next != DTM.NULL);
232   
233       if (DTM.NULL != next)
234       {
235         m_pos++;
236         return next;
237       }
238       else
239       {
240         m_foundLast = true;
241   
242         return DTM.NULL;
243       }
244     }
245     finally
246     {
247       if (-1 != m_stackFrame)
248       {
249         // These two statements need to be combined into one operation.
250
vars.setStackFrame(savedStart);
251       }
252     }
253   }
254   
255   /**
256    * Initialize the context values for this expression
257    * after it is cloned.
258    *
259    * @param execContext The XPath runtime context for this
260    * transformation.
261    */

262   public void setRoot(int context, Object JavaDoc environment)
263   {
264     super.setRoot(context, environment);
265     m_traverser = m_cdtm.getAxisTraverser(m_axis);
266     
267     String JavaDoc localName = getLocalName();
268     String JavaDoc namespace = getNamespace();
269     int what = m_whatToShow;
270     // System.out.println("what: ");
271
// NodeTest.debugWhatToShow(what);
272
if(DTMFilter.SHOW_ALL == what
273        || localName == NodeTest.WILD
274        || namespace == NodeTest.WILD)
275     {
276       m_extendedTypeID = 0;
277     }
278     else
279     {
280       int type = getNodeTypeTest(what);
281       m_extendedTypeID = m_cdtm.getExpandedTypeID(namespace, localName, type);
282     }
283     
284   }
285   
286   /**
287    * Return the first node out of the nodeset, if this expression is
288    * a nodeset expression. This is the default implementation for
289    * nodesets.
290    * <p>WARNING: Do not mutate this class from this function!</p>
291    * @param xctxt The XPath runtime context.
292    * @return the first node out of the nodeset, or DTM.NULL.
293    */

294   public int asNode(XPathContext xctxt)
295     throws javax.xml.transform.TransformerException JavaDoc
296   {
297     if(getPredicateCount() > 0)
298       return super.asNode(xctxt);
299
300     int current = xctxt.getCurrentNode();
301     
302     DTM dtm = xctxt.getDTM(current);
303     DTMAxisTraverser traverser = dtm.getAxisTraverser(m_axis);
304     
305     String JavaDoc localName = getLocalName();
306     String JavaDoc namespace = getNamespace();
307     int what = m_whatToShow;
308     
309     // System.out.print(" (DescendantIterator) ");
310

311     // System.out.println("what: ");
312
// NodeTest.debugWhatToShow(what);
313
if(DTMFilter.SHOW_ALL == what
314        || localName == NodeTest.WILD
315        || namespace == NodeTest.WILD)
316     {
317       return traverser.first(current);
318     }
319     else
320     {
321       int type = getNodeTypeTest(what);
322       int extendedType = dtm.getExpandedTypeID(namespace, localName, type);
323       return traverser.first(current, extendedType);
324     }
325   }
326   
327   /**
328    * Detaches the iterator from the set which it iterated over, releasing
329    * any computational resources and placing the iterator in the INVALID
330    * state. After<code>detach</code> has been invoked, calls to
331    * <code>nextNode</code> or<code>previousNode</code> will raise the
332    * exception INVALID_STATE_ERR.
333    */

334   public void detach()
335   {
336     if (m_allowDetach) {
337       m_traverser = null;
338       m_extendedTypeID = 0;
339
340       // Always call the superclass detach last!
341
super.detach();
342     }
343   }
344   
345   /**
346    * Returns the axis being iterated, if it is known.
347    *
348    * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
349    * types.
350    */

351   public int getAxis()
352   {
353     return m_axis;
354   }
355   
356   
357   /** The traverser to use to navigate over the descendants. */
358   transient protected DTMAxisTraverser m_traverser;
359   
360   /** The axis that we are traversing. */
361   protected int m_axis;
362   
363   /** The extended type ID, not set until setRoot. */
364   protected int m_extendedTypeID;
365   
366   /**
367    * @see Expression#deepEquals(Expression)
368    */

369   public boolean deepEquals(Expression expr)
370   {
371     if(!super.deepEquals(expr))
372         return false;
373         
374     if(m_axis != ((DescendantIterator)expr).m_axis)
375         return false;
376         
377     return true;
378   }
379
380   
381 }
382
Popular Tags