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 }