001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: DTMDefaultBaseIterators.java 468653 2006-10-28 07:07:05Z minchau $
020 */
021 package org.apache.xml.dtm.ref;
022
023 import org.apache.xml.dtm.*;
024
025 import javax.xml.transform.Source;
026
027 import org.apache.xml.utils.XMLStringFactory;
028
029 import org.apache.xml.res.XMLErrorResources;
030 import org.apache.xml.res.XMLMessages;
031 import org.apache.xalan.xsltc.dom.NodeCounter;
032
033 /**
034 * This class implements the traversers for DTMDefaultBase.
035 */
036 public abstract class DTMDefaultBaseIterators extends DTMDefaultBaseTraversers
037 {
038
039 /**
040 * Construct a DTMDefaultBaseTraversers object from a DOM node.
041 *
042 * @param mgr The DTMManager who owns this DTM.
043 * @param source The object that is used to specify the construction source.
044 * @param dtmIdentity The DTM identity ID for this DTM.
045 * @param whiteSpaceFilter The white space filter for this DTM, which may
046 * be null.
047 * @param xstringfactory The factory to use for creating XMLStrings.
048 * @param doIndexing true if the caller considers it worth it to use
049 * indexing schemes.
050 */
051 public DTMDefaultBaseIterators(DTMManager mgr, Source source,
052 int dtmIdentity,
053 DTMWSFilter whiteSpaceFilter,
054 XMLStringFactory xstringfactory,
055 boolean doIndexing)
056 {
057 super(mgr, source, dtmIdentity, whiteSpaceFilter,
058 xstringfactory, doIndexing);
059 }
060
061 /**
062 * Construct a DTMDefaultBaseTraversers object from a DOM node.
063 *
064 * @param mgr The DTMManager who owns this DTM.
065 * @param source The object that is used to specify the construction source.
066 * @param dtmIdentity The DTM identity ID for this DTM.
067 * @param whiteSpaceFilter The white space filter for this DTM, which may
068 * be null.
069 * @param xstringfactory The factory to use for creating XMLStrings.
070 * @param doIndexing true if the caller considers it worth it to use
071 * indexing schemes.
072 * @param blocksize The block size of the DTM.
073 * @param usePrevsib true if we want to build the previous sibling node array.
074 * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
075 */
076 public DTMDefaultBaseIterators(DTMManager mgr, Source source,
077 int dtmIdentity,
078 DTMWSFilter whiteSpaceFilter,
079 XMLStringFactory xstringfactory,
080 boolean doIndexing,
081 int blocksize,
082 boolean usePrevsib,
083 boolean newNameTable)
084 {
085 super(mgr, source, dtmIdentity, whiteSpaceFilter,
086 xstringfactory, doIndexing, blocksize, usePrevsib, newNameTable);
087 }
088
089 /**
090 * Get an iterator that can navigate over an XPath Axis, predicated by
091 * the extended type ID.
092 * Returns an iterator that must be initialized
093 * with a start node (using iterator.setStartNode()).
094 *
095 * @param axis One of Axes.ANCESTORORSELF, etc.
096 * @param type An extended type ID.
097 *
098 * @return A DTMAxisIterator, or null if the given axis isn't supported.
099 */
100 public DTMAxisIterator getTypedAxisIterator(int axis, int type)
101 {
102
103 DTMAxisIterator iterator = null;
104
105 /* This causes an error when using patterns for elements that
106 do not exist in the DOM (translet types which do not correspond
107 to a DOM type are mapped to the DOM.ELEMENT type).
108 */
109
110 // if (type == NO_TYPE) {
111 // return(EMPTYITERATOR);
112 // }
113 // else if (type == ELEMENT) {
114 // iterator = new FilterIterator(getAxisIterator(axis),
115 // getElementFilter());
116 // }
117 // else
118 {
119 switch (axis)
120 {
121 case Axis.SELF :
122 iterator = new TypedSingletonIterator(type);
123 break;
124 case Axis.CHILD :
125 iterator = new TypedChildrenIterator(type);
126 break;
127 case Axis.PARENT :
128 return (new ParentIterator().setNodeType(type));
129 case Axis.ANCESTOR :
130 return (new TypedAncestorIterator(type));
131 case Axis.ANCESTORORSELF :
132 return ((new TypedAncestorIterator(type)).includeSelf());
133 case Axis.ATTRIBUTE :
134 return (new TypedAttributeIterator(type));
135 case Axis.DESCENDANT :
136 iterator = new TypedDescendantIterator(type);
137 break;
138 case Axis.DESCENDANTORSELF :
139 iterator = (new TypedDescendantIterator(type)).includeSelf();
140 break;
141 case Axis.FOLLOWING :
142 iterator = new TypedFollowingIterator(type);
143 break;
144 case Axis.PRECEDING :
145 iterator = new TypedPrecedingIterator(type);
146 break;
147 case Axis.FOLLOWINGSIBLING :
148 iterator = new TypedFollowingSiblingIterator(type);
149 break;
150 case Axis.PRECEDINGSIBLING :
151 iterator = new TypedPrecedingSiblingIterator(type);
152 break;
153 case Axis.NAMESPACE :
154 iterator = new TypedNamespaceIterator(type);
155 break;
156 case Axis.ROOT :
157 iterator = new TypedRootIterator(type);
158 break;
159 default :
160 throw new DTMException(XMLMessages.createXMLMessage(
161 XMLErrorResources.ER_TYPED_ITERATOR_AXIS_NOT_IMPLEMENTED,
162 new Object[]{Axis.getNames(axis)}));
163 //"Error: typed iterator for axis "
164 //+ Axis.names[axis] + "not implemented");
165 }
166 }
167
168 return (iterator);
169 }
170
171 /**
172 * This is a shortcut to the iterators that implement the
173 * XPath axes.
174 * Returns a bare-bones iterator that must be initialized
175 * with a start node (using iterator.setStartNode()).
176 *
177 * @param axis One of Axes.ANCESTORORSELF, etc.
178 *
179 * @return A DTMAxisIterator, or null if the given axis isn't supported.
180 */
181 public DTMAxisIterator getAxisIterator(final int axis)
182 {
183
184 DTMAxisIterator iterator = null;
185
186 switch (axis)
187 {
188 case Axis.SELF :
189 iterator = new SingletonIterator();
190 break;
191 case Axis.CHILD :
192 iterator = new ChildrenIterator();
193 break;
194 case Axis.PARENT :
195 return (new ParentIterator());
196 case Axis.ANCESTOR :
197 return (new AncestorIterator());
198 case Axis.ANCESTORORSELF :
199 return ((new AncestorIterator()).includeSelf());
200 case Axis.ATTRIBUTE :
201 return (new AttributeIterator());
202 case Axis.DESCENDANT :
203 iterator = new DescendantIterator();
204 break;
205 case Axis.DESCENDANTORSELF :
206 iterator = (new DescendantIterator()).includeSelf();
207 break;
208 case Axis.FOLLOWING :
209 iterator = new FollowingIterator();
210 break;
211 case Axis.PRECEDING :
212 iterator = new PrecedingIterator();
213 break;
214 case Axis.FOLLOWINGSIBLING :
215 iterator = new FollowingSiblingIterator();
216 break;
217 case Axis.PRECEDINGSIBLING :
218 iterator = new PrecedingSiblingIterator();
219 break;
220 case Axis.NAMESPACE :
221 iterator = new NamespaceIterator();
222 break;
223 case Axis.ROOT :
224 iterator = new RootIterator();
225 break;
226 default :
227 throw new DTMException(XMLMessages.createXMLMessage(
228 XMLErrorResources.ER_ITERATOR_AXIS_NOT_IMPLEMENTED,
229 new Object[]{Axis.getNames(axis)}));
230 //"Error: iterator for axis '" + Axis.names[axis]
231 //+ "' not implemented");
232 }
233
234 return (iterator);
235 }
236
237 /**
238 * Abstract superclass defining behaviors shared by all DTMDefault's
239 * internal implementations of DTMAxisIterator. Subclass this (and
240 * override, if necessary) to implement the specifics of an
241 * individual axis iterator.
242 *
243 * Currently there isn't a lot here
244 */
245 public abstract class InternalAxisIteratorBase extends DTMAxisIteratorBase
246 {
247
248 // %REVIEW% We could opt to share _nodeType and setNodeType() as
249 // well, and simply ignore them in iterators which don't use them.
250 // But Scott's worried about the overhead involved in cloning
251 // these, and wants them to have as few fields as possible. Note
252 // that we can't create a TypedInternalAxisIteratorBase because
253 // those are often based on the untyped versions and Java doesn't
254 // support multiple inheritance. <sigh/>
255
256 /**
257 * Current iteration location. Usually this is the last location
258 * returned (starting point for the next() search); for single-node
259 * iterators it may instead be initialized to point to that single node.
260 */
261 protected int _currentNode;
262
263 /**
264 * Remembers the current node for the next call to gotoMark().
265 *
266 * %REVIEW% Should this save _position too?
267 */
268 public void setMark()
269 {
270 _markedNode = _currentNode;
271 }
272
273 /**
274 * Restores the current node remembered by setMark().
275 *
276 * %REVEIW% Should this restore _position too?
277 */
278 public void gotoMark()
279 {
280 _currentNode = _markedNode;
281 }
282
283 } // end of InternalAxisIteratorBase
284
285 /**
286 * Iterator that returns all immediate children of a given node
287 */
288 public final class ChildrenIterator extends InternalAxisIteratorBase
289 {
290
291 /**
292 * Setting start to END should 'close' the iterator,
293 * i.e. subsequent call to next() should return END.
294 *
295 * If the iterator is not restartable, this has no effect.
296 * %REVIEW% Should it return/throw something in that case,
297 * or set current node to END, to indicate request-not-honored?
298 *
299 * @param node Sets the root of the iteration.
300 *
301 * @return A DTMAxisIterator set to the start of the iteration.
302 */
303 public DTMAxisIterator setStartNode(int node)
304 {
305 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
306 if (node == DTMDefaultBase.ROOTNODE)
307 node = getDocument();
308 if (_isRestartable)
309 {
310 _startNode = node;
311 _currentNode = (node == DTM.NULL) ? DTM.NULL
312 : _firstch(makeNodeIdentity(node));
313
314 return resetPosition();
315 }
316
317 return this;
318 }
319
320 /**
321 * Get the next node in the iteration.
322 *
323 * @return The next node handle in the iteration, or END if no more
324 * are available.
325 */
326 public int next()
327 {
328 if (_currentNode != NULL) {
329 int node = _currentNode;
330 _currentNode = _nextsib(node);
331 return returnNode(makeNodeHandle(node));
332 }
333
334 return END;
335 }
336 } // end of ChildrenIterator
337
338 /**
339 * Iterator that returns the parent of a given node. Note that
340 * this delivers only a single node; if you want all the ancestors,
341 * see AncestorIterator.
342 */
343 public final class ParentIterator extends InternalAxisIteratorBase
344 {
345
346 /** The extended type ID that was requested. */
347 private int _nodeType = -1;
348
349 /**
350 * Set start to END should 'close' the iterator,
351 * i.e. subsequent call to next() should return END.
352 *
353 * @param node Sets the root of the iteration.
354 *
355 * @return A DTMAxisIterator set to the start of the iteration.
356 */
357 public DTMAxisIterator setStartNode(int node)
358 {
359 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
360 if (node == DTMDefaultBase.ROOTNODE)
361 node = getDocument();
362 if (_isRestartable)
363 {
364 _startNode = node;
365 _currentNode = getParent(node);
366
367 return resetPosition();
368 }
369
370 return this;
371 }
372
373 /**
374 * Set the node type of the parent that we're looking for.
375 * Note that this does _not_ mean "find the nearest ancestor of
376 * this type", but "yield the parent if it is of this type".
377 *
378 *
379 * @param type extended type ID.
380 *
381 * @return ParentIterator configured with the type filter set.
382 */
383 public DTMAxisIterator setNodeType(final int type)
384 {
385
386 _nodeType = type;
387
388 return this;
389 }
390
391 /**
392 * Get the next node in the iteration. In this case, we return
393 * only the immediate parent, _if_ it matches the requested nodeType.
394 *
395 * @return The next node handle in the iteration, or END.
396 */
397 public int next()
398 {
399 int result = _currentNode;
400
401 if (_nodeType >= DTM.NTYPES) {
402 if (_nodeType != getExpandedTypeID(_currentNode)) {
403 result = END;
404 }
405 } else if (_nodeType != NULL) {
406 if (_nodeType != getNodeType(_currentNode)) {
407 result = END;
408 }
409 }
410
411 _currentNode = END;
412
413 return returnNode(result);
414 }
415 } // end of ParentIterator
416
417 /**
418 * Iterator that returns children of a given type for a given node.
419 * The functionality chould be achieved by putting a filter on top
420 * of a basic child iterator, but a specialised iterator is used
421 * for efficiency (both speed and size of translet).
422 */
423 public final class TypedChildrenIterator extends InternalAxisIteratorBase
424 {
425
426 /** The extended type ID that was requested. */
427 private final int _nodeType;
428
429 /**
430 * Constructor TypedChildrenIterator
431 *
432 *
433 * @param nodeType The extended type ID being requested.
434 */
435 public TypedChildrenIterator(int nodeType)
436 {
437 _nodeType = nodeType;
438 }
439
440 /**
441 * Set start to END should 'close' the iterator,
442 * i.e. subsequent call to next() should return END.
443 *
444 * @param node Sets the root of the iteration.
445 *
446 * @return A DTMAxisIterator set to the start of the iteration.
447 */
448 public DTMAxisIterator setStartNode(int node)
449 {
450 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
451 if (node == DTMDefaultBase.ROOTNODE)
452 node = getDocument();
453 if (_isRestartable)
454 {
455 _startNode = node;
456 _currentNode = (node == DTM.NULL)
457 ? DTM.NULL
458 : _firstch(makeNodeIdentity(_startNode));
459
460 return resetPosition();
461 }
462
463 return this;
464 }
465
466 /**
467 * Get the next node in the iteration.
468 *
469 * @return The next node handle in the iteration, or END.
470 */
471 public int next()
472 {
473 int eType;
474 int node = _currentNode;
475
476 int nodeType = _nodeType;
477
478 if (nodeType >= DTM.NTYPES) {
479 while (node != DTM.NULL && _exptype(node) != nodeType) {
480 node = _nextsib(node);
481 }
482 } else {
483 while (node != DTM.NULL) {
484 eType = _exptype(node);
485 if (eType < DTM.NTYPES) {
486 if (eType == nodeType) {
487 break;
488 }
489 } else if (m_expandedNameTable.getType(eType) == nodeType) {
490 break;
491 }
492 node = _nextsib(node);
493 }
494 }
495
496 if (node == DTM.NULL) {
497 _currentNode = DTM.NULL;
498 return DTM.NULL;
499 } else {
500 _currentNode = _nextsib(node);
501 return returnNode(makeNodeHandle(node));
502 }
503
504 }
505 } // end of TypedChildrenIterator
506
507 /**
508 * Iterator that returns children within a given namespace for a
509 * given node. The functionality chould be achieved by putting a
510 * filter on top of a basic child iterator, but a specialised
511 * iterator is used for efficiency (both speed and size of translet).
512 */
513 public final class NamespaceChildrenIterator
514 extends InternalAxisIteratorBase
515 {
516
517 /** The extended type ID being requested. */
518 private final int _nsType;
519
520 /**
521 * Constructor NamespaceChildrenIterator
522 *
523 *
524 * @param type The extended type ID being requested.
525 */
526 public NamespaceChildrenIterator(final int type)
527 {
528 _nsType = type;
529 }
530
531 /**
532 * Set start to END should 'close' the iterator,
533 * i.e. subsequent call to next() should return END.
534 *
535 * @param node Sets the root of the iteration.
536 *
537 * @return A DTMAxisIterator set to the start of the iteration.
538 */
539 public DTMAxisIterator setStartNode(int node)
540 {
541 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
542 if (node == DTMDefaultBase.ROOTNODE)
543 node = getDocument();
544 if (_isRestartable)
545 {
546 _startNode = node;
547 _currentNode = (node == DTM.NULL) ? DTM.NULL : NOTPROCESSED;
548
549 return resetPosition();
550 }
551
552 return this;
553 }
554
555 /**
556 * Get the next node in the iteration.
557 *
558 * @return The next node handle in the iteration, or END.
559 */
560 public int next()
561 {
562 if (_currentNode != DTM.NULL) {
563 for (int node = (NOTPROCESSED == _currentNode)
564 ? _firstch(makeNodeIdentity(_startNode))
565 : _nextsib(_currentNode);
566 node != END;
567 node = _nextsib(node)) {
568 if (m_expandedNameTable.getNamespaceID(_exptype(node)) == _nsType) {
569 _currentNode = node;
570
571 return returnNode(node);
572 }
573 }
574 }
575
576 return END;
577 }
578 } // end of NamespaceChildrenIterator
579
580 /**
581 * Iterator that returns the namespace nodes as defined by the XPath data model
582 * for a given node.
583 */
584 public class NamespaceIterator
585 extends InternalAxisIteratorBase
586 {
587
588 /**
589 * Constructor NamespaceAttributeIterator
590 */
591 public NamespaceIterator()
592 {
593
594 super();
595 }
596
597 /**
598 * Set start to END should 'close' the iterator,
599 * i.e. subsequent call to next() should return END.
600 *
601 * @param node Sets the root of the iteration.
602 *
603 * @return A DTMAxisIterator set to the start of the iteration.
604 */
605 public DTMAxisIterator setStartNode(int node)
606 {
607 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
608 if (node == DTMDefaultBase.ROOTNODE)
609 node = getDocument();
610 if (_isRestartable)
611 {
612 _startNode = node;
613 _currentNode = getFirstNamespaceNode(node, true);
614
615 return resetPosition();
616 }
617
618 return this;
619 }
620
621 /**
622 * Get the next node in the iteration.
623 *
624 * @return The next node handle in the iteration, or END.
625 */
626 public int next()
627 {
628
629 int node = _currentNode;
630
631 if (DTM.NULL != node)
632 _currentNode = getNextNamespaceNode(_startNode, node, true);
633
634 return returnNode(node);
635 }
636 } // end of NamespaceIterator
637
638 /**
639 * Iterator that returns the namespace nodes as defined by the XPath data model
640 * for a given node, filtered by extended type ID.
641 */
642 public class TypedNamespaceIterator extends NamespaceIterator
643 {
644
645 /** The extended type ID that was requested. */
646 private final int _nodeType;
647
648 /**
649 * Constructor TypedNamespaceIterator
650 *
651 *
652 * @param nodeType The extended type ID being requested.
653 */
654 public TypedNamespaceIterator(int nodeType)
655 {
656 super();
657 _nodeType = nodeType;
658 }
659
660 /**
661 * Get the next node in the iteration.
662 *
663 * @return The next node handle in the iteration, or END.
664 */
665 public int next()
666 {
667 int node;
668
669 for (node = _currentNode;
670 node != END;
671 node = getNextNamespaceNode(_startNode, node, true)) {
672 if (getExpandedTypeID(node) == _nodeType
673 || getNodeType(node) == _nodeType
674 || getNamespaceType(node) == _nodeType) {
675 _currentNode = node;
676
677 return returnNode(node);
678 }
679 }
680
681 return (_currentNode =END);
682 }
683 } // end of TypedNamespaceIterator
684
685 /**
686 * Iterator that returns the the root node as defined by the XPath data model
687 * for a given node.
688 */
689 public class RootIterator
690 extends InternalAxisIteratorBase
691 {
692
693 /**
694 * Constructor RootIterator
695 */
696 public RootIterator()
697 {
698
699 super();
700 }
701
702 /**
703 * Set start to END should 'close' the iterator,
704 * i.e. subsequent call to next() should return END.
705 *
706 * @param node Sets the root of the iteration.
707 *
708 * @return A DTMAxisIterator set to the start of the iteration.
709 */
710 public DTMAxisIterator setStartNode(int node)
711 {
712
713 if (_isRestartable)
714 {
715 _startNode = getDocumentRoot(node);
716 _currentNode = NULL;
717
718 return resetPosition();
719 }
720
721 return this;
722 }
723
724 /**
725 * Get the next node in the iteration.
726 *
727 * @return The next node handle in the iteration, or END.
728 */
729 public int next()
730 {
731 if(_startNode == _currentNode)
732 return NULL;
733
734 _currentNode = _startNode;
735
736 return returnNode(_startNode);
737 }
738 } // end of RootIterator
739
740 /**
741 * Iterator that returns the namespace nodes as defined by the XPath data model
742 * for a given node, filtered by extended type ID.
743 */
744 public class TypedRootIterator extends RootIterator
745 {
746
747 /** The extended type ID that was requested. */
748 private final int _nodeType;
749
750 /**
751 * Constructor TypedRootIterator
752 *
753 * @param nodeType The extended type ID being requested.
754 */
755 public TypedRootIterator(int nodeType)
756 {
757 super();
758 _nodeType = nodeType;
759 }
760
761 /**
762 * Get the next node in the iteration.
763 *
764 * @return The next node handle in the iteration, or END.
765 */
766 public int next()
767 {
768 if(_startNode == _currentNode)
769 return NULL;
770
771 int nodeType = _nodeType;
772 int node = _startNode;
773 int expType = getExpandedTypeID(node);
774
775 _currentNode = node;
776
777 if (nodeType >= DTM.NTYPES) {
778 if (nodeType == expType) {
779 return returnNode(node);
780 }
781 } else {
782 if (expType < DTM.NTYPES) {
783 if (expType == nodeType) {
784 return returnNode(node);
785 }
786 } else {
787 if (m_expandedNameTable.getType(expType) == nodeType) {
788 return returnNode(node);
789 }
790 }
791 }
792
793 return END;
794 }
795 } // end of TypedRootIterator
796
797 /**
798 * Iterator that returns attributes within a given namespace for a node.
799 */
800 public final class NamespaceAttributeIterator
801 extends InternalAxisIteratorBase
802 {
803
804 /** The extended type ID being requested. */
805 private final int _nsType;
806
807 /**
808 * Constructor NamespaceAttributeIterator
809 *
810 *
811 * @param nsType The extended type ID being requested.
812 */
813 public NamespaceAttributeIterator(int nsType)
814 {
815
816 super();
817
818 _nsType = nsType;
819 }
820
821 /**
822 * Set start to END should 'close' the iterator,
823 * i.e. subsequent call to next() should return END.
824 *
825 * @param node Sets the root of the iteration.
826 *
827 * @return A DTMAxisIterator set to the start of the iteration.
828 */
829 public DTMAxisIterator setStartNode(int node)
830 {
831 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
832 if (node == DTMDefaultBase.ROOTNODE)
833 node = getDocument();
834 if (_isRestartable)
835 {
836 _startNode = node;
837 _currentNode = getFirstNamespaceNode(node, false);
838
839 return resetPosition();
840 }
841
842 return this;
843 }
844
845 /**
846 * Get the next node in the iteration.
847 *
848 * @return The next node handle in the iteration, or END.
849 */
850 public int next()
851 {
852
853 int node = _currentNode;
854
855 if (DTM.NULL != node)
856 _currentNode = getNextNamespaceNode(_startNode, node, false);
857
858 return returnNode(node);
859 }
860 } // end of NamespaceAttributeIterator
861
862 /**
863 * Iterator that returns all siblings of a given node.
864 */
865 public class FollowingSiblingIterator extends InternalAxisIteratorBase
866 {
867
868 /**
869 * Set start to END should 'close' the iterator,
870 * i.e. subsequent call to next() should return END.
871 *
872 * @param node Sets the root of the iteration.
873 *
874 * @return A DTMAxisIterator set to the start of the iteration.
875 */
876 public DTMAxisIterator setStartNode(int node)
877 {
878 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
879 if (node == DTMDefaultBase.ROOTNODE)
880 node = getDocument();
881 if (_isRestartable)
882 {
883 _startNode = node;
884 _currentNode = makeNodeIdentity(node);
885
886 return resetPosition();
887 }
888
889 return this;
890 }
891
892 /**
893 * Get the next node in the iteration.
894 *
895 * @return The next node handle in the iteration, or END.
896 */
897 public int next()
898 {
899 _currentNode = (_currentNode == DTM.NULL) ? DTM.NULL
900 : _nextsib(_currentNode);
901 return returnNode(makeNodeHandle(_currentNode));
902 }
903 } // end of FollowingSiblingIterator
904
905 /**
906 * Iterator that returns all following siblings of a given node.
907 */
908 public final class TypedFollowingSiblingIterator
909 extends FollowingSiblingIterator
910 {
911
912 /** The extended type ID that was requested. */
913 private final int _nodeType;
914
915 /**
916 * Constructor TypedFollowingSiblingIterator
917 *
918 *
919 * @param type The extended type ID being requested.
920 */
921 public TypedFollowingSiblingIterator(int type)
922 {
923 _nodeType = type;
924 }
925
926 /**
927 * Get the next node in the iteration.
928 *
929 * @return The next node handle in the iteration, or END.
930 */
931 public int next()
932 {
933 if (_currentNode == DTM.NULL) {
934 return DTM.NULL;
935 }
936
937 int node = _currentNode;
938 int eType;
939 int nodeType = _nodeType;
940
941 if (nodeType >= DTM.NTYPES) {
942 do {
943 node = _nextsib(node);
944 } while (node != DTM.NULL && _exptype(node) != nodeType);
945 } else {
946 while ((node = _nextsib(node)) != DTM.NULL) {
947 eType = _exptype(node);
948 if (eType < DTM.NTYPES) {
949 if (eType == nodeType) {
950 break;
951 }
952 } else if (m_expandedNameTable.getType(eType) == nodeType) {
953 break;
954 }
955 }
956 }
957
958 _currentNode = node;
959
960 return (_currentNode == DTM.NULL)
961 ? DTM.NULL
962 : returnNode(makeNodeHandle(_currentNode));
963 }
964 } // end of TypedFollowingSiblingIterator
965
966 /**
967 * Iterator that returns attribute nodes (of what nodes?)
968 */
969 public final class AttributeIterator extends InternalAxisIteratorBase
970 {
971
972 // assumes caller will pass element nodes
973
974 /**
975 * Set start to END should 'close' the iterator,
976 * i.e. subsequent call to next() should return END.
977 *
978 * @param node Sets the root of the iteration.
979 *
980 * @return A DTMAxisIterator set to the start of the iteration.
981 */
982 public DTMAxisIterator setStartNode(int node)
983 {
984 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
985 if (node == DTMDefaultBase.ROOTNODE)
986 node = getDocument();
987 if (_isRestartable)
988 {
989 _startNode = node;
990 _currentNode = getFirstAttributeIdentity(makeNodeIdentity(node));
991
992 return resetPosition();
993 }
994
995 return this;
996 }
997
998 /**
999 * Get the next node in the iteration.
1000 *
1001 * @return The next node handle in the iteration, or END.
1002 */
1003 public int next()
1004 {
1005
1006 final int node = _currentNode;
1007
1008 if (node != NULL) {
1009 _currentNode = getNextAttributeIdentity(node);
1010 return returnNode(makeNodeHandle(node));
1011 }
1012
1013 return NULL;
1014 }
1015 } // end of AttributeIterator
1016
1017 /**
1018 * Iterator that returns attribute nodes of a given type
1019 */
1020 public final class TypedAttributeIterator extends InternalAxisIteratorBase
1021 {
1022
1023 /** The extended type ID that was requested. */
1024 private final int _nodeType;
1025
1026 /**
1027 * Constructor TypedAttributeIterator
1028 *
1029 *
1030 * @param nodeType The extended type ID that is requested.
1031 */
1032 public TypedAttributeIterator(int nodeType)
1033 {
1034 _nodeType = nodeType;
1035 }
1036
1037 // assumes caller will pass element nodes
1038
1039 /**
1040 * Set start to END should 'close' the iterator,
1041 * i.e. subsequent call to next() should return END.
1042 *
1043 * @param node Sets the root of the iteration.
1044 *
1045 * @return A DTMAxisIterator set to the start of the iteration.
1046 */
1047 public DTMAxisIterator setStartNode(int node)
1048 {
1049 if (_isRestartable)
1050 {
1051 _startNode = node;
1052
1053 _currentNode = getTypedAttribute(node, _nodeType);
1054
1055 return resetPosition();
1056 }
1057
1058 return this;
1059 }
1060
1061 /**
1062 * Get the next node in the iteration.
1063 *
1064 * @return The next node handle in the iteration, or END.
1065 */
1066 public int next()
1067 {
1068
1069 final int node = _currentNode;
1070
1071 // singleton iterator, since there can only be one attribute of
1072 // a given type.
1073 _currentNode = NULL;
1074
1075 return returnNode(node);
1076 }
1077 } // end of TypedAttributeIterator
1078
1079 /**
1080 * Iterator that returns preceding siblings of a given node
1081 */
1082 public class PrecedingSiblingIterator extends InternalAxisIteratorBase
1083 {
1084
1085 /**
1086 * The node identity of _startNode for this iterator
1087 */
1088 protected int _startNodeID;
1089
1090 /**
1091 * True if this iterator has a reversed axis.
1092 *
1093 * @return true.
1094 */
1095 public boolean isReverse()
1096 {
1097 return true;
1098 }
1099
1100 /**
1101 * Set start to END should 'close' the iterator,
1102 * i.e. subsequent call to next() should return END.
1103 *
1104 * @param node Sets the root of the iteration.
1105 *
1106 * @return A DTMAxisIterator set to the start of the iteration.
1107 */
1108 public DTMAxisIterator setStartNode(int node)
1109 {
1110 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1111 if (node == DTMDefaultBase.ROOTNODE)
1112 node = getDocument();
1113 if (_isRestartable)
1114 {
1115 _startNode = node;
1116 node = _startNodeID = makeNodeIdentity(node);
1117
1118 if(node == NULL)
1119 {
1120 _currentNode = node;
1121 return resetPosition();
1122 }
1123
1124 int type = m_expandedNameTable.getType(_exptype(node));
1125 if(ExpandedNameTable.ATTRIBUTE == type
1126 || ExpandedNameTable.NAMESPACE == type )
1127 {
1128 _currentNode = node;
1129 }
1130 else
1131 {
1132 // Be careful to handle the Document node properly
1133 _currentNode = _parent(node);
1134 if(NULL!=_currentNode)
1135 _currentNode = _firstch(_currentNode);
1136 else
1137 _currentNode = node;
1138 }
1139
1140 return resetPosition();
1141 }
1142
1143 return this;
1144 }
1145
1146 /**
1147 * Get the next node in the iteration.
1148 *
1149 * @return The next node handle in the iteration, or END.
1150 */
1151 public int next()
1152 {
1153
1154 if (_currentNode == _startNodeID || _currentNode == DTM.NULL)
1155 {
1156 return NULL;
1157 }
1158 else
1159 {
1160 final int node = _currentNode;
1161 _currentNode = _nextsib(node);
1162
1163 return returnNode(makeNodeHandle(node));
1164 }
1165 }
1166 } // end of PrecedingSiblingIterator
1167
1168 /**
1169 * Iterator that returns preceding siblings of a given type for
1170 * a given node
1171 */
1172 public final class TypedPrecedingSiblingIterator
1173 extends PrecedingSiblingIterator
1174 {
1175
1176 /** The extended type ID that was requested. */
1177 private final int _nodeType;
1178
1179 /**
1180 * Constructor TypedPrecedingSiblingIterator
1181 *
1182 *
1183 * @param type The extended type ID being requested.
1184 */
1185 public TypedPrecedingSiblingIterator(int type)
1186 {
1187 _nodeType = type;
1188 }
1189
1190 /**
1191 * Get the next node in the iteration.
1192 *
1193 * @return The next node handle in the iteration, or END.
1194 */
1195 public int next()
1196 {
1197 int node = _currentNode;
1198 int expType;
1199
1200 int nodeType = _nodeType;
1201 int startID = _startNodeID;
1202
1203 if (nodeType >= DTM.NTYPES) {
1204 while (node != NULL && node != startID && _exptype(node) != nodeType) {
1205 node = _nextsib(node);
1206 }
1207 } else {
1208 while (node != NULL && node != startID) {
1209 expType = _exptype(node);
1210 if (expType < DTM.NTYPES) {
1211 if (expType == nodeType) {
1212 break;
1213 }
1214 } else {
1215 if (m_expandedNameTable.getType(expType) == nodeType) {
1216 break;
1217 }
1218 }
1219 node = _nextsib(node);
1220 }
1221 }
1222
1223 if (node == DTM.NULL || node == _startNodeID) {
1224 _currentNode = NULL;
1225 return NULL;
1226 } else {
1227 _currentNode = _nextsib(node);
1228 return returnNode(makeNodeHandle(node));
1229 }
1230 }
1231 } // end of TypedPrecedingSiblingIterator
1232
1233 /**
1234 * Iterator that returns preceding nodes of a given node.
1235 * This includes the node set {root+1, start-1}, but excludes
1236 * all ancestors, attributes, and namespace nodes.
1237 */
1238 public class PrecedingIterator extends InternalAxisIteratorBase
1239 {
1240
1241 /** The max ancestors, but it can grow... */
1242 private final int _maxAncestors = 8;
1243
1244 /**
1245 * The stack of start node + ancestors up to the root of the tree,
1246 * which we must avoid.
1247 */
1248 protected int[] _stack = new int[_maxAncestors];
1249
1250 /** (not sure yet... -sb) */
1251 protected int _sp, _oldsp;
1252
1253 protected int _markedsp, _markedNode, _markedDescendant;
1254
1255 /* _currentNode precedes candidates. This is the identity, not the handle! */
1256
1257 /**
1258 * True if this iterator has a reversed axis.
1259 *
1260 * @return true since this iterator is a reversed axis.
1261 */
1262 public boolean isReverse()
1263 {
1264 return true;
1265 }
1266
1267 /**
1268 * Returns a deep copy of this iterator. The cloned iterator is not reset.
1269 *
1270 * @return a deep copy of this iterator.
1271 */
1272 public DTMAxisIterator cloneIterator()
1273 {
1274 _isRestartable = false;
1275
1276 try
1277 {
1278 final PrecedingIterator clone = (PrecedingIterator) super.clone();
1279 final int[] stackCopy = new int[_stack.length];
1280 System.arraycopy(_stack, 0, stackCopy, 0, _stack.length);
1281
1282 clone._stack = stackCopy;
1283
1284 // return clone.reset();
1285 return clone;
1286 }
1287 catch (CloneNotSupportedException e)
1288 {
1289 throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED, null)); //"Iterator clone not supported.");
1290 }
1291 }
1292
1293 /**
1294 * Set start to END should 'close' the iterator,
1295 * i.e. subsequent call to next() should return END.
1296 *
1297 * @param node Sets the root of the iteration.
1298 *
1299 * @return A DTMAxisIterator set to the start of the iteration.
1300 */
1301 public DTMAxisIterator setStartNode(int node)
1302 {
1303 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1304 if (node == DTMDefaultBase.ROOTNODE)
1305 node = getDocument();
1306 if (_isRestartable)
1307 {
1308 node = makeNodeIdentity(node);
1309
1310 // iterator is not a clone
1311 int parent, index;
1312
1313 if (_type(node) == DTM.ATTRIBUTE_NODE)
1314 node = _parent(node);
1315
1316 _startNode = node;
1317 _stack[index = 0] = node;
1318
1319
1320
1321 parent=node;
1322 while ((parent = _parent(parent)) != NULL)
1323 {
1324 if (++index == _stack.length)
1325 {
1326 final int[] stack = new int[index + 4];
1327 System.arraycopy(_stack, 0, stack, 0, index);
1328 _stack = stack;
1329 }
1330 _stack[index] = parent;
1331 }
1332 if(index>0)
1333 --index; // Pop actual root node (if not start) back off the stack
1334
1335 _currentNode=_stack[index]; // Last parent before root node
1336
1337 _oldsp = _sp = index;
1338
1339 return resetPosition();
1340 }
1341
1342 return this;
1343 }
1344
1345 /**
1346 * Get the next node in the iteration.
1347 *
1348 * @return The next node handle in the iteration, or END.
1349 */
1350 public int next()
1351 {
1352 // Bugzilla 8324: We were forgetting to skip Attrs and NS nodes.
1353 // Also recoded the loop controls for clarity and to flatten out
1354 // the tail-recursion.
1355 for(++_currentNode;
1356 _sp>=0;
1357 ++_currentNode)
1358 {
1359 if(_currentNode < _stack[_sp])
1360 {
1361 if(_type(_currentNode) != ATTRIBUTE_NODE &&
1362 _type(_currentNode) != NAMESPACE_NODE)
1363 return returnNode(makeNodeHandle(_currentNode));
1364 }
1365 else
1366 --_sp;
1367 }
1368 return NULL;
1369 }
1370
1371 // redefine DTMAxisIteratorBase's reset
1372
1373 /**
1374 * Resets the iterator to the last start node.
1375 *
1376 * @return A DTMAxisIterator, which may or may not be the same as this
1377 * iterator.
1378 */
1379 public DTMAxisIterator reset()
1380 {
1381
1382 _sp = _oldsp;
1383
1384 return resetPosition();
1385 }
1386
1387 public void setMark() {
1388 _markedsp = _sp;
1389 _markedNode = _currentNode;
1390 _markedDescendant = _stack[0];
1391 }
1392
1393 public void gotoMark() {
1394 _sp = _markedsp;
1395 _currentNode = _markedNode;
1396 }
1397 } // end of PrecedingIterator
1398
1399 /**
1400 * Iterator that returns preceding nodes of agiven type for a
1401 * given node. This includes the node set {root+1, start-1}, but
1402 * excludes all ancestors.
1403 */
1404 public final class TypedPrecedingIterator extends PrecedingIterator
1405 {
1406
1407 /** The extended type ID that was requested. */
1408 private final int _nodeType;
1409
1410 /**
1411 * Constructor TypedPrecedingIterator
1412 *
1413 *
1414 * @param type The extended type ID being requested.
1415 */
1416 public TypedPrecedingIterator(int type)
1417 {
1418 _nodeType = type;
1419 }
1420
1421 /**
1422 * Get the next node in the iteration.
1423 *
1424 * @return The next node handle in the iteration, or END.
1425 */
1426 public int next()
1427 {
1428 int node = _currentNode;
1429 int nodeType = _nodeType;
1430
1431 if (nodeType >= DTM.NTYPES) {
1432 while (true) {
1433 node = node + 1;
1434
1435 if (_sp < 0) {
1436 node = NULL;
1437 break;
1438 } else if (node >= _stack[_sp]) {
1439 if (--_sp < 0) {
1440 node = NULL;
1441 break;
1442 }
1443 } else if (_exptype(node) == nodeType) {
1444 break;
1445 }
1446 }
1447 } else {
1448 int expType;
1449
1450 while (true) {
1451 node = node + 1;
1452
1453 if (_sp < 0) {
1454 node = NULL;
1455 break;
1456 } else if (node >= _stack[_sp]) {
1457 if (--_sp < 0) {
1458 node = NULL;
1459 break;
1460 }
1461 } else {
1462 expType = _exptype(node);
1463 if (expType < DTM.NTYPES) {
1464 if (expType == nodeType) {
1465 break;
1466 }
1467 } else {
1468 if (m_expandedNameTable.getType(expType) == nodeType) {
1469 break;
1470 }
1471 }
1472 }
1473 }
1474 }
1475
1476 _currentNode = node;
1477
1478 return (node == NULL) ? NULL : returnNode(makeNodeHandle(node));
1479 }
1480 } // end of TypedPrecedingIterator
1481
1482 /**
1483 * Iterator that returns following nodes of for a given node.
1484 */
1485 public class FollowingIterator extends InternalAxisIteratorBase
1486 {
1487 DTMAxisTraverser m_traverser; // easier for now
1488
1489 public FollowingIterator()
1490 {
1491 m_traverser = getAxisTraverser(Axis.FOLLOWING);
1492 }
1493
1494 /**
1495 * Set start to END should 'close' the iterator,
1496 * i.e. subsequent call to next() should return END.
1497 *
1498 * @param node Sets the root of the iteration.
1499 *
1500 * @return A DTMAxisIterator set to the start of the iteration.
1501 */
1502 public DTMAxisIterator setStartNode(int node)
1503 {
1504 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1505 if (node == DTMDefaultBase.ROOTNODE)
1506 node = getDocument();
1507 if (_isRestartable)
1508 {
1509 _startNode = node;
1510
1511 // ?? -sb
1512 // find rightmost descendant (or self)
1513 // int current;
1514 // while ((node = getLastChild(current = node)) != NULL){}
1515 // _currentNode = current;
1516 _currentNode = m_traverser.first(node);
1517
1518 // _currentNode precedes possible following(node) nodes
1519 return resetPosition();
1520 }
1521
1522 return this;
1523 }
1524
1525 /**
1526 * Get the next node in the iteration.
1527 *
1528 * @return The next node handle in the iteration, or END.
1529 */
1530 public int next()
1531 {
1532
1533 int node = _currentNode;
1534
1535 _currentNode = m_traverser.next(_startNode, _currentNode);
1536
1537 return returnNode(node);
1538 }
1539 } // end of FollowingIterator
1540
1541 /**
1542 * Iterator that returns following nodes of a given type for a given node.
1543 */
1544 public final class TypedFollowingIterator extends FollowingIterator
1545 {
1546
1547 /** The extended type ID that was requested. */
1548 private final int _nodeType;
1549
1550 /**
1551 * Constructor TypedFollowingIterator
1552 *
1553 *
1554 * @param type The extended type ID being requested.
1555 */
1556 public TypedFollowingIterator(int type)
1557 {
1558 _nodeType = type;
1559 }
1560
1561 /**
1562 * Get the next node in the iteration.
1563 *
1564 * @return The next node handle in the iteration, or END.
1565 */
1566 public int next()
1567 {
1568
1569 int node;
1570
1571 do{
1572 node = _currentNode;
1573
1574 _currentNode = m_traverser.next(_startNode, _currentNode);
1575
1576 }
1577 while (node != DTM.NULL
1578 && (getExpandedTypeID(node) != _nodeType && getNodeType(node) != _nodeType));
1579
1580 return (node == DTM.NULL ? DTM.NULL :returnNode(node));
1581 }
1582 } // end of TypedFollowingIterator
1583
1584 /**
1585 * Iterator that returns the ancestors of a given node in document
1586 * order. (NOTE! This was changed from the XSLTC code!)
1587 */
1588 public class AncestorIterator extends InternalAxisIteratorBase
1589 {
1590 org.apache.xml.utils.NodeVector m_ancestors =
1591 new org.apache.xml.utils.NodeVector();
1592
1593 int m_ancestorsPos;
1594
1595 int m_markedPos;
1596
1597 /** The real start node for this axes, since _startNode will be adjusted. */
1598 int m_realStartNode;
1599
1600 /**
1601 * Get start to END should 'close' the iterator,
1602 * i.e. subsequent call to next() should return END.
1603 *
1604 * @return The root node of the iteration.
1605 */
1606 public int getStartNode()
1607 {
1608 return m_realStartNode;
1609 }
1610
1611 /**
1612 * True if this iterator has a reversed axis.
1613 *
1614 * @return true since this iterator is a reversed axis.
1615 */
1616 public final boolean isReverse()
1617 {
1618 return true;
1619 }
1620
1621 /**
1622 * Returns a deep copy of this iterator. The cloned iterator is not reset.
1623 *
1624 * @return a deep copy of this iterator.
1625 */
1626 public DTMAxisIterator cloneIterator()
1627 {
1628 _isRestartable = false; // must set to false for any clone
1629
1630 try
1631 {
1632 final AncestorIterator clone = (AncestorIterator) super.clone();
1633
1634 clone._startNode = _startNode;
1635
1636 // return clone.reset();
1637 return clone;
1638 }
1639 catch (CloneNotSupportedException e)
1640 {
1641 throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED, null)); //"Iterator clone not supported.");
1642 }
1643 }
1644
1645 /**
1646 * Set start to END should 'close' the iterator,
1647 * i.e. subsequent call to next() should return END.
1648 *
1649 * @param node Sets the root of the iteration.
1650 *
1651 * @return A DTMAxisIterator set to the start of the iteration.
1652 */
1653 public DTMAxisIterator setStartNode(int node)
1654 {
1655 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1656 if (node == DTMDefaultBase.ROOTNODE)
1657 node = getDocument();
1658 m_realStartNode = node;
1659
1660 if (_isRestartable)
1661 {
1662 int nodeID = makeNodeIdentity(node);
1663
1664 if (!_includeSelf && node != DTM.NULL) {
1665 nodeID = _parent(nodeID);
1666 node = makeNodeHandle(nodeID);
1667 }
1668
1669 _startNode = node;
1670
1671 while (nodeID != END) {
1672 m_ancestors.addElement(node);
1673 nodeID = _parent(nodeID);
1674 node = makeNodeHandle(nodeID);
1675 }
1676 m_ancestorsPos = m_ancestors.size()-1;
1677
1678 _currentNode = (m_ancestorsPos>=0)
1679 ? m_ancestors.elementAt(m_ancestorsPos)
1680 : DTM.NULL;
1681
1682 return resetPosition();
1683 }
1684
1685 return this;
1686 }
1687
1688 /**
1689 * Resets the iterator to the last start node.
1690 *
1691 * @return A DTMAxisIterator, which may or may not be the same as this
1692 * iterator.
1693 */
1694 public DTMAxisIterator reset()
1695 {
1696
1697 m_ancestorsPos = m_ancestors.size()-1;
1698
1699 _currentNode = (m_ancestorsPos>=0) ? m_ancestors.elementAt(m_ancestorsPos)
1700 : DTM.NULL;
1701
1702 return resetPosition();
1703 }
1704
1705 /**
1706 * Get the next node in the iteration.
1707 *
1708 * @return The next node handle in the iteration, or END.
1709 */
1710 public int next()
1711 {
1712
1713 int next = _currentNode;
1714
1715 int pos = --m_ancestorsPos;
1716
1717 _currentNode = (pos >= 0) ? m_ancestors.elementAt(m_ancestorsPos)
1718 : DTM.NULL;
1719
1720 return returnNode(next);
1721 }
1722
1723 public void setMark() {
1724 m_markedPos = m_ancestorsPos;
1725 }
1726
1727 public void gotoMark() {
1728 m_ancestorsPos = m_markedPos;
1729 _currentNode = m_ancestorsPos>=0 ? m_ancestors.elementAt(m_ancestorsPos)
1730 : DTM.NULL;
1731 }
1732 } // end of AncestorIterator
1733
1734 /**
1735 * Typed iterator that returns the ancestors of a given node.
1736 */
1737 public final class TypedAncestorIterator extends AncestorIterator
1738 {
1739
1740 /** The extended type ID that was requested. */
1741 private final int _nodeType;
1742
1743 /**
1744 * Constructor TypedAncestorIterator
1745 *
1746 *
1747 * @param type The extended type ID being requested.
1748 */
1749 public TypedAncestorIterator(int type)
1750 {
1751 _nodeType = type;
1752 }
1753
1754 /**
1755 * Set start to END should 'close' the iterator,
1756 * i.e. subsequent call to next() should return END.
1757 *
1758 * @param node Sets the root of the iteration.
1759 *
1760 * @return A DTMAxisIterator set to the start of the iteration.
1761 */
1762 public DTMAxisIterator setStartNode(int node)
1763 {
1764 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1765 if (node == DTMDefaultBase.ROOTNODE)
1766 node = getDocument();
1767 m_realStartNode = node;
1768
1769 if (_isRestartable)
1770 {
1771 int nodeID = makeNodeIdentity(node);
1772 int nodeType = _nodeType;
1773
1774 if (!_includeSelf && node != DTM.NULL) {
1775 nodeID = _parent(nodeID);
1776 }
1777
1778 _startNode = node;
1779
1780 if (nodeType >= DTM.NTYPES) {
1781 while (nodeID != END) {
1782 int eType = _exptype(nodeID);
1783
1784 if (eType == nodeType) {
1785 m_ancestors.addElement(makeNodeHandle(nodeID));
1786 }
1787 nodeID = _parent(nodeID);
1788 }
1789 } else {
1790 while (nodeID != END) {
1791 int eType = _exptype(nodeID);
1792
1793 if ((eType >= DTM.NTYPES
1794 && m_expandedNameTable.getType(eType) == nodeType)
1795 || (eType < DTM.NTYPES && eType == nodeType)) {
1796 m_ancestors.addElement(makeNodeHandle(nodeID));
1797 }
1798 nodeID = _parent(nodeID);
1799 }
1800 }
1801 m_ancestorsPos = m_ancestors.size()-1;
1802
1803 _currentNode = (m_ancestorsPos>=0)
1804 ? m_ancestors.elementAt(m_ancestorsPos)
1805 : DTM.NULL;
1806
1807 return resetPosition();
1808 }
1809
1810 return this;
1811 }
1812 } // end of TypedAncestorIterator
1813
1814 /**
1815 * Iterator that returns the descendants of a given node.
1816 */
1817 public class DescendantIterator extends InternalAxisIteratorBase
1818 {
1819
1820 /**
1821 * Set start to END should 'close' the iterator,
1822 * i.e. subsequent call to next() should return END.
1823 *
1824 * @param node Sets the root of the iteration.
1825 *
1826 * @return A DTMAxisIterator set to the start of the iteration.
1827 */
1828 public DTMAxisIterator setStartNode(int node)
1829 {
1830 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1831 if (node == DTMDefaultBase.ROOTNODE)
1832 node = getDocument();
1833 if (_isRestartable)
1834 {
1835 node = makeNodeIdentity(node);
1836 _startNode = node;
1837
1838 if (_includeSelf)
1839 node--;
1840
1841 _currentNode = node;
1842
1843 return resetPosition();
1844 }
1845
1846 return this;
1847 }
1848
1849 /**
1850 * Tell if this node identity is a descendant. Assumes that
1851 * the node info for the element has already been obtained.
1852 *
1853 * This one-sided test works only if the parent has been
1854 * previously tested and is known to be a descendent. It fails if
1855 * the parent is the _startNode's next sibling, or indeed any node
1856 * that follows _startNode in document order. That may suffice
1857 * for this iterator, but it's not really an isDescendent() test.
1858 * %REVIEW% rename?
1859 *
1860 * @param identity The index number of the node in question.
1861 * @return true if the index is a descendant of _startNode.
1862 */
1863 protected boolean isDescendant(int identity)
1864 {
1865 return (_parent(identity) >= _startNode) || (_startNode == identity);
1866 }
1867
1868 /**
1869 * Get the next node in the iteration.
1870 *
1871 * @return The next node handle in the iteration, or END.
1872 */
1873 public int next()
1874 {
1875 if (_startNode == NULL) {
1876 return NULL;
1877 }
1878
1879 if (_includeSelf && (_currentNode + 1) == _startNode)
1880 return returnNode(makeNodeHandle(++_currentNode)); // | m_dtmIdent);
1881
1882 int node = _currentNode;
1883 int type;
1884
1885 do {
1886 node++;
1887 type = _type(node);
1888
1889 if (NULL == type ||!isDescendant(node)) {
1890 _currentNode = NULL;
1891 return END;
1892 }
1893 } while(ATTRIBUTE_NODE == type || TEXT_NODE == type
1894 || NAMESPACE_NODE == type);
1895
1896 _currentNode = node;
1897 return returnNode(makeNodeHandle(node)); // make handle.
1898 }
1899
1900 /**
1901 * Reset.
1902 *
1903 */
1904 public DTMAxisIterator reset()
1905 {
1906
1907 final boolean temp = _isRestartable;
1908
1909 _isRestartable = true;
1910
1911 setStartNode(makeNodeHandle(_startNode));
1912
1913 _isRestartable = temp;
1914
1915 return this;
1916 }
1917
1918 } // end of DescendantIterator
1919
1920 /**
1921 * Typed iterator that returns the descendants of a given node.
1922 */
1923 public final class TypedDescendantIterator extends DescendantIterator
1924 {
1925
1926 /** The extended type ID that was requested. */
1927 private final int _nodeType;
1928
1929 /**
1930 * Constructor TypedDescendantIterator
1931 *
1932 *
1933 * @param nodeType Extended type ID being requested.
1934 */
1935 public TypedDescendantIterator(int nodeType)
1936 {
1937 _nodeType = nodeType;
1938 }
1939
1940 /**
1941 * Get the next node in the iteration.
1942 *
1943 * @return The next node handle in the iteration, or END.
1944 */
1945 public int next()
1946 {
1947 int node;
1948 int type;
1949
1950 if (_startNode == NULL) {
1951 return NULL;
1952 }
1953
1954 node = _currentNode;
1955
1956 do
1957 {
1958 node++;
1959 type = _type(node);
1960
1961 if (NULL == type ||!isDescendant(node)) {
1962 _currentNode = NULL;
1963 return END;
1964 }
1965 }
1966 while (type != _nodeType && _exptype(node) != _nodeType);
1967
1968 _currentNode = node;
1969 return returnNode(makeNodeHandle(node));
1970 }
1971 } // end of TypedDescendantIterator
1972
1973 /**
1974 * Iterator that returns the descendants of a given node.
1975 * I'm not exactly clear about this one... -sb
1976 */
1977 public class NthDescendantIterator extends DescendantIterator
1978 {
1979
1980 /** The current nth position. */
1981 int _pos;
1982
1983 /**
1984 * Constructor NthDescendantIterator
1985 *
1986 *
1987 * @param pos The nth position being requested.
1988 */
1989 public NthDescendantIterator(int pos)
1990 {
1991 _pos = pos;
1992 }
1993
1994 /**
1995 * Get the next node in the iteration.
1996 *
1997 * @return The next node handle in the iteration, or END.
1998 */
1999 public int next()
2000 {
2001
2002 // I'm not exactly clear yet what this is doing... -sb
2003 int node;
2004
2005 while ((node = super.next()) != END)
2006 {
2007 node = makeNodeIdentity(node);
2008
2009 int parent = _parent(node);
2010 int child = _firstch(parent);
2011 int pos = 0;
2012
2013 do
2014 {
2015 int type = _type(child);
2016
2017 if (ELEMENT_NODE == type)
2018 pos++;
2019 }
2020 while ((pos < _pos) && (child = _nextsib(child)) != END);
2021
2022 if (node == child)
2023 return node;
2024 }
2025
2026 return (END);
2027 }
2028 } // end of NthDescendantIterator
2029
2030 /**
2031 * Class SingletonIterator.
2032 */
2033 public class SingletonIterator extends InternalAxisIteratorBase
2034 {
2035
2036 /** (not sure yet what this is. -sb) (sc & sb remove final to compile in JDK 1.1.8) */
2037 private boolean _isConstant;
2038
2039 /**
2040 * Constructor SingletonIterator
2041 *
2042 */
2043 public SingletonIterator()
2044 {
2045 this(Integer.MIN_VALUE, false);
2046 }
2047
2048 /**
2049 * Constructor SingletonIterator
2050 *
2051 *
2052 * @param node The node handle to return.
2053 */
2054 public SingletonIterator(int node)
2055 {
2056 this(node, false);
2057 }
2058
2059 /**
2060 * Constructor SingletonIterator
2061 *
2062 *
2063 * @param node the node handle to return.
2064 * @param constant (Not sure what this is yet. -sb)
2065 */
2066 public SingletonIterator(int node, boolean constant)
2067 {
2068 _currentNode = _startNode = node;
2069 _isConstant = constant;
2070 }
2071
2072 /**
2073 * Set start to END should 'close' the iterator,
2074 * i.e. subsequent call to next() should return END.
2075 *
2076 * @param node Sets the root of the iteration.
2077 *
2078 * @return A DTMAxisIterator set to the start of the iteration.
2079 */
2080 public DTMAxisIterator setStartNode(int node)
2081 {
2082 //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
2083 if (node == DTMDefaultBase.ROOTNODE)
2084 node = getDocument();
2085 if (_isConstant)
2086 {
2087 _currentNode = _startNode;
2088
2089 return resetPosition();
2090 }
2091 else if (_isRestartable)
2092 {
2093 _currentNode = _startNode = node;
2094
2095 return resetPosition();
2096 }
2097
2098 return this;
2099 }
2100
2101 /**
2102 * Resets the iterator to the last start node.
2103 *
2104 * @return A DTMAxisIterator, which may or may not be the same as this
2105 * iterator.
2106 */
2107 public DTMAxisIterator reset()
2108 {
2109
2110 if (_isConstant)
2111 {
2112 _currentNode = _startNode;
2113
2114 return resetPosition();
2115 }
2116 else
2117 {
2118 final boolean temp = _isRestartable;
2119
2120 _isRestartable = true;
2121
2122 setStartNode(_startNode);
2123
2124 _isRestartable = temp;
2125 }
2126
2127 return this;
2128 }
2129
2130 /**
2131 * Get the next node in the iteration.
2132 *
2133 * @return The next node handle in the iteration, or END.
2134 */
2135 public int next()
2136 {
2137
2138 final int result = _currentNode;
2139
2140 _currentNode = END;
2141
2142 return returnNode(result);
2143 }
2144 } // end of SingletonIterator
2145
2146 /**
2147 * Iterator that returns a given node only if it is of a given type.
2148 */
2149 public final class TypedSingletonIterator extends SingletonIterator
2150 {
2151
2152 /** The extended type ID that was requested. */
2153 private final int _nodeType;
2154
2155 /**
2156 * Constructor TypedSingletonIterator
2157 *
2158 *
2159 * @param nodeType The extended type ID being requested.
2160 */
2161 public TypedSingletonIterator(int nodeType)
2162 {
2163 _nodeType = nodeType;
2164 }
2165
2166 /**
2167 * Get the next node in the iteration.
2168 *
2169 * @return The next node handle in the iteration, or END.
2170 */
2171 public int next()
2172 {
2173
2174 //final int result = super.next();
2175 final int result = _currentNode;
2176 int nodeType = _nodeType;
2177
2178 _currentNode = END;
2179
2180 if (nodeType >= DTM.NTYPES) {
2181 if (getExpandedTypeID(result) == nodeType) {
2182 return returnNode(result);
2183 }
2184 } else {
2185 if (getNodeType(result) == nodeType) {
2186 return returnNode(result);
2187 }
2188 }
2189
2190 return NULL;
2191 }
2192 } // end of TypedSingletonIterator
2193 }