1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xalan" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, Lotus
  53. * Development Corporation., http://www.lotus.com. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package org.apache.xml.dtm.ref;
  58. import org.apache.xml.dtm.*;
  59. import javax.xml.transform.Source;
  60. import org.apache.xml.utils.XMLStringFactory;
  61. import org.apache.xalan.res.XSLTErrorResources;
  62. import org.apache.xalan.res.XSLMessages;
  63. /**
  64. * This class implements the traversers for DTMDefaultBase.
  65. */
  66. public abstract class DTMDefaultBaseIterators extends DTMDefaultBaseTraversers
  67. {
  68. /**
  69. * Construct a DTMDefaultBaseTraversers object from a DOM node.
  70. *
  71. * @param mgr The DTMManager who owns this DTM.
  72. * @param domSource the DOM source that this DTM will wrap.
  73. * @param source The object that is used to specify the construction source.
  74. * @param dtmIdentity The DTM identity ID for this DTM.
  75. * @param whiteSpaceFilter The white space filter for this DTM, which may
  76. * be null.
  77. * @param xstringfactory The factory to use for creating XMLStrings.
  78. * @param doIndexing true if the caller considers it worth it to use
  79. * indexing schemes.
  80. */
  81. public DTMDefaultBaseIterators(DTMManager mgr, Source source,
  82. int dtmIdentity,
  83. DTMWSFilter whiteSpaceFilter,
  84. XMLStringFactory xstringfactory,
  85. boolean doIndexing)
  86. {
  87. super(mgr, source, dtmIdentity, whiteSpaceFilter,
  88. xstringfactory, doIndexing);
  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. */
  101. public DTMAxisIterator getTypedAxisIterator(int axis, int type)
  102. {
  103. DTMAxisIterator iterator = null;
  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. // if (type == NO_TYPE) {
  109. // return(EMPTYITERATOR);
  110. // }
  111. // else if (type == ELEMENT) {
  112. // iterator = new FilterIterator(getAxisIterator(axis),
  113. // getElementFilter());
  114. // }
  115. // else
  116. {
  117. switch (axis)
  118. {
  119. case Axis.SELF :
  120. iterator = new TypedSingletonIterator(type);
  121. break;
  122. case Axis.CHILD :
  123. iterator = new TypedChildrenIterator(type);
  124. break;
  125. case Axis.PARENT :
  126. return (new ParentIterator().setNodeType(type));
  127. case Axis.ANCESTOR :
  128. return (new TypedAncestorIterator(type));
  129. case Axis.ANCESTORORSELF :
  130. return ((new TypedAncestorIterator(type)).includeSelf());
  131. case Axis.ATTRIBUTE :
  132. return (new TypedAttributeIterator(type));
  133. case Axis.DESCENDANT :
  134. iterator = new TypedDescendantIterator(type);
  135. break;
  136. case Axis.DESCENDANTORSELF :
  137. iterator = (new TypedDescendantIterator(type)).includeSelf();
  138. break;
  139. case Axis.FOLLOWING :
  140. iterator = new TypedFollowingIterator(type);
  141. break;
  142. case Axis.PRECEDING :
  143. iterator = new TypedPrecedingIterator(type);
  144. break;
  145. case Axis.FOLLOWINGSIBLING :
  146. iterator = new TypedFollowingSiblingIterator(type);
  147. break;
  148. case Axis.PRECEDINGSIBLING :
  149. iterator = new TypedPrecedingSiblingIterator(type);
  150. break;
  151. case Axis.NAMESPACE :
  152. iterator = new TypedNamespaceIterator(type);
  153. break;
  154. case Axis.ROOT :
  155. iterator = new TypedRootIterator(type);
  156. break;
  157. default :
  158. throw new DTMException(XSLMessages.createMessage(XSLTErrorResources.ER_TYPED_ITERATOR_AXIS_NOT_IMPLEMENTED, new Object[]{Axis.names[axis]})); //"Error: typed iterator for axis "
  159. //+ Axis.names[axis] + "not implemented");
  160. }
  161. }
  162. return (iterator);
  163. }
  164. /**
  165. * This is a shortcut to the iterators that implement the
  166. * XPath axes.
  167. * Returns a bare-bones iterator that must be initialized
  168. * with a start node (using iterator.setStartNode()).
  169. *
  170. * @param axis One of Axes.ANCESTORORSELF, etc.
  171. *
  172. * @return A DTMAxisIterator, or null if the given axis isn't supported.
  173. */
  174. public DTMAxisIterator getAxisIterator(final int axis)
  175. {
  176. DTMAxisIterator iterator = null;
  177. switch (axis)
  178. {
  179. case Axis.SELF :
  180. iterator = new SingletonIterator();
  181. break;
  182. case Axis.CHILD :
  183. iterator = new ChildrenIterator();
  184. break;
  185. case Axis.PARENT :
  186. return (new ParentIterator());
  187. case Axis.ANCESTOR :
  188. return (new AncestorIterator());
  189. case Axis.ANCESTORORSELF :
  190. return ((new AncestorIterator()).includeSelf());
  191. case Axis.ATTRIBUTE :
  192. return (new AttributeIterator());
  193. case Axis.DESCENDANT :
  194. iterator = new DescendantIterator();
  195. break;
  196. case Axis.DESCENDANTORSELF :
  197. iterator = (new DescendantIterator()).includeSelf();
  198. break;
  199. case Axis.FOLLOWING :
  200. iterator = new FollowingIterator();
  201. break;
  202. case Axis.PRECEDING :
  203. iterator = new PrecedingIterator();
  204. break;
  205. case Axis.FOLLOWINGSIBLING :
  206. iterator = new FollowingSiblingIterator();
  207. break;
  208. case Axis.PRECEDINGSIBLING :
  209. iterator = new PrecedingSiblingIterator();
  210. break;
  211. case Axis.NAMESPACE :
  212. iterator = new NamespaceIterator();
  213. break;
  214. case Axis.ROOT :
  215. iterator = new RootIterator();
  216. break;
  217. default :
  218. throw new DTMException(XSLMessages.createMessage(XSLTErrorResources.ER_ITERATOR_AXIS_NOT_IMPLEMENTED, new Object[]{Axis.names[axis]})); //"Error: iterator for axis '" + Axis.names[axis]
  219. //+ "' not implemented");
  220. }
  221. return (iterator);
  222. }
  223. /**
  224. * Abstract superclass defining behaviors shared by all DTMDefault's
  225. * internal implementations of DTMAxisIterator. Subclass this (and
  226. * override, if necessary) to implement the specifics of an
  227. * individual axis iterator.
  228. *
  229. * Currently there isn't a lot here
  230. */
  231. private abstract class InternalAxisIteratorBase extends DTMAxisIteratorBase
  232. {
  233. // %REVIEW% We could opt to share _nodeType and setNodeType() as
  234. // well, and simply ignore them in iterators which don't use them.
  235. // But Scott's worried about the overhead involved in cloning
  236. // these, and wants them to have as few fields as possible. Note
  237. // that we can't create a TypedInternalAxisIteratorBase because
  238. // those are often based on the untyped versions and Java doesn't
  239. // support multiple inheritance. <sigh/>
  240. /**
  241. * Current iteration location. Usually this is the last location
  242. * returned (starting point for the next() search); for single-node
  243. * iterators it may instead be initialized to point to that single node.
  244. */
  245. protected int _currentNode;
  246. /**
  247. * Remembers the current node for the next call to gotoMark().
  248. *
  249. * %REVIEW% Should this save _position too?
  250. */
  251. public void setMark()
  252. {
  253. _markedNode = _currentNode;
  254. }
  255. /**
  256. * Restores the current node remembered by setMark().
  257. *
  258. * %REVEIW% Should this restore _position too?
  259. */
  260. public void gotoMark()
  261. {
  262. _currentNode = _markedNode;
  263. }
  264. } // end of InternalAxisIteratorBase
  265. /**
  266. * Iterator that returns all immediate children of a given node
  267. */
  268. private final class ChildrenIterator extends InternalAxisIteratorBase
  269. {
  270. /**
  271. * Setting start to END should 'close' the iterator,
  272. * i.e. subsequent call to next() should return END.
  273. *
  274. * If the iterator is not restartable, this has no effect.
  275. * %REVIEW% Should it return/throw something in that case,
  276. * or set current node to END, to indicate request-not-honored?
  277. *
  278. * @param node Sets the root of the iteration.
  279. *
  280. * @return A DTMAxisIterator set to the start of the iteration.
  281. */
  282. public DTMAxisIterator setStartNode(final int node)
  283. {
  284. if (_isRestartable)
  285. {
  286. _startNode = node;
  287. _currentNode = NOTPROCESSED;
  288. return resetPosition();
  289. }
  290. return this;
  291. }
  292. /**
  293. * Get the next node in the iteration.
  294. *
  295. * @return The next node handle in the iteration, or END if no more
  296. * are available.
  297. */
  298. public int next()
  299. {
  300. _currentNode = (NOTPROCESSED == _currentNode)
  301. ? getFirstChild(_startNode)
  302. : getNextSibling(_currentNode);
  303. return returnNode(_currentNode);
  304. }
  305. } // end of ChildrenIterator
  306. /**
  307. * Iterator that returns the parent of a given node. Note that
  308. * this delivers only a single node; if you want all the ancestors,
  309. * see AncestorIterator.
  310. */
  311. private final class ParentIterator extends InternalAxisIteratorBase
  312. {
  313. /** The extended type ID that was requested. */
  314. private int _nodeType = -1;
  315. /**
  316. * Set start to END should 'close' the iterator,
  317. * i.e. subsequent call to next() should return END.
  318. *
  319. * @param node Sets the root of the iteration.
  320. *
  321. * @return A DTMAxisIterator set to the start of the iteration.
  322. */
  323. public DTMAxisIterator setStartNode(int node)
  324. {
  325. if (_isRestartable)
  326. {
  327. _startNode = node;
  328. _currentNode = getParent(node);
  329. return resetPosition();
  330. }
  331. return this;
  332. }
  333. /**
  334. * Set the node type of the parent that we're looking for.
  335. * Note that this does _not_ mean "find the nearest ancestor of
  336. * this type", but "yield the parent if it is of this type".
  337. *
  338. *
  339. * @param type extended type ID.
  340. *
  341. * @return ParentIterator configured with the type filter set.
  342. */
  343. public DTMAxisIterator setNodeType(final int type)
  344. {
  345. _nodeType = type;
  346. return this;
  347. }
  348. /**
  349. * Get the next node in the iteration. In this case, we return
  350. * only the immediate parent, _if_ it matches the requested nodeType.
  351. *
  352. * @return The next node handle in the iteration, or END.
  353. */
  354. public int next()
  355. {
  356. int result = _currentNode;
  357. if ((_nodeType != -1) && (getExpandedTypeID(_currentNode) != _nodeType))
  358. result = END;
  359. else
  360. result = _currentNode;
  361. _currentNode = END;
  362. return returnNode(result);
  363. }
  364. } // end of ParentIterator
  365. /**
  366. * Iterator that returns children of a given type for a given node.
  367. * The functionality chould be achieved by putting a filter on top
  368. * of a basic child iterator, but a specialised iterator is used
  369. * for efficiency (both speed and size of translet).
  370. */
  371. private final class TypedChildrenIterator extends InternalAxisIteratorBase
  372. {
  373. /** The extended type ID that was requested. */
  374. private final int _nodeType;
  375. /**
  376. * Constructor TypedChildrenIterator
  377. *
  378. *
  379. * @param nodeType The extended type ID being requested.
  380. */
  381. public TypedChildrenIterator(int nodeType)
  382. {
  383. _nodeType = nodeType;
  384. }
  385. /**
  386. * Set start to END should 'close' the iterator,
  387. * i.e. subsequent call to next() should return END.
  388. *
  389. * @param node Sets the root of the iteration.
  390. *
  391. * @return A DTMAxisIterator set to the start of the iteration.
  392. */
  393. public DTMAxisIterator setStartNode(int node)
  394. {
  395. if (_isRestartable)
  396. {
  397. _startNode = node;
  398. _currentNode = NOTPROCESSED;
  399. return resetPosition();
  400. }
  401. return this;
  402. }
  403. /**
  404. * Get the next node in the iteration.
  405. *
  406. * @return The next node handle in the iteration, or END.
  407. */
  408. public int next()
  409. {
  410. for (int node = (NOTPROCESSED == _currentNode)
  411. ? getFirstChild(_startNode)
  412. : getNextSibling(_currentNode); node
  413. != END; node = getNextSibling(node))
  414. {
  415. if (getExpandedTypeID(node) == _nodeType)
  416. {
  417. _currentNode = node;
  418. return returnNode(node);
  419. }
  420. }
  421. return END;
  422. }
  423. } // end of TypedChildrenIterator
  424. /**
  425. * Iterator that returns children within a given namespace for a
  426. * given node. The functionality chould be achieved by putting a
  427. * filter on top of a basic child iterator, but a specialised
  428. * iterator is used for efficiency (both speed and size of translet).
  429. */
  430. private final class NamespaceChildrenIterator
  431. extends InternalAxisIteratorBase
  432. {
  433. /** The extended type ID being requested. */
  434. private final int _nsType;
  435. /**
  436. * Constructor NamespaceChildrenIterator
  437. *
  438. *
  439. * @param type The extended type ID being requested.
  440. */
  441. public NamespaceChildrenIterator(final int type)
  442. {
  443. _nsType = type;
  444. }
  445. /**
  446. * Set start to END should 'close' the iterator,
  447. * i.e. subsequent call to next() should return END.
  448. *
  449. * @param node Sets the root of the iteration.
  450. *
  451. * @return A DTMAxisIterator set to the start of the iteration.
  452. */
  453. public DTMAxisIterator setStartNode(int node)
  454. {
  455. if (_isRestartable)
  456. {
  457. _startNode = node;
  458. _currentNode = NOTPROCESSED;
  459. return resetPosition();
  460. }
  461. return this;
  462. }
  463. /**
  464. * Get the next node in the iteration.
  465. *
  466. * @return The next node handle in the iteration, or END.
  467. */
  468. public int next()
  469. {
  470. for (int node = (NOTPROCESSED == _currentNode)
  471. ? getFirstChild(_startNode)
  472. : getNextSibling(_currentNode); node
  473. != END; node = getNextSibling(node))
  474. {
  475. if (getNamespaceType(node) == _nsType)
  476. {
  477. _currentNode = node;
  478. return returnNode(node);
  479. }
  480. }
  481. return END;
  482. }
  483. } // end of TypedChildrenIterator
  484. /**
  485. * Iterator that returns the namespace nodes as defined by the XPath data model
  486. * for a given node.
  487. */
  488. private class NamespaceIterator
  489. extends InternalAxisIteratorBase
  490. {
  491. /**
  492. * Constructor NamespaceAttributeIterator
  493. */
  494. public NamespaceIterator()
  495. {
  496. super();
  497. }
  498. /**
  499. * Set start to END should 'close' the iterator,
  500. * i.e. subsequent call to next() should return END.
  501. *
  502. * @param node Sets the root of the iteration.
  503. *
  504. * @return A DTMAxisIterator set to the start of the iteration.
  505. */
  506. public DTMAxisIterator setStartNode(int node)
  507. {
  508. if (_isRestartable)
  509. {
  510. _startNode = node;
  511. _currentNode = getFirstNamespaceNode(node, true);
  512. return resetPosition();
  513. }
  514. return this;
  515. }
  516. /**
  517. * Get the next node in the iteration.
  518. *
  519. * @return The next node handle in the iteration, or END.
  520. */
  521. public int next()
  522. {
  523. int node = _currentNode;
  524. if (DTM.NULL != node)
  525. _currentNode = getNextNamespaceNode(_startNode, node, true);
  526. return returnNode(node);
  527. }
  528. } // end of NamespaceIterator
  529. /**
  530. * Iterator that returns the namespace nodes as defined by the XPath data model
  531. * for a given node, filtered by extended type ID.
  532. */
  533. private class TypedNamespaceIterator extends NamespaceIterator
  534. {
  535. /** The extended type ID that was requested. */
  536. private final int _nodeType;
  537. /**
  538. * Constructor TypedChildrenIterator
  539. *
  540. *
  541. * @param nodeType The extended type ID being requested.
  542. */
  543. public TypedNamespaceIterator(int nodeType)
  544. {
  545. super();
  546. _nodeType = nodeType;
  547. }
  548. /**
  549. * Get the next node in the iteration.
  550. *
  551. * @return The next node handle in the iteration, or END.
  552. */
  553. public int next()
  554. {
  555. for (int node = super.next(); node != END; node = super.next())
  556. {
  557. if (getExpandedTypeID(node) == _nodeType)
  558. {
  559. _currentNode = node;
  560. return returnNode(node);
  561. }
  562. }
  563. return END;
  564. }
  565. } // end of TypedNamespaceIterator
  566. /**
  567. * Iterator that returns the the root node as defined by the XPath data model
  568. * for a given node.
  569. */
  570. private class RootIterator
  571. extends InternalAxisIteratorBase
  572. {
  573. /**
  574. * Constructor RootIterator
  575. */
  576. public RootIterator()
  577. {
  578. super();
  579. }
  580. /**
  581. * Set start to END should 'close' the iterator,
  582. * i.e. subsequent call to next() should return END.
  583. *
  584. * @param node Sets the root of the iteration.
  585. *
  586. * @return A DTMAxisIterator set to the start of the iteration.
  587. */
  588. public DTMAxisIterator setStartNode(int node)
  589. {
  590. if (_isRestartable)
  591. {
  592. _startNode = getDocumentRoot(node);
  593. _currentNode = NULL;
  594. return resetPosition();
  595. }
  596. return this;
  597. }
  598. /**
  599. * Get the next node in the iteration.
  600. *
  601. * @return The next node handle in the iteration, or END.
  602. */
  603. public int next()
  604. {
  605. if(_startNode == _currentNode)
  606. return NULL;
  607. _currentNode = _startNode;
  608. return returnNode(_startNode);
  609. }
  610. } // end of RootIterator
  611. /**
  612. * Iterator that returns the namespace nodes as defined by the XPath data model
  613. * for a given node, filtered by extended type ID.
  614. */
  615. private class TypedRootIterator extends RootIterator
  616. {
  617. /** The extended type ID that was requested. */
  618. private final int _nodeType;
  619. /**
  620. * Constructor TypedRootIterator
  621. *
  622. * @param nodeType The extended type ID being requested.
  623. */
  624. public TypedRootIterator(int nodeType)
  625. {
  626. super();
  627. _nodeType = nodeType;
  628. }
  629. /**
  630. * Get the next node in the iteration.
  631. *
  632. * @return The next node handle in the iteration, or END.
  633. */
  634. public int next()
  635. {
  636. for (int node = super.next(); node != END; node = super.next())
  637. {
  638. if (getExpandedTypeID(node) == _nodeType)
  639. {
  640. _currentNode = node;
  641. return returnNode(node);
  642. }
  643. }
  644. return END;
  645. }
  646. } // end of TypedRootIterator
  647. /**
  648. * Iterator that returns attributes within a given namespace for a node.
  649. */
  650. private final class NamespaceAttributeIterator
  651. extends InternalAxisIteratorBase
  652. {
  653. /** The extended type ID being requested. */
  654. private final int _nsType;
  655. /**
  656. * Constructor NamespaceAttributeIterator
  657. *
  658. *
  659. * @param nsType The extended type ID being requested.
  660. */
  661. public NamespaceAttributeIterator(int nsType)
  662. {
  663. super();
  664. _nsType = nsType;
  665. }
  666. /**
  667. * Set start to END should 'close' the iterator,
  668. * i.e. subsequent call to next() should return END.
  669. *
  670. * @param node Sets the root of the iteration.
  671. *
  672. * @return A DTMAxisIterator set to the start of the iteration.
  673. */
  674. public DTMAxisIterator setStartNode(int node)
  675. {
  676. if (_isRestartable)
  677. {
  678. _startNode = node;
  679. _currentNode = getFirstNamespaceNode(node, false);
  680. return resetPosition();
  681. }
  682. return this;
  683. }
  684. /**
  685. * Get the next node in the iteration.
  686. *
  687. * @return The next node handle in the iteration, or END.
  688. */
  689. public int next()
  690. {
  691. int node = _currentNode;
  692. if (DTM.NULL != node)
  693. _currentNode = getNextNamespaceNode(_startNode, node, false);
  694. return returnNode(node);
  695. }
  696. } // end of TypedChildrenIterator
  697. /**
  698. * Iterator that returns all siblings of a given node.
  699. */
  700. private class FollowingSiblingIterator extends InternalAxisIteratorBase
  701. {
  702. /**
  703. * Set start to END should 'close' the iterator,
  704. * i.e. subsequent call to next() should return END.
  705. *
  706. * @param node Sets the root of the iteration.
  707. *
  708. * @return A DTMAxisIterator set to the start of the iteration.
  709. */
  710. public DTMAxisIterator setStartNode(int node)
  711. {
  712. if (_isRestartable)
  713. {
  714. _currentNode = _startNode = node;
  715. return resetPosition();
  716. }
  717. return this;
  718. }
  719. /**
  720. * Get the next node in the iteration.
  721. *
  722. * @return The next node handle in the iteration, or END.
  723. */
  724. public int next()
  725. {
  726. return returnNode(_currentNode = getNextSibling(_currentNode));
  727. }
  728. } // end of FollowingSiblingIterator
  729. /**
  730. * Iterator that returns all following siblings of a given node.
  731. */
  732. private final class TypedFollowingSiblingIterator
  733. extends FollowingSiblingIterator
  734. {
  735. /** The extended type ID that was requested. */
  736. private final int _nodeType;
  737. /**
  738. * Constructor TypedFollowingSiblingIterator
  739. *
  740. *
  741. * @param type The extended type ID being requested.
  742. */
  743. public TypedFollowingSiblingIterator(int type)
  744. {
  745. _nodeType = type;
  746. }
  747. /**
  748. * Get the next node in the iteration.
  749. *
  750. * @return The next node handle in the iteration, or END.
  751. */
  752. public int next()
  753. {
  754. int node;
  755. while ((node = super.next()) != NULL
  756. && getExpandedTypeID(node) != _nodeType){}
  757. return node;
  758. }
  759. } // end of TypedFollowingSiblingIterator
  760. /**
  761. * Iterator that returns attribute nodes (of what nodes?)
  762. */
  763. private final class AttributeIterator extends InternalAxisIteratorBase
  764. {
  765. // assumes caller will pass element nodes
  766. /**
  767. * Set start to END should 'close' the iterator,
  768. * i.e. subsequent call to next() should return END.
  769. *
  770. * @param node Sets the root of the iteration.
  771. *
  772. * @return A DTMAxisIterator set to the start of the iteration.
  773. */
  774. public DTMAxisIterator setStartNode(int node)
  775. {
  776. if (_isRestartable)
  777. {
  778. _startNode = node;
  779. _currentNode = getFirstAttribute(node);
  780. return resetPosition();
  781. }
  782. return this;
  783. }
  784. /**
  785. * Get the next node in the iteration.
  786. *
  787. * @return The next node handle in the iteration, or END.
  788. */
  789. public int next()
  790. {
  791. final int node = _currentNode;
  792. _currentNode = getNextAttribute(node);
  793. return returnNode(node);
  794. }
  795. } // end of AttributeIterator
  796. /**
  797. * Iterator that returns attribute nodes of a given type
  798. */
  799. private final class TypedAttributeIterator extends InternalAxisIteratorBase
  800. {
  801. /** The extended type ID that was requested. */
  802. private final int _nodeType;
  803. /**
  804. * Constructor TypedAttributeIterator
  805. *
  806. *
  807. * @param nodeType The extended type ID that is requested.
  808. */
  809. public TypedAttributeIterator(int nodeType)
  810. {
  811. _nodeType = nodeType;
  812. }
  813. // assumes caller will pass element nodes
  814. /**
  815. * Set start to END should 'close' the iterator,
  816. * i.e. subsequent call to next() should return END.
  817. *
  818. * @param node Sets the root of the iteration.
  819. *
  820. * @return A DTMAxisIterator set to the start of the iteration.
  821. */
  822. public DTMAxisIterator setStartNode(int node)
  823. {
  824. if (_isRestartable)
  825. {
  826. _startNode = node;
  827. for (node = getFirstAttribute(node); node != END;
  828. node = getNextAttribute(node))
  829. {
  830. if (getExpandedTypeID(node) == _nodeType)
  831. break;
  832. }
  833. _currentNode = node;
  834. return resetPosition();
  835. }
  836. return this;
  837. }
  838. /**
  839. * Get the next node in the iteration.
  840. *
  841. * @return The next node handle in the iteration, or END.
  842. */
  843. public int next()
  844. {
  845. final int node = _currentNode;
  846. // singleton iterator, since there can only be one attribute of
  847. // a given type.
  848. _currentNode = NULL;
  849. return returnNode(node);
  850. }
  851. } // end of TypedAttributeIterator
  852. /**
  853. * Iterator that returns preceding siblings of a given node
  854. */
  855. private class PrecedingSiblingIterator extends InternalAxisIteratorBase
  856. {
  857. /**
  858. * True if this iterator has a reversed axis.
  859. *
  860. * @return true.
  861. */
  862. public boolean isReverse()
  863. {
  864. return true;
  865. }
  866. /**
  867. * Set start to END should 'close' the iterator,
  868. * i.e. subsequent call to next() should return END.
  869. *
  870. * @param node Sets the root of the iteration.
  871. *
  872. * @return A DTMAxisIterator set to the start of the iteration.
  873. */
  874. public DTMAxisIterator setStartNode(int node)
  875. {
  876. if (_isRestartable)
  877. {
  878. _startNode = node;
  879. if(node == NULL)
  880. {
  881. _currentNode = node;
  882. return resetPosition();
  883. }
  884. int type = m_expandedNameTable.getType(getExpandedTypeID(node));
  885. if(ExpandedNameTable.ATTRIBUTE == type
  886. || ExpandedNameTable.NAMESPACE == type )
  887. {
  888. _currentNode = node;
  889. }
  890. else
  891. {
  892. // Be careful to handle the Document node properly
  893. _currentNode = getParent(node);
  894. if(NULL!=_currentNode)
  895. _currentNode = getFirstChild(_currentNode);
  896. else
  897. _currentNode = node;
  898. }
  899. return resetPosition();
  900. }
  901. return this;
  902. }
  903. /**
  904. * Get the next node in the iteration.
  905. *
  906. * @return The next node handle in the iteration, or END.
  907. */
  908. public int next()
  909. {
  910. if (_currentNode == _startNode)
  911. {
  912. return NULL;
  913. }
  914. else
  915. {
  916. final int node = _currentNode;
  917. _currentNode = getNextSibling(node);
  918. return returnNode(node);
  919. }
  920. }
  921. } // end of PrecedingSiblingIterator
  922. /**
  923. * Iterator that returns preceding siblings of a given type for
  924. * a given node
  925. */
  926. private final class TypedPrecedingSiblingIterator
  927. extends PrecedingSiblingIterator
  928. {
  929. /** The extended type ID that was requested. */
  930. private final int _nodeType;
  931. /**
  932. * Constructor TypedPrecedingSiblingIterator
  933. *
  934. *
  935. * @param type The extended type ID being requested.
  936. */
  937. public TypedPrecedingSiblingIterator(int type)
  938. {
  939. _nodeType = type;
  940. }
  941. /**
  942. * Get the next node in the iteration.
  943. *
  944. * @return The next node handle in the iteration, or END.
  945. */
  946. public int next()
  947. {
  948. int node;
  949. while ((node = super.next()) != NULL
  950. && getExpandedTypeID(node) != _nodeType){}
  951. return node;
  952. }
  953. } // end of PrecedingSiblingIterator
  954. /**
  955. * Iterator that returns preceding nodes of a given node.
  956. * This includes the node set {root+1, start-1}, but excludes
  957. * all ancestors, attributes, and namespace nodes.
  958. */
  959. private class PrecedingIterator extends InternalAxisIteratorBase
  960. {
  961. /** The max ancestors, but it can grow... */
  962. private final int _maxAncestors = 8;
  963. /**
  964. * The stack of start node + ancestors up to the root of the tree,
  965. * which we must avoid.
  966. */
  967. private int[] _stack = new int[_maxAncestors];
  968. /** (not sure yet... -sb) */
  969. private int _sp, _oldsp;
  970. /* _currentNode precedes candidates. This is the identity, not the handle! */
  971. /**
  972. * True if this iterator has a reversed axis.
  973. *
  974. * @return true since this iterator is a reversed axis.
  975. */
  976. public boolean isReverse()
  977. {
  978. return true;
  979. }
  980. /**
  981. * Returns a deep copy of this iterator. The cloned iterator is not reset.
  982. *
  983. * @return a deep copy of this iterator.
  984. */
  985. public DTMAxisIterator cloneIterator()
  986. {
  987. _isRestartable = false;
  988. try
  989. {
  990. final PrecedingIterator clone = (PrecedingIterator) super.clone();
  991. final int[] stackCopy = new int[_stack.length];
  992. System.arraycopy(_stack, 0, stackCopy, 0, _stack.length);
  993. clone._stack = stackCopy;
  994. // return clone.reset();
  995. return clone;
  996. }
  997. catch (CloneNotSupportedException e)
  998. {
  999. throw new DTMException(XSLMessages.createMessage(XSLTErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED, null)); //"Iterator clone not supported.");
  1000. }
  1001. }
  1002. /**
  1003. * Set start to END should 'close' the iterator,
  1004. * i.e. subsequent call to next() should return END.
  1005. *
  1006. * @param node Sets the root of the iteration.
  1007. *
  1008. * @return A DTMAxisIterator set to the start of the iteration.
  1009. */
  1010. public DTMAxisIterator setStartNode(int node)
  1011. {
  1012. if (_isRestartable)
  1013. {
  1014. node = makeNodeIdentity(node);
  1015. // iterator is not a clone
  1016. int parent, index;
  1017. _startNode = node;
  1018. _stack[index = 0] = node;
  1019. parent=node;
  1020. while ((parent = _parent(parent)) != NULL)
  1021. {
  1022. if (++index == _stack.length)
  1023. {
  1024. final int[] stack = new int[index + 4];
  1025. System.arraycopy(_stack, 0, stack, 0, index);
  1026. _stack = stack;
  1027. }
  1028. _stack[index] = parent;
  1029. }
  1030. if(index>0)
  1031. --index; // Pop actual root node (if not start) back off the stack
  1032. _currentNode=_stack[index]; // Last parent before root node
  1033. _oldsp = _sp = index;
  1034. return resetPosition();
  1035. }
  1036. return this;
  1037. }
  1038. /**
  1039. * Get the next node in the iteration.
  1040. *
  1041. * @return The next node handle in the iteration, or END.
  1042. */
  1043. public int next()
  1044. {
  1045. // Bugzilla 8324: We were forgetting to skip Attrs and NS nodes.
  1046. // Also recoded the loop controls for clarity and to flatten out
  1047. // the tail-recursion.
  1048. for(++_currentNode;
  1049. _sp>=0;
  1050. ++_currentNode)
  1051. {
  1052. if(_currentNode < _stack[_sp])
  1053. {
  1054. if(_type(_currentNode) != ATTRIBUTE_NODE &&
  1055. _type(_currentNode) != NAMESPACE_NODE)
  1056. return returnNode(makeNodeHandle(_currentNode));
  1057. }
  1058. else
  1059. --_sp;
  1060. }
  1061. return NULL;
  1062. }
  1063. // redefine DTMAxisIteratorBase's reset
  1064. /**
  1065. * Resets the iterator to the last start node.
  1066. *
  1067. * @return A DTMAxisIterator, which may or may not be the same as this
  1068. * iterator.
  1069. */
  1070. public DTMAxisIterator reset()
  1071. {
  1072. _sp = _oldsp;
  1073. return resetPosition();
  1074. }
  1075. } // end of PrecedingIterator
  1076. /**
  1077. * Iterator that returns preceding nodes of agiven type for a
  1078. * given node. This includes the node set {root+1, start-1}, but
  1079. * excludes all ancestors.
  1080. */
  1081. private final class TypedPrecedingIterator extends PrecedingIterator
  1082. {
  1083. /** The extended type ID that was requested. */
  1084. private final int _nodeType;
  1085. /**
  1086. * Constructor TypedPrecedingIterator
  1087. *
  1088. *
  1089. * @param type The extended type ID being requested.
  1090. */
  1091. public TypedPrecedingIterator(int type)
  1092. {
  1093. _nodeType = type;
  1094. }
  1095. /**
  1096. * Get the next node in the iteration.
  1097. *
  1098. * @return The next node handle in the iteration, or END.
  1099. */
  1100. public int next()
  1101. {
  1102. int node;
  1103. while ((node = super.next()) != NULL
  1104. && getExpandedTypeID(node) != _nodeType){}
  1105. return node;
  1106. }
  1107. } // end of TypedPrecedingIterator
  1108. /**
  1109. * Iterator that returns following nodes of for a given node.
  1110. */
  1111. private class FollowingIterator extends InternalAxisIteratorBase
  1112. {
  1113. DTMAxisTraverser m_traverser; // easier for now
  1114. public FollowingIterator()
  1115. {
  1116. m_traverser = getAxisTraverser(Axis.FOLLOWING);
  1117. }
  1118. /**
  1119. * Set start to END should 'close' the iterator,
  1120. * i.e. subsequent call to next() should return END.
  1121. *
  1122. * @param node Sets the root of the iteration.
  1123. *
  1124. * @return A DTMAxisIterator set to the start of the iteration.
  1125. */
  1126. public DTMAxisIterator setStartNode(int node)
  1127. {
  1128. if (_isRestartable)
  1129. {
  1130. _startNode = node;
  1131. // ?? -sb
  1132. // find rightmost descendant (or self)
  1133. // int current;
  1134. // while ((node = getLastChild(current = node)) != NULL){}
  1135. // _currentNode = current;
  1136. _currentNode = m_traverser.first(node);
  1137. // _currentNode precedes possible following(node) nodes
  1138. return resetPosition();
  1139. }
  1140. return this;
  1141. }
  1142. /**
  1143. * Get the next node in the iteration.
  1144. *
  1145. * @return The next node handle in the iteration, or END.
  1146. */
  1147. public int next()
  1148. {
  1149. int node = _currentNode;
  1150. _currentNode = m_traverser.next(_startNode, _currentNode);
  1151. return returnNode(node);
  1152. }
  1153. } // end of FollowingIterator
  1154. /**
  1155. * Iterator that returns following nodes of a given type for a given node.
  1156. */
  1157. private final class TypedFollowingIterator extends FollowingIterator
  1158. {
  1159. /** The extended type ID that was requested. */
  1160. private final int _nodeType;
  1161. /**
  1162. * Constructor TypedFollowingIterator
  1163. *
  1164. *
  1165. * @param type The extended type ID being requested.
  1166. */
  1167. public TypedFollowingIterator(int type)
  1168. {
  1169. _nodeType = type;
  1170. }
  1171. /**
  1172. * Get the next node in the iteration.
  1173. *
  1174. * @return The next node handle in the iteration, or END.
  1175. */
  1176. public int next()
  1177. {
  1178. int node;
  1179. while ((node = super.next()) != NULL
  1180. && getExpandedTypeID(node) != _nodeType){}
  1181. return returnNode(node);
  1182. }
  1183. } // end of TypedFollowingIterator
  1184. /**
  1185. * Iterator that returns the ancestors of a given node in document
  1186. * order. (NOTE! This was changed from the XSLTC code!)
  1187. */
  1188. private class AncestorIterator extends InternalAxisIteratorBase
  1189. {
  1190. org.apache.xml.utils.NodeVector m_ancestors =
  1191. new org.apache.xml.utils.NodeVector();
  1192. int m_ancestorsPos;
  1193. /** The real start node for this axes, since _startNode will be adjusted. */
  1194. int m_realStartNode;
  1195. /**
  1196. * Get start to END should 'close' the iterator,
  1197. * i.e. subsequent call to next() should return END.
  1198. *
  1199. * @return The root node of the iteration.
  1200. */
  1201. public int getStartNode()
  1202. {
  1203. return m_realStartNode;
  1204. }
  1205. /**
  1206. * True if this iterator has a reversed axis.
  1207. *
  1208. * @return true since this iterator is a reversed axis.
  1209. */
  1210. public final boolean isReverse()
  1211. {
  1212. return true;
  1213. }
  1214. /**
  1215. * Returns the last element in this interation.
  1216. *
  1217. * %TBD% %BUG% This is returning a nodeHandle rather than a _position
  1218. * value. That conflicts with what everyone else is doing. And it's
  1219. * talking about the start node, which conflicts with some of the
  1220. * other reverse iterators. DEFINITE BUG; needs to be reconciled.
  1221. *
  1222. * @return the last element in this interation.
  1223. */
  1224. public int getLast()
  1225. {
  1226. return (_startNode);
  1227. }
  1228. /**
  1229. * Returns a deep copy of this iterator. The cloned iterator is not reset.
  1230. *
  1231. * @return a deep copy of this iterator.
  1232. */
  1233. public DTMAxisIterator cloneIterator()
  1234. {
  1235. _isRestartable = false; // must set to false for any clone
  1236. try
  1237. {
  1238. final AncestorIterator clone = (AncestorIterator) super.clone();
  1239. clone._startNode = _startNode;
  1240. // return clone.reset();
  1241. return clone;
  1242. }
  1243. catch (CloneNotSupportedException e)
  1244. {
  1245. throw new DTMException(XSLMessages.createMessage(XSLTErrorResources.ER_ITERATOR_CLONE_NOT_SUPPORTED, null)); //"Iterator clone not supported.");
  1246. }
  1247. }
  1248. /**
  1249. * Set start to END should 'close' the iterator,
  1250. * i.e. subsequent call to next() should return END.
  1251. *
  1252. * @param node Sets the root of the iteration.
  1253. *
  1254. * @return A DTMAxisIterator set to the start of the iteration.
  1255. */
  1256. public DTMAxisIterator setStartNode(int node)
  1257. {
  1258. m_realStartNode = node;
  1259. if (_isRestartable)
  1260. {
  1261. if (_includeSelf)
  1262. _startNode = node;
  1263. else
  1264. _startNode = getParent(node);
  1265. node = _startNode;
  1266. while (node != END)
  1267. {
  1268. m_ancestors.addElement(node);
  1269. node = getParent(node);
  1270. }
  1271. m_ancestorsPos = m_ancestors.size()-1;
  1272. _currentNode = (m_ancestorsPos>=0)
  1273. ? m_ancestors.elementAt(m_ancestorsPos)
  1274. : DTM.NULL;
  1275. return resetPosition();
  1276. }
  1277. return this;
  1278. }
  1279. /**
  1280. * Resets the iterator to the last start node.
  1281. *
  1282. * @return A DTMAxisIterator, which may or may not be the same as this
  1283. * iterator.
  1284. */
  1285. public DTMAxisIterator reset()
  1286. {
  1287. m_ancestorsPos = m_ancestors.size()-1;
  1288. _currentNode = (m_ancestorsPos>=0) ? m_ancestors.elementAt(m_ancestorsPos)
  1289. : DTM.NULL;
  1290. return resetPosition();
  1291. }
  1292. /**
  1293. * Get the next node in the iteration.
  1294. *
  1295. * @return The next node handle in the iteration, or END.
  1296. */
  1297. public int next()
  1298. {
  1299. int next = _currentNode;
  1300. int pos = --m_ancestorsPos;
  1301. _currentNode = (pos >= 0) ? m_ancestors.elementAt(m_ancestorsPos)
  1302. : DTM.NULL;
  1303. return returnNode(next);
  1304. }
  1305. } // end of AncestorIterator
  1306. /**
  1307. * Typed iterator that returns the ancestors of a given node.
  1308. */
  1309. private final class TypedAncestorIterator extends AncestorIterator
  1310. {
  1311. /** The extended type ID that was requested. */
  1312. private final int _nodeType;
  1313. /**
  1314. * Constructor TypedAncestorIterator
  1315. *
  1316. *
  1317. * @param type The extended type ID being requested.
  1318. */
  1319. public TypedAncestorIterator(int type)
  1320. {
  1321. _nodeType = type;
  1322. }
  1323. /**
  1324. * Get the next node in the iteration.
  1325. *
  1326. * @return The next node handle in the iteration, or END.
  1327. */
  1328. public int next()
  1329. {
  1330. int node;
  1331. while ((node = super.next()) != NULL)
  1332. {
  1333. if (getExpandedTypeID(node) == _nodeType)
  1334. return returnNode(node);
  1335. }
  1336. return (NULL);
  1337. }
  1338. /**
  1339. * Returns the last element in this interation.
  1340. *
  1341. * @return the last element in this interation.
  1342. */
  1343. public int getLast()
  1344. {
  1345. int last = NULL;
  1346. int curr = _startNode;
  1347. while (curr != NULL)
  1348. {
  1349. if (getExpandedTypeID(curr) == _nodeType)
  1350. last = curr;
  1351. curr = getParent(curr);
  1352. }
  1353. return (last);
  1354. }
  1355. } // end of TypedAncestorIterator
  1356. /**
  1357. * Iterator that returns the descendants of a given node.
  1358. */
  1359. private class DescendantIterator extends InternalAxisIteratorBase
  1360. {
  1361. /**
  1362. * Set start to END should 'close' the iterator,
  1363. * i.e. subsequent call to next() should return END.
  1364. *
  1365. * @param node Sets the root of the iteration.
  1366. *
  1367. * @return A DTMAxisIterator set to the start of the iteration.
  1368. */
  1369. public DTMAxisIterator setStartNode(int node)
  1370. {
  1371. if (_isRestartable)
  1372. {
  1373. node = makeNodeIdentity(node);
  1374. _startNode = node;
  1375. if (_includeSelf)
  1376. node--;
  1377. _currentNode = node;
  1378. return resetPosition();
  1379. }
  1380. return this;
  1381. }
  1382. /**
  1383. * Tell if this node identity is a descendant. Assumes that
  1384. * the node info for the element has already been obtained.
  1385. *
  1386. * This one-sided test works only if the parent has been
  1387. * previously tested and is known to be a descendent. It fails if
  1388. * the parent is the _startNode's next sibling, or indeed any node
  1389. * that follows _startNode in document order. That may suffice
  1390. * for this iterator, but it's not really an isDescendent() test.
  1391. * %REVIEW% rename?
  1392. *
  1393. * @param identity The index number of the node in question.
  1394. * @return true if the index is a descendant of _startNode.
  1395. */
  1396. protected boolean isDescendant(int identity)
  1397. {
  1398. return (_startNode == identity) || _parent(identity) >= _startNode;
  1399. }
  1400. /**
  1401. * Get the next node in the iteration.
  1402. *
  1403. * @return The next node handle in the iteration, or END.
  1404. */
  1405. public int next()
  1406. {
  1407. while (true)
  1408. {
  1409. int node = ++_currentNode;
  1410. int type = _type(node);
  1411. if (NULL == type ||!isDescendant(node))
  1412. return END;
  1413. if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
  1414. continue;
  1415. return returnNode(makeNodeHandle(node)); // make handle.
  1416. }
  1417. }
  1418. } // end of DescendantIterator
  1419. /**
  1420. * Typed iterator that returns the descendants of a given node.
  1421. */
  1422. private final class TypedDescendantIterator extends DescendantIterator
  1423. {
  1424. /** The extended type ID that was requested. */
  1425. private final int _nodeType;
  1426. /**
  1427. * Constructor TypedDescendantIterator
  1428. *
  1429. *
  1430. * @param nodeType Extended type ID being requested.
  1431. */
  1432. public TypedDescendantIterator(int nodeType)
  1433. {
  1434. _nodeType = nodeType;
  1435. }
  1436. /**
  1437. * Get the next node in the iteration.
  1438. *
  1439. * @return The next node handle in the iteration, or END.
  1440. */
  1441. public int next()
  1442. {
  1443. int node;
  1444. while ((node = super.next()) != NULL
  1445. && getExpandedTypeID(node) != _nodeType){}
  1446. return node;
  1447. }
  1448. } // end of TypedDescendantIterator
  1449. /**
  1450. * Iterator that returns the descendants of a given node.
  1451. * I'm not exactly clear about this one... -sb
  1452. */
  1453. private class NthDescendantIterator extends DescendantIterator
  1454. {
  1455. /** The current nth position. */
  1456. int _pos;
  1457. /**
  1458. * Constructor NthDescendantIterator
  1459. *
  1460. *
  1461. * @param pos The nth position being requested.
  1462. */
  1463. public NthDescendantIterator(int pos)
  1464. {
  1465. _pos = pos;
  1466. }
  1467. /**
  1468. * Get the next node in the iteration.
  1469. *
  1470. * @return The next node handle in the iteration, or END.
  1471. */
  1472. public int next()
  1473. {
  1474. // I'm not exactly clear yet what this is doing... -sb
  1475. int node;
  1476. while ((node = super.next()) != END)
  1477. {
  1478. node = makeNodeIdentity(node);
  1479. int parent = _parent(node);
  1480. int child = _firstch(parent);
  1481. int pos = 0;
  1482. do
  1483. {
  1484. int type = _type(child);
  1485. if (ELEMENT_NODE == type)
  1486. pos++;
  1487. }
  1488. while ((pos < _pos) && (child = _nextsib(child)) != END);
  1489. if (node == child)
  1490. return node;
  1491. }
  1492. return (END);
  1493. }
  1494. } // end of NthDescendantIterator
  1495. /**
  1496. * Class SingletonIterator.
  1497. */
  1498. private class SingletonIterator extends InternalAxisIteratorBase
  1499. {
  1500. /** (not sure yet what this is. -sb) (sc & sb remove final to compile in JDK 1.1.8) */
  1501. private boolean _isConstant;
  1502. /**
  1503. * Constructor SingletonIterator
  1504. *
  1505. */
  1506. public SingletonIterator()
  1507. {
  1508. this(Integer.MIN_VALUE, false);
  1509. }
  1510. /**
  1511. * Constructor SingletonIterator
  1512. *
  1513. *
  1514. * @param node The node handle to return.
  1515. */
  1516. public SingletonIterator(int node)
  1517. {
  1518. this(node, false);
  1519. }
  1520. /**
  1521. * Constructor SingletonIterator
  1522. *
  1523. *
  1524. * @param node the node handle to return.
  1525. * @param constant (Not sure what this is yet. -sb)
  1526. */
  1527. public SingletonIterator(int node, boolean constant)
  1528. {
  1529. _currentNode = _startNode = node;
  1530. _isConstant = constant;
  1531. }
  1532. /**
  1533. * Set start to END should 'close' the iterator,
  1534. * i.e. subsequent call to next() should return END.
  1535. *
  1536. * @param node Sets the root of the iteration.
  1537. *
  1538. * @return A DTMAxisIterator set to the start of the iteration.
  1539. */
  1540. public DTMAxisIterator setStartNode(int node)
  1541. {
  1542. if (_isConstant)
  1543. {
  1544. _currentNode = _startNode;
  1545. return resetPosition();
  1546. }
  1547. else if (_isRestartable)
  1548. {
  1549. if (_currentNode == Integer.MIN_VALUE)
  1550. {
  1551. _currentNode = _startNode = node;
  1552. }
  1553. return resetPosition();
  1554. }
  1555. return this;
  1556. }
  1557. /**
  1558. * Resets the iterator to the last start node.
  1559. *
  1560. * @return A DTMAxisIterator, which may or may not be the same as this
  1561. * iterator.
  1562. */
  1563. public DTMAxisIterator reset()
  1564. {
  1565. if (_isConstant)
  1566. {
  1567. _currentNode = _startNode;
  1568. return resetPosition();
  1569. }
  1570. else
  1571. {
  1572. final boolean temp = _isRestartable;
  1573. _isRestartable = true;
  1574. setStartNode(_startNode);
  1575. _isRestartable = temp;
  1576. }
  1577. return this;
  1578. }
  1579. /**
  1580. * Get the next node in the iteration.
  1581. *
  1582. * @return The next node handle in the iteration, or END.
  1583. */
  1584. public int next()
  1585. {
  1586. final int result = _currentNode;
  1587. _currentNode = END;
  1588. return returnNode(result);
  1589. }
  1590. }
  1591. /**
  1592. * Iterator that returns a given node only if it is of a given type.
  1593. */
  1594. private final class TypedSingletonIterator extends SingletonIterator
  1595. {
  1596. /** The extended type ID that was requested. */
  1597. private final int _nodeType;
  1598. /**
  1599. * Constructor TypedSingletonIterator
  1600. *
  1601. *
  1602. * @param nodeType The extended type ID being requested.
  1603. */
  1604. public TypedSingletonIterator(int nodeType)
  1605. {
  1606. _nodeType = nodeType;
  1607. }
  1608. /**
  1609. * Get the next node in the iteration.
  1610. *
  1611. * @return The next node handle in the iteration, or END.
  1612. */
  1613. public int next()
  1614. {
  1615. final int result = super.next();
  1616. return getExpandedTypeID(result) == _nodeType ? result : NULL;
  1617. }
  1618. } // end of TypedSingletonIterator
  1619. }