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: DTMDefaultBaseTraversers.java,v 1.19 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. * PLEASE NOTE that the public interface for all traversers should be
  29. * in terms of DTM Node Handles... but they may use the internal node
  30. * identity indices within their logic, for efficiency's sake. Be very
  31. * careful to avoid confusing these when maintaining this code.
  32. * */
  33. public abstract class DTMDefaultBaseTraversers extends DTMDefaultBase
  34. {
  35. /**
  36. * Construct a DTMDefaultBaseTraversers object from a DOM node.
  37. *
  38. * @param mgr The DTMManager who owns this DTM.
  39. * @param domSource the DOM source that this DTM will wrap.
  40. * @param source The object that is used to specify the construction source.
  41. * @param dtmIdentity The DTM identity ID for this DTM.
  42. * @param whiteSpaceFilter The white space filter for this DTM, which may
  43. * be null.
  44. * @param xstringfactory The factory to use for creating XMLStrings.
  45. * @param doIndexing true if the caller considers it worth it to use
  46. * indexing schemes.
  47. */
  48. public DTMDefaultBaseTraversers(DTMManager mgr, Source source,
  49. int dtmIdentity,
  50. DTMWSFilter whiteSpaceFilter,
  51. XMLStringFactory xstringfactory,
  52. boolean doIndexing)
  53. {
  54. super(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory,
  55. doIndexing);
  56. }
  57. /**
  58. * Construct a DTMDefaultBaseTraversers object from a DOM node.
  59. *
  60. * @param mgr The DTMManager who owns this DTM.
  61. * @param domSource the DOM source that this DTM will wrap.
  62. * @param source The object that is used to specify the construction source.
  63. * @param dtmIdentity The DTM identity ID for this DTM.
  64. * @param whiteSpaceFilter The white space filter for this DTM, which may
  65. * be null.
  66. * @param xstringfactory The factory to use for creating XMLStrings.
  67. * @param doIndexing true if the caller considers it worth it to use
  68. * indexing schemes.
  69. * @param blocksize The block size of the DTM.
  70. * @param usePrevsib true if we want to build the previous sibling node array.
  71. * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
  72. */
  73. public DTMDefaultBaseTraversers(DTMManager mgr, Source source,
  74. int dtmIdentity,
  75. DTMWSFilter whiteSpaceFilter,
  76. XMLStringFactory xstringfactory,
  77. boolean doIndexing,
  78. int blocksize,
  79. boolean usePrevsib,
  80. boolean newNameTable)
  81. {
  82. super(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory,
  83. doIndexing, blocksize, usePrevsib, newNameTable);
  84. }
  85. /**
  86. * This returns a stateless "traverser", that can navigate
  87. * over an XPath axis, though perhaps not in document order.
  88. *
  89. * @param axis One of Axes.ANCESTORORSELF, etc.
  90. *
  91. * @return A DTMAxisTraverser, or null if the given axis isn't supported.
  92. */
  93. public DTMAxisTraverser getAxisTraverser(final int axis)
  94. {
  95. DTMAxisTraverser traverser;
  96. if (null == m_traversers) // Cache of stateless traversers for this DTM
  97. {
  98. m_traversers = new DTMAxisTraverser[Axis.names.length];
  99. traverser = null;
  100. }
  101. else
  102. {
  103. traverser = m_traversers[axis]; // Share/reuse existing traverser
  104. if (traverser != null)
  105. return traverser;
  106. }
  107. switch (axis) // Generate new traverser
  108. {
  109. case Axis.ANCESTOR :
  110. traverser = new AncestorTraverser();
  111. break;
  112. case Axis.ANCESTORORSELF :
  113. traverser = new AncestorOrSelfTraverser();
  114. break;
  115. case Axis.ATTRIBUTE :
  116. traverser = new AttributeTraverser();
  117. break;
  118. case Axis.CHILD :
  119. traverser = new ChildTraverser();
  120. break;
  121. case Axis.DESCENDANT :
  122. traverser = new DescendantTraverser();
  123. break;
  124. case Axis.DESCENDANTORSELF :
  125. traverser = new DescendantOrSelfTraverser();
  126. break;
  127. case Axis.FOLLOWING :
  128. traverser = new FollowingTraverser();
  129. break;
  130. case Axis.FOLLOWINGSIBLING :
  131. traverser = new FollowingSiblingTraverser();
  132. break;
  133. case Axis.NAMESPACE :
  134. traverser = new NamespaceTraverser();
  135. break;
  136. case Axis.NAMESPACEDECLS :
  137. traverser = new NamespaceDeclsTraverser();
  138. break;
  139. case Axis.PARENT :
  140. traverser = new ParentTraverser();
  141. break;
  142. case Axis.PRECEDING :
  143. traverser = new PrecedingTraverser();
  144. break;
  145. case Axis.PRECEDINGSIBLING :
  146. traverser = new PrecedingSiblingTraverser();
  147. break;
  148. case Axis.SELF :
  149. traverser = new SelfTraverser();
  150. break;
  151. case Axis.ALL :
  152. traverser = new AllFromRootTraverser();
  153. break;
  154. case Axis.ALLFROMNODE :
  155. traverser = new AllFromNodeTraverser();
  156. break;
  157. case Axis.PRECEDINGANDANCESTOR :
  158. traverser = new PrecedingAndAncestorTraverser();
  159. break;
  160. case Axis.DESCENDANTSFROMROOT :
  161. traverser = new DescendantFromRootTraverser();
  162. break;
  163. case Axis.DESCENDANTSORSELFFROMROOT :
  164. traverser = new DescendantOrSelfFromRootTraverser();
  165. break;
  166. case Axis.ROOT :
  167. traverser = new RootTraverser();
  168. break;
  169. case Axis.FILTEREDLIST :
  170. return null; // Don't want to throw an exception for this one.
  171. default :
  172. throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_UNKNOWN_AXIS_TYPE, new Object[]{Integer.toString(axis)})); //"Unknown axis traversal type: "+axis);
  173. }
  174. if (null == traverser)
  175. throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_AXIS_TRAVERSER_NOT_SUPPORTED, new Object[]{Axis.names[axis]}));
  176. // "Axis traverser not supported: "
  177. // + Axis.names[axis]);
  178. m_traversers[axis] = traverser;
  179. return traverser;
  180. }
  181. /**
  182. * Implements traversal of the Ancestor access, in reverse document order.
  183. */
  184. private class AncestorTraverser extends DTMAxisTraverser
  185. {
  186. /**
  187. * Traverse to the next node after the current node.
  188. *
  189. * @param context The context node if this iteration.
  190. * @param current The current node of the iteration.
  191. *
  192. * @return the next node in the iteration, or DTM.NULL.
  193. */
  194. public int next(int context, int current)
  195. {
  196. return getParent(current);
  197. }
  198. /**
  199. * Traverse to the next node after the current node that is matched
  200. * by the expanded type ID.
  201. *
  202. * @param context The context node of this iteration.
  203. * @param current The current node of the iteration.
  204. * @param expandedTypeID The expanded type ID that must match.
  205. *
  206. * @return the next node in the iteration, or DTM.NULL.
  207. */
  208. public int next(int context, int current, int expandedTypeID)
  209. {
  210. // Process using identities
  211. current = makeNodeIdentity(current);
  212. while (DTM.NULL != (current = m_parent.elementAt(current)))
  213. {
  214. if (m_exptype.elementAt(current) == expandedTypeID)
  215. return makeNodeHandle(current);
  216. }
  217. return NULL;
  218. }
  219. }
  220. /**
  221. * Implements traversal of the Ancestor access, in reverse document order.
  222. */
  223. private class AncestorOrSelfTraverser extends AncestorTraverser
  224. {
  225. /**
  226. * By the nature of the stateless traversal, the context node can not be
  227. * returned or the iteration will go into an infinate loop. To see if
  228. * the self node should be processed, use this function.
  229. *
  230. * @param context The context node of this traversal.
  231. *
  232. * @return the first node in the traversal.
  233. */
  234. public int first(int context)
  235. {
  236. return context;
  237. }
  238. /**
  239. * By the nature of the stateless traversal, the context node can not be
  240. * returned or the iteration will go into an infinate loop. To see if
  241. * the self node should be processed, use this function. If the context
  242. * node does not match the expanded type ID, this function will return
  243. * false.
  244. *
  245. * @param context The context node of this traversal.
  246. * @param expandedTypeID The expanded type ID that must match.
  247. *
  248. * @return the first node in the traversal.
  249. */
  250. public int first(int context, int expandedTypeID)
  251. {
  252. return (getExpandedTypeID(context) == expandedTypeID)
  253. ? context : next(context, context, expandedTypeID);
  254. }
  255. }
  256. /**
  257. * Implements traversal of the Attribute access
  258. */
  259. private class AttributeTraverser extends DTMAxisTraverser
  260. {
  261. /**
  262. * Traverse to the next node after the current node.
  263. *
  264. * @param context The context node of this iteration.
  265. * @param current The current node of the iteration.
  266. *
  267. * @return the next node in the iteration, or DTM.NULL.
  268. */
  269. public int next(int context, int current)
  270. {
  271. return (context == current)
  272. ? getFirstAttribute(context) : getNextAttribute(current);
  273. }
  274. /**
  275. * Traverse to the next node after the current node that is matched
  276. * by the expanded type ID.
  277. *
  278. * @param context The context node of this iteration.
  279. * @param current The current node of the iteration.
  280. * @param expandedTypeID The expanded type ID that must match.
  281. *
  282. * @return the next node in the iteration, or DTM.NULL.
  283. */
  284. public int next(int context, int current, int expandedTypeID)
  285. {
  286. current = (context == current)
  287. ? getFirstAttribute(context) : getNextAttribute(current);
  288. do
  289. {
  290. if (getExpandedTypeID(current) == expandedTypeID)
  291. return current;
  292. }
  293. while (DTM.NULL != (current = getNextAttribute(current)));
  294. return NULL;
  295. }
  296. }
  297. /**
  298. * Implements traversal of the Ancestor access, in reverse document order.
  299. */
  300. private class ChildTraverser extends DTMAxisTraverser
  301. {
  302. /**
  303. * Get the next indexed node that matches the expanded type ID. Before
  304. * calling this function, one should first call
  305. * {@link #isIndexed(int) isIndexed} to make sure that the index can
  306. * contain nodes that match the given expanded type ID.
  307. *
  308. * @param axisRoot The root identity of the axis.
  309. * @param nextPotential The node found must match or occur after this node.
  310. * @param expandedTypeID The expanded type ID for the request.
  311. *
  312. * @return The node ID or NULL if not found.
  313. */
  314. protected int getNextIndexed(int axisRoot, int nextPotential,
  315. int expandedTypeID)
  316. {
  317. int nsIndex = m_expandedNameTable.getNamespaceID(expandedTypeID);
  318. int lnIndex = m_expandedNameTable.getLocalNameID(expandedTypeID);
  319. for (; ; )
  320. {
  321. int nextID = findElementFromIndex(nsIndex, lnIndex, nextPotential);
  322. if (NOTPROCESSED != nextID)
  323. {
  324. int parentID = m_parent.elementAt(nextID);
  325. // Is it a child?
  326. if(parentID == axisRoot)
  327. return nextID;
  328. // If the parent occured before the subtree root, then
  329. // we know it is past the child axis.
  330. if(parentID < axisRoot)
  331. return NULL;
  332. // Otherwise, it could be a descendant below the subtree root
  333. // children, or it could be after the subtree root. So we have
  334. // to climb up until the parent is less than the subtree root, in
  335. // which case we return NULL, or until it is equal to the subtree
  336. // root, in which case we continue to look.
  337. do
  338. {
  339. parentID = m_parent.elementAt(parentID);
  340. if(parentID < axisRoot)
  341. return NULL;
  342. }
  343. while(parentID > axisRoot);
  344. // System.out.println("Found node via index: "+first);
  345. nextPotential = nextID+1;
  346. continue;
  347. }
  348. nextNode();
  349. if(!(m_nextsib.elementAt(axisRoot) == NOTPROCESSED))
  350. break;
  351. }
  352. return DTM.NULL;
  353. }
  354. /**
  355. * By the nature of the stateless traversal, the context node can not be
  356. * returned or the iteration will go into an infinate loop. So to traverse
  357. * an axis, the first function must be used to get the first node.
  358. *
  359. * <p>This method needs to be overloaded only by those axis that process
  360. * the self node. <\p>
  361. *
  362. * @param context The context node of this traversal. This is the point
  363. * that the traversal starts from.
  364. * @return the first node in the traversal.
  365. */
  366. public int first(int context)
  367. {
  368. return getFirstChild(context);
  369. }
  370. /**
  371. * By the nature of the stateless traversal, the context node can not be
  372. * returned or the iteration will go into an infinate loop. So to traverse
  373. * an axis, the first function must be used to get the first node.
  374. *
  375. * <p>This method needs to be overloaded only by those axis that process
  376. * the self node. <\p>
  377. *
  378. * @param context The context node of this traversal. This is the point
  379. * of origin for the traversal -- its "root node" or starting point.
  380. * @param expandedTypeID The expanded type ID that must match.
  381. *
  382. * @return the first node in the traversal.
  383. */
  384. public int first(int context, int expandedTypeID)
  385. {
  386. if(true)
  387. {
  388. int identity = makeNodeIdentity(context);
  389. int firstMatch = getNextIndexed(identity, _firstch(identity),
  390. expandedTypeID);
  391. return makeNodeHandle(firstMatch);
  392. }
  393. else
  394. {
  395. // %REVIEW% Dead code. Eliminate?
  396. for (int current = _firstch(makeNodeIdentity(context));
  397. DTM.NULL != current;
  398. current = _nextsib(current))
  399. {
  400. if (m_exptype.elementAt(current) == expandedTypeID)
  401. return makeNodeHandle(current);
  402. }
  403. return NULL;
  404. }
  405. }
  406. /**
  407. * Traverse to the next node after the current node.
  408. *
  409. * @param context The context node of this iteration.
  410. * @param current The current node of the iteration.
  411. *
  412. * @return the next node in the iteration, or DTM.NULL.
  413. */
  414. public int next(int context, int current)
  415. {
  416. return getNextSibling(current);
  417. }
  418. /**
  419. * Traverse to the next node after the current node that is matched
  420. * by the expanded type ID.
  421. *
  422. * @param context The context node of this iteration.
  423. * @param current The current node of the iteration.
  424. * @param expandedTypeID The expanded type ID that must match.
  425. *
  426. * @return the next node in the iteration, or DTM.NULL.
  427. */
  428. public int next(int context, int current, int expandedTypeID)
  429. {
  430. // Process in Identifier space
  431. for (current = _nextsib(makeNodeIdentity(current));
  432. DTM.NULL != current;
  433. current = _nextsib(current))
  434. {
  435. if (m_exptype.elementAt(current) == expandedTypeID)
  436. return makeNodeHandle(current);
  437. }
  438. return NULL;
  439. }
  440. }
  441. /**
  442. * Super class for derived classes that want a convenient way to access
  443. * the indexing mechanism.
  444. */
  445. private abstract class IndexedDTMAxisTraverser extends DTMAxisTraverser
  446. {
  447. /**
  448. * Tell if the indexing is on and the given expanded type ID matches
  449. * what is in the indexes. Derived classes should call this before
  450. * calling {@link #getNextIndexed(int, int, int) getNextIndexed} method.
  451. *
  452. * @param expandedTypeID The expanded type ID being requested.
  453. *
  454. * @return true if it is OK to call the
  455. * {@link #getNextIndexed(int, int, int) getNextIndexed} method.
  456. */
  457. protected final boolean isIndexed(int expandedTypeID)
  458. {
  459. return (m_indexing
  460. && ExpandedNameTable.ELEMENT
  461. == m_expandedNameTable.getType(expandedTypeID));
  462. }
  463. /**
  464. * Tell if a node is outside the axis being traversed. This method must be
  465. * implemented by derived classes, and must be robust enough to handle any
  466. * node that occurs after the axis root.
  467. *
  468. * @param axisRoot The root identity of the axis.
  469. * @param identity The node in question.
  470. *
  471. * @return true if the given node falls outside the axis being traversed.
  472. */
  473. protected abstract boolean isAfterAxis(int axisRoot, int identity);
  474. /**
  475. * Tell if the axis has been fully processed to tell if a the wait for
  476. * an arriving node should terminate. This method must be implemented
  477. * be a derived class.
  478. *
  479. * @param axisRoot The root identity of the axis.
  480. *
  481. * @return true if the axis has been fully processed.
  482. */
  483. protected abstract boolean axisHasBeenProcessed(int axisRoot);
  484. /**
  485. * Get the next indexed node that matches the expanded type ID. Before
  486. * calling this function, one should first call
  487. * {@link #isIndexed(int) isIndexed} to make sure that the index can
  488. * contain nodes that match the given expanded type ID.
  489. *
  490. * @param axisRoot The root identity of the axis.
  491. * @param nextPotential The node found must match or occur after this node.
  492. * @param expandedTypeID The expanded type ID for the request.
  493. *
  494. * @return The node ID or NULL if not found.
  495. */
  496. protected int getNextIndexed(int axisRoot, int nextPotential,
  497. int expandedTypeID)
  498. {
  499. int nsIndex = m_expandedNameTable.getNamespaceID(expandedTypeID);
  500. int lnIndex = m_expandedNameTable.getLocalNameID(expandedTypeID);
  501. while(true)
  502. {
  503. int next = findElementFromIndex(nsIndex, lnIndex, nextPotential);
  504. if (NOTPROCESSED != next)
  505. {
  506. if (isAfterAxis(axisRoot, next))
  507. return NULL;
  508. // System.out.println("Found node via index: "+first);
  509. return next;
  510. }
  511. else if(axisHasBeenProcessed(axisRoot))
  512. break;
  513. nextNode();
  514. }
  515. return DTM.NULL;
  516. }
  517. }
  518. /**
  519. * Implements traversal of the Ancestor access, in reverse document order.
  520. */
  521. private class DescendantTraverser extends IndexedDTMAxisTraverser
  522. {
  523. /**
  524. * Get the first potential identity that can be returned. This should
  525. * be overridded by classes that need to return the self node.
  526. *
  527. * @param identity The node identity of the root context of the traversal.
  528. *
  529. * @return The first potential node that can be in the traversal.
  530. */
  531. protected int getFirstPotential(int identity)
  532. {
  533. return identity + 1;
  534. }
  535. /**
  536. * Tell if the axis has been fully processed to tell if a the wait for
  537. * an arriving node should terminate.
  538. *
  539. * @param axisRoot The root identity of the axis.
  540. *
  541. * @return true if the axis has been fully processed.
  542. */
  543. protected boolean axisHasBeenProcessed(int axisRoot)
  544. {
  545. return !(m_nextsib.elementAt(axisRoot) == NOTPROCESSED);
  546. }
  547. /**
  548. * Get the subtree root identity from the handle that was passed in by
  549. * the caller. Derived classes may override this to change the root
  550. * context of the traversal.
  551. *
  552. * @param handle handle to the root context.
  553. * @return identity of the root of the subtree.
  554. */
  555. protected int getSubtreeRoot(int handle)
  556. {
  557. return makeNodeIdentity(handle);
  558. }
  559. /**
  560. * Tell if this node identity is a descendant. Assumes that
  561. * the node info for the element has already been obtained.
  562. *
  563. * %REVIEW% This is really parentFollowsRootInDocumentOrder ...
  564. * which fails if the parent starts after the root ends.
  565. * May be sufficient for this class's logic, but misleadingly named!
  566. *
  567. * @param subtreeRootIdentity The root context of the subtree in question.
  568. * @param identity The index number of the node in question.
  569. * @return true if the index is a descendant of _startNode.
  570. */
  571. protected boolean isDescendant(int subtreeRootIdentity, int identity)
  572. {
  573. return _parent(identity) >= subtreeRootIdentity;
  574. }
  575. /**
  576. * Tell if a node is outside the axis being traversed. This method must be
  577. * implemented by derived classes, and must be robust enough to handle any
  578. * node that occurs after the axis root.
  579. *
  580. * @param axisRoot The root identity of the axis.
  581. * @param identity The node in question.
  582. *
  583. * @return true if the given node falls outside the axis being traversed.
  584. */
  585. protected boolean isAfterAxis(int axisRoot, int identity)
  586. {
  587. // %REVIEW% Is there *any* cheaper way to do this?
  588. // Yes. In ID space, compare to axisRoot's successor
  589. // (next-sib or ancestor's-next-sib). Probably shallower search.
  590. do
  591. {
  592. if(identity == axisRoot)
  593. return false;
  594. identity = m_parent.elementAt(identity);
  595. }
  596. while(identity >= axisRoot);
  597. return true;
  598. }
  599. /**
  600. * By the nature of the stateless traversal, the context node can not be
  601. * returned or the iteration will go into an infinate loop. So to traverse
  602. * an axis, the first function must be used to get the first node.
  603. *
  604. * <p>This method needs to be overloaded only by those axis that process
  605. * the self node. <\p>
  606. *
  607. * @param context The context node of this traversal. This is the point
  608. * of origin for the traversal -- its "root node" or starting point.
  609. * @param expandedTypeID The expanded type ID that must match.
  610. *
  611. * @return the first node in the traversal.
  612. */
  613. public int first(int context, int expandedTypeID)
  614. {
  615. if (isIndexed(expandedTypeID))
  616. {
  617. int identity = getSubtreeRoot(context);
  618. int firstPotential = getFirstPotential(identity);
  619. return makeNodeHandle(getNextIndexed(identity, firstPotential, expandedTypeID));
  620. }
  621. return next(context, context, expandedTypeID);
  622. }
  623. /**
  624. * Traverse to the next node after the current node.
  625. *
  626. * @param context The context node of this iteration.
  627. * @param current The current node of the iteration.
  628. *
  629. * @return the next node in the iteration, or DTM.NULL.
  630. */
  631. public int next(int context, int current)
  632. {
  633. int subtreeRootIdent = getSubtreeRoot(context);
  634. for (current = makeNodeIdentity(current) + 1; ; current++)
  635. {
  636. int type = _type(current); // may call nextNode()
  637. if (!isDescendant(subtreeRootIdent, current))
  638. return NULL;
  639. if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
  640. continue;
  641. return makeNodeHandle(current); // make handle.
  642. }
  643. }
  644. /**
  645. * Traverse to the next node after the current node that is matched
  646. * by the expanded type ID.
  647. *
  648. * @param context The context node of this iteration.
  649. * @param current The current node of the iteration.
  650. * @param expandedTypeID The expanded type ID that must match.
  651. *
  652. * @return the next node in the iteration, or DTM.NULL.
  653. */
  654. public int next(int context, int current, int expandedTypeID)
  655. {
  656. int subtreeRootIdent = getSubtreeRoot(context);
  657. current = makeNodeIdentity(current) + 1;
  658. if (isIndexed(expandedTypeID))
  659. {
  660. return makeNodeHandle(getNextIndexed(subtreeRootIdent, current, expandedTypeID));
  661. }
  662. for (; ; current++)
  663. {
  664. int exptype = _exptype(current); // may call nextNode()
  665. if (!isDescendant(subtreeRootIdent, current))
  666. return NULL;
  667. if (exptype != expandedTypeID)
  668. continue;
  669. return makeNodeHandle(current); // make handle.
  670. }
  671. }
  672. }
  673. /**
  674. * Implements traversal of the Ancestor access, in reverse document order.
  675. */
  676. private class DescendantOrSelfTraverser extends DescendantTraverser
  677. {
  678. /**
  679. * Get the first potential identity that can be returned, which is the
  680. * axis context, in this case.
  681. *
  682. * @param identity The node identity of the root context of the traversal.
  683. *
  684. * @return The axis context.
  685. */
  686. protected int getFirstPotential(int identity)
  687. {
  688. return identity;
  689. }
  690. /**
  691. * By the nature of the stateless traversal, the context node can not be
  692. * returned or the iteration will go into an infinate loop. To see if
  693. * the self node should be processed, use this function.
  694. *
  695. * @param context The context node of this traversal.
  696. *
  697. * @return the first node in the traversal.
  698. */
  699. public int first(int context)
  700. {
  701. return context;
  702. }
  703. }
  704. /**
  705. * Implements traversal of the entire subtree, including the root node.
  706. */
  707. private class AllFromNodeTraverser extends DescendantOrSelfTraverser
  708. {
  709. /**
  710. * Traverse to the next node after the current node.
  711. *
  712. * @param context The context node of this iteration.
  713. * @param current The current node of the iteration.
  714. *
  715. * @return the next node in the iteration, or DTM.NULL.
  716. */
  717. public int next(int context, int current)
  718. {
  719. int subtreeRootIdent = makeNodeIdentity(context);
  720. for (current = makeNodeIdentity(current) + 1; ; current++)
  721. {
  722. // Trickological code: _exptype() has the side-effect of
  723. // running nextNode until the specified node has been loaded,
  724. // and thus can be used to ensure that incremental construction of
  725. // the DTM has gotten this far. Using it just for that side-effect
  726. // is quite a kluge...
  727. _exptype(current); // make sure it's here.
  728. if (!isDescendant(subtreeRootIdent, current))
  729. return NULL;
  730. return makeNodeHandle(current); // make handle.
  731. }
  732. }
  733. }
  734. /**
  735. * Implements traversal of the following access, in document order.
  736. */
  737. private class FollowingTraverser extends DescendantTraverser
  738. {
  739. /**
  740. * Get the first of the following.
  741. *
  742. * @param context The context node of this traversal. This is the point
  743. * that the traversal starts from.
  744. * @return the first node in the traversal.
  745. */
  746. public int first(int context)
  747. {
  748. // Compute in ID space
  749. context=makeNodeIdentity(context);
  750. int first;
  751. int type = _type(context);
  752. if ((DTM.ATTRIBUTE_NODE == type) || (DTM.NAMESPACE_NODE == type))
  753. {
  754. context = _parent(context);
  755. first = _firstch(context);
  756. if (NULL != first)
  757. return makeNodeHandle(first);
  758. }
  759. do
  760. {
  761. first = _nextsib(context);
  762. if (NULL == first)
  763. context = _parent(context);
  764. }
  765. while (NULL == first && NULL != context);
  766. return makeNodeHandle(first);
  767. }
  768. /**
  769. * Get the first of the following.
  770. *
  771. * @param context The context node of this traversal. This is the point
  772. * of origin for the traversal -- its "root node" or starting point.
  773. * @param expandedTypeID The expanded type ID that must match.
  774. *
  775. * @return the first node in the traversal.
  776. */
  777. public int first(int context, int expandedTypeID)
  778. {
  779. // %REVIEW% This looks like it might want shift into identity space
  780. // to avoid repeated conversion in the individual functions
  781. int first;
  782. int type = getNodeType(context);
  783. if ((DTM.ATTRIBUTE_NODE == type) || (DTM.NAMESPACE_NODE == type))
  784. {
  785. context = getParent(context);
  786. first = getFirstChild(context);
  787. if (NULL != first)
  788. {
  789. if (getExpandedTypeID(first) == expandedTypeID)
  790. return first;
  791. else
  792. return next(context, first, expandedTypeID);
  793. }
  794. }
  795. do
  796. {
  797. first = getNextSibling(context);
  798. if (NULL == first)
  799. context = getParent(context);
  800. else
  801. {
  802. if (getExpandedTypeID(first) == expandedTypeID)
  803. return first;
  804. else
  805. return next(context, first, expandedTypeID);
  806. }
  807. }
  808. while (NULL == first && NULL != context);
  809. return first;
  810. }
  811. /**
  812. * Traverse to the next node after the current node.
  813. *
  814. * @param context The context node of this iteration.
  815. * @param current The current node of the iteration.
  816. *
  817. * @return the next node in the iteration, or DTM.NULL.
  818. */
  819. public int next(int context, int current)
  820. {
  821. // Compute in identity space
  822. current=makeNodeIdentity(current);
  823. while (true)
  824. {
  825. current++; // Only works on IDs, not handles.
  826. // %REVIEW% Are we using handles or indexes?
  827. int type = _type(current); // may call nextNode()
  828. if (NULL == type)
  829. return NULL;
  830. if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
  831. continue;
  832. return makeNodeHandle(current); // make handle.
  833. }
  834. }
  835. /**
  836. * Traverse to the next node after the current node that is matched
  837. * by the expanded type ID.
  838. *
  839. * @param context The context node of this iteration.
  840. * @param current The current node of the iteration.
  841. * @param expandedTypeID The expanded type ID that must match.
  842. *
  843. * @return the next node in the iteration, or DTM.NULL.
  844. */
  845. public int next(int context, int current, int expandedTypeID)
  846. {
  847. // Compute in ID space
  848. current=makeNodeIdentity(current);
  849. while (true)
  850. {
  851. current++;
  852. int etype = _exptype(current); // may call nextNode()
  853. if (NULL == etype)
  854. return NULL;
  855. if (etype != expandedTypeID)
  856. continue;
  857. return makeNodeHandle(current); // make handle.
  858. }
  859. }
  860. }
  861. /**
  862. * Implements traversal of the Ancestor access, in reverse document order.
  863. */
  864. private class FollowingSiblingTraverser extends DTMAxisTraverser
  865. {
  866. /**
  867. * Traverse to the next node after the current node.
  868. *
  869. * @param context The context node of this iteration.
  870. * @param current The current node of the iteration.
  871. *
  872. * @return the next node in the iteration, or DTM.NULL.
  873. */
  874. public int next(int context, int current)
  875. {
  876. return getNextSibling(current);
  877. }
  878. /**
  879. * Traverse to the next node after the current node that is matched
  880. * by the expanded type ID.
  881. *
  882. * @param context The context node of this iteration.
  883. * @param current The current node of the iteration.
  884. * @param expandedTypeID The expanded type ID that must match.
  885. *
  886. * @return the next node in the iteration, or DTM.NULL.
  887. */
  888. public int next(int context, int current, int expandedTypeID)
  889. {
  890. while (DTM.NULL != (current = getNextSibling(current)))
  891. {
  892. if (getExpandedTypeID(current) == expandedTypeID)
  893. return current;
  894. }
  895. return NULL;
  896. }
  897. }
  898. /**
  899. * Implements traversal of the Ancestor access, in reverse document order.
  900. */
  901. private class NamespaceDeclsTraverser extends DTMAxisTraverser
  902. {
  903. /**
  904. * Traverse to the next node after the current node.
  905. *
  906. * @param context The context node of this iteration.
  907. * @param current The current node of the iteration.
  908. *
  909. * @return the next node in the iteration, or DTM.NULL.
  910. */
  911. public int next(int context, int current)
  912. {
  913. return (context == current)
  914. ? getFirstNamespaceNode(context, false)
  915. : getNextNamespaceNode(context, current, false);
  916. }
  917. /**
  918. * Traverse to the next node after the current node that is matched
  919. * by the expanded type ID.
  920. *
  921. * @param context The context node of this iteration.
  922. * @param current The current node of the iteration.
  923. * @param expandedTypeID The expanded type ID that must match.
  924. *
  925. * @return the next node in the iteration, or DTM.NULL.
  926. */
  927. public int next(int context, int current, int expandedTypeID)
  928. {
  929. current = (context == current)
  930. ? getFirstNamespaceNode(context, false)
  931. : getNextNamespaceNode(context, current, false);
  932. do
  933. {
  934. if (getExpandedTypeID(current) == expandedTypeID)
  935. return current;
  936. }
  937. while (DTM.NULL
  938. != (current = getNextNamespaceNode(context, current, false)));
  939. return NULL;
  940. }
  941. }
  942. /**
  943. * Implements traversal of the Ancestor access, in reverse document order.
  944. */
  945. private class NamespaceTraverser extends DTMAxisTraverser
  946. {
  947. /**
  948. * Traverse to the next node after the current node.
  949. *
  950. * @param context The context node of this iteration.
  951. * @param current The current node of the iteration.
  952. *
  953. * @return the next node in the iteration, or DTM.NULL.
  954. */
  955. public int next(int context, int current)
  956. {
  957. return (context == current)
  958. ? getFirstNamespaceNode(context, true)
  959. : getNextNamespaceNode(context, current, true);
  960. }
  961. /**
  962. * Traverse to the next node after the current node that is matched
  963. * by the expanded type ID.
  964. *
  965. * @param context The context node of this iteration.
  966. * @param current The current node of the iteration.
  967. * @param expandedTypeID The expanded type ID that must match.
  968. *
  969. * @return the next node in the iteration, or DTM.NULL.
  970. */
  971. public int next(int context, int current, int expandedTypeID)
  972. {
  973. current = (context == current)
  974. ? getFirstNamespaceNode(context, true)
  975. : getNextNamespaceNode(context, current, true);
  976. do
  977. {
  978. if (getExpandedTypeID(current) == expandedTypeID)
  979. return current;
  980. }
  981. while (DTM.NULL
  982. != (current = getNextNamespaceNode(context, current, true)));
  983. return NULL;
  984. }
  985. }
  986. /**
  987. * Implements traversal of the Ancestor access, in reverse document order.
  988. */
  989. private class ParentTraverser extends DTMAxisTraverser
  990. {
  991. /**
  992. * By the nature of the stateless traversal, the context node can not be
  993. * returned or the iteration will go into an infinate loop. So to traverse
  994. * an axis, the first function must be used to get the first node.
  995. *
  996. * <p>This method needs to be overloaded only by those axis that process
  997. * the self node. <\p>
  998. *
  999. * @param context The context node of this traversal. This is the point
  1000. * that the traversal starts from.
  1001. * @return the first node in the traversal.
  1002. */
  1003. public int first(int context)
  1004. {
  1005. return getParent(context);
  1006. }
  1007. /**
  1008. * By the nature of the stateless traversal, the context node can not be
  1009. * returned or the iteration will go into an infinate loop. So to traverse
  1010. * an axis, the first function must be used to get the first node.
  1011. *
  1012. * <p>This method needs to be overloaded only by those axis that process
  1013. * the self node. <\p>
  1014. *
  1015. * @param context The context node of this traversal. This is the point
  1016. * of origin for the traversal -- its "root node" or starting point.
  1017. * @param expandedTypeID The expanded type ID that must match.
  1018. *
  1019. * @return the first node in the traversal.
  1020. */
  1021. public int first(int current, int expandedTypeID)
  1022. {
  1023. // Compute in ID space
  1024. current = makeNodeIdentity(current);
  1025. while (NULL != (current = m_parent.elementAt(current)))
  1026. {
  1027. if (m_exptype.elementAt(current) == expandedTypeID)
  1028. return makeNodeHandle(current);
  1029. }
  1030. return NULL;
  1031. }
  1032. /**
  1033. * Traverse to the next node after the current node.
  1034. *
  1035. * @param context The context node of this iteration.
  1036. * @param current The current node of the iteration.
  1037. *
  1038. * @return the next node in the iteration, or DTM.NULL.
  1039. */
  1040. public int next(int context, int current)
  1041. {
  1042. return NULL;
  1043. }
  1044. /**
  1045. * Traverse to the next node after the current node that is matched
  1046. * by the expanded type ID.
  1047. *
  1048. * @param context The context node of this iteration.
  1049. * @param current The current node of the iteration.
  1050. * @param expandedTypeID The expanded type ID that must match.
  1051. *
  1052. * @return the next node in the iteration, or DTM.NULL.
  1053. */
  1054. public int next(int context, int current, int expandedTypeID)
  1055. {
  1056. return NULL;
  1057. }
  1058. }
  1059. /**
  1060. * Implements traversal of the Ancestor access, in reverse document order.
  1061. */
  1062. private class PrecedingTraverser extends DTMAxisTraverser
  1063. {
  1064. /**
  1065. * Tell if the current identity is an ancestor of the context identity.
  1066. * This is an expensive operation, made worse by the stateless traversal.
  1067. * But the preceding axis is used fairly infrequently.
  1068. *
  1069. * @param contextIdent The context node of the axis traversal.
  1070. * @param currentIdent The node in question.
  1071. * @return true if the currentIdent node is an ancestor of contextIdent.
  1072. */
  1073. protected boolean isAncestor(int contextIdent, int currentIdent)
  1074. {
  1075. // %REVIEW% See comments in IsAfterAxis; using the "successor" of
  1076. // contextIdent is probably more efficient.
  1077. for (contextIdent = m_parent.elementAt(contextIdent); DTM.NULL != contextIdent;
  1078. contextIdent = m_parent.elementAt(contextIdent))
  1079. {
  1080. if (contextIdent == currentIdent)
  1081. return true;
  1082. }
  1083. return false;
  1084. }
  1085. /**
  1086. * Traverse to the next node after the current node.
  1087. *
  1088. * @param context The context node of this iteration.
  1089. * @param current The current node of the iteration.
  1090. *
  1091. * @return the next node in the iteration, or DTM.NULL.
  1092. */
  1093. public int next(int context, int current)
  1094. {
  1095. // compute in ID space
  1096. int subtreeRootIdent = makeNodeIdentity(context);
  1097. for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
  1098. {
  1099. short type = _type(current);
  1100. if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type
  1101. || isAncestor(subtreeRootIdent, current))
  1102. continue;
  1103. return makeNodeHandle(current); // make handle.
  1104. }
  1105. return NULL;
  1106. }
  1107. /**
  1108. * Traverse to the next node after the current node that is matched
  1109. * by the expanded type ID.
  1110. *
  1111. * @param context The context node of this iteration.
  1112. * @param current The current node of the iteration.
  1113. * @param expandedTypeID The expanded type ID that must match.
  1114. *
  1115. * @return the next node in the iteration, or DTM.NULL.
  1116. */
  1117. public int next(int context, int current, int expandedTypeID)
  1118. {
  1119. // Compute in ID space
  1120. int subtreeRootIdent = makeNodeIdentity(context);
  1121. for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
  1122. {
  1123. int exptype = m_exptype.elementAt(current);
  1124. if (exptype != expandedTypeID
  1125. || isAncestor(subtreeRootIdent, current))
  1126. continue;
  1127. return makeNodeHandle(current); // make handle.
  1128. }
  1129. return NULL;
  1130. }
  1131. }
  1132. /**
  1133. * Implements traversal of the Ancestor and the Preceding axis,
  1134. * in reverse document order.
  1135. */
  1136. private class PrecedingAndAncestorTraverser extends DTMAxisTraverser
  1137. {
  1138. /**
  1139. * Traverse to the next node after the current node.
  1140. *
  1141. * @param context The context node of this iteration.
  1142. * @param current The current node of the iteration.
  1143. *
  1144. * @return the next node in the iteration, or DTM.NULL.
  1145. */
  1146. public int next(int context, int current)
  1147. {
  1148. // Compute in ID space
  1149. int subtreeRootIdent = makeNodeIdentity(context );
  1150. for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
  1151. {
  1152. short type = _type(current);
  1153. if (ATTRIBUTE_NODE == type || NAMESPACE_NODE == type)
  1154. continue;
  1155. return makeNodeHandle(current); // make handle.
  1156. }
  1157. return NULL;
  1158. }
  1159. /**
  1160. * Traverse to the next node after the current node that is matched
  1161. * by the expanded type ID.
  1162. *
  1163. * @param context The context node of this iteration.
  1164. * @param current The current node of the iteration.
  1165. * @param expandedTypeID The expanded type ID that must match.
  1166. *
  1167. * @return the next node in the iteration, or DTM.NULL.
  1168. */
  1169. public int next(int context, int current, int expandedTypeID)
  1170. {
  1171. // Compute in ID space
  1172. int subtreeRootIdent = makeNodeIdentity(context);
  1173. for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
  1174. {
  1175. int exptype = m_exptype.elementAt(current);
  1176. if (exptype != expandedTypeID)
  1177. continue;
  1178. return makeNodeHandle(current); // make handle.
  1179. }
  1180. return NULL;
  1181. }
  1182. }
  1183. /**
  1184. * Implements traversal of the Ancestor access, in reverse document order.
  1185. */
  1186. private class PrecedingSiblingTraverser extends DTMAxisTraverser
  1187. {
  1188. /**
  1189. * Traverse to the next node after the current node.
  1190. *
  1191. * @param context The context node of this iteration.
  1192. * @param current The current node of the iteration.
  1193. *
  1194. * @return the next node in the iteration, or DTM.NULL.
  1195. */
  1196. public int next(int context, int current)
  1197. {
  1198. return getPreviousSibling(current);
  1199. }
  1200. /**
  1201. * Traverse to the next node after the current node that is matched
  1202. * by the expanded type ID.
  1203. *
  1204. * @param context The context node of this iteration.
  1205. * @param current The current node of the iteration.
  1206. * @param expandedTypeID The expanded type ID that must match.
  1207. *
  1208. * @return the next node in the iteration, or DTM.NULL.
  1209. */
  1210. public int next(int context, int current, int expandedTypeID)
  1211. {
  1212. while (DTM.NULL != (current = getPreviousSibling(current)))
  1213. {
  1214. if (getExpandedTypeID(current) == expandedTypeID)
  1215. return current;
  1216. }
  1217. return NULL;
  1218. }
  1219. }
  1220. /**
  1221. * Implements traversal of the Self axis.
  1222. */
  1223. private class SelfTraverser extends DTMAxisTraverser
  1224. {
  1225. /**
  1226. * By the nature of the stateless traversal, the context node can not be
  1227. * returned or the iteration will go into an infinate loop. To see if
  1228. * the self node should be processed, use this function.
  1229. *
  1230. * @param context The context node of this traversal.
  1231. *
  1232. * @return the first node in the traversal.
  1233. */
  1234. public int first(int context)
  1235. {
  1236. return context;
  1237. }
  1238. /**
  1239. * By the nature of the stateless traversal, the context node can not be
  1240. * returned or the iteration will go into an infinate loop. To see if
  1241. * the self node should be processed, use this function. If the context
  1242. * node does not match the expanded type ID, this function will return
  1243. * false.
  1244. *
  1245. * @param context The context node of this traversal.
  1246. * @param expandedTypeID The expanded type ID that must match.
  1247. *
  1248. * @return the first node in the traversal.
  1249. */
  1250. public int first(int context, int expandedTypeID)
  1251. {
  1252. return (getExpandedTypeID(context) == expandedTypeID) ? context : NULL;
  1253. }
  1254. /**
  1255. * Traverse to the next node after the current node.
  1256. *
  1257. * @param context The context node of this iteration.
  1258. * @param current The current node of the iteration.
  1259. *
  1260. * @return Always return NULL for this axis.
  1261. */
  1262. public int next(int context, int current)
  1263. {
  1264. return NULL;
  1265. }
  1266. /**
  1267. * Traverse to the next node after the current node that is matched
  1268. * by the expanded type ID.
  1269. *
  1270. * @param context The context node of this iteration.
  1271. * @param current The current node of the iteration.
  1272. * @param expandedTypeID The expanded type ID that must match.
  1273. *
  1274. * @return the next node in the iteration, or DTM.NULL.
  1275. */
  1276. public int next(int context, int current, int expandedTypeID)
  1277. {
  1278. return NULL;
  1279. }
  1280. }
  1281. /**
  1282. * Implements traversal of the Ancestor access, in reverse document order.
  1283. */
  1284. private class AllFromRootTraverser extends AllFromNodeTraverser
  1285. {
  1286. /**
  1287. * Return the root.
  1288. *
  1289. * @param context The context node of this traversal.
  1290. *
  1291. * @return the first node in the traversal.
  1292. */
  1293. public int first(int context)
  1294. {
  1295. return getDocumentRoot(context);
  1296. }
  1297. /**
  1298. * Return the root if it matches the expanded type ID.
  1299. *
  1300. * @param context The context node of this traversal.
  1301. * @param expandedTypeID The expanded type ID that must match.
  1302. *
  1303. * @return the first node in the traversal.
  1304. */
  1305. public int first(int context, int expandedTypeID)
  1306. {
  1307. return (getExpandedTypeID(getDocumentRoot(context)) == expandedTypeID)
  1308. ? context : next(context, context, expandedTypeID);
  1309. }
  1310. /**
  1311. * Traverse to the next node after the current node.
  1312. *
  1313. * @param context The context node of this iteration.
  1314. * @param current The current node of the iteration.
  1315. *
  1316. * @return the next node in the iteration, or DTM.NULL.
  1317. */
  1318. public int next(int context, int current)
  1319. {
  1320. // Compute in ID space
  1321. int subtreeRootIdent = makeNodeIdentity(context);
  1322. for (current = makeNodeIdentity(current) + 1; ; current++)
  1323. {
  1324. // Kluge test: Just make sure +1 yielded a real node
  1325. int type = _type(current); // may call nextNode()
  1326. if (type == NULL)
  1327. return NULL;
  1328. return makeNodeHandle(current); // make handle.
  1329. }
  1330. }
  1331. /**
  1332. * Traverse to the next node after the current node that is matched
  1333. * by the expanded type ID.
  1334. *
  1335. * @param context The context node of this iteration.
  1336. * @param current The current node of the iteration.
  1337. * @param expandedTypeID The expanded type ID that must match.
  1338. *
  1339. * @return the next node in the iteration, or DTM.NULL.
  1340. */
  1341. public int next(int context, int current, int expandedTypeID)
  1342. {
  1343. // Compute in ID space
  1344. int subtreeRootIdent = makeNodeIdentity(context);
  1345. for (current = makeNodeIdentity(current) + 1; ; current++)
  1346. {
  1347. int exptype = _exptype(current); // may call nextNode()
  1348. if (exptype == NULL)
  1349. return NULL;
  1350. if (exptype != expandedTypeID)
  1351. continue;
  1352. return makeNodeHandle(current); // make handle.
  1353. }
  1354. }
  1355. }
  1356. /**
  1357. * Implements traversal of the Self axis.
  1358. */
  1359. private class RootTraverser extends AllFromRootTraverser
  1360. {
  1361. /**
  1362. * Return the root if it matches the expanded type ID,
  1363. * else return null (nothing found)
  1364. *
  1365. * @param context The context node of this traversal.
  1366. * @param expandedTypeID The expanded type ID that must match.
  1367. *
  1368. * @return the first node in the traversal.
  1369. */
  1370. public int first(int context, int expandedTypeID)
  1371. {
  1372. int root=getDocumentRoot(context);
  1373. return (getExpandedTypeID(root) == expandedTypeID)
  1374. ? root : NULL;
  1375. }
  1376. /**
  1377. * Traverse to the next node after the current node.
  1378. *
  1379. * @param context The context node of this iteration.
  1380. * @param current The current node of the iteration.
  1381. *
  1382. * @return Always return NULL for this axis.
  1383. */
  1384. public int next(int context, int current)
  1385. {
  1386. return NULL;
  1387. }
  1388. /**
  1389. * Traverse to the next node after the current node that is matched
  1390. * by the expanded type ID.
  1391. *
  1392. * @param context The context node of this iteration.
  1393. * @param current The current node of the iteration.
  1394. * @param expandedTypeID The expanded type ID that must match.
  1395. *
  1396. * @return the next node in the iteration, or DTM.NULL.
  1397. */
  1398. public int next(int context, int current, int expandedTypeID)
  1399. {
  1400. return NULL;
  1401. }
  1402. }
  1403. /**
  1404. * A non-xpath axis, returns all nodes that aren't namespaces or attributes,
  1405. * from and including the root.
  1406. */
  1407. private class DescendantOrSelfFromRootTraverser extends DescendantTraverser
  1408. {
  1409. /**
  1410. * Get the first potential identity that can be returned, which is the axis
  1411. * root context in this case.
  1412. *
  1413. * @param identity The node identity of the root context of the traversal.
  1414. *
  1415. * @return The identity argument.
  1416. */
  1417. protected int getFirstPotential(int identity)
  1418. {
  1419. return identity;
  1420. }
  1421. /**
  1422. * Get the first potential identity that can be returned.
  1423. * @param handle handle to the root context.
  1424. * @return identity of the root of the subtree.
  1425. */
  1426. protected int getSubtreeRoot(int handle)
  1427. {
  1428. // %REVIEW% Shouldn't this always be 0?
  1429. return makeNodeIdentity(getDocument());
  1430. }
  1431. /**
  1432. * Return the root.
  1433. *
  1434. * @param context The context node of this traversal.
  1435. *
  1436. * @return the first node in the traversal.
  1437. */
  1438. public int first(int context)
  1439. {
  1440. return getDocumentRoot(context);
  1441. }
  1442. /**
  1443. * By the nature of the stateless traversal, the context node can not be
  1444. * returned or the iteration will go into an infinate loop. So to traverse
  1445. * an axis, the first function must be used to get the first node.
  1446. *
  1447. * <p>This method needs to be overloaded only by those axis that process
  1448. * the self node. <\p>
  1449. *
  1450. * @param context The context node of this traversal. This is the point
  1451. * of origin for the traversal -- its "root node" or starting point.
  1452. * @param expandedTypeID The expanded type ID that must match.
  1453. *
  1454. * @return the first node in the traversal.
  1455. */
  1456. public int first(int context, int expandedTypeID)
  1457. {
  1458. if (isIndexed(expandedTypeID))
  1459. {
  1460. int identity = 0;
  1461. int firstPotential = getFirstPotential(identity);
  1462. return makeNodeHandle(getNextIndexed(identity, firstPotential, expandedTypeID));
  1463. }
  1464. int root = first(context);
  1465. return next(root, root, expandedTypeID);
  1466. }
  1467. }
  1468. /**
  1469. * A non-xpath axis, returns all nodes that aren't namespaces or attributes,
  1470. * from but not including the root.
  1471. */
  1472. private class DescendantFromRootTraverser extends DescendantTraverser
  1473. {
  1474. /**
  1475. * Get the first potential identity that can be returned, which is the axis
  1476. * root context in this case.
  1477. *
  1478. * @param identity The node identity of the root context of the traversal.
  1479. *
  1480. * @return The identity argument.
  1481. */
  1482. protected int getFirstPotential(int identity)
  1483. {
  1484. return _firstch(0);
  1485. }
  1486. /**
  1487. * Get the first potential identity that can be returned.
  1488. * @param handle handle to the root context.
  1489. * @return identity of the root of the subtree.
  1490. */
  1491. protected int getSubtreeRoot(int handle)
  1492. {
  1493. return 0;
  1494. }
  1495. /**
  1496. * Return the root.
  1497. *
  1498. * @param context The context node of this traversal.
  1499. *
  1500. * @return the first node in the traversal.
  1501. */
  1502. public int first(int context)
  1503. {
  1504. return makeNodeHandle(_firstch(0));
  1505. }
  1506. /**
  1507. * By the nature of the stateless traversal, the context node can not be
  1508. * returned or the iteration will go into an infinate loop. So to traverse
  1509. * an axis, the first function must be used to get the first node.
  1510. *
  1511. * <p>This method needs to be overloaded only by those axis that process
  1512. * the self node. <\p>
  1513. *
  1514. * @param context The context node of this traversal. This is the point
  1515. * of origin for the traversal -- its "root node" or starting point.
  1516. * @param expandedTypeID The expanded type ID that must match.
  1517. *
  1518. * @return the first node in the traversal.
  1519. */
  1520. public int first(int context, int expandedTypeID)
  1521. {
  1522. if (isIndexed(expandedTypeID))
  1523. {
  1524. int identity = 0;
  1525. int firstPotential = getFirstPotential(identity);
  1526. return makeNodeHandle(getNextIndexed(identity, firstPotential, expandedTypeID));
  1527. }
  1528. int root = getDocumentRoot(context);
  1529. return next(root, root, expandedTypeID);
  1530. }
  1531. }
  1532. }