~vcs-imports/xena/trunk

« back to all changes in this revision

Viewing changes to ext/src/xalan-j_2_7_1/src/org/apache/xml/dtm/ref/DTMAxisIteratorBase.java

  • Committer: matthewoliver
  • Date: 2009-12-10 03:18:07 UTC
  • Revision ID: vcs-imports@canonical.com-20091210031807-l086qguzdlljtkl9
Merged Xena Testing into Xena Stable for the Xena 5 release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: DTMAxisIteratorBase.java,v 1.2 2009/12/10 03:18:39 matthewoliver Exp $
 
20
 */
 
21
package org.apache.xml.dtm.ref;
 
22
 
 
23
import org.apache.xml.dtm.DTMAxisIterator;
 
24
 
 
25
/**
 
26
 * This class serves as a default base for implementations of mutable
 
27
 * DTMAxisIterators.
 
28
 */
 
29
public abstract class DTMAxisIteratorBase implements DTMAxisIterator
 
30
{
 
31
 
 
32
  /** The position of the last node within the iteration, as defined by XPath.
 
33
   * Note that this is _not_ the node's handle within the DTM. Also, don't
 
34
   * confuse it with the current (most recently returned) position.
 
35
   */
 
36
  protected int _last = -1;
 
37
 
 
38
  /** The position of the current node within the iteration, as defined by XPath.
 
39
   * Note that this is _not_ the node's handle within the DTM!
 
40
   */
 
41
  protected int _position = 0;
 
42
 
 
43
  /** The position of the marked node within the iteration;
 
44
   * a saved itaration state that we may want to come back to.
 
45
   * Note that only one mark is maintained; there is no stack.
 
46
   */
 
47
  protected int _markedNode;
 
48
 
 
49
  /** The handle to the start, or root, of the iteration.
 
50
   * Set this to END to construct an empty iterator.
 
51
   */
 
52
  protected int _startNode = DTMAxisIterator.END;
 
53
 
 
54
  /** True if the start node should be considered part of the iteration.
 
55
   * False will cause it to be skipped.
 
56
   */
 
57
  protected boolean _includeSelf = false;
 
58
 
 
59
  /** True if this iteration can be restarted. False otherwise (eg, if
 
60
   * we are iterating over a stream that can not be re-scanned, or if
 
61
   * the iterator was produced by cloning another iterator.)
 
62
   */
 
63
  protected boolean _isRestartable = true;
 
64
  
 
65
  /**
 
66
   * Get start to END should 'close' the iterator,
 
67
   * i.e. subsequent call to next() should return END.
 
68
   *
 
69
   * @return The root node of the iteration.
 
70
   */
 
71
  public int getStartNode()
 
72
  {
 
73
    return _startNode;
 
74
  }
 
75
 
 
76
  /**
 
77
   * @return A DTMAxisIterator which has been reset to the start node,
 
78
   * which may or may not be the same as this iterator.
 
79
   * */
 
80
  public DTMAxisIterator reset()
 
81
  {
 
82
 
 
83
    final boolean temp = _isRestartable;
 
84
 
 
85
    _isRestartable = true;
 
86
 
 
87
    setStartNode(_startNode);
 
88
 
 
89
    _isRestartable = temp;
 
90
 
 
91
    return this;
 
92
  }
 
93
 
 
94
  /**
 
95
   * Set the flag to include the start node in the iteration. 
 
96
   *
 
97
   *
 
98
   * @return This default method returns just returns this DTMAxisIterator,
 
99
   * after setting the flag.
 
100
   * (Returning "this" permits C++-style chaining of
 
101
   * method calls into a single expression.)
 
102
   */
 
103
  public DTMAxisIterator includeSelf()
 
104
  {
 
105
 
 
106
    _includeSelf = true;
 
107
 
 
108
    return this;
 
109
  }
 
110
 
 
111
  /** Returns the position of the last node within the iteration, as
 
112
   * defined by XPath.  In a forward iterator, I believe this equals the number of nodes which this
 
113
   * iterator will yield. In a reverse iterator, I believe it should return
 
114
   * 1 (since the "last" is the first produced.)
 
115
   *
 
116
   * This may be an expensive operation when called the first time, since
 
117
   * it may have to iterate through a large part of the document to produce
 
118
   * its answer.
 
119
   *
 
120
   * @return The number of nodes in this iterator (forward) or 1 (reverse).
 
121
   */
 
122
  public int getLast()
 
123
  {
 
124
 
 
125
    if (_last == -1)            // Not previously established
 
126
    {
 
127
      // Note that we're doing both setMark() -- which saves _currentChild
 
128
      // -- and explicitly saving our position counter (number of nodes
 
129
      // yielded so far).
 
130
      //
 
131
      // %REVIEW% Should position also be saved by setMark()?
 
132
      // (It wasn't in the XSLTC version, but I don't understand why not.)
 
133
 
 
134
      final int temp = _position; // Save state
 
135
      setMark();
 
136
 
 
137
      reset();                  // Count the nodes found by this iterator
 
138
      do
 
139
      {
 
140
        _last++;
 
141
      }
 
142
      while (next() != END);
 
143
 
 
144
      gotoMark();               // Restore saved state
 
145
      _position = temp;
 
146
    }
 
147
 
 
148
    return _last;
 
149
  }
 
150
 
 
151
  /**
 
152
   * @return The position of the current node within the set, as defined by
 
153
   * XPath. Note that this is one-based, not zero-based.
 
154
   */
 
155
  public int getPosition()
 
156
  {
 
157
    return _position == 0 ? 1 : _position;
 
158
  }
 
159
 
 
160
  /**
 
161
   * @return true if this iterator has a reversed axis, else false
 
162
   */
 
163
  public boolean isReverse()
 
164
  {
 
165
    return false;
 
166
  }
 
167
 
 
168
  /**
 
169
   * Returns a deep copy of this iterator. Cloned iterators may not be
 
170
   * restartable. The iterator being cloned may or may not become
 
171
   * non-restartable as a side effect of this operation.
 
172
   *
 
173
   * @return a deep copy of this iterator.
 
174
   */
 
175
  public DTMAxisIterator cloneIterator()
 
176
  {
 
177
 
 
178
    try
 
179
    {
 
180
      final DTMAxisIteratorBase clone = (DTMAxisIteratorBase) super.clone();
 
181
 
 
182
      clone._isRestartable = false;
 
183
 
 
184
      // return clone.reset();
 
185
      return clone;
 
186
    }
 
187
    catch (CloneNotSupportedException e)
 
188
    {
 
189
      throw new org.apache.xml.utils.WrappedRuntimeException(e);
 
190
    }
 
191
  }
 
192
 
 
193
  /**
 
194
   * Do any final cleanup that is required before returning the node that was
 
195
   * passed in, and then return it. The intended use is
 
196
   * <br />
 
197
   * <code>return returnNode(node);</code>
 
198
   *
 
199
   * %REVIEW% If we're calling it purely for side effects, should we really
 
200
   * be bothering with a return value? Something like
 
201
   * <br />
 
202
   * <code> accept(node); return node; </code>
 
203
   * <br />
 
204
   * would probably optimize just about as well and avoid questions
 
205
   * about whether what's returned could ever be different from what's
 
206
   * passed in.
 
207
   *
 
208
   * @param node Node handle which iteration is about to yield.
 
209
   *
 
210
   * @return The node handle passed in.  */
 
211
  protected final int returnNode(final int node)
 
212
  {
 
213
    _position++;
 
214
 
 
215
    return node;
 
216
  }
 
217
 
 
218
  /**
 
219
   * Reset the position to zero. NOTE that this does not change the iteration
 
220
   * state, only the position number associated with that state.
 
221
   *
 
222
   * %REVIEW% Document when this would be used?
 
223
   *
 
224
   * @return This instance.
 
225
   */
 
226
  protected final DTMAxisIterator resetPosition()
 
227
  {
 
228
 
 
229
    _position = 0;
 
230
 
 
231
    return this;
 
232
  }
 
233
  
 
234
  /**
 
235
   * Returns true if all the nodes in the iteration well be returned in document 
 
236
   * order.
 
237
   * 
 
238
   * @return true as a default.
 
239
   */
 
240
  public boolean isDocOrdered()
 
241
  {
 
242
    return true;
 
243
  }
 
244
  
 
245
  /**
 
246
   * Returns the axis being iterated, if it is known.
 
247
   * 
 
248
   * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple 
 
249
   * types.
 
250
   */
 
251
  public int getAxis()
 
252
  {
 
253
    return -1;
 
254
  }
 
255
  
 
256
  public void setRestartable(boolean isRestartable) {
 
257
    _isRestartable = isRestartable;
 
258
  }  
 
259
 
 
260
  /**
 
261
   * Return the node at the given position.
 
262
   * 
 
263
   * @param position The position
 
264
   * @return The node at the given position.
 
265
   */
 
266
  public int getNodeByPosition(int position)
 
267
  {
 
268
    if (position > 0) {
 
269
      final int pos = isReverse() ? getLast() - position + 1
 
270
                                   : position;
 
271
      int node;
 
272
      while ((node = next()) != DTMAxisIterator.END) {
 
273
        if (pos == getPosition()) {
 
274
          return node;
 
275
        }
 
276
      }
 
277
    }
 
278
    return END;
 
279
  }
 
280
  
 
281
}