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