KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xml > dtm > ref > DTMAxisIteratorBase


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: DTMAxisIteratorBase.java,v 1.11 2004/02/16 23:06:11 minchau Exp $
18  */

19 package org.apache.xml.dtm.ref;
20
21 import org.apache.xml.dtm.DTMAxisIterator;
22
23 /**
24  * This class serves as a default base for implementations of mutable
25  * DTMAxisIterators.
26  */

27 public abstract class DTMAxisIteratorBase implements DTMAxisIterator
28 {
29
30   /** The position of the last node within the iteration, as defined by XPath.
31    * Note that this is _not_ the node's handle within the DTM. Also, don't
32    * confuse it with the current (most recently returned) position.
33    */

34   protected int _last = -1;
35
36   /** The position of the current node within the iteration, as defined by XPath.
37    * Note that this is _not_ the node's handle within the DTM!
38    */

39   protected int _position = 0;
40
41   /** The position of the marked node within the iteration;
42    * a saved itaration state that we may want to come back to.
43    * Note that only one mark is maintained; there is no stack.
44    */

45   protected int _markedNode;
46
47   /** The handle to the start, or root, of the iteration.
48    * Set this to END to construct an empty iterator.
49    */

50   protected int _startNode = DTMAxisIterator.END;
51
52   /** True if the start node should be considered part of the iteration.
53    * False will cause it to be skipped.
54    */

55   protected boolean _includeSelf = false;
56
57   /** True if this iteration can be restarted. False otherwise (eg, if
58    * we are iterating over a stream that can not be re-scanned, or if
59    * the iterator was produced by cloning another iterator.)
60    */

61   protected boolean _isRestartable = true;
62   
63   /**
64    * Get start to END should 'close' the iterator,
65    * i.e. subsequent call to next() should return END.
66    *
67    * @return The root node of the iteration.
68    */

69   public int getStartNode()
70   {
71     return _startNode;
72   }
73
74   /**
75    * @return A DTMAxisIterator which has been reset to the start node,
76    * which may or may not be the same as this iterator.
77    * */

78   public DTMAxisIterator reset()
79   {
80
81     final boolean temp = _isRestartable;
82
83     _isRestartable = true;
84
85     setStartNode(_startNode);
86
87     _isRestartable = temp;
88
89     return this;
90   }
91
92   /**
93    * Set the flag to include the start node in the iteration.
94    *
95    *
96    * @return This default method returns just returns this DTMAxisIterator,
97    * after setting the flag.
98    * (Returning "this" permits C++-style chaining of
99    * method calls into a single expression.)
100    */

101   public DTMAxisIterator includeSelf()
102   {
103
104     _includeSelf = true;
105
106     return this;
107   }
108
109   /** Returns the position of the last node within the iteration, as
110    * defined by XPath. In a forward iterator, I believe this equals the number of nodes which this
111    * iterator will yield. In a reverse iterator, I believe it should return
112    * 1 (since the "last" is the first produced.)
113    *
114    * This may be an expensive operation when called the first time, since
115    * it may have to iterate through a large part of the document to produce
116    * its answer.
117    *
118    * @return The number of nodes in this iterator (forward) or 1 (reverse).
119    */

120   public int getLast()
121   {
122
123     if (_last == -1) // Not previously established
124
{
125       // Note that we're doing both setMark() -- which saves _currentChild
126
// -- and explicitly saving our position counter (number of nodes
127
// yielded so far).
128
//
129
// %REVIEW% Should position also be saved by setMark()?
130
// (It wasn't in the XSLTC version, but I don't understand why not.)
131

132       final int temp = _position; // Save state
133
setMark();
134
135       reset(); // Count the nodes found by this iterator
136
do
137       {
138         _last++;
139       }
140       while (next() != END);
141
142       gotoMark(); // Restore saved state
143
_position = temp;
144     }
145
146     return _last;
147   }
148
149   /**
150    * @return The position of the current node within the set, as defined by
151    * XPath. Note that this is one-based, not zero-based.
152    */

153   public int getPosition()
154   {
155     return _position == 0 ? 1 : _position;
156   }
157
158   /**
159    * @return true if this iterator has a reversed axis, else false
160    */

161   public boolean isReverse()
162   {
163     return false;
164   }
165
166   /**
167    * Returns a deep copy of this iterator. Cloned iterators may not be
168    * restartable. The iterator being cloned may or may not become
169    * non-restartable as a side effect of this operation.
170    *
171    * @return a deep copy of this iterator.
172    */

173   public DTMAxisIterator cloneIterator()
174   {
175
176     try
177     {
178       final DTMAxisIteratorBase clone = (DTMAxisIteratorBase) super.clone();
179
180       clone._isRestartable = false;
181
182       // return clone.reset();
183
return clone;
184     }
185     catch (CloneNotSupportedException JavaDoc e)
186     {
187       throw new org.apache.xml.utils.WrappedRuntimeException(e);
188     }
189   }
190
191   /**
192    * Do any final cleanup that is required before returning the node that was
193    * passed in, and then return it. The intended use is
194    * <br />
195    * <code>return returnNode(node);</code>
196    *
197    * %REVIEW% If we're calling it purely for side effects, should we really
198    * be bothering with a return value? Something like
199    * <br />
200    * <code> accept(node); return node; </code>
201    * <br />
202    * would probably optimize just about as well and avoid questions
203    * about whether what's returned could ever be different from what's
204    * passed in.
205    *
206    * @param node Node handle which iteration is about to yield.
207    *
208    * @return The node handle passed in. */

209   protected final int returnNode(final int node)
210   {
211     _position++;
212
213     return node;
214   }
215
216   /**
217    * Reset the position to zero. NOTE that this does not change the iteration
218    * state, only the position number associated with that state.
219    *
220    * %REVIEW% Document when this would be used?
221    *
222    * @return This instance.
223    */

224   protected final DTMAxisIterator resetPosition()
225   {
226
227     _position = 0;
228
229     return this;
230   }
231   
232   /**
233    * Returns true if all the nodes in the iteration well be returned in document
234    * order.
235    *
236    * @return true as a default.
237    */

238   public boolean isDocOrdered()
239   {
240     return true;
241   }
242   
243   /**
244    * Returns the axis being iterated, if it is known.
245    *
246    * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
247    * types.
248    */

249   public int getAxis()
250   {
251     return -1;
252   }
253   
254   public void setRestartable(boolean isRestartable) {
255     _isRestartable = isRestartable;
256   }
257
258   /**
259    * Return the node at the given position.
260    *
261    * @param position The position
262    * @return The node at the given position.
263    */

264   public int getNodeByPosition(int position)
265   {
266     if (position > 0) {
267       final int pos = isReverse() ? getLast() - position + 1
268                                    : position;
269       int node;
270       while ((node = next()) != DTMAxisIterator.END) {
271         if (pos == getPosition()) {
272           return node;
273         }
274       }
275     }
276     return END;
277   }
278   
279 }
280
Popular Tags