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