KickJava   Java API By Example, From Geeks To Geeks.

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


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

19 package org.apache.xpath.axes;
20
21 import org.apache.xalan.res.XSLMessages;
22 import org.apache.xml.dtm.DTM;
23 import org.apache.xml.dtm.DTMFilter;
24 import org.apache.xml.dtm.DTMIterator;
25 import org.apache.xml.dtm.DTMManager;
26 import org.apache.xml.utils.PrefixResolver;
27 import org.apache.xpath.ExpressionOwner;
28 import org.apache.xpath.XPathContext;
29 import org.apache.xpath.XPathVisitor;
30 import org.apache.xpath.compiler.Compiler;
31 import org.apache.xpath.objects.XNodeSet;
32 import org.apache.xpath.objects.XObject;
33 import org.apache.xpath.res.XPATHErrorResources;
34
35 /**
36  * This class extends NodeSetDTM, which implements NodeIterator,
37  * and fetches nodes one at a time in document order based on a XPath
38  * <a HREF="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a>.
39  *
40  * <p>If setShouldCacheNodes(true) is called,
41  * as each node is iterated via nextNode(), the node is also stored
42  * in the NodeVector, so that previousNode() can easily be done, except in
43  * the case where the LocPathIterator is "owned" by a UnionPathIterator,
44  * in which case the UnionPathIterator will cache the nodes.</p>
45  * @xsl.usage advanced
46  */

47 public abstract class LocPathIterator extends PredicatedNodeTest
48         implements Cloneable JavaDoc, DTMIterator, java.io.Serializable JavaDoc, PathComponent
49 {
50     
51   /**
52    * Create a LocPathIterator object.
53    *
54    * @param nscontext The namespace context for this iterator,
55    * should be OK if null.
56    */

57   protected LocPathIterator()
58   {
59   }
60
61
62   /**
63    * Create a LocPathIterator object.
64    *
65    * @param nscontext The namespace context for this iterator,
66    * should be OK if null.
67    */

68   protected LocPathIterator(PrefixResolver nscontext)
69   {
70
71     setLocPathIterator(this);
72     m_prefixResolver = nscontext;
73   }
74
75   /**
76    * Create a LocPathIterator object, including creation
77    * of step walkers from the opcode list, and call back
78    * into the Compiler to create predicate expressions.
79    *
80    * @param compiler The Compiler which is creating
81    * this expression.
82    * @param opPos The position of this iterator in the
83    * opcode list from the compiler.
84    *
85    * @throws javax.xml.transform.TransformerException
86    */

87   protected LocPathIterator(Compiler JavaDoc compiler, int opPos, int analysis)
88           throws javax.xml.transform.TransformerException JavaDoc
89   {
90     this(compiler, opPos, analysis, true);
91   }
92
93   /**
94    * Create a LocPathIterator object, including creation
95    * of step walkers from the opcode list, and call back
96    * into the Compiler to create predicate expressions.
97    *
98    * @param compiler The Compiler which is creating
99    * this expression.
100    * @param opPos The position of this iterator in the
101    * opcode list from the compiler.
102    * @param shouldLoadWalkers True if walkers should be
103    * loaded, or false if this is a derived iterator and
104    * it doesn't wish to load child walkers.
105    *
106    * @throws javax.xml.transform.TransformerException
107    */

108   protected LocPathIterator(
109           Compiler JavaDoc compiler, int opPos, int analysis, boolean shouldLoadWalkers)
110             throws javax.xml.transform.TransformerException JavaDoc
111   {
112     setLocPathIterator(this);
113   }
114   
115   /**
116    * Get the analysis bits for this walker, as defined in the WalkerFactory.
117    * @return One of WalkerFactory#BIT_DESCENDANT, etc.
118    */

119   public int getAnalysisBits()
120   {
121     int axis = getAxis();
122     int bit = WalkerFactory.getAnalysisBitFromAxes(axis);
123     return bit;
124   }
125   
126   /**
127    * Read the object from a serialization stream.
128    *
129    * @param stream Input stream to read from
130    *
131    * @throws java.io.IOException
132    * @throws javax.xml.transform.TransformerException
133    */

134   private void readObject(java.io.ObjectInputStream JavaDoc stream)
135           throws java.io.IOException JavaDoc, javax.xml.transform.TransformerException JavaDoc
136   {
137     try
138     {
139       stream.defaultReadObject();
140       m_clones = new IteratorPool(this);
141     }
142     catch (ClassNotFoundException JavaDoc cnfe)
143     {
144       throw new javax.xml.transform.TransformerException JavaDoc(cnfe);
145     }
146   }
147   
148   /**
149    * Set the environment in which this iterator operates, which should provide:
150    * a node (the context node... same value as "root" defined below)
151    * a pair of non-zero positive integers (the context position and the context size)
152    * a set of variable bindings
153    * a function library
154    * the set of namespace declarations in scope for the expression.
155    *
156    * <p>At this time the exact implementation of this environment is application
157    * dependent. Probably a proper interface will be created fairly soon.</p>
158    *
159    * @param environment The environment object.
160    */

161   public void setEnvironment(Object JavaDoc environment)
162   {
163     // no-op for now.
164
}
165   
166   /**
167    * Get an instance of a DTM that "owns" a node handle. Since a node
168    * iterator may be passed without a DTMManager, this allows the
169    * caller to easily get the DTM using just the iterator.
170    *
171    * @param nodeHandle the nodeHandle.
172    *
173    * @return a non-null DTM reference.
174    */

175   public DTM getDTM(int nodeHandle)
176   {
177     // %OPT%
178
return m_execContext.getDTM(nodeHandle);
179   }
180   
181   /**
182    * Get an instance of the DTMManager. Since a node
183    * iterator may be passed without a DTMManager, this allows the
184    * caller to easily get the DTMManager using just the iterator.
185    *
186    * @return a non-null DTMManager reference.
187    */

188   public DTMManager getDTMManager()
189   {
190     return m_execContext.getDTMManager();
191   }
192   
193   /**
194    * Execute this iterator, meaning create a clone that can
195    * store state, and initialize it for fast execution from
196    * the current runtime state. When this is called, no actual
197    * query from the current context node is performed.
198    *
199    * @param xctxt The XPath execution context.
200    *
201    * @return An XNodeSet reference that holds this iterator.
202    *
203    * @throws javax.xml.transform.TransformerException
204    */

205   public XObject execute(XPathContext xctxt)
206           throws javax.xml.transform.TransformerException JavaDoc
207   {
208
209     XNodeSet iter = new XNodeSet((LocPathIterator)m_clones.getInstance());
210
211     iter.setRoot(xctxt.getCurrentNode(), xctxt);
212
213     return iter;
214   }
215     
216   /**
217    * Execute an expression in the XPath runtime context, and return the
218    * result of the expression.
219    *
220    *
221    * @param xctxt The XPath runtime context.
222    * @param handler The target content handler.
223    *
224    * @return The result of the expression in the form of a <code>XObject</code>.
225    *
226    * @throws javax.xml.transform.TransformerException if a runtime exception
227    * occurs.
228    * @throws org.xml.sax.SAXException
229    */

230   public void executeCharsToContentHandler(
231           XPathContext xctxt, org.xml.sax.ContentHandler JavaDoc handler)
232             throws javax.xml.transform.TransformerException JavaDoc,
233                    org.xml.sax.SAXException JavaDoc
234   {
235     LocPathIterator clone = (LocPathIterator)m_clones.getInstance();
236
237     int current = xctxt.getCurrentNode();
238     clone.setRoot(current, xctxt);
239     
240     int node = clone.nextNode();
241     DTM dtm = clone.getDTM(node);
242     clone.detach();
243     
244     if(node != DTM.NULL)
245     {
246       dtm.dispatchCharactersEvents(node, handler, false);
247     }
248   }
249   
250   /**
251    * Given an select expression and a context, evaluate the XPath
252    * and return the resulting iterator.
253    *
254    * @param xctxt The execution context.
255    * @param contextNode The node that "." expresses.
256    * @param namespaceContext The context in which namespaces in the
257    * XPath are supposed to be expanded.
258    *
259    * @throws TransformerException thrown if the active ProblemListener decides
260    * the error condition is severe enough to halt processing.
261    *
262    * @throws javax.xml.transform.TransformerException
263    * @xsl.usage experimental
264    */

265   public DTMIterator asIterator(
266           XPathContext xctxt, int contextNode)
267             throws javax.xml.transform.TransformerException JavaDoc
268   {
269     XNodeSet iter = new XNodeSet((LocPathIterator)m_clones.getInstance());
270
271     iter.setRoot(contextNode, xctxt);
272
273     return iter;
274   }
275
276   
277   /**
278    * Tell if the expression is a nodeset expression.
279    *
280    * @return true if the expression can be represented as a nodeset.
281    */

282   public boolean isNodesetExpr()
283   {
284     return true;
285   }
286   
287   /**
288    * Return the first node out of the nodeset, if this expression is
289    * a nodeset expression. This is the default implementation for
290    * nodesets. Derived classes should try and override this and return a
291    * value without having to do a clone operation.
292    * @param xctxt The XPath runtime context.
293    * @return the first node out of the nodeset, or DTM.NULL.
294    */

295   public int asNode(XPathContext xctxt)
296     throws javax.xml.transform.TransformerException JavaDoc
297   {
298     DTMIterator iter = (DTMIterator)m_clones.getInstance();
299     
300     int current = xctxt.getCurrentNode();
301     
302     iter.setRoot(current, xctxt);
303
304     int next = iter.nextNode();
305     // m_clones.freeInstance(iter);
306
iter.detach();
307     return next;
308   }
309   
310   /**
311    * Evaluate this operation directly to a boolean.
312    *
313    * @param xctxt The runtime execution context.
314    *
315    * @return The result of the operation as a boolean.
316    *
317    * @throws javax.xml.transform.TransformerException
318    */

319   public boolean bool(XPathContext xctxt)
320           throws javax.xml.transform.TransformerException JavaDoc
321   {
322     return (asNode(xctxt) != DTM.NULL);
323   }
324
325
326   /**
327    * Set if this is an iterator at the upper level of
328    * the XPath.
329    *
330    * @param b true if this location path is at the top level of the
331    * expression.
332    * @xsl.usage advanced
333    */

334   public void setIsTopLevel(boolean b)
335   {
336     m_isTopLevel = b;
337   }
338
339   /**
340    * Get if this is an iterator at the upper level of
341    * the XPath.
342    *
343    * @return true if this location path is at the top level of the
344    * expression.
345    * @xsl.usage advanced
346    */

347   public boolean getIsTopLevel()
348   {
349     return m_isTopLevel;
350   }
351   
352   /**
353    * Initialize the context values for this expression
354    * after it is cloned.
355    *
356    * @param execContext The XPath runtime context for this
357    * transformation.
358    */

359   public void setRoot(int context, Object JavaDoc environment)
360   {
361
362     m_context = context;
363     
364     XPathContext xctxt = (XPathContext)environment;
365     m_execContext = xctxt;
366     m_cdtm = xctxt.getDTM(context);
367     
368     m_currentContextNode = context; // only if top level?
369

370     // Yech, shouldn't have to do this. -sb
371
if(null == m_prefixResolver)
372         m_prefixResolver = xctxt.getNamespaceContext();
373         
374     m_lastFetched = DTM.NULL;
375     m_foundLast = false;
376     m_pos = 0;
377     m_length = -1;
378
379     if (m_isTopLevel)
380       this.m_stackFrame = xctxt.getVarStack().getStackFrame();
381       
382     // reset();
383
}
384
385   /**
386    * Set the next position index of this iterator.
387    *
388    * @param next A value greater than or equal to zero that indicates the next
389    * node position to fetch.
390    */

391   protected void setNextPosition(int next)
392   {
393     assertion(false, "setNextPosition not supported in this iterator!");
394   }
395
396   /**
397    * Get the current position, which is one less than
398    * the next nextNode() call will retrieve. i.e. if
399    * you call getCurrentPos() and the return is 0, the next
400    * fetch will take place at index 1.
401    *
402    * @return A value greater than or equal to zero that indicates the next
403    * node position to fetch.
404    */

405   public final int getCurrentPos()
406   {
407     return m_pos;
408   }
409
410
411   /**
412    * If setShouldCacheNodes(true) is called, then nodes will
413    * be cached. They are not cached by default.
414    *
415    * @param b True if this iterator should cache nodes.
416    */

417   public void setShouldCacheNodes(boolean b)
418   {
419
420     assertion(false, "setShouldCacheNodes not supported by this iterater!");
421   }
422   
423   /**
424    * Tells if this iterator can have nodes added to it or set via
425    * the <code>setItem(int node, int index)</code> method.
426    *
427    * @return True if the nodelist can be mutated.
428    */

429   public boolean isMutable()
430   {
431     return false;
432   }
433
434   /**
435    * Set the current position in the node set.
436    *
437    * @param i Must be a valid index greater
438    * than or equal to zero and less than m_cachedNodes.size().
439    */

440   public void setCurrentPos(int i)
441   {
442     assertion(false, "setCurrentPos not supported by this iterator!");
443   }
444   
445   /**
446    * Increment the current position in the node set.
447    */

448   public void incrementCurrentPos()
449   {
450     m_pos++;
451   }
452
453
454   /**
455    * Get the length of the cached nodes.
456    *
457    * <p>Note: for the moment at least, this only returns
458    * the size of the nodes that have been fetched to date,
459    * it doesn't attempt to run to the end to make sure we
460    * have found everything. This should be reviewed.</p>
461    *
462    * @return The size of the current cache list.
463    */

464   public int size()
465   {
466     assertion(false, "size() not supported by this iterator!");
467     return 0;
468   }
469
470   /**
471    * Returns the <code>index</code> th item in the collection. If
472    * <code>index</code> is greater than or equal to the number of nodes in
473    * the list, this returns <code>null</code> .
474    * @param index Index into the collection.
475    * @return The node at the <code>index</code> th position in the
476    * <code>NodeList</code> , or <code>null</code> if that is not a valid
477    * index.
478    */

479   public int item(int index)
480   {
481     assertion(false, "item(int index) not supported by this iterator!");
482     return 0;
483   }
484   
485   /**
486    * Sets the node at the specified index of this vector to be the
487    * specified node. The previous component at that position is discarded.
488    *
489    * <p>The index must be a value greater than or equal to 0 and less
490    * than the current size of the vector.
491    * The iterator must be in cached mode.</p>
492    *
493    * <p>Meant to be used for sorted iterators.</p>
494    *
495    * @param node Node to set
496    * @param index Index of where to set the node
497    */

498   public void setItem(int node, int index)
499   {
500     assertion(false, "setItem not supported by this iterator!");
501   }
502
503   /**
504    * The number of nodes in the list. The range of valid child node indices
505    * is 0 to <code>length-1</code> inclusive.
506    *
507    * @return The number of nodes in the list, always greater or equal to zero.
508    */

509   public int getLength()
510   {
511     // Tell if this is being called from within a predicate.
512
boolean isPredicateTest = (this == m_execContext.getSubContextList());
513
514     // And get how many total predicates are part of this step.
515
int predCount = getPredicateCount();
516     
517     // If we have already calculated the length, and the current predicate
518
// is the first predicate, then return the length. We don't cache
519
// the anything but the length of the list to the first predicate.
520
if (-1 != m_length && isPredicateTest && m_predicateIndex < 1)
521         return m_length;
522     
523     // I'm a bit worried about this one, since it doesn't have the
524
// checks found above. I suspect it's fine. -sb
525
if (m_foundLast)
526         return m_pos;
527         
528     // Create a clone, and count from the current position to the end
529
// of the list, not taking into account the current predicate and
530
// predicates after the current one.
531
int pos = (m_predicateIndex >= 0) ? getProximityPosition() : m_pos;
532               
533     LocPathIterator clone;
534
535     try
536     {
537       clone = (LocPathIterator) clone();
538     }
539     catch (CloneNotSupportedException JavaDoc cnse)
540     {
541       return -1;
542     }
543
544     // We want to clip off the last predicate, but only if we are a sub
545
// context node list, NOT if we are a context list. See pos68 test,
546
// also test against bug4638.
547
if (predCount > 0 && isPredicateTest)
548     {
549       // Don't call setPredicateCount, because it clones and is slower.
550
clone.m_predCount = m_predicateIndex;
551       // The line above used to be:
552
// clone.m_predCount = predCount - 1;
553
// ...which looks like a dumb bug to me. -sb
554
}
555
556     int next;
557
558     while (DTM.NULL != (next = clone.nextNode()))
559     {
560       pos++;
561     }
562     
563     if (isPredicateTest && m_predicateIndex < 1)
564       m_length = pos;
565     
566     return pos;
567   }
568
569   /**
570    * Tells if this NodeSetDTM is "fresh", in other words, if
571    * the first nextNode() that is called will return the
572    * first node in the set.
573    *
574    * @return true of nextNode has not been called.
575    */

576   public boolean isFresh()
577   {
578     return (m_pos == 0);
579   }
580
581   /**
582    * Returns the previous node in the set and moves the position of the
583    * iterator backwards in the set.
584    * @return The previous <code>Node</code> in the set being iterated over,
585    * or<code>null</code> if there are no more members in that set.
586    */

587   public int previousNode()
588   {
589     throw new RuntimeException JavaDoc(
590       XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_CANNOT_ITERATE, null)); //"This NodeSetDTM can not iterate to a previous node!");
591
}
592
593   /**
594    * This attribute determines which node types are presented via the
595    * iterator. The available set of constants is defined in the
596    * <code>NodeFilter</code> interface.
597    *
598    * <p>This is somewhat useless at this time, since it doesn't
599    * really return information that tells what this iterator will
600    * show. It is here only to fullfill the DOM NodeIterator
601    * interface.</p>
602    *
603    * @return For now, always NodeFilter.SHOW_ALL & ~NodeFilter.SHOW_ENTITY_REFERENCE.
604    * @see org.w3c.dom.traversal.NodeIterator
605    */

606   public int getWhatToShow()
607   {
608
609     // TODO: ??
610
return DTMFilter.SHOW_ALL & ~DTMFilter.SHOW_ENTITY_REFERENCE;
611   }
612
613   /**
614    * The filter used to screen nodes. Not used at this time,
615    * this is here only to fullfill the DOM NodeIterator
616    * interface.
617    *
618    * @return Always null.
619    * @see org.w3c.dom.traversal.NodeIterator
620    */

621   public DTMFilter getFilter()
622   {
623     return null;
624   }
625
626   /**
627    * The root node of the Iterator, as specified when it was created.
628    *
629    * @return The "root" of this iterator, which, in XPath terms,
630    * is the node context for this iterator.
631    */

632   public int getRoot()
633   {
634     return m_context;
635   }
636
637   /**
638    * The value of this flag determines whether the children of entity
639    * reference nodes are visible to the iterator. If false, they will be
640    * skipped over.
641    * <br> To produce a view of the document that has entity references
642    * expanded and does not expose the entity reference node itself, use the
643    * whatToShow flags to hide the entity reference node and set
644    * expandEntityReferences to true when creating the iterator. To produce
645    * a view of the document that has entity reference nodes but no entity
646    * expansion, use the whatToShow flags to show the entity reference node
647    * and set expandEntityReferences to false.
648    *
649    * @return Always true, since entity reference nodes are not
650    * visible in the XPath model.
651    */

652   public boolean getExpandEntityReferences()
653   {
654     return true;
655   }
656   
657   /** Control over whether it is OK for detach to reset the iterator. */
658   protected boolean m_allowDetach = true;
659   
660   /**
661    * Specify if it's OK for detach to release the iterator for reuse.
662    *
663    * @param allowRelease true if it is OK for detach to release this iterator
664    * for pooling.
665    */

666   public void allowDetachToRelease(boolean allowRelease)
667   {
668     m_allowDetach = allowRelease;
669   }
670
671   /**
672    * Detaches the iterator from the set which it iterated over, releasing
673    * any computational resources and placing the iterator in the INVALID
674    * state. After<code>detach</code> has been invoked, calls to
675    * <code>nextNode</code> or<code>previousNode</code> will raise the
676    * exception INVALID_STATE_ERR.
677    */

678   public void detach()
679   {
680     if(m_allowDetach)
681     {
682       // sb: allow reusing of cached nodes when possible?
683
// m_cachedNodes = null;
684
m_execContext = null;
685       // m_prefixResolver = null; sb: Why would this ever want to be null?
686
m_cdtm = null;
687       m_length = -1;
688       m_pos = 0;
689       m_lastFetched = DTM.NULL;
690       m_context = DTM.NULL;
691       m_currentContextNode = DTM.NULL;
692       
693       m_clones.freeInstance(this);
694     }
695   }
696   
697   /**
698    * Reset the iterator.
699    */

700   public void reset()
701   {
702     assertion(false, "This iterator can not reset!");
703   }
704
705   /**
706    * Get a cloned Iterator that is reset to the beginning
707    * of the query.
708    *
709    * @return A cloned NodeIterator set of the start of the query.
710    *
711    * @throws CloneNotSupportedException
712    */

713   public DTMIterator cloneWithReset() throws CloneNotSupportedException JavaDoc
714   {
715     LocPathIterator clone;
716 // clone = (LocPathIterator) clone();
717
clone = (LocPathIterator)m_clones.getInstanceOrThrow();
718     clone.m_execContext = m_execContext;
719     clone.m_cdtm = m_cdtm;
720     
721     clone.m_context = m_context;
722     clone.m_currentContextNode = m_currentContextNode;
723     clone.m_stackFrame = m_stackFrame;
724
725     // clone.reset();
726

727     return clone;
728   }
729
730 // /**
731
// * Get a cloned LocPathIterator that holds the same
732
// * position as this iterator.
733
// *
734
// * @return A clone of this iterator that holds the same node position.
735
// *
736
// * @throws CloneNotSupportedException
737
// */
738
// public Object clone() throws CloneNotSupportedException
739
// {
740
//
741
// LocPathIterator clone = (LocPathIterator) super.clone();
742
//
743
// return clone;
744
// }
745

746   /**
747    * Returns the next node in the set and advances the position of the
748    * iterator in the set. After a NodeIterator is created, the first call
749    * to nextNode() returns the first node in the set.
750    * @return The next <code>Node</code> in the set being iterated over, or
751    * <code>null</code> if there are no more members in that set.
752    */

753   public abstract int nextNode();
754
755   /**
756    * Bottleneck the return of a next node, to make returns
757    * easier from nextNode().
758    *
759    * @param nextNode The next node found, may be null.
760    *
761    * @return The same node that was passed as an argument.
762    */

763   protected int returnNextNode(int nextNode)
764   {
765
766     if (DTM.NULL != nextNode)
767     {
768       m_pos++;
769     }
770
771     m_lastFetched = nextNode;
772
773     if (DTM.NULL == nextNode)
774       m_foundLast = true;
775
776     return nextNode;
777   }
778
779   /**
780    * Return the last fetched node. Needed to support the UnionPathIterator.
781    *
782    * @return The last fetched node, or null if the last fetch was null.
783    */

784   public int getCurrentNode()
785   {
786     return m_lastFetched;
787   }
788
789   /**
790    * If an index is requested, NodeSetDTM will call this method
791    * to run the iterator to the index. By default this sets
792    * m_next to the index. If the index argument is -1, this
793    * signals that the iterator should be run to the end.
794    *
795    * @param index The index to run to, or -1 if the iterator
796    * should run to the end.
797    */

798   public void runTo(int index)
799   {
800
801     if (m_foundLast || ((index >= 0) && (index <= getCurrentPos())))
802       return;
803
804     int n;
805
806     if (-1 == index)
807     {
808       while (DTM.NULL != (n = nextNode()));
809     }
810     else
811     {
812       while (DTM.NULL != (n = nextNode()))
813       {
814         if (getCurrentPos() >= index)
815           break;
816       }
817     }
818   }
819
820   /**
821    * Tells if we've found the last node yet.
822    *
823    * @return true if the last nextNode returned null.
824    */

825   public final boolean getFoundLast()
826   {
827     return m_foundLast;
828   }
829
830   /**
831    * The XPath execution context we are operating on.
832    *
833    * @return XPath execution context this iterator is operating on,
834    * or null if setRoot has not been called.
835    */

836   public final XPathContext getXPathContext()
837   {
838     return m_execContext;
839   }
840
841   /**
842    * The node context for the iterator.
843    *
844    * @return The node context, same as getRoot().
845    */

846   public final int getContext()
847   {
848     return m_context;
849   }
850
851   /**
852    * The node context from where the expression is being
853    * executed from (i.e. for current() support).
854    *
855    * @return The top-level node context of the entire expression.
856    */

857   public final int getCurrentContextNode()
858   {
859     return m_currentContextNode;
860   }
861
862   /**
863    * Set the current context node for this iterator.
864    *
865    * @param n Must be a non-null reference to the node context.
866    */

867   public final void setCurrentContextNode(int n)
868   {
869     m_currentContextNode = n;
870   }
871   
872 // /**
873
// * Set the current context node for this iterator.
874
// *
875
// * @param n Must be a non-null reference to the node context.
876
// */
877
// public void setRoot(int n)
878
// {
879
// m_context = n;
880
// m_cdtm = m_execContext.getDTM(n);
881
// }
882

883   /**
884    * Return the saved reference to the prefix resolver that
885    * was in effect when this iterator was created.
886    *
887    * @return The prefix resolver or this iterator, which may be null.
888    */

889   public final PrefixResolver getPrefixResolver()
890   {
891     if(null == m_prefixResolver)
892     {
893         m_prefixResolver = (PrefixResolver)getExpressionOwner();
894     }
895
896     return m_prefixResolver;
897   }
898         
899 // /**
900
// * Get the analysis pattern built by the WalkerFactory.
901
// *
902
// * @return The analysis pattern built by the WalkerFactory.
903
// */
904
// int getAnalysis()
905
// {
906
// return m_analysis;
907
// }
908

909 // /**
910
// * Set the analysis pattern built by the WalkerFactory.
911
// *
912
// * @param a The analysis pattern built by the WalkerFactory.
913
// */
914
// void setAnalysis(int a)
915
// {
916
// m_analysis = a;
917
// }
918

919   /**
920    * @see org.apache.xpath.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
921    */

922   public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
923   {
924         if(visitor.visitLocationPath(owner, this))
925         {
926             visitor.visitStep(owner, this);
927             callPredicateVisitors(visitor);
928         }
929   }
930
931   
932   //============= State Data =============
933

934   /**
935    * The pool for cloned iterators. Iterators need to be cloned
936    * because the hold running state, and thus the original iterator
937    * expression from the stylesheet pool can not be used.
938    */

939   transient protected IteratorPool m_clones = new IteratorPool(this);
940   
941   /**
942    * The dtm of the context node. Careful about using this... it may not
943    * be the dtm of the current node.
944    */

945   transient protected DTM m_cdtm;
946   
947   /**
948    * The stack frame index for this iterator.
949    */

950   transient int m_stackFrame = -1;
951
952   /**
953    * Value determined at compile time, indicates that this is an
954    * iterator at the top level of the expression, rather than inside
955    * a predicate.
956    * @serial
957    */

958   private boolean m_isTopLevel = false;
959
960   /** The last node that was fetched, usually by nextNode. */
961   transient public int m_lastFetched = DTM.NULL;
962
963   /**
964    * The context node for this iterator, which doesn't change through
965    * the course of the iteration.
966    */

967   transient protected int m_context = DTM.NULL;
968
969   /**
970    * The node context from where the expression is being
971    * executed from (i.e. for current() support). Different
972    * from m_context in that this is the context for the entire
973    * expression, rather than the context for the subexpression.
974    */

975   transient protected int m_currentContextNode = DTM.NULL;
976   
977   /**
978    * The current position of the context node.
979    */

980   transient protected int m_pos = 0;
981   
982   transient protected int m_length = -1;
983
984   /**
985    * Fast access to the current prefix resolver. It isn't really
986    * clear that this is needed.
987    * @serial
988    */

989   private PrefixResolver m_prefixResolver;
990
991   /**
992    * The XPathContext reference, needed for execution of many
993    * operations.
994    */

995   transient protected XPathContext m_execContext;
996   
997   /**
998    * Returns true if all the nodes in the iteration well be returned in document
999    * order.
1000   *
1001   * @return true as a default.
1002   */

1003  public boolean isDocOrdered()
1004  {
1005    return true;
1006  }
1007  
1008  /**
1009   * Returns the axis being iterated, if it is known.
1010   *
1011   * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
1012   * types.
1013   */

1014  public int getAxis()
1015  {
1016    return -1;
1017  }
1018
1019
1020// /**
1021
// * The analysis pattern built by the WalkerFactory.
1022
// * TODO: Move to LocPathIterator.
1023
// * @see org.apache.xpath.axes.WalkerFactory
1024
// * @serial
1025
// */
1026
// protected int m_analysis = 0x00000000;
1027
/**
1028   * @see PredicatedNodeTest#getLastPos(XPathContext)
1029   */

1030  public int getLastPos(XPathContext xctxt)
1031  {
1032    return getLength();
1033  }
1034
1035}
1036
Popular Tags