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: DTMDefaultBase.java,v 1.39 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 com.sun.org.apache.xml.internal.utils.SuballocatedIntVector;
  22. import com.sun.org.apache.xml.internal.utils.BoolStack;
  23. import java.util.Vector;
  24. import javax.xml.transform.Source;
  25. import com.sun.org.apache.xml.internal.utils.XMLString;
  26. import com.sun.org.apache.xml.internal.utils.XMLStringFactory;
  27. import com.sun.org.apache.xml.internal.res.XMLMessages;
  28. import com.sun.org.apache.xml.internal.res.XMLErrorResources;
  29. import java.io.*; // for dumpDTM
  30. /**
  31. * The <code>DTMDefaultBase</code> class serves as a helper base for DTMs.
  32. * It sets up structures for navigation and type, while leaving data
  33. * management and construction to the derived classes.
  34. */
  35. public abstract class DTMDefaultBase implements DTM
  36. {
  37. static boolean JJK_DEBUG=false;
  38. // This constant is likely to be removed in the future. Use the
  39. // getDocument() method instead of ROOTNODE to get at the root
  40. // node of a DTM.
  41. /** The identity of the root node. */
  42. public static final int ROOTNODE = 0;
  43. /**
  44. * The number of nodes, which is also used to determine the next
  45. * node index.
  46. */
  47. protected int m_size = 0;
  48. /** The expanded names, one array element for each node. */
  49. protected SuballocatedIntVector m_exptype;
  50. /** First child values, one array element for each node. */
  51. protected SuballocatedIntVector m_firstch;
  52. /** Next sibling values, one array element for each node. */
  53. protected SuballocatedIntVector m_nextsib;
  54. /** Previous sibling values, one array element for each node. */
  55. protected SuballocatedIntVector m_prevsib;
  56. /** Previous sibling values, one array element for each node. */
  57. protected SuballocatedIntVector m_parent;
  58. /** Vector of SuballocatedIntVectors of NS decl sets */
  59. protected Vector m_namespaceDeclSets = null;
  60. /** SuballocatedIntVector of elements at which corresponding
  61. * namespaceDeclSets were defined */
  62. protected SuballocatedIntVector m_namespaceDeclSetElements = null;
  63. /**
  64. * These hold indexes to elements based on namespace and local name.
  65. * The base lookup is the the namespace. The second lookup is the local
  66. * name, and the last array contains the the first free element
  67. * at the start, and the list of element handles following.
  68. */
  69. protected int[][][] m_elemIndexes;
  70. /** The default block size of the node arrays */
  71. public static final int DEFAULT_BLOCKSIZE = 512; // favor small docs.
  72. /** The number of blocks for the node arrays */
  73. public static final int DEFAULT_NUMBLOCKS = 32;
  74. /** The number of blocks used for small documents & RTFs */
  75. public static final int DEFAULT_NUMBLOCKS_SMALL = 4;
  76. /** The block size of the node arrays */
  77. //protected final int m_blocksize;
  78. /**
  79. * The value to use when the information has not been built yet.
  80. */
  81. protected static final int NOTPROCESSED = DTM.NULL - 1;
  82. /**
  83. * The DTM manager who "owns" this DTM.
  84. */
  85. public DTMManager m_mgr;
  86. /**
  87. * m_mgr cast to DTMManagerDefault, or null if it isn't an instance
  88. * (Efficiency hook)
  89. */
  90. protected DTMManagerDefault m_mgrDefault=null;
  91. /** The document identity number(s). If we have overflowed the addressing
  92. * range of the first that was assigned to us, we may add others. */
  93. protected SuballocatedIntVector m_dtmIdent;
  94. /** The mask for the identity.
  95. %REVIEW% Should this really be set to the _DEFAULT? What if
  96. a particular DTM wanted to use another value? */
  97. //protected final static int m_mask = DTMManager.IDENT_NODE_DEFAULT;
  98. /** The base URI for this document. */
  99. protected String m_documentBaseURI;
  100. /**
  101. * The whitespace filter that enables elements to strip whitespace or not.
  102. */
  103. protected DTMWSFilter m_wsfilter;
  104. /** Flag indicating whether to strip whitespace nodes */
  105. protected boolean m_shouldStripWS = false;
  106. /** Stack of flags indicating whether to strip whitespace nodes */
  107. protected BoolStack m_shouldStripWhitespaceStack;
  108. /** The XMLString factory for creating XMLStrings. */
  109. protected XMLStringFactory m_xstrf;
  110. /**
  111. * The table for exandedNameID lookups. This may or may not be the same
  112. * table as is contained in the DTMManagerDefault.
  113. */
  114. protected ExpandedNameTable m_expandedNameTable;
  115. /** true if indexing is turned on. */
  116. protected boolean m_indexing;
  117. /**
  118. * Construct a DTMDefaultBase object using the default block size.
  119. *
  120. * @param mgr The DTMManager who owns this DTM.
  121. * @param domSource the DOM source that this DTM will wrap.
  122. * @param source The object that is used to specify the construction source.
  123. * @param dtmIdentity The DTM identity ID for this DTM.
  124. * @param whiteSpaceFilter The white space filter for this DTM, which may
  125. * be null.
  126. * @param xstringfactory The factory to use for creating XMLStrings.
  127. * @param doIndexing true if the caller considers it worth it to use
  128. * indexing schemes.
  129. */
  130. public DTMDefaultBase(DTMManager mgr, Source source, int dtmIdentity,
  131. DTMWSFilter whiteSpaceFilter,
  132. XMLStringFactory xstringfactory, boolean doIndexing)
  133. {
  134. this(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory,
  135. doIndexing, DEFAULT_BLOCKSIZE, true, false);
  136. }
  137. /**
  138. * Construct a DTMDefaultBase object from a DOM node.
  139. *
  140. * @param mgr The DTMManager who owns this DTM.
  141. * @param domSource the DOM source that this DTM will wrap.
  142. * @param source The object that is used to specify the construction source.
  143. * @param dtmIdentity The DTM identity ID for this DTM.
  144. * @param whiteSpaceFilter The white space filter for this DTM, which may
  145. * be null.
  146. * @param xstringfactory The factory to use for creating XMLStrings.
  147. * @param doIndexing true if the caller considers it worth it to use
  148. * indexing schemes.
  149. * @param blocksize The block size of the DTM.
  150. * @param usePrevsib true if we want to build the previous sibling node array.
  151. * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
  152. */
  153. public DTMDefaultBase(DTMManager mgr, Source source, int dtmIdentity,
  154. DTMWSFilter whiteSpaceFilter,
  155. XMLStringFactory xstringfactory, boolean doIndexing,
  156. int blocksize, boolean usePrevsib,
  157. boolean newNameTable)
  158. {
  159. // Use smaller sizes for the internal node arrays if the block size
  160. // is small.
  161. int numblocks;
  162. if (blocksize <= 64)
  163. {
  164. numblocks = DEFAULT_NUMBLOCKS_SMALL;
  165. m_dtmIdent= new SuballocatedIntVector(4, 1);
  166. }
  167. else
  168. {
  169. numblocks = DEFAULT_NUMBLOCKS;
  170. m_dtmIdent= new SuballocatedIntVector(32);
  171. }
  172. m_exptype = new SuballocatedIntVector(blocksize, numblocks);
  173. m_firstch = new SuballocatedIntVector(blocksize, numblocks);
  174. m_nextsib = new SuballocatedIntVector(blocksize, numblocks);
  175. m_parent = new SuballocatedIntVector(blocksize, numblocks);
  176. // Only create the m_prevsib array if the usePrevsib flag is true.
  177. // Some DTM implementations (e.g. SAXImpl) do not need this array.
  178. // We can save the time to build it in those cases.
  179. if (usePrevsib)
  180. m_prevsib = new SuballocatedIntVector(blocksize, numblocks);
  181. m_mgr = mgr;
  182. if(mgr instanceof DTMManagerDefault)
  183. m_mgrDefault=(DTMManagerDefault)mgr;
  184. m_documentBaseURI = (null != source) ? source.getSystemId() : null;
  185. m_dtmIdent.setElementAt(dtmIdentity,0);
  186. m_wsfilter = whiteSpaceFilter;
  187. m_xstrf = xstringfactory;
  188. m_indexing = doIndexing;
  189. if (doIndexing)
  190. {
  191. m_expandedNameTable = new ExpandedNameTable();
  192. }
  193. else
  194. {
  195. // Note that this fails if we aren't talking to an instance of
  196. // DTMManagerDefault
  197. m_expandedNameTable = m_mgrDefault.getExpandedNameTable(this);
  198. }
  199. if (null != whiteSpaceFilter)
  200. {
  201. m_shouldStripWhitespaceStack = new BoolStack();
  202. pushShouldStripWhitespace(false);
  203. }
  204. }
  205. /**
  206. * Ensure that the size of the element indexes can hold the information.
  207. *
  208. * @param namespaceID Namespace ID index.
  209. * @param LocalNameID Local name ID.
  210. */
  211. protected void ensureSizeOfIndex(int namespaceID, int LocalNameID)
  212. {
  213. if (null == m_elemIndexes)
  214. {
  215. m_elemIndexes = new int[namespaceID + 20][][];
  216. }
  217. else if (m_elemIndexes.length <= namespaceID)
  218. {
  219. int[][][] indexes = m_elemIndexes;
  220. m_elemIndexes = new int[namespaceID + 20][][];
  221. System.arraycopy(indexes, 0, m_elemIndexes, 0, indexes.length);
  222. }
  223. int[][] localNameIndex = m_elemIndexes[namespaceID];
  224. if (null == localNameIndex)
  225. {
  226. localNameIndex = new int[LocalNameID + 100][];
  227. m_elemIndexes[namespaceID] = localNameIndex;
  228. }
  229. else if (localNameIndex.length <= LocalNameID)
  230. {
  231. int[][] indexes = localNameIndex;
  232. localNameIndex = new int[LocalNameID + 100][];
  233. System.arraycopy(indexes, 0, localNameIndex, 0, indexes.length);
  234. m_elemIndexes[namespaceID] = localNameIndex;
  235. }
  236. int[] elemHandles = localNameIndex[LocalNameID];
  237. if (null == elemHandles)
  238. {
  239. elemHandles = new int[128];
  240. localNameIndex[LocalNameID] = elemHandles;
  241. elemHandles[0] = 1;
  242. }
  243. else if (elemHandles.length <= elemHandles[0] + 1)
  244. {
  245. int[] indexes = elemHandles;
  246. elemHandles = new int[elemHandles[0] + 1024];
  247. System.arraycopy(indexes, 0, elemHandles, 0, indexes.length);
  248. localNameIndex[LocalNameID] = elemHandles;
  249. }
  250. }
  251. /**
  252. * Add a node to the element indexes. The node will not be added unless
  253. * it's an element.
  254. *
  255. * @param expandedTypeID The expanded type ID of the node.
  256. * @param identity The node identity index.
  257. */
  258. protected void indexNode(int expandedTypeID, int identity)
  259. {
  260. ExpandedNameTable ent = m_expandedNameTable;
  261. short type = ent.getType(expandedTypeID);
  262. if (DTM.ELEMENT_NODE == type)
  263. {
  264. int namespaceID = ent.getNamespaceID(expandedTypeID);
  265. int localNameID = ent.getLocalNameID(expandedTypeID);
  266. ensureSizeOfIndex(namespaceID, localNameID);
  267. int[] index = m_elemIndexes[namespaceID][localNameID];
  268. index[index[0]] = identity;
  269. index[0]++;
  270. }
  271. }
  272. /**
  273. * Find the first index that occurs in the list that is greater than or
  274. * equal to the given value.
  275. *
  276. * @param list A list of integers.
  277. * @param start The start index to begin the search.
  278. * @param len The number of items to search.
  279. * @param value Find the slot that has a value that is greater than or
  280. * identical to this argument.
  281. *
  282. * @return The index in the list of the slot that is higher or identical
  283. * to the identity argument, or -1 if no node is higher or equal.
  284. */
  285. protected int findGTE(int[] list, int start, int len, int value)
  286. {
  287. int low = start;
  288. int high = start + (len - 1);
  289. int end = high;
  290. while (low <= high)
  291. {
  292. int mid = (low + high) / 2;
  293. int c = list[mid];
  294. if (c > value)
  295. high = mid - 1;
  296. else if (c < value)
  297. low = mid + 1;
  298. else
  299. return mid;
  300. }
  301. return (low <= end && list[low] > value) ? low : -1;
  302. }
  303. /**
  304. * Find the first matching element from the index at or after the
  305. * given node.
  306. *
  307. * @param nsIndex The namespace index lookup.
  308. * @param lnIndex The local name index lookup.
  309. * @param firstPotential The first potential match that is worth looking at.
  310. *
  311. * @return The first node that is greater than or equal to the
  312. * firstPotential argument, or DTM.NOTPROCESSED if not found.
  313. */
  314. int findElementFromIndex(int nsIndex, int lnIndex, int firstPotential)
  315. {
  316. int[][][] indexes = m_elemIndexes;
  317. if (null != indexes && nsIndex < indexes.length)
  318. {
  319. int[][] lnIndexs = indexes[nsIndex];
  320. if (null != lnIndexs && lnIndex < lnIndexs.length)
  321. {
  322. int[] elems = lnIndexs[lnIndex];
  323. if (null != elems)
  324. {
  325. int pos = findGTE(elems, 1, elems[0], firstPotential);
  326. if (pos > -1)
  327. {
  328. return elems[pos];
  329. }
  330. }
  331. }
  332. }
  333. return NOTPROCESSED;
  334. }
  335. /**
  336. * Get the next node identity value in the list, and call the iterator
  337. * if it hasn't been added yet.
  338. *
  339. * @param identity The node identity (index).
  340. * @return identity+1, or DTM.NULL.
  341. */
  342. protected abstract int getNextNodeIdentity(int identity);
  343. /**
  344. * This method should try and build one or more nodes in the table.
  345. *
  346. * @return The true if a next node is found or false if
  347. * there are no more nodes.
  348. */
  349. protected abstract boolean nextNode();
  350. /**
  351. * Get the number of nodes that have been added.
  352. *
  353. * @return the number of nodes that have been mapped.
  354. */
  355. protected abstract int getNumberOfNodes();
  356. /** Stateless axis traversers, lazely built. */
  357. protected DTMAxisTraverser[] m_traversers;
  358. // /**
  359. // * Ensure that the size of the information arrays can hold another entry
  360. // * at the given index.
  361. // *
  362. // * @param index On exit from this function, the information arrays sizes must be
  363. // * at least index+1.
  364. // */
  365. // protected void ensureSize(int index)
  366. // {
  367. // // We've cut over to Suballocated*Vector, which are self-sizing.
  368. // }
  369. /**
  370. * Get the simple type ID for the given node identity.
  371. *
  372. * @param identity The node identity.
  373. *
  374. * @return The simple type ID, or DTM.NULL.
  375. */
  376. protected short _type(int identity)
  377. {
  378. int info = _exptype(identity);
  379. if (NULL != info)
  380. return m_expandedNameTable.getType(info);
  381. else
  382. return NULL;
  383. }
  384. /**
  385. * Get the expanded type ID for the given node identity.
  386. *
  387. * @param identity The node identity.
  388. *
  389. * @return The expanded type ID, or DTM.NULL.
  390. */
  391. protected int _exptype(int identity)
  392. {
  393. if (identity == DTM.NULL)
  394. return NULL;
  395. // Reorganized test and loop into single flow
  396. // Tiny performance improvement, saves a few bytes of code, clearer.
  397. // %OPT% Other internal getters could be treated simliarly
  398. while (identity>=m_size)
  399. {
  400. if (!nextNode() && identity >= m_size)
  401. return NULL;
  402. }
  403. return m_exptype.elementAt(identity);
  404. }
  405. /**
  406. * Get the level in the tree for the given node identity.
  407. *
  408. * @param identity The node identity.
  409. *
  410. * @return The tree level, or DTM.NULL.
  411. */
  412. protected int _level(int identity)
  413. {
  414. while (identity>=m_size)
  415. {
  416. boolean isMore = nextNode();
  417. if (!isMore && identity >= m_size)
  418. return NULL;
  419. }
  420. int i=0;
  421. while(NULL != (identity=_parent(identity)))
  422. ++i;
  423. return i;
  424. }
  425. /**
  426. * Get the first child for the given node identity.
  427. *
  428. * @param identity The node identity.
  429. *
  430. * @return The first child identity, or DTM.NULL.
  431. */
  432. protected int _firstch(int identity)
  433. {
  434. // Boiler-plate code for each of the _xxx functions, except for the array.
  435. int info = (identity >= m_size) ? NOTPROCESSED : m_firstch.elementAt(identity);
  436. // Check to see if the information requested has been processed, and,
  437. // if not, advance the iterator until we the information has been
  438. // processed.
  439. while (info == NOTPROCESSED)
  440. {
  441. boolean isMore = nextNode();
  442. if (identity >= m_size &&!isMore)
  443. return NULL;
  444. else
  445. {
  446. info = m_firstch.elementAt(identity);
  447. if(info == NOTPROCESSED && !isMore)
  448. return NULL;
  449. }
  450. }
  451. return info;
  452. }
  453. /**
  454. * Get the next sibling for the given node identity.
  455. *
  456. * @param identity The node identity.
  457. *
  458. * @return The next sibling identity, or DTM.NULL.
  459. */
  460. protected int _nextsib(int identity)
  461. {
  462. // Boiler-plate code for each of the _xxx functions, except for the array.
  463. int info = (identity >= m_size) ? NOTPROCESSED : m_nextsib.elementAt(identity);
  464. // Check to see if the information requested has been processed, and,
  465. // if not, advance the iterator until we the information has been
  466. // processed.
  467. while (info == NOTPROCESSED)
  468. {
  469. boolean isMore = nextNode();
  470. if (identity >= m_size &&!isMore)
  471. return NULL;
  472. else
  473. {
  474. info = m_nextsib.elementAt(identity);
  475. if(info == NOTPROCESSED && !isMore)
  476. return NULL;
  477. }
  478. }
  479. return info;
  480. }
  481. /**
  482. * Get the previous sibling for the given node identity.
  483. *
  484. * @param identity The node identity.
  485. *
  486. * @return The previous sibling identity, or DTM.NULL.
  487. */
  488. protected int _prevsib(int identity)
  489. {
  490. if (identity < m_size)
  491. return m_prevsib.elementAt(identity);
  492. // Check to see if the information requested has been processed, and,
  493. // if not, advance the iterator until we the information has been
  494. // processed.
  495. while (true)
  496. {
  497. boolean isMore = nextNode();
  498. if (identity >= m_size && !isMore)
  499. return NULL;
  500. else if (identity < m_size)
  501. return m_prevsib.elementAt(identity);
  502. }
  503. }
  504. /**
  505. * Get the parent for the given node identity.
  506. *
  507. * @param identity The node identity.
  508. *
  509. * @return The parent identity, or DTM.NULL.
  510. */
  511. protected int _parent(int identity)
  512. {
  513. if (identity < m_size)
  514. return m_parent.elementAt(identity);
  515. // Check to see if the information requested has been processed, and,
  516. // if not, advance the iterator until we the information has been
  517. // processed.
  518. while (true)
  519. {
  520. boolean isMore = nextNode();
  521. if (identity >= m_size && !isMore)
  522. return NULL;
  523. else if (identity < m_size)
  524. return m_parent.elementAt(identity);
  525. }
  526. }
  527. /**
  528. * Diagnostics function to dump the DTM.
  529. */
  530. public void dumpDTM(OutputStream os)
  531. {
  532. try
  533. {
  534. if(os==null)
  535. {
  536. File f = new File("DTMDump"+((Object)this).hashCode()+".txt");
  537. System.err.println("Dumping... "+f.getAbsolutePath());
  538. os=new FileOutputStream(f);
  539. }
  540. PrintStream ps = new PrintStream(os);
  541. while (nextNode()){}
  542. int nRecords = m_size;
  543. ps.println("Total nodes: " + nRecords);
  544. for (int index = 0; index < nRecords; ++index)
  545. {
  546. int i=makeNodeHandle(index);
  547. ps.println("=========== index=" + index + " handle=" + i + " ===========");
  548. ps.println("NodeName: " + getNodeName(i));
  549. ps.println("NodeNameX: " + getNodeNameX(i));
  550. ps.println("LocalName: " + getLocalName(i));
  551. ps.println("NamespaceURI: " + getNamespaceURI(i));
  552. ps.println("Prefix: " + getPrefix(i));
  553. int exTypeID = _exptype(index);
  554. ps.println("Expanded Type ID: "
  555. + Integer.toHexString(exTypeID));
  556. int type = _type(index);
  557. String typestring;
  558. switch (type)
  559. {
  560. case DTM.ATTRIBUTE_NODE :
  561. typestring = "ATTRIBUTE_NODE";
  562. break;
  563. case DTM.CDATA_SECTION_NODE :
  564. typestring = "CDATA_SECTION_NODE";
  565. break;
  566. case DTM.COMMENT_NODE :
  567. typestring = "COMMENT_NODE";
  568. break;
  569. case DTM.DOCUMENT_FRAGMENT_NODE :
  570. typestring = "DOCUMENT_FRAGMENT_NODE";
  571. break;
  572. case DTM.DOCUMENT_NODE :
  573. typestring = "DOCUMENT_NODE";
  574. break;
  575. case DTM.DOCUMENT_TYPE_NODE :
  576. typestring = "DOCUMENT_NODE";
  577. break;
  578. case DTM.ELEMENT_NODE :
  579. typestring = "ELEMENT_NODE";
  580. break;
  581. case DTM.ENTITY_NODE :
  582. typestring = "ENTITY_NODE";
  583. break;
  584. case DTM.ENTITY_REFERENCE_NODE :
  585. typestring = "ENTITY_REFERENCE_NODE";
  586. break;
  587. case DTM.NAMESPACE_NODE :
  588. typestring = "NAMESPACE_NODE";
  589. break;
  590. case DTM.NOTATION_NODE :
  591. typestring = "NOTATION_NODE";
  592. break;
  593. case DTM.NULL :
  594. typestring = "NULL";
  595. break;
  596. case DTM.PROCESSING_INSTRUCTION_NODE :
  597. typestring = "PROCESSING_INSTRUCTION_NODE";
  598. break;
  599. case DTM.TEXT_NODE :
  600. typestring = "TEXT_NODE";
  601. break;
  602. default :
  603. typestring = "Unknown!";
  604. break;
  605. }
  606. ps.println("Type: " + typestring);
  607. int firstChild = _firstch(index);
  608. if (DTM.NULL == firstChild)
  609. ps.println("First child: DTM.NULL");
  610. else if (NOTPROCESSED == firstChild)
  611. ps.println("First child: NOTPROCESSED");
  612. else
  613. ps.println("First child: " + firstChild);
  614. if (m_prevsib != null)
  615. {
  616. int prevSibling = _prevsib(index);
  617. if (DTM.NULL == prevSibling)
  618. ps.println("Prev sibling: DTM.NULL");
  619. else if (NOTPROCESSED == prevSibling)
  620. ps.println("Prev sibling: NOTPROCESSED");
  621. else
  622. ps.println("Prev sibling: " + prevSibling);
  623. }
  624. int nextSibling = _nextsib(index);
  625. if (DTM.NULL == nextSibling)
  626. ps.println("Next sibling: DTM.NULL");
  627. else if (NOTPROCESSED == nextSibling)
  628. ps.println("Next sibling: NOTPROCESSED");
  629. else
  630. ps.println("Next sibling: " + nextSibling);
  631. int parent = _parent(index);
  632. if (DTM.NULL == parent)
  633. ps.println("Parent: DTM.NULL");
  634. else if (NOTPROCESSED == parent)
  635. ps.println("Parent: NOTPROCESSED");
  636. else
  637. ps.println("Parent: " + parent);
  638. int level = _level(index);
  639. ps.println("Level: " + level);
  640. ps.println("Node Value: " + getNodeValue(i));
  641. ps.println("String Value: " + getStringValue(i));
  642. }
  643. }
  644. catch(IOException ioe)
  645. {
  646. ioe.printStackTrace(System.err);
  647. System.exit(-1);
  648. }
  649. }
  650. /**
  651. * Diagnostics function to dump a single node.
  652. *
  653. * %REVIEW% KNOWN GLITCH: If you pass it a node index rather than a
  654. * node handle, it works just fine... but the displayed identity
  655. * number before the colon is different, which complicates comparing
  656. * it with nodes printed the other way. We could always OR the DTM ID
  657. * into the value, to suppress that distinction...
  658. *
  659. * %REVIEW% This might want to be moved up to DTMDefaultBase, or possibly
  660. * DTM itself, since it's a useful diagnostic and uses only DTM's public
  661. * APIs.
  662. */
  663. public String dumpNode(int nodeHandle)
  664. {
  665. if(nodeHandle==DTM.NULL)
  666. return "[null]";
  667. String typestring;
  668. switch (getNodeType(nodeHandle))
  669. {
  670. case DTM.ATTRIBUTE_NODE :
  671. typestring = "ATTR";
  672. break;
  673. case DTM.CDATA_SECTION_NODE :
  674. typestring = "CDATA";
  675. break;
  676. case DTM.COMMENT_NODE :
  677. typestring = "COMMENT";
  678. break;
  679. case DTM.DOCUMENT_FRAGMENT_NODE :
  680. typestring = "DOC_FRAG";
  681. break;
  682. case DTM.DOCUMENT_NODE :
  683. typestring = "DOC";
  684. break;
  685. case DTM.DOCUMENT_TYPE_NODE :
  686. typestring = "DOC_TYPE";
  687. break;
  688. case DTM.ELEMENT_NODE :
  689. typestring = "ELEMENT";
  690. break;
  691. case DTM.ENTITY_NODE :
  692. typestring = "ENTITY";
  693. break;
  694. case DTM.ENTITY_REFERENCE_NODE :
  695. typestring = "ENT_REF";
  696. break;
  697. case DTM.NAMESPACE_NODE :
  698. typestring = "NAMESPACE";
  699. break;
  700. case DTM.NOTATION_NODE :
  701. typestring = "NOTATION";
  702. break;
  703. case DTM.NULL :
  704. typestring = "null";
  705. break;
  706. case DTM.PROCESSING_INSTRUCTION_NODE :
  707. typestring = "PI";
  708. break;
  709. case DTM.TEXT_NODE :
  710. typestring = "TEXT";
  711. break;
  712. default :
  713. typestring = "Unknown!";
  714. break;
  715. }
  716. StringBuffer sb=new StringBuffer();
  717. sb.append("["+nodeHandle+": "+typestring+
  718. "(0x"+Integer.toHexString(getExpandedTypeID(nodeHandle))+") "+
  719. getNodeNameX(nodeHandle)+" {"+getNamespaceURI(nodeHandle)+"}"+
  720. "=\""+ getNodeValue(nodeHandle)+"\"]");
  721. return sb.toString();
  722. }
  723. // ========= DTM Implementation Control Functions. ==============
  724. /**
  725. * Set an implementation dependent feature.
  726. * <p>
  727. * %REVIEW% Do we really expect to set features on DTMs?
  728. *
  729. * @param featureId A feature URL.
  730. * @param state true if this feature should be on, false otherwise.
  731. */
  732. public void setFeature(String featureId, boolean state){}
  733. // ========= Document Navigation Functions =========
  734. /**
  735. * Given a node handle, test if it has child nodes.
  736. * <p> %REVIEW% This is obviously useful at the DOM layer, where it
  737. * would permit testing this without having to create a proxy
  738. * node. It's less useful in the DTM API, where
  739. * (dtm.getFirstChild(nodeHandle)!=DTM.NULL) is just as fast and
  740. * almost as self-evident. But it's a convenience, and eases porting
  741. * of DOM code to DTM. </p>
  742. *
  743. * @param nodeHandle int Handle of the node.
  744. * @return int true if the given node has child nodes.
  745. */
  746. public boolean hasChildNodes(int nodeHandle)
  747. {
  748. int identity = makeNodeIdentity(nodeHandle);
  749. int firstChild = _firstch(identity);
  750. return firstChild != DTM.NULL;
  751. }
  752. /** Given a node identity, return a node handle. If extended addressing
  753. * has been used (multiple DTM IDs), we need to map the high bits of the
  754. * identity into the proper DTM ID.
  755. *
  756. * This has been made FINAL to facilitate inlining, since we do not expect
  757. * any subclass of DTMDefaultBase to ever change the algorithm. (I don't
  758. * really like doing so, and would love to have an excuse not to...)
  759. *
  760. * %REVIEW% Is it worth trying to specialcase small documents?
  761. * %REVIEW% Should this be exposed at the package/public layers?
  762. *
  763. * @param nodeIdentity Internal offset to this node's records.
  764. * @return NodeHandle (external representation of node)
  765. * */
  766. final public int makeNodeHandle(int nodeIdentity)
  767. {
  768. if(NULL==nodeIdentity) return NULL;
  769. if(JJK_DEBUG && nodeIdentity>DTMManager.IDENT_NODE_DEFAULT)
  770. System.err.println("GONK! (only useful in limited situations)");
  771. return m_dtmIdent.elementAt(nodeIdentity >>> DTMManager.IDENT_DTM_NODE_BITS)
  772. + (nodeIdentity & DTMManager.IDENT_NODE_DEFAULT) ;
  773. }
  774. /** Given a node handle, return a node identity. If extended addressing
  775. * has been used (multiple DTM IDs), we need to map the high bits of the
  776. * identity into the proper DTM ID and thence find the proper offset
  777. * to add to the low bits of the identity
  778. *
  779. * This has been made FINAL to facilitate inlining, since we do not expect
  780. * any subclass of DTMDefaultBase to ever change the algorithm. (I don't
  781. * really like doing so, and would love to have an excuse not to...)
  782. *
  783. * %OPT% Performance is critical for this operation.
  784. *
  785. * %REVIEW% Should this be exposed at the package/public layers?
  786. *
  787. * @param NodeHandle (external representation of node)
  788. * @return nodeIdentity Internal offset to this node's records.
  789. * */
  790. final public int makeNodeIdentity(int nodeHandle)
  791. {
  792. if(NULL==nodeHandle) return NULL;
  793. if(m_mgrDefault!=null)
  794. {
  795. // Optimization: use the DTMManagerDefault's fast DTMID-to-offsets
  796. // table. I'm not wild about this solution but this operation
  797. // needs need extreme speed.
  798. int whichDTMindex=nodeHandle>>>DTMManager.IDENT_DTM_NODE_BITS;
  799. // %REVIEW% Wish I didn't have to perform the pre-test, but
  800. // someone is apparently asking DTMs whether they contain nodes
  801. // which really don't belong to them. That's probably a bug
  802. // which should be fixed, but until it is:
  803. if(m_mgrDefault.m_dtms[whichDTMindex]!=this)
  804. return NULL;
  805. else
  806. return
  807. m_mgrDefault.m_dtm_offsets[whichDTMindex]
  808. | (nodeHandle & DTMManager.IDENT_NODE_DEFAULT);
  809. }
  810. int whichDTMid=m_dtmIdent.indexOf(nodeHandle & DTMManager.IDENT_DTM_DEFAULT);
  811. return (whichDTMid==NULL)
  812. ? NULL
  813. : (whichDTMid << DTMManager.IDENT_DTM_NODE_BITS)
  814. + (nodeHandle & DTMManager.IDENT_NODE_DEFAULT);
  815. }
  816. /**
  817. * Given a node handle, get the handle of the node's first child.
  818. * If not yet resolved, waits for more nodes to be added to the document and
  819. * tries again.
  820. *
  821. * @param nodeHandle int Handle of the node.
  822. * @return int DTM node-number of first child, or DTM.NULL to indicate none exists.
  823. */
  824. public int getFirstChild(int nodeHandle)
  825. {
  826. int identity = makeNodeIdentity(nodeHandle);
  827. int firstChild = _firstch(identity);
  828. return makeNodeHandle(firstChild);
  829. }
  830. /**
  831. * Given a node handle, get the handle of the node's first child.
  832. * If not yet resolved, waits for more nodes to be added to the document and
  833. * tries again.
  834. *
  835. * @param nodeHandle int Handle of the node.
  836. * @return int DTM node-number of first child, or DTM.NULL to indicate none exists.
  837. */
  838. public int getTypedFirstChild(int nodeHandle, int nodeType)
  839. {
  840. int firstChild, eType;
  841. if (nodeType < DTM.NTYPES) {
  842. for (firstChild = _firstch(makeNodeIdentity(nodeHandle));
  843. firstChild != DTM.NULL;
  844. firstChild = _nextsib(firstChild)) {
  845. eType = _exptype(firstChild);
  846. if (eType == nodeType
  847. || (eType >= DTM.NTYPES
  848. && m_expandedNameTable.getType(eType) == nodeType)) {
  849. return makeNodeHandle(firstChild);
  850. }
  851. }
  852. } else {
  853. for (firstChild = _firstch(makeNodeIdentity(nodeHandle));
  854. firstChild != DTM.NULL;
  855. firstChild = _nextsib(firstChild)) {
  856. if (_exptype(firstChild) == nodeType) {
  857. return makeNodeHandle(firstChild);
  858. }
  859. }
  860. }
  861. return DTM.NULL;
  862. }
  863. /**
  864. * Given a node handle, advance to its last child.
  865. * If not yet resolved, waits for more nodes to be added to the document and
  866. * tries again.
  867. *
  868. * @param nodeHandle int Handle of the node.
  869. * @return int Node-number of last child,
  870. * or DTM.NULL to indicate none exists.
  871. */
  872. public int getLastChild(int nodeHandle)
  873. {
  874. int identity = makeNodeIdentity(nodeHandle);
  875. int child = _firstch(identity);
  876. int lastChild = DTM.NULL;
  877. while (child != DTM.NULL)
  878. {
  879. lastChild = child;
  880. child = _nextsib(child);
  881. }
  882. return makeNodeHandle(lastChild);
  883. }
  884. /**
  885. * Retrieves an attribute node by by qualified name and namespace URI.
  886. *
  887. * @param nodeHandle int Handle of the node upon which to look up this attribute..
  888. * @param namespaceURI The namespace URI of the attribute to
  889. * retrieve, or null.
  890. * @param name The local name of the attribute to
  891. * retrieve.
  892. * @return The attribute node handle with the specified name (
  893. * <code>nodeName</code>) or <code>DTM.NULL</code> if there is no such
  894. * attribute.
  895. */
  896. public abstract int getAttributeNode(int nodeHandle, String namespaceURI,
  897. String name);
  898. /**
  899. * Given a node handle, get the index of the node's first attribute.
  900. *
  901. * @param nodeHandle int Handle of the node.
  902. * @return Handle of first attribute, or DTM.NULL to indicate none exists.
  903. */
  904. public int getFirstAttribute(int nodeHandle)
  905. {
  906. int nodeID = makeNodeIdentity(nodeHandle);
  907. return makeNodeHandle(getFirstAttributeIdentity(nodeID));
  908. }
  909. /**
  910. * Given a node identity, get the index of the node's first attribute.
  911. *
  912. * @param identity int identity of the node.
  913. * @return Identity of first attribute, or DTM.NULL to indicate none exists.
  914. */
  915. protected int getFirstAttributeIdentity(int identity) {
  916. int type = _type(identity);
  917. if (DTM.ELEMENT_NODE == type)
  918. {
  919. // Assume that attributes and namespaces immediately follow the element.
  920. while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
  921. {
  922. // Assume this can not be null.
  923. type = _type(identity);
  924. if (type == DTM.ATTRIBUTE_NODE)
  925. {
  926. return identity;
  927. }
  928. else if (DTM.NAMESPACE_NODE != type)
  929. {
  930. break;
  931. }
  932. }
  933. }
  934. return DTM.NULL;
  935. }
  936. /**
  937. * Given a node handle and an expanded type ID, get the index of the node's
  938. * attribute of that type, if any.
  939. *
  940. * @param nodeHandle int Handle of the node.
  941. * @param attType int expanded type ID of the required attribute.
  942. * @return Handle of attribute of the required type, or DTM.NULL to indicate
  943. * none exists.
  944. */
  945. protected int getTypedAttribute(int nodeHandle, int attType) {
  946. int type = getNodeType(nodeHandle);
  947. if (DTM.ELEMENT_NODE == type) {
  948. int identity = makeNodeIdentity(nodeHandle);
  949. while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
  950. {
  951. type = _type(identity);
  952. if (type == DTM.ATTRIBUTE_NODE)
  953. {
  954. if (_exptype(identity) == attType) return makeNodeHandle(identity);
  955. }
  956. else if (DTM.NAMESPACE_NODE != type)
  957. {
  958. break;
  959. }
  960. }
  961. }
  962. return DTM.NULL;
  963. }
  964. /**
  965. * Given a node handle, advance to its next sibling.
  966. * If not yet resolved, waits for more nodes to be added to the document and
  967. * tries again.
  968. * @param nodeHandle int Handle of the node.
  969. * @return int Node-number of next sibling,
  970. * or DTM.NULL to indicate none exists.
  971. */
  972. public int getNextSibling(int nodeHandle)
  973. {
  974. if (nodeHandle == DTM.NULL)
  975. return DTM.NULL;
  976. return makeNodeHandle(_nextsib(makeNodeIdentity(nodeHandle)));
  977. }
  978. /**
  979. * Given a node handle, advance to its next sibling.
  980. * If not yet resolved, waits for more nodes to be added to the document and
  981. * tries again.
  982. * @param nodeHandle int Handle of the node.
  983. * @return int Node-number of next sibling,
  984. * or DTM.NULL to indicate none exists.
  985. */
  986. public int getTypedNextSibling(int nodeHandle, int nodeType)
  987. {
  988. if (nodeHandle == DTM.NULL)
  989. return DTM.NULL;
  990. int node = makeNodeIdentity(nodeHandle);
  991. int eType;
  992. while ((node = _nextsib(node)) != DTM.NULL &&
  993. ((eType = _exptype(node)) != nodeType &&
  994. m_expandedNameTable.getType(eType)!= nodeType));
  995. //_type(node) != nodeType));
  996. return (node == DTM.NULL ? DTM.NULL : makeNodeHandle(node));
  997. }
  998. /**
  999. * Given a node handle, find its preceeding sibling.
  1000. * WARNING: DTM is asymmetric; this operation is resolved by search, and is
  1001. * relatively expensive.
  1002. *
  1003. * @param nodeHandle the id of the node.
  1004. * @return int Node-number of the previous sib,
  1005. * or DTM.NULL to indicate none exists.
  1006. */
  1007. public int getPreviousSibling(int nodeHandle)
  1008. {
  1009. if (nodeHandle == DTM.NULL)
  1010. return DTM.NULL;
  1011. if (m_prevsib != null)
  1012. return makeNodeHandle(_prevsib(makeNodeIdentity(nodeHandle)));
  1013. else
  1014. {
  1015. // If the previous sibling array is not built, we get at
  1016. // the previous sibling using the parent, firstch and
  1017. // nextsib arrays.
  1018. int nodeID = makeNodeIdentity(nodeHandle);
  1019. int parent = _parent(nodeID);
  1020. int node = _firstch(parent);
  1021. int result = DTM.NULL;
  1022. while (node != nodeID)
  1023. {
  1024. result = node;
  1025. node = _nextsib(node);
  1026. }
  1027. return makeNodeHandle(result);
  1028. }
  1029. }
  1030. /**
  1031. * Given a node handle, advance to the next attribute.
  1032. * If an attr, we advance to
  1033. * the next attr on the same node. If not an attribute, we return NULL.
  1034. *
  1035. * @param nodeHandle int Handle of the node.
  1036. * @return int DTM node-number of the resolved attr,
  1037. * or DTM.NULL to indicate none exists.
  1038. */
  1039. public int getNextAttribute(int nodeHandle) {
  1040. int nodeID = makeNodeIdentity(nodeHandle);
  1041. if (_type(nodeID) == DTM.ATTRIBUTE_NODE) {
  1042. return makeNodeHandle(getNextAttributeIdentity(nodeID));
  1043. }
  1044. return DTM.NULL;
  1045. }
  1046. /**
  1047. * Given a node identity for an attribute, advance to the next attribute.
  1048. *
  1049. * @param identity int identity of the attribute node. This
  1050. * <strong>must</strong> be an attribute node.
  1051. *
  1052. * @return int DTM node-identity of the resolved attr,
  1053. * or DTM.NULL to indicate none exists.
  1054. *
  1055. */
  1056. protected int getNextAttributeIdentity(int identity) {
  1057. // Assume that attributes and namespace nodes immediately follow the element
  1058. while (DTM.NULL != (identity = getNextNodeIdentity(identity))) {
  1059. int type = _type(identity);
  1060. if (type == DTM.ATTRIBUTE_NODE) {
  1061. return identity;
  1062. } else if (type != DTM.NAMESPACE_NODE) {
  1063. break;
  1064. }
  1065. }
  1066. return DTM.NULL;
  1067. }
  1068. /** Lazily created namespace lists. */
  1069. private Vector m_namespaceLists = null; // on demand
  1070. /** Build table of namespace declaration
  1071. * locations during DTM construction. Table is a Vector of
  1072. * SuballocatedIntVectors containing the namespace node HANDLES declared at
  1073. * that ID, plus an SuballocatedIntVector of the element node INDEXES at which
  1074. * these declarations appeared.
  1075. *
  1076. * NOTE: Since this occurs during model build, nodes will be encountered
  1077. * in doucment order and thus the table will be ordered by element,
  1078. * permitting binary-search as a possible retrieval optimization.
  1079. *
  1080. * %REVIEW% Directly managed arrays rather than vectors?
  1081. * %REVIEW% Handles or IDs? Given usage, I think handles.
  1082. * */
  1083. protected void declareNamespaceInContext(int elementNodeIndex,int namespaceNodeIndex)
  1084. {
  1085. SuballocatedIntVector nsList=null;
  1086. if(m_namespaceDeclSets==null)
  1087. {
  1088. // First
  1089. m_namespaceDeclSetElements=new SuballocatedIntVector(32);
  1090. m_namespaceDeclSetElements.addElement(elementNodeIndex);
  1091. m_namespaceDeclSets=new Vector();
  1092. nsList=new SuballocatedIntVector(32);
  1093. m_namespaceDeclSets.addElement(nsList);
  1094. }
  1095. else
  1096. {
  1097. // Most recent. May be -1 (none) if DTM was pruned.
  1098. // %OPT% Is there a lastElement() method? Should there be?
  1099. int last=m_namespaceDeclSetElements.size()-1;
  1100. if(last>=0 && elementNodeIndex==m_namespaceDeclSetElements.elementAt(last))
  1101. {
  1102. nsList=(SuballocatedIntVector)m_namespaceDeclSets.elementAt(last);
  1103. }
  1104. }
  1105. if(nsList==null)
  1106. {
  1107. m_namespaceDeclSetElements.addElement(elementNodeIndex);
  1108. SuballocatedIntVector inherited =
  1109. findNamespaceContext(_parent(elementNodeIndex));
  1110. if (inherited!=null) {
  1111. // %OPT% Count-down might be faster, but debuggability may
  1112. // be better this way, and if we ever decide we want to
  1113. // keep this ordered by expanded-type...
  1114. int isize=inherited.size();
  1115. // Base the size of a new namespace list on the
  1116. // size of the inherited list - but within reason!
  1117. nsList=new SuballocatedIntVector(Math.max(Math.min(isize+16,2048),
  1118. 32));
  1119. for(int i=0;i<isize;++i)
  1120. {
  1121. nsList.addElement(inherited.elementAt(i));
  1122. }
  1123. } else {
  1124. nsList=new SuballocatedIntVector(32);
  1125. }
  1126. m_namespaceDeclSets.addElement(nsList);
  1127. }
  1128. // Handle overwriting inherited.
  1129. // %OPT% Keep sorted? (By expanded-name rather than by doc order...)
  1130. // Downside: Would require insertElementAt if not found,
  1131. // which has recopying costs. But these are generally short lists...
  1132. int newEType=_exptype(namespaceNodeIndex);
  1133. for(int i=nsList.size()-1;i>=0;--i)
  1134. {
  1135. if(newEType==getExpandedTypeID(nsList.elementAt(i)))
  1136. {
  1137. nsList.setElementAt(makeNodeHandle(namespaceNodeIndex),i);
  1138. return;
  1139. }
  1140. }
  1141. nsList.addElement(makeNodeHandle(namespaceNodeIndex));
  1142. }
  1143. /** Retrieve list of namespace declaration locations
  1144. * active at this node. List is an SuballocatedIntVector whose
  1145. * entries are the namespace node HANDLES declared at that ID.
  1146. *
  1147. * %REVIEW% Directly managed arrays rather than vectors?
  1148. * %REVIEW% Handles or IDs? Given usage, I think handles.
  1149. * */
  1150. protected SuballocatedIntVector findNamespaceContext(int elementNodeIndex)
  1151. {
  1152. if (null!=m_namespaceDeclSetElements)
  1153. {
  1154. // %OPT% Is binary-search really saving us a lot versus linear?
  1155. // (... It may be, in large docs with many NS decls.)
  1156. int wouldBeAt=findInSortedSuballocatedIntVector(m_namespaceDeclSetElements,
  1157. elementNodeIndex);
  1158. if(wouldBeAt>=0) // Found it
  1159. return (SuballocatedIntVector) m_namespaceDeclSets.elementAt(wouldBeAt);
  1160. if(wouldBeAt == -1) // -1-wouldbeat == 0
  1161. return null; // Not after anything; definitely not found
  1162. // Not found, but we know where it should have been.
  1163. // Search back until we find an ancestor or run out.
  1164. wouldBeAt=-1-wouldBeAt;
  1165. // Decrement wouldBeAt to find last possible ancestor
  1166. int candidate=m_namespaceDeclSetElements.elementAt(-- wouldBeAt);
  1167. int ancestor=_parent(elementNodeIndex);
  1168. // Special case: if the candidate is before the given node, and
  1169. // is in the earliest possible position in the document, it
  1170. // must have the namespace declarations we're interested in.
  1171. if (wouldBeAt == 0 && candidate < ancestor) {
  1172. int rootHandle = getDocumentRoot(makeNodeHandle(elementNodeIndex));
  1173. int rootID = makeNodeIdentity(rootHandle);
  1174. int uppermostNSCandidateID;
  1175. if (getNodeType(rootHandle) == DTM.DOCUMENT_NODE) {
  1176. int ch = _firstch(rootID);
  1177. uppermostNSCandidateID = (ch != DTM.NULL) ? ch : rootID;
  1178. } else {
  1179. uppermostNSCandidateID = rootID;
  1180. }
  1181. if (candidate == uppermostNSCandidateID) {
  1182. return (SuballocatedIntVector)m_namespaceDeclSets.elementAt(wouldBeAt);
  1183. }
  1184. }
  1185. while(wouldBeAt>=0 && ancestor>0)
  1186. {
  1187. if (candidate==ancestor) {
  1188. // Found ancestor in list
  1189. return (SuballocatedIntVector)m_namespaceDeclSets.elementAt(wouldBeAt);
  1190. } else if (candidate<ancestor) {
  1191. // Too deep in tree
  1192. do {
  1193. ancestor=_parent(ancestor);
  1194. } while (candidate < ancestor);
  1195. } else if(wouldBeAt > 0){
  1196. // Too late in list
  1197. candidate=m_namespaceDeclSetElements.elementAt(--wouldBeAt);
  1198. }
  1199. else
  1200. break;
  1201. }
  1202. }
  1203. return null; // No namespaces known at this node
  1204. }
  1205. /**
  1206. * Subroutine: Locate the specified node within
  1207. * m_namespaceDeclSetElements, or the last element which
  1208. * preceeds it in document order
  1209. *
  1210. * %REVIEW% Inlne this into findNamespaceContext? Create SortedSuballocatedIntVector type?
  1211. *
  1212. * @param elementNodeIndex Index of a node to look up.
  1213. *
  1214. * @return If positive or zero, the index of the found item.
  1215. * If negative, index of the point at which it would have appeared,
  1216. * encoded as -1-index and hence reconvertable by subtracting
  1217. * it from -1. (Encoding because I don't want to recompare the strings
  1218. * but don't want to burn bytes on a datatype to hold a flagged value.)
  1219. */
  1220. protected int findInSortedSuballocatedIntVector(SuballocatedIntVector vector, int lookfor)
  1221. {
  1222. // Binary search
  1223. int i = 0;
  1224. if(vector != null) {
  1225. int first = 0;
  1226. int last = vector.size() - 1;
  1227. while (first <= last) {
  1228. i = (first + last) / 2;
  1229. int test = lookfor-vector.elementAt(i);
  1230. if(test == 0) {
  1231. return i; // Name found
  1232. }
  1233. else if (test < 0) {
  1234. last = i - 1; // looked too late
  1235. }
  1236. else {
  1237. first = i + 1; // looked ot early
  1238. }
  1239. }
  1240. if (first > i) {
  1241. i = first; // Clean up at loop end
  1242. }
  1243. }
  1244. return -1 - i; // not-found has to be encoded.
  1245. }
  1246. /**
  1247. * Given a node handle, get the index of the node's first child.
  1248. * If not yet resolved, waits for more nodes to be added to the document and
  1249. * tries again
  1250. *
  1251. * @param nodeHandle handle to node, which should probably be an element
  1252. * node, but need not be.
  1253. *
  1254. * @param inScope true if all namespaces in scope should be returned,
  1255. * false if only the namespace declarations should be
  1256. * returned.
  1257. * @return handle of first namespace, or DTM.NULL to indicate none exists.
  1258. */
  1259. public int getFirstNamespaceNode(int nodeHandle, boolean inScope)
  1260. {
  1261. if(inScope)
  1262. {
  1263. int identity = makeNodeIdentity(nodeHandle);
  1264. if (_type(identity) == DTM.ELEMENT_NODE)
  1265. {
  1266. SuballocatedIntVector nsContext=findNamespaceContext(identity);
  1267. if(nsContext==null || nsContext.size()<1)
  1268. return NULL;
  1269. return nsContext.elementAt(0);
  1270. }
  1271. else
  1272. return NULL;
  1273. }
  1274. else
  1275. {
  1276. // Assume that attributes and namespaces immediately
  1277. // follow the element.
  1278. //
  1279. // %OPT% Would things be faster if all NS nodes were built
  1280. // before all Attr nodes? Some costs at build time for 2nd
  1281. // pass...
  1282. int identity = makeNodeIdentity(nodeHandle);
  1283. if (_type(identity) == DTM.ELEMENT_NODE)
  1284. {
  1285. while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
  1286. {
  1287. int type = _type(identity);
  1288. if (type == DTM.NAMESPACE_NODE)
  1289. return makeNodeHandle(identity);
  1290. else if (DTM.ATTRIBUTE_NODE != type)
  1291. break;
  1292. }
  1293. return NULL;
  1294. }
  1295. else
  1296. return NULL;
  1297. }
  1298. }
  1299. /**
  1300. * Given a namespace handle, advance to the next namespace.
  1301. *
  1302. * @param baseHandle handle to original node from where the first namespace
  1303. * was relative to (needed to return nodes in document order).
  1304. * @param namespaceHandle handle to node which must be of type
  1305. * NAMESPACE_NODE.
  1306. * @param nodeHandle A namespace handle for which we will find the next node.
  1307. * @param inScope true if all namespaces that are in scope should be processed,
  1308. * otherwise just process the nodes in the given element handle.
  1309. * @return handle of next namespace, or DTM.NULL to indicate none exists.
  1310. */
  1311. public int getNextNamespaceNode(int baseHandle, int nodeHandle,
  1312. boolean inScope)
  1313. {
  1314. if(inScope)
  1315. {
  1316. //Since we've been given the base, try direct lookup
  1317. //(could look from nodeHandle but this is at least one
  1318. //comparison/get-parent faster)
  1319. //SuballocatedIntVector nsContext=findNamespaceContext(nodeHandle & m_mask);
  1320. SuballocatedIntVector nsContext=findNamespaceContext(makeNodeIdentity(baseHandle));
  1321. if(nsContext==null)
  1322. return NULL;
  1323. int i=1 + nsContext.indexOf(nodeHandle);
  1324. if(i<=0 || i==nsContext.size())
  1325. return NULL;
  1326. return nsContext.elementAt(i);
  1327. }
  1328. else
  1329. {
  1330. // Assume that attributes and namespace nodes immediately follow the element.
  1331. int identity = makeNodeIdentity(nodeHandle);
  1332. while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
  1333. {
  1334. int type = _type(identity);
  1335. if (type == DTM.NAMESPACE_NODE)
  1336. {
  1337. return makeNodeHandle(identity);
  1338. }
  1339. else if (type != DTM.ATTRIBUTE_NODE)
  1340. {
  1341. break;
  1342. }
  1343. }
  1344. }
  1345. return DTM.NULL;
  1346. }
  1347. /**
  1348. * Given a node handle, find its parent node.
  1349. *
  1350. * @param nodeHandle the id of the node.
  1351. * @return int Node-number of parent,
  1352. * or DTM.NULL to indicate none exists.
  1353. */
  1354. public int getParent(int nodeHandle)
  1355. {
  1356. int identity = makeNodeIdentity(nodeHandle);
  1357. if (identity > 0)
  1358. return makeNodeHandle(_parent(identity));
  1359. else
  1360. return DTM.NULL;
  1361. }
  1362. /**
  1363. * Find the Document node handle for the document currently under construction.
  1364. * PLEASE NOTE that most people should use getOwnerDocument(nodeHandle) instead;
  1365. * this version of the operation is primarily intended for use during negotiation
  1366. * with the DTM Manager.
  1367. *
  1368. * @param nodeHandle the id of the node.
  1369. * @return int Node handle of document, which should always be valid.
  1370. */
  1371. public int getDocument()
  1372. {
  1373. return m_dtmIdent.elementAt(0); // makeNodeHandle(0)
  1374. }
  1375. /**
  1376. * Given a node handle, find the owning document node. This has the exact
  1377. * same semantics as the DOM Document method of the same name, in that if
  1378. * the nodeHandle is a document node, it will return NULL.
  1379. *
  1380. * <p>%REVIEW% Since this is DOM-specific, it may belong at the DOM
  1381. * binding layer. Included here as a convenience function and to
  1382. * aid porting of DOM code to DTM.</p>
  1383. *
  1384. * @param nodeHandle the id of the node.
  1385. * @return int Node handle of owning document, or -1 if the node was a Docment
  1386. */
  1387. public int getOwnerDocument(int nodeHandle)
  1388. {
  1389. if (DTM.DOCUMENT_NODE == getNodeType(nodeHandle))
  1390. return DTM.NULL;
  1391. return getDocumentRoot(nodeHandle);
  1392. }
  1393. /**
  1394. * Given a node handle, find the owning document node. Unlike the DOM,
  1395. * this considers the owningDocument of a Document to be itself.
  1396. *
  1397. * @param nodeHandle the id of the node.
  1398. * @return int Node handle of owning document, or the nodeHandle if it is
  1399. * a Document.
  1400. */
  1401. public int getDocumentRoot(int nodeHandle)
  1402. {
  1403. return getDocument();
  1404. }
  1405. /**
  1406. * Get the string-value of a node as a String object
  1407. * (see http://www.w3.org/TR/xpath#data-model
  1408. * for the definition of a node's string-value).
  1409. *
  1410. * @param nodeHandle The node ID.
  1411. *
  1412. * @return A string object that represents the string-value of the given node.
  1413. */
  1414. public abstract XMLString getStringValue(int nodeHandle);
  1415. /**
  1416. * Get number of character array chunks in
  1417. * the string-value of a node.
  1418. * (see http://www.w3.org/TR/xpath#data-model
  1419. * for the definition of a node's string-value).
  1420. * Note that a single text node may have multiple text chunks.
  1421. *
  1422. * @param nodeHandle The node ID.
  1423. *
  1424. * @return number of character array chunks in
  1425. * the string-value of a node.
  1426. */
  1427. public int getStringValueChunkCount(int nodeHandle)
  1428. {
  1429. // %TBD%
  1430. error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//("getStringValueChunkCount not yet supported!");
  1431. return 0;
  1432. }
  1433. /**
  1434. * Get a character array chunk in the string-value of a node.
  1435. * (see http://www.w3.org/TR/xpath#data-model
  1436. * for the definition of a node's string-value).
  1437. * Note that a single text node may have multiple text chunks.
  1438. *
  1439. * @param nodeHandle The node ID.
  1440. * @param chunkIndex Which chunk to get.
  1441. * @param startAndLen An array of 2 where the start position and length of
  1442. * the chunk will be returned.
  1443. *
  1444. * @return The character array reference where the chunk occurs.
  1445. */
  1446. public char[] getStringValueChunk(int nodeHandle, int chunkIndex,
  1447. int[] startAndLen)
  1448. {
  1449. // %TBD%
  1450. error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"getStringValueChunk not yet supported!");
  1451. return null;
  1452. }
  1453. /**
  1454. * Given a node handle, return an ID that represents the node's expanded name.
  1455. *
  1456. * @param nodeHandle The handle to the node in question.
  1457. *
  1458. * @return the expanded-name id of the node.
  1459. */
  1460. public int getExpandedTypeID(int nodeHandle)
  1461. {
  1462. // %REVIEW% This _should_ only be null if someone asked the wrong DTM about the node...
  1463. // which one would hope would never happen...
  1464. int id=makeNodeIdentity(nodeHandle);
  1465. if(id==NULL)
  1466. return NULL;
  1467. return _exptype(id);
  1468. }
  1469. /**
  1470. * Given an expanded name, return an ID. If the expanded-name does not
  1471. * exist in the internal tables, the entry will be created, and the ID will
  1472. * be returned. Any additional nodes that are created that have this
  1473. * expanded name will use this ID.
  1474. *
  1475. * @param nodeHandle The handle to the node in question.
  1476. * @param type The simple type, i.e. one of ELEMENT, ATTRIBUTE, etc.
  1477. *
  1478. * @param namespace The namespace URI, which may be null, may be an empty
  1479. * string (which will be the same as null), or may be a
  1480. * namespace URI.
  1481. * @param localName The local name string, which must be a valid
  1482. * <a href="http://www.w3.org/TR/REC-xml-names/">NCName</a>.
  1483. *
  1484. * @return the expanded-name id of the node.
  1485. */
  1486. public int getExpandedTypeID(String namespace, String localName, int type)
  1487. {
  1488. ExpandedNameTable ent = m_expandedNameTable;
  1489. return ent.getExpandedTypeID(namespace, localName, type);
  1490. }
  1491. /**
  1492. * Given an expanded-name ID, return the local name part.
  1493. *
  1494. * @param ExpandedNameID an ID that represents an expanded-name.
  1495. * @return String Local name of this node.
  1496. */
  1497. public String getLocalNameFromExpandedNameID(int expandedNameID)
  1498. {
  1499. return m_expandedNameTable.getLocalName(expandedNameID);
  1500. }
  1501. /**
  1502. * Given an expanded-name ID, return the namespace URI part.
  1503. *
  1504. * @param ExpandedNameID an ID that represents an expanded-name.
  1505. * @return String URI value of this node's namespace, or null if no
  1506. * namespace was resolved.
  1507. */
  1508. public String getNamespaceFromExpandedNameID(int expandedNameID)
  1509. {
  1510. return m_expandedNameTable.getNamespace(expandedNameID);
  1511. }
  1512. /**
  1513. * Returns the namespace type of a specific node
  1514. * @param nodeHandle the id of the node.
  1515. * @return the ID of the namespace.
  1516. */
  1517. public int getNamespaceType(final int nodeHandle)
  1518. {
  1519. int identity = makeNodeIdentity(nodeHandle);
  1520. int expandedNameID = _exptype(identity);
  1521. return m_expandedNameTable.getNamespaceID(expandedNameID);
  1522. }
  1523. /**
  1524. * Given a node handle, return its DOM-style node name. This will
  1525. * include names such as #text or #document.
  1526. *
  1527. * @param nodeHandle the id of the node.
  1528. * @return String Name of this node, which may be an empty string.
  1529. * %REVIEW% Document when empty string is possible...
  1530. * %REVIEW-COMMENT% It should never be empty, should it?
  1531. */
  1532. public abstract String getNodeName(int nodeHandle);
  1533. /**
  1534. * Given a node handle, return the XPath node name. This should be
  1535. * the name as described by the XPath data model, NOT the DOM-style
  1536. * name.
  1537. *
  1538. * @param nodeHandle the id of the node.
  1539. * @return String Name of this node, which may be an empty string.
  1540. */
  1541. public String getNodeNameX(int nodeHandle)
  1542. {
  1543. /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */
  1544. error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");
  1545. return null;
  1546. }
  1547. /**
  1548. * Given a node handle, return its XPath-style localname.
  1549. * (As defined in Namespaces, this is the portion of the name after any
  1550. * colon character).
  1551. *
  1552. * @param nodeHandle the id of the node.
  1553. * @return String Local name of this node.
  1554. */
  1555. public abstract String getLocalName(int nodeHandle);
  1556. /**
  1557. * Given a namespace handle, return the prefix that the namespace decl is
  1558. * mapping.
  1559. * Given a node handle, return the prefix used to map to the namespace.
  1560. *
  1561. * <p> %REVIEW% Are you sure you want "" for no prefix? </p>
  1562. * <p> %REVIEW-COMMENT% I think so... not totally sure. -sb </p>
  1563. *
  1564. * @param nodeHandle the id of the node.
  1565. * @return String prefix of this node's name, or "" if no explicit
  1566. * namespace prefix was given.
  1567. */
  1568. public abstract String getPrefix(int nodeHandle);
  1569. /**
  1570. * Given a node handle, return its DOM-style namespace URI
  1571. * (As defined in Namespaces, this is the declared URI which this node's
  1572. * prefix -- or default in lieu thereof -- was mapped to.)
  1573. *
  1574. * <p>%REVIEW% Null or ""? -sb</p>
  1575. *
  1576. * @param nodeHandle the id of the node.
  1577. * @return String URI value of this node's namespace, or null if no
  1578. * namespace was resolved.
  1579. */
  1580. public abstract String getNamespaceURI(int nodeHandle);
  1581. /**
  1582. * Given a node handle, return its node value. This is mostly
  1583. * as defined by the DOM, but may ignore some conveniences.
  1584. * <p>
  1585. *
  1586. * @param nodeHandle The node id.
  1587. * @return String Value of this node, or null if not
  1588. * meaningful for this node type.
  1589. */
  1590. public abstract String getNodeValue(int nodeHandle);
  1591. /**
  1592. * Given a node handle, return its DOM-style node type.
  1593. * <p>
  1594. * %REVIEW% Generally, returning short is false economy. Return int?
  1595. * %REVIEW% Make assumption that node has already arrived. Is OK?
  1596. *
  1597. * @param nodeHandle The node id.
  1598. * @return int Node type, as per the DOM's Node._NODE constants.
  1599. */
  1600. public short getNodeType(int nodeHandle)
  1601. {
  1602. if (nodeHandle == DTM.NULL)
  1603. return DTM.NULL;
  1604. return m_expandedNameTable.getType(_exptype(makeNodeIdentity(nodeHandle)));
  1605. }
  1606. /**
  1607. * Get the depth level of this node in the tree (equals 1 for
  1608. * a parentless node).
  1609. *
  1610. * @param nodeHandle The node id.
  1611. * @return the number of ancestors, plus one
  1612. * @xsl.usage internal
  1613. */
  1614. public short getLevel(int nodeHandle)
  1615. {
  1616. // Apparently, the axis walker stuff requires levels to count from 1.
  1617. int identity = makeNodeIdentity(nodeHandle);
  1618. return (short) (_level(identity) + 1);
  1619. }
  1620. /**
  1621. * Get the identity of this node in the tree
  1622. *
  1623. * @param nodeHandle The node handle.
  1624. * @return the node identity
  1625. * @xsl.usage internal
  1626. */
  1627. public int getNodeIdent(int nodeHandle)
  1628. {
  1629. /*if (nodeHandle != DTM.NULL)
  1630. return nodeHandle & m_mask;
  1631. else
  1632. return DTM.NULL;*/
  1633. return makeNodeIdentity(nodeHandle);
  1634. }
  1635. /**
  1636. * Get the handle of this node in the tree
  1637. *
  1638. * @param nodeId The node identity.
  1639. * @return the node handle
  1640. * @xsl.usage internal
  1641. */
  1642. public int getNodeHandle(int nodeId)
  1643. {
  1644. /*if (nodeId != DTM.NULL)
  1645. return nodeId | m_dtmIdent;
  1646. else
  1647. return DTM.NULL;*/
  1648. return makeNodeHandle(nodeId);
  1649. }
  1650. // ============== Document query functions ==============
  1651. /**
  1652. * Tests whether DTM DOM implementation implements a specific feature and
  1653. * that feature is supported by this node.
  1654. *
  1655. * @param feature The name of the feature to test.
  1656. * @param versionThis is the version number of the feature to test.
  1657. * If the version is not
  1658. * specified, supporting any version of the feature will cause the
  1659. * method to return <code>true</code>.
  1660. * @param version The version string of the feature requested, may be null.
  1661. * @return Returns <code>true</code> if the specified feature is
  1662. * supported on this node, <code>false</code> otherwise.
  1663. */
  1664. public boolean isSupported(String feature, String version)
  1665. {
  1666. // %TBD%
  1667. return false;
  1668. }
  1669. /**
  1670. * Return the base URI of the document entity. If it is not known
  1671. * (because the document was parsed from a socket connection or from
  1672. * standard input, for example), the value of this property is unknown.
  1673. *
  1674. * @return the document base URI String object or null if unknown.
  1675. */
  1676. public String getDocumentBaseURI()
  1677. {
  1678. return m_documentBaseURI;
  1679. }
  1680. /**
  1681. * Set the base URI of the document entity.
  1682. *
  1683. * @param baseURI the document base URI String object or null if unknown.
  1684. */
  1685. public void setDocumentBaseURI(String baseURI)
  1686. {
  1687. m_documentBaseURI = baseURI;
  1688. }
  1689. /**
  1690. * Return the system identifier of the document entity. If
  1691. * it is not known, the value of this property is unknown.
  1692. *
  1693. * @param nodeHandle The node id, which can be any valid node handle.
  1694. * @return the system identifier String object or null if unknown.
  1695. */
  1696. public String getDocumentSystemIdentifier(int nodeHandle)
  1697. {
  1698. // %REVIEW% OK? -sb
  1699. return m_documentBaseURI;
  1700. }
  1701. /**
  1702. * Return the name of the character encoding scheme
  1703. * in which the document entity is expressed.
  1704. *
  1705. * @param nodeHandle The node id, which can be any valid node handle.
  1706. * @return the document encoding String object.
  1707. * @xsl.usage internal
  1708. */
  1709. public String getDocumentEncoding(int nodeHandle)
  1710. {
  1711. // %REVIEW% OK?? -sb
  1712. return "UTF-8";
  1713. }
  1714. /**
  1715. * Return an indication of the standalone status of the document,
  1716. * either "yes" or "no". This property is derived from the optional
  1717. * standalone document declaration in the XML declaration at the
  1718. * beginning of the document entity, and has no value if there is no
  1719. * standalone document declaration.
  1720. *
  1721. * @param nodeHandle The node id, which can be any valid node handle.
  1722. * @return the document standalone String object, either "yes", "no", or null.
  1723. */
  1724. public String getDocumentStandalone(int nodeHandle)
  1725. {
  1726. return null;
  1727. }
  1728. /**
  1729. * Return a string representing the XML version of the document. This
  1730. * property is derived from the XML declaration optionally present at the
  1731. * beginning of the document entity, and has no value if there is no XML
  1732. * declaration.
  1733. *
  1734. * @param documentHandle The document handle
  1735. *
  1736. * @return the document version String object.
  1737. */
  1738. public String getDocumentVersion(int documentHandle)
  1739. {
  1740. return null;
  1741. }
  1742. /**
  1743. * Return an indication of
  1744. * whether the processor has read the complete DTD. Its value is a
  1745. * boolean. If it is false, then certain properties (indicated in their
  1746. * descriptions below) may be unknown. If it is true, those properties
  1747. * are never unknown.
  1748. *
  1749. * @return <code>true</code> if all declarations were processed;
  1750. * <code>false</code> otherwise.
  1751. */
  1752. public boolean getDocumentAllDeclarationsProcessed()
  1753. {
  1754. // %REVIEW% OK?
  1755. return true;
  1756. }
  1757. /**
  1758. * A document type declaration information item has the following properties:
  1759. *
  1760. * 1. [system identifier] The system identifier of the external subset, if
  1761. * it exists. Otherwise this property has no value.
  1762. *
  1763. * @return the system identifier String object, or null if there is none.
  1764. */
  1765. public abstract String getDocumentTypeDeclarationSystemIdentifier();
  1766. /**
  1767. * Return the public identifier of the external subset,
  1768. * normalized as described in 4.2.2 External Entities [XML]. If there is
  1769. * no external subset or if it has no public identifier, this property
  1770. * has no value.
  1771. *
  1772. * @param the document type declaration handle
  1773. *
  1774. * @return the public identifier String object, or null if there is none.
  1775. */
  1776. public abstract String getDocumentTypeDeclarationPublicIdentifier();
  1777. /**
  1778. * Returns the <code>Element</code> whose <code>ID</code> is given by
  1779. * <code>elementId</code>. If no such element exists, returns
  1780. * <code>DTM.NULL</code>. Behavior is not defined if more than one element
  1781. * has this <code>ID</code>. Attributes (including those
  1782. * with the name "ID") are not of type ID unless so defined by DTD/Schema
  1783. * information available to the DTM implementation.
  1784. * Implementations that do not know whether attributes are of type ID or
  1785. * not are expected to return <code>DTM.NULL</code>.
  1786. *
  1787. * <p>%REVIEW% Presumably IDs are still scoped to a single document,
  1788. * and this operation searches only within a single document, right?
  1789. * Wouldn't want collisions between DTMs in the same process.</p>
  1790. *
  1791. * @param elementId The unique <code>id</code> value for an element.
  1792. * @return The handle of the matching element.
  1793. */
  1794. public abstract int getElementById(String elementId);
  1795. /**
  1796. * The getUnparsedEntityURI function returns the URI of the unparsed
  1797. * entity with the specified name in the same document as the context
  1798. * node (see [3.3 Unparsed Entities]). It returns the empty string if
  1799. * there is no such entity.
  1800. * <p>
  1801. * XML processors may choose to use the System Identifier (if one
  1802. * is provided) to resolve the entity, rather than the URI in the
  1803. * Public Identifier. The details are dependent on the processor, and
  1804. * we would have to support some form of plug-in resolver to handle
  1805. * this properly. Currently, we simply return the System Identifier if
  1806. * present, and hope that it a usable URI or that our caller can
  1807. * map it to one.
  1808. * TODO: Resolve Public Identifiers... or consider changing function name.
  1809. * <p>
  1810. * If we find a relative URI
  1811. * reference, XML expects it to be resolved in terms of the base URI
  1812. * of the document. The DOM doesn't do that for us, and it isn't
  1813. * entirely clear whether that should be done here; currently that's
  1814. * pushed up to a higher level of our application. (Note that DOM Level
  1815. * 1 didn't store the document's base URI.)
  1816. * TODO: Consider resolving Relative URIs.
  1817. * <p>
  1818. * (The DOM's statement that "An XML processor may choose to
  1819. * completely expand entities before the structure model is passed
  1820. * to the DOM" refers only to parsed entities, not unparsed, and hence
  1821. * doesn't affect this function.)
  1822. *
  1823. * @param name A string containing the Entity Name of the unparsed
  1824. * entity.
  1825. *
  1826. * @return String containing the URI of the Unparsed Entity, or an
  1827. * empty string if no such entity exists.
  1828. */
  1829. public abstract String getUnparsedEntityURI(String name);
  1830. // ============== Boolean methods ================
  1831. /**
  1832. * Return true if the xsl:strip-space or xsl:preserve-space was processed
  1833. * during construction of the DTM document.
  1834. *
  1835. * @return true if this DTM supports prestripping.
  1836. */
  1837. public boolean supportsPreStripping()
  1838. {
  1839. return true;
  1840. }
  1841. /**
  1842. * Figure out whether nodeHandle2 should be considered as being later
  1843. * in the document than nodeHandle1, in Document Order as defined
  1844. * by the XPath model. This may not agree with the ordering defined
  1845. * by other XML applications.
  1846. * <p>
  1847. * There are some cases where ordering isn't defined, and neither are
  1848. * the results of this function -- though we'll generally return false.
  1849. *
  1850. * @param nodeHandle1 Node handle to perform position comparison on.
  1851. * @param nodeHandle2 Second Node handle to perform position comparison on .
  1852. *
  1853. * @return true if node1 comes before node2, otherwise return false.
  1854. * You can think of this as
  1855. * <code>(node1.documentOrderPosition <= node2.documentOrderPosition)</code>.
  1856. */
  1857. public boolean isNodeAfter(int nodeHandle1, int nodeHandle2)
  1858. {
  1859. // These return NULL if the node doesn't belong to this document.
  1860. int index1 = makeNodeIdentity(nodeHandle1);
  1861. int index2 = makeNodeIdentity(nodeHandle2);
  1862. return index1!=NULL & index2!=NULL & index1 <= index2;
  1863. }
  1864. /**
  1865. * 2. [element content whitespace] A boolean indicating whether the
  1866. * character is white space appearing within element content (see [XML],
  1867. * 2.10 "White Space Handling"). Note that validating XML processors are
  1868. * required by XML 1.0 to provide this information. If there is no
  1869. * declaration for the containing element, this property has no value for
  1870. * white space characters. If no declaration has been read, but the [all
  1871. * declarations processed] property of the document information item is
  1872. * false (so there may be an unread declaration), then the value of this
  1873. * property is unknown for white space characters. It is always false for
  1874. * characters that are not white space.
  1875. *
  1876. * @param nodeHandle the node ID.
  1877. * @return <code>true</code> if the character data is whitespace;
  1878. * <code>false</code> otherwise.
  1879. */
  1880. public boolean isCharacterElementContentWhitespace(int nodeHandle)
  1881. {
  1882. // %TBD%
  1883. return false;
  1884. }
  1885. /**
  1886. * 10. [all declarations processed] This property is not strictly speaking
  1887. * part of the infoset of the document. Rather it is an indication of
  1888. * whether the processor has read the complete DTD. Its value is a
  1889. * boolean. If it is false, then certain properties (indicated in their
  1890. * descriptions below) may be unknown. If it is true, those properties
  1891. * are never unknown.
  1892. *
  1893. * @param the document handle
  1894. *
  1895. * @param documentHandle A node handle that must identify a document.
  1896. * @return <code>true</code> if all declarations were processed;
  1897. * <code>false</code> otherwise.
  1898. */
  1899. public boolean isDocumentAllDeclarationsProcessed(int documentHandle)
  1900. {
  1901. return true;
  1902. }
  1903. /**
  1904. * 5. [specified] A flag indicating whether this attribute was actually
  1905. * specified in the start-tag of its element, or was defaulted from the
  1906. * DTD.
  1907. *
  1908. * @param attributeHandle The attribute handle in question.
  1909. *
  1910. * @return <code>true</code> if the attribute was specified;
  1911. * <code>false</code> if it was defaulted.
  1912. */
  1913. public abstract boolean isAttributeSpecified(int attributeHandle);
  1914. // ========== Direct SAX Dispatch, for optimization purposes ========
  1915. /**
  1916. * Directly call the
  1917. * characters method on the passed ContentHandler for the
  1918. * string-value of the given node (see http://www.w3.org/TR/xpath#data-model
  1919. * for the definition of a node's string-value). Multiple calls to the
  1920. * ContentHandler's characters methods may well occur for a single call to
  1921. * this method.
  1922. *
  1923. * @param nodeHandle The node ID.
  1924. * @param ch A non-null reference to a ContentHandler.
  1925. * @param normalize true if the content should be normalized according to
  1926. * the rules for the XPath
  1927. * <a href="http://www.w3.org/TR/xpath#function-normalize-space">normalize-space</a>
  1928. * function.
  1929. *
  1930. * @throws org.xml.sax.SAXException
  1931. */
  1932. public abstract void dispatchCharactersEvents(
  1933. int nodeHandle, org.xml.sax.ContentHandler ch, boolean normalize)
  1934. throws org.xml.sax.SAXException;
  1935. /**
  1936. * Directly create SAX parser events from a subtree.
  1937. *
  1938. * @param nodeHandle The node ID.
  1939. * @param ch A non-null reference to a ContentHandler.
  1940. *
  1941. * @throws org.xml.sax.SAXException
  1942. */
  1943. public abstract void dispatchToEvents(
  1944. int nodeHandle, org.xml.sax.ContentHandler ch)
  1945. throws org.xml.sax.SAXException;
  1946. /**
  1947. * Return an DOM node for the given node.
  1948. *
  1949. * @param nodeHandle The node ID.
  1950. *
  1951. * @return A node representation of the DTM node.
  1952. */
  1953. public org.w3c.dom.Node getNode(int nodeHandle)
  1954. {
  1955. return new DTMNodeProxy(this, nodeHandle);
  1956. }
  1957. // ==== Construction methods (may not be supported by some implementations!) =====
  1958. /**
  1959. * Append a child to the end of the document. Please note that the node
  1960. * is always cloned if it is owned by another document.
  1961. *
  1962. * <p>%REVIEW% "End of the document" needs to be defined more clearly.
  1963. * Does it become the last child of the Document? Of the root element?</p>
  1964. *
  1965. * @param newChild Must be a valid new node handle.
  1966. * @param clone true if the child should be cloned into the document.
  1967. * @param cloneDepth if the clone argument is true, specifies that the
  1968. * clone should include all it's children.
  1969. */
  1970. public void appendChild(int newChild, boolean clone, boolean cloneDepth)
  1971. {
  1972. error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"appendChild not yet supported!");
  1973. }
  1974. /**
  1975. * Append a text node child that will be constructed from a string,
  1976. * to the end of the document.
  1977. *
  1978. * <p>%REVIEW% "End of the document" needs to be defined more clearly.
  1979. * Does it become the last child of the Document? Of the root element?</p>
  1980. *
  1981. * @param str Non-null reverence to a string.
  1982. */
  1983. public void appendTextChild(String str)
  1984. {
  1985. error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"appendTextChild not yet supported!");
  1986. }
  1987. /**
  1988. * Simple error for asserts and the like.
  1989. *
  1990. * @param msg Error message to report.
  1991. */
  1992. protected void error(String msg)
  1993. {
  1994. throw new DTMException(msg);
  1995. }
  1996. /**
  1997. * Find out whether or not to strip whispace nodes.
  1998. *
  1999. *
  2000. * @return whether or not to strip whispace nodes.
  2001. */
  2002. protected boolean getShouldStripWhitespace()
  2003. {
  2004. return m_shouldStripWS;
  2005. }
  2006. /**
  2007. * Set whether to strip whitespaces and push in current value of
  2008. * m_shouldStripWS in m_shouldStripWhitespaceStack.
  2009. *
  2010. * @param shouldStrip Flag indicating whether to strip whitespace nodes
  2011. */
  2012. protected void pushShouldStripWhitespace(boolean shouldStrip)
  2013. {
  2014. m_shouldStripWS = shouldStrip;
  2015. if (null != m_shouldStripWhitespaceStack)
  2016. m_shouldStripWhitespaceStack.push(shouldStrip);
  2017. }
  2018. /**
  2019. * Set whether to strip whitespaces at this point by popping out
  2020. * m_shouldStripWhitespaceStack.
  2021. *
  2022. */
  2023. protected void popShouldStripWhitespace()
  2024. {
  2025. if (null != m_shouldStripWhitespaceStack)
  2026. m_shouldStripWS = m_shouldStripWhitespaceStack.popAndTop();
  2027. }
  2028. /**
  2029. * Set whether to strip whitespaces and set the top of the stack to
  2030. * the current value of m_shouldStripWS.
  2031. *
  2032. *
  2033. * @param shouldStrip Flag indicating whether to strip whitespace nodes
  2034. */
  2035. protected void setShouldStripWhitespace(boolean shouldStrip)
  2036. {
  2037. m_shouldStripWS = shouldStrip;
  2038. if (null != m_shouldStripWhitespaceStack)
  2039. m_shouldStripWhitespaceStack.setTop(shouldStrip);
  2040. }
  2041. /**
  2042. * A dummy routine to satisify the abstract interface. If the DTM
  2043. * implememtation that extends the default base requires notification
  2044. * of registration, they can override this method.
  2045. */
  2046. public void documentRegistration()
  2047. {
  2048. }
  2049. /**
  2050. * A dummy routine to satisify the abstract interface. If the DTM
  2051. * implememtation that extends the default base requires notification
  2052. * when the document is being released, they can override this method
  2053. */
  2054. public void documentRelease()
  2055. {
  2056. }
  2057. /**
  2058. * Migrate a DTM built with an old DTMManager to a new DTMManager.
  2059. * After the migration, the new DTMManager will treat the DTM as
  2060. * one that is built by itself.
  2061. * This is used to support DTM sharing between multiple transformations.
  2062. * @param manager the DTMManager
  2063. */
  2064. public void migrateTo(DTMManager mgr)
  2065. {
  2066. m_mgr = mgr;
  2067. if(mgr instanceof DTMManagerDefault)
  2068. m_mgrDefault=(DTMManagerDefault)mgr;
  2069. }
  2070. /** Query which DTMManager this DTM is currently being handled by.
  2071. *
  2072. * %REVEW% Should this become part of the base DTM API?
  2073. *
  2074. * @return a DTMManager, or null if this is a "stand-alone" DTM.
  2075. */
  2076. public DTMManager getManager()
  2077. {
  2078. return m_mgr;
  2079. }
  2080. /** Query which DTMIDs this DTM is currently using within the DTMManager.
  2081. *
  2082. * %REVEW% Should this become part of the base DTM API?
  2083. *
  2084. * @return an IntVector, or null if this is a "stand-alone" DTM.
  2085. */
  2086. public SuballocatedIntVector getDTMIDs()
  2087. {
  2088. if(m_mgr==null) return null;
  2089. return m_dtmIdent;
  2090. }
  2091. }