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 */ DTMDefaultBaseIterators(DTMManager mgr, Source source, int dtmIdentity, DTMWSFilter whiteSpaceFilter, XMLStringFactory xstringfactory, boolean doIndexing)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 */ DTMDefaultBaseIterators(DTMManager mgr, Source source, int dtmIdentity, DTMWSFilter whiteSpaceFilter, XMLStringFactory xstringfactory, boolean doIndexing, int blocksize, boolean usePrevsib, boolean newNameTable)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 */ getTypedAxisIterator(int axis, int type)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 */ getAxisIterator(final int axis)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 */ setMark()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 */ gotoMark()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 */ setStartNode(int node)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 */ next()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 */ setStartNode(int node)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 */ setNodeType(final int type)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 */ next()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 */ TypedChildrenIterator(int nodeType)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 */ setStartNode(int node)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 */ next()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 */ NamespaceChildrenIterator(final int type)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 */ setStartNode(int node)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 */ next()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 */ NamespaceIterator()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 */ setStartNode(int node)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 */ next()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 */ TypedNamespaceIterator(int nodeType)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 */ next()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 */ RootIterator()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 */ setStartNode(int node)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 */ next()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 */ TypedRootIterator(int nodeType)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 */ next()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 */ NamespaceAttributeIterator(int nsType)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 */ setStartNode(int node)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 */ next()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 */ setStartNode(int node)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 */ next()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 */ TypedFollowingSiblingIterator(int type)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 */ next()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 */ setStartNode(int node)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 */ next()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 */ TypedAttributeIterator(int nodeType)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 */ setStartNode(int node)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 */ next()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 */ isReverse()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 */ setStartNode(int node)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 */ next()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 */ TypedPrecedingSiblingIterator(int type)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 */ next()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 */ isReverse()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 */ cloneIterator()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 */ setStartNode(int node)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 */ next()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 */ reset()1378 public DTMAxisIterator reset() 1379 { 1380 1381 _sp = _oldsp; 1382 1383 return resetPosition(); 1384 } 1385 setMark()1386 public void setMark() { 1387 _markedsp = _sp; 1388 _markedNode = _currentNode; 1389 _markedDescendant = _stack[0]; 1390 } 1391 gotoMark()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 */ TypedPrecedingIterator(int type)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 */ next()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 FollowingIterator()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 */ setStartNode(int node)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 */ next()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 */ TypedFollowingIterator(int type)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 */ next()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 */ getStartNode()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 */ isReverse()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 */ cloneIterator()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 */ setStartNode(int node)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 */ reset()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 */ next()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 setMark()1722 public void setMark() { 1723 m_markedPos = m_ancestorsPos; 1724 } 1725 gotoMark()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 */ TypedAncestorIterator(int type)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 */ setStartNode(int node)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 */ setStartNode(int node)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 */ isDescendant(int identity)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 */ next()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 */ reset()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 */ TypedDescendantIterator(int nodeType)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 */ next()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 */ NthDescendantIterator(int pos)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 */ next()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 */ SingletonIterator()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 */ SingletonIterator(int node)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 */ SingletonIterator(int node, boolean constant)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 */ setStartNode(int node)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 */ reset()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 */ next()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 */ TypedSingletonIterator(int nodeType)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 */ next()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