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