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