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 java.util.Hashtable;
  60. //import java.util.Stack;
  61. import java.util.Vector;
  62. import javax.xml.transform.SourceLocator;
  63. import org.apache.xml.dtm.ref.ChunkedIntArray;
  64. import org.apache.xml.utils.FastStringBuffer;
  65. import org.xml.sax.ContentHandler;
  66. import org.xml.sax.Locator;
  67. import org.xml.sax.Attributes;
  68. import org.xml.sax.ext.LexicalHandler;
  69. import org.apache.xml.utils.XMLString;
  70. import org.apache.xml.utils.XMLStringFactory;
  71. /**
  72. * This is the implementation of the DTM document interface. It receives
  73. * requests from an XML content handler similar to that of an XML DOM or SAX parser
  74. * to store information from the xml document in an array based
  75. * dtm table structure. This informtion is used later for document navigation,
  76. * query, and SAX event dispatch functions. The DTM can also be used directly as a
  77. * document composition model for an application. The requests received are:
  78. * <ul>
  79. * <li>initiating DTM to set the doc handle</li>
  80. * <li>resetting DTM for data structure reuse</li>
  81. * <li>hinting the end of document to adjust the end of data structure pointers</li>
  82. * <li>createnodes (element, comment, text, attribute, ....)</li>
  83. * <li>hinting the end of an element to patch parent and siblings<li>
  84. * <li>setting application provided symbol name stringpool data structures</li>
  85. * </ul>
  86. * <p>State: In progress!!</p>
  87. *
  88. * %REVIEW% I _think_ the SAX convention is that "no namespace" is expressed
  89. * as "" rather than as null (which is the DOM's convention). What should
  90. * DTM expect? What should it do with the other?
  91. *
  92. * <p>Origin: the implemention is a composite logic based on the DTM of XalanJ1 and
  93. * DocImpl, DocumentImpl, ElementImpl, TextImpl, etc. of XalanJ2</p>
  94. */
  95. public class DTMDocumentImpl
  96. implements DTM, org.xml.sax.ContentHandler, org.xml.sax.ext.LexicalHandler
  97. {
  98. // Number of lower bits used to represent node index.
  99. protected static final byte DOCHANDLE_SHIFT = 22;
  100. // Masks the lower order of node handle.
  101. // Same as {@link DTMConstructor.IDENT_NODE_DEFAULT}
  102. protected static final int NODEHANDLE_MASK = (1 << (DOCHANDLE_SHIFT + 1)) - 1;
  103. // Masks the higher order Document handle
  104. // Same as {@link DTMConstructor.IDENT_DOC_DEFAULT}
  105. protected static final int DOCHANDLE_MASK = -1 - NODEHANDLE_MASK;
  106. int m_docHandle = NULL; // masked document handle for this dtm document
  107. int m_docElement = NULL; // nodeHandle to the root of the actual dtm doc content
  108. // Context for parse-and-append operations
  109. int currentParent = 0; // current parent - default is document root
  110. int previousSibling = 0; // previous sibling - no previous sibling
  111. protected int m_currentNode = -1; // current node
  112. // The tree under construction can itself be used as
  113. // the element stack, so m_elemStack isn't needed.
  114. //protected Stack m_elemStack = new Stack(); // element stack
  115. private boolean previousSiblingWasParent = false;
  116. // Local cache for record-at-a-time fetch
  117. int gotslot[] = new int[4];
  118. // endDocument recieved?
  119. private boolean done = false;
  120. boolean m_isError = false;
  121. private final boolean DEBUG = false;
  122. /** The document base URI. */
  123. protected String m_documentBaseURI;
  124. /** If we're building the model incrementally on demand, we need to
  125. * be able to tell the source when to send us more data.
  126. *
  127. * Note that if this has not been set, and you attempt to read ahead
  128. * of the current build point, we'll probably throw a null-pointer
  129. * exception. We could try to wait-and-retry instead, as a very poor
  130. * fallback, but that has all the known problems with multithreading
  131. * on multiprocessors and we Don't Want to Go There.
  132. *
  133. * @see setIncrementalSAXSource
  134. */
  135. private IncrementalSAXSource m_incrSAXSource=null;
  136. // ========= DTM data structure declarations. ==============
  137. // nodes array: integer array blocks to hold the first level reference of the nodes,
  138. // each reference slot is addressed by a nodeHandle index value.
  139. // Assumes indices are not larger than {@link NODEHANDLE_MASK}
  140. // ({@link DOCHANDLE_SHIFT} bits).
  141. ChunkedIntArray nodes = new ChunkedIntArray(4);
  142. // text/comment table: string buffer to hold the text string values of the document,
  143. // each of which is addressed by the absolute offset and length in the buffer
  144. private FastStringBuffer m_char = new FastStringBuffer();
  145. // Start of string currently being accumulated into m_char;
  146. // needed because the string may be appended in several chunks.
  147. private int m_char_current_start=0;
  148. // %TBD% INITIALIZATION/STARTUP ISSUES
  149. // -- Should we really be creating these, or should they be
  150. // passed in from outside? Scott want to be able to share
  151. // pools across multiple documents, so setting them here is
  152. // probably not the right default.
  153. private DTMStringPool m_localNames = new DTMStringPool();
  154. private DTMStringPool m_nsNames = new DTMStringPool();
  155. private DTMStringPool m_prefixNames = new DTMStringPool();
  156. // %TBD% If we use the current ExpandedNameTable mapper, it
  157. // needs to be bound to the NS and local name pools. Which
  158. // means it needs to attach to them AFTER we've resolved their
  159. // startup. Or it needs to attach to this document and
  160. // retrieve them each time. Or this needs to be
  161. // an interface _implemented_ by this class... which might be simplest!
  162. private ExpandedNameTable m_expandedNames=
  163. new ExpandedNameTable(m_localNames,m_nsNames);
  164. private XMLStringFactory m_xsf;
  165. /**
  166. * Construct a DTM.
  167. *
  168. * @param documentNumber the ID number assigned to this document.
  169. * It will be shifted up into the high bits and returned as part of
  170. * all node ID numbers, so those IDs indicate which document they
  171. * came from as well as a location within the document. It is the
  172. * DTMManager's responsibility to assign a unique number to each
  173. * document.
  174. */
  175. public DTMDocumentImpl(DTMManager mgr, int documentNumber,
  176. DTMWSFilter whiteSpaceFilter,
  177. XMLStringFactory xstringfactory){
  178. initDocument(documentNumber); // clear nodes and document handle
  179. m_xsf = xstringfactory;
  180. }
  181. /** Bind a IncrementalSAXSource to this DTM. If we discover we need nodes
  182. * that have not yet been built, we will ask this object to send us more
  183. * events, and it will manage interactions with its data sources.
  184. *
  185. * Note that we do not actually build the IncrementalSAXSource, since we don't
  186. * know what source it's reading from, what thread that source will run in,
  187. * or when it will run.
  188. *
  189. * @param source The IncrementalSAXSource that we want to recieve events from
  190. * on demand.
  191. */
  192. public void setIncrementalSAXSource(IncrementalSAXSource source)
  193. {
  194. m_incrSAXSource=source;
  195. // Establish SAX-stream link so we can receive the requested data
  196. source.setContentHandler(this);
  197. source.setLexicalHandler(this);
  198. // Are the following really needed? IncrementalSAXSource doesn't yet
  199. // support them, and they're mostly no-ops here...
  200. //source.setErrorHandler(this);
  201. //source.setDTDHandler(this);
  202. //source.setDeclHandler(this);
  203. }
  204. /**
  205. * Wrapper for ChunkedIntArray.append, to automatically update the
  206. * previous sibling's "next" reference (if necessary) and periodically
  207. * wake a reader who may have encountered incomplete data and entered
  208. * a wait state.
  209. * @param w0 int As in ChunkedIntArray.append
  210. * @param w1 int As in ChunkedIntArray.append
  211. * @param w2 int As in ChunkedIntArray.append
  212. * @param w3 int As in ChunkedIntArray.append
  213. * @return int As in ChunkedIntArray.append
  214. * @see ChunkedIntArray.append
  215. */
  216. private final int appendNode(int w0, int w1, int w2, int w3)
  217. {
  218. // A decent compiler may inline this.
  219. int slotnumber = nodes.appendSlot(w0, w1, w2, w3);
  220. if (DEBUG) System.out.println(slotnumber+": "+w0+" "+w1+" "+w2+" "+w3);
  221. if (previousSiblingWasParent)
  222. nodes.writeEntry(previousSibling,2,slotnumber);
  223. previousSiblingWasParent = false; // Set the default; endElement overrides
  224. return slotnumber;
  225. }
  226. // ========= DTM Implementation Control Functions. ==============
  227. /**
  228. * Set an implementation dependent feature.
  229. * <p>
  230. * %REVIEW% Do we really expect to set features on DTMs?
  231. *
  232. * @param featureId A feature URL.
  233. * @param state true if this feature should be on, false otherwise.
  234. */
  235. public void setFeature(String featureId, boolean state) {};
  236. /**
  237. * Set a reference pointer to the element name symbol table.
  238. * %REVIEW% Should this really be Public? Changing it while
  239. * DTM is in use would be a disaster.
  240. *
  241. * @param poolRef DTMStringPool reference to an instance of table.
  242. */
  243. public void setLocalNameTable(DTMStringPool poolRef) {
  244. m_localNames = poolRef;
  245. }
  246. /**
  247. * Get a reference pointer to the element name symbol table.
  248. *
  249. * @return DTMStringPool reference to an instance of table.
  250. */
  251. public DTMStringPool getLocalNameTable() {
  252. return m_localNames;
  253. }
  254. /**
  255. * Set a reference pointer to the namespace URI symbol table.
  256. * %REVIEW% Should this really be Public? Changing it while
  257. * DTM is in use would be a disaster.
  258. *
  259. * @param poolRef DTMStringPool reference to an instance of table.
  260. */
  261. public void setNsNameTable(DTMStringPool poolRef) {
  262. m_nsNames = poolRef;
  263. }
  264. /**
  265. * Get a reference pointer to the namespace URI symbol table.
  266. *
  267. * @return DTMStringPool reference to an instance of table.
  268. */
  269. public DTMStringPool getNsNameTable() {
  270. return m_nsNames;
  271. }
  272. /**
  273. * Set a reference pointer to the prefix name symbol table.
  274. * %REVIEW% Should this really be Public? Changing it while
  275. * DTM is in use would be a disaster.
  276. *
  277. * @param poolRef DTMStringPool reference to an instance of table.
  278. */
  279. public void setPrefixNameTable(DTMStringPool poolRef) {
  280. m_prefixNames = poolRef;
  281. }
  282. /**
  283. * Get a reference pointer to the prefix name symbol table.
  284. *
  285. * @return DTMStringPool reference to an instance of table.
  286. */
  287. public DTMStringPool getPrefixNameTable() {
  288. return m_prefixNames;
  289. }
  290. /**
  291. * Set a reference pointer to the content-text repository
  292. *
  293. * @param bufferRef FastStringBuffer reference to an instance of
  294. * buffer
  295. */
  296. void setContentBuffer(FastStringBuffer buffer) {
  297. m_char = buffer;
  298. }
  299. /**
  300. * Get a reference pointer to the content-text repository
  301. *
  302. * @return FastStringBuffer reference to an instance of buffer
  303. */
  304. FastStringBuffer getContentBuffer() {
  305. return m_char;
  306. }
  307. /** getContentHandler returns "our SAX builder" -- the thing that
  308. * someone else should send SAX events to in order to extend this
  309. * DTM model.
  310. *
  311. * @return null if this model doesn't respond to SAX events,
  312. * "this" if the DTM object has a built-in SAX ContentHandler,
  313. * the IncrementalSAXSource if we're bound to one and should receive
  314. * the SAX stream via it for incremental build purposes...
  315. * */
  316. public org.xml.sax.ContentHandler getContentHandler()
  317. {
  318. if (m_incrSAXSource instanceof IncrementalSAXSource_Filter)
  319. return (ContentHandler) m_incrSAXSource;
  320. else
  321. return this;
  322. }
  323. /**
  324. * Return this DTM's lexical handler.
  325. *
  326. * %REVIEW% Should this return null if constrution already done/begun?
  327. *
  328. * @return null if this model doesn't respond to lexical SAX events,
  329. * "this" if the DTM object has a built-in SAX ContentHandler,
  330. * the IncrementalSAXSource if we're bound to one and should receive
  331. * the SAX stream via it for incremental build purposes...
  332. */
  333. public LexicalHandler getLexicalHandler()
  334. {
  335. if (m_incrSAXSource instanceof IncrementalSAXSource_Filter)
  336. return (LexicalHandler) m_incrSAXSource;
  337. else
  338. return this;
  339. }
  340. /**
  341. * Return this DTM's EntityResolver.
  342. *
  343. * @return null if this model doesn't respond to SAX entity ref events.
  344. */
  345. public org.xml.sax.EntityResolver getEntityResolver()
  346. {
  347. return null;
  348. }
  349. /**
  350. * Return this DTM's DTDHandler.
  351. *
  352. * @return null if this model doesn't respond to SAX dtd events.
  353. */
  354. public org.xml.sax.DTDHandler getDTDHandler()
  355. {
  356. return null;
  357. }
  358. /**
  359. * Return this DTM's ErrorHandler.
  360. *
  361. * @return null if this model doesn't respond to SAX error events.
  362. */
  363. public org.xml.sax.ErrorHandler getErrorHandler()
  364. {
  365. return null;
  366. }
  367. /**
  368. * Return this DTM's DeclHandler.
  369. *
  370. * @return null if this model doesn't respond to SAX Decl events.
  371. */
  372. public org.xml.sax.ext.DeclHandler getDeclHandler()
  373. {
  374. return null;
  375. }
  376. /** @return true iff we're building this model incrementally (eg
  377. * we're partnered with a IncrementalSAXSource) and thus require that the
  378. * transformation and the parse run simultaneously. Guidance to the
  379. * DTMManager.
  380. * */
  381. public boolean needsTwoThreads()
  382. {
  383. return null!=m_incrSAXSource;
  384. }
  385. //================================================================
  386. // ========= SAX2 ContentHandler methods =========
  387. // Accept SAX events, use them to build/extend the DTM tree.
  388. // Replaces the deprecated DocumentHandler interface.
  389. public void characters(char[] ch, int start, int length)
  390. throws org.xml.sax.SAXException
  391. {
  392. // Actually creating the text node is handled by
  393. // processAccumulatedText(); here we just accumulate the
  394. // characters into the buffer.
  395. m_char.append(ch,start,length);
  396. }
  397. // Flush string accumulation into a text node
  398. private void processAccumulatedText()
  399. {
  400. int len=m_char.length();
  401. if(len!=m_char_current_start)
  402. {
  403. // The FastStringBuffer has been previously agreed upon
  404. appendTextChild(m_char_current_start,len-m_char_current_start);
  405. m_char_current_start=len;
  406. }
  407. }
  408. public void endDocument()
  409. throws org.xml.sax.SAXException
  410. {
  411. // May need to tell the low-level builder code to pop up a level.
  412. // There _should't_ be any significant pending text at this point.
  413. appendEndDocument();
  414. }
  415. public void endElement(java.lang.String namespaceURI, java.lang.String localName,
  416. java.lang.String qName)
  417. throws org.xml.sax.SAXException
  418. {
  419. processAccumulatedText();
  420. // No args but we do need to tell the low-level builder code to
  421. // pop up a level.
  422. appendEndElement();
  423. }
  424. public void endPrefixMapping(java.lang.String prefix)
  425. throws org.xml.sax.SAXException
  426. {
  427. // No-op
  428. }
  429. public void ignorableWhitespace(char[] ch, int start, int length)
  430. throws org.xml.sax.SAXException
  431. {
  432. // %TBD% I believe ignorable text isn't part of the DTM model...?
  433. }
  434. public void processingInstruction(java.lang.String target, java.lang.String data)
  435. throws org.xml.sax.SAXException
  436. {
  437. processAccumulatedText();
  438. // %TBD% Which pools do target and data go into?
  439. }
  440. public void setDocumentLocator(Locator locator)
  441. {
  442. // No-op for DTM
  443. }
  444. public void skippedEntity(java.lang.String name)
  445. throws org.xml.sax.SAXException
  446. {
  447. processAccumulatedText();
  448. //%TBD%
  449. }
  450. public void startDocument()
  451. throws org.xml.sax.SAXException
  452. {
  453. appendStartDocument();
  454. }
  455. public void startElement(java.lang.String namespaceURI, java.lang.String localName,
  456. java.lang.String qName, Attributes atts)
  457. throws org.xml.sax.SAXException
  458. {
  459. processAccumulatedText();
  460. // %TBD% Split prefix off qname
  461. String prefix=null;
  462. int colon=qName.indexOf(':');
  463. if(colon>0)
  464. prefix=qName.substring(0,colon);
  465. // %TBD% Where do we pool expandedName, or is it just the union, or...
  466. /**/System.out.println("Prefix="+prefix+" index="+m_prefixNames.stringToIndex(prefix));
  467. appendStartElement(m_nsNames.stringToIndex(namespaceURI),
  468. m_localNames.stringToIndex(localName),
  469. m_prefixNames.stringToIndex(prefix)); /////// %TBD%
  470. // %TBD% I'm assuming that DTM will require resequencing of
  471. // NS decls before other attrs, hence two passes are taken.
  472. // %TBD% Is there an easier way to test for NSDecl?
  473. int nAtts=(atts==null) ? 0 : atts.getLength();
  474. // %TBD% Countdown is more efficient if nobody cares about sequence.
  475. for(int i=nAtts-1;i>=0;--i)
  476. {
  477. qName=atts.getQName(i);
  478. if(qName.startsWith("xmlns:") || "xmlns".equals(qName))
  479. {
  480. prefix=null;
  481. colon=qName.indexOf(':');
  482. if(colon>0)
  483. {
  484. prefix=qName.substring(0,colon);
  485. }
  486. else
  487. {
  488. // %REVEIW% Null or ""?
  489. prefix=null; // Default prefix
  490. }
  491. appendNSDeclaration(
  492. m_prefixNames.stringToIndex(prefix),
  493. m_nsNames.stringToIndex(atts.getValue(i)),
  494. atts.getType(i).equalsIgnoreCase("ID"));
  495. }
  496. }
  497. for(int i=nAtts-1;i>=0;--i)
  498. {
  499. qName=atts.getQName(i);
  500. if(!(qName.startsWith("xmlns:") || "xmlns".equals(qName)))
  501. {
  502. // %TBD% I hate having to extract the prefix into a new
  503. // string when we may never use it. Consider pooling whole
  504. // qNames, which are already strings?
  505. prefix=null;
  506. colon=qName.indexOf(':');
  507. if(colon>0)
  508. {
  509. prefix=qName.substring(0,colon);
  510. localName=qName.substring(colon+1);
  511. }
  512. else
  513. {
  514. prefix=""; // Default prefix
  515. localName=qName;
  516. }
  517. m_char.append(atts.getValue(i)); // Single-string value
  518. int contentEnd=m_char.length();
  519. if(!("xmlns".equals(prefix) || "xmlns".equals(qName)))
  520. appendAttribute(m_nsNames.stringToIndex(atts.getURI(i)),
  521. m_localNames.stringToIndex(localName),
  522. m_prefixNames.stringToIndex(prefix),
  523. atts.getType(i).equalsIgnoreCase("ID"),
  524. m_char_current_start, contentEnd-m_char_current_start);
  525. m_char_current_start=contentEnd;
  526. }
  527. }
  528. }
  529. public void startPrefixMapping(java.lang.String prefix, java.lang.String uri)
  530. throws org.xml.sax.SAXException
  531. {
  532. // No-op in DTM, handled during element/attr processing?
  533. }
  534. //
  535. // LexicalHandler support. Not all SAX2 parsers support these events
  536. // but we may want to pass them through when they exist...
  537. //
  538. public void comment(char[] ch, int start, int length)
  539. throws org.xml.sax.SAXException
  540. {
  541. processAccumulatedText();
  542. m_char.append(ch,start,length); // Single-string value
  543. appendComment(m_char_current_start,length);
  544. m_char_current_start+=length;
  545. }
  546. public void endCDATA()
  547. throws org.xml.sax.SAXException
  548. {
  549. // No-op in DTM
  550. }
  551. public void endDTD()
  552. throws org.xml.sax.SAXException
  553. {
  554. // No-op in DTM
  555. }
  556. public void endEntity(java.lang.String name)
  557. throws org.xml.sax.SAXException
  558. {
  559. // No-op in DTM
  560. }
  561. public void startCDATA()
  562. throws org.xml.sax.SAXException
  563. {
  564. // No-op in DTM
  565. }
  566. public void startDTD(java.lang.String name, java.lang.String publicId,
  567. java.lang.String systemId)
  568. throws org.xml.sax.SAXException
  569. {
  570. // No-op in DTM
  571. }
  572. public void startEntity(java.lang.String name)
  573. throws org.xml.sax.SAXException
  574. {
  575. // No-op in DTM
  576. }
  577. //================================================================
  578. // ========= Document Handler Functions =========
  579. // %REVIEW% jjk -- DocumentHandler is SAX Level 1, and deprecated....
  580. // and this wasn't a fully compliant or declared implementation of that API
  581. // in any case. Phase out in favor of SAX2 ContentHandler/LexicalHandler
  582. /**
  583. * Reset a dtm document to its initial (empty) state.
  584. *
  585. * The DTMManager will invoke this method when the dtm is created.
  586. *
  587. * @param docHandle int the handle for the DTM document.
  588. */
  589. final void initDocument(int documentNumber)
  590. {
  591. // save masked DTM document handle
  592. m_docHandle = documentNumber<<DOCHANDLE_SHIFT;
  593. // Initialize the doc -- no parent, no next-sib
  594. nodes.writeSlot(0,DOCUMENT_NODE,-1,-1,0);
  595. // wait for the first startElement to create the doc root node
  596. done = false;
  597. }
  598. // /**
  599. // * Receive hint of the end of a document.
  600. // *
  601. // * <p>The content handler will invoke this method only once, and it will
  602. // * be the last method invoked during the parse. The handler shall not
  603. // * not invoke this method until it has either abandoned parsing
  604. // * (because of an unrecoverable error) or reached the end of
  605. // * input.</p>
  606. // */
  607. // public void documentEnd()
  608. // {
  609. // done = true;
  610. // // %TBD% may need to notice the last slot number and slot count to avoid
  611. // // residual data from provious use of this DTM
  612. // }
  613. // /**
  614. // * Receive notification of the beginning of a document.
  615. // *
  616. // * <p>The SAX parser will invoke this method only once, before any
  617. // * other methods in this interface.</p>
  618. // */
  619. // public void reset()
  620. // {
  621. // // %TBD% reset slot 0 to indicate ChunkedIntArray reuse or wait for
  622. // // the next initDocument().
  623. // m_docElement = NULL; // reset nodeHandle to the root of the actual dtm doc content
  624. // initDocument(0);
  625. // }
  626. // /**
  627. // * Factory method; creates an Element node in this document.
  628. // *
  629. // * The node created will be chained according to its natural order of request
  630. // * received. %TBD% It can be rechained later via the optional DTM writable interface.
  631. // *
  632. // * <p>The XML content handler will invoke endElement() method after all
  633. // * of the element's content are processed in order to give DTM the indication
  634. // * to prepare and patch up parent and sibling node pointers.</p>
  635. // *
  636. // * <p>The following interface for createElement will use an index value corresponds
  637. // * to the symbol entry in the DTMDStringPool based symbol tables.</p>
  638. // *
  639. // * @param nsIndex The namespace of the node
  640. // * @param nameIndex The element name.
  641. // * @see #endElement
  642. // * @see org.xml.sax.Attributes
  643. // * @return nodeHandle int of the element created
  644. // */
  645. // public int createElement(int nsIndex, int nameIndex, Attributes atts)
  646. // {
  647. // // do document root node creation here on the first element, create nodes for
  648. // // this element and its attributes, store the element, namespace, and attritute
  649. // // name indexes to the nodes array, keep track of the current node and parent
  650. // // element used
  651. // // W0 High: Namespace Low: Node Type
  652. // int w0 = (nsIndex << 16) | ELEMENT_NODE;
  653. // // W1: Parent
  654. // int w1 = currentParent;
  655. // // W2: Next (initialized as 0)
  656. // int w2 = 0;
  657. // // W3: Tagname
  658. // int w3 = nameIndex;
  659. // //int ourslot = nodes.appendSlot(w0, w1, w2, w3);
  660. // int ourslot = appendNode(w0, w1, w2, w3);
  661. // currentParent = ourslot;
  662. // previousSibling = 0;
  663. // setAttributes(atts);
  664. // // set the root element pointer when creating the first element node
  665. // if (m_docElement == NULL)
  666. // m_docElement = ourslot;
  667. // return (m_docHandle | ourslot);
  668. // }
  669. // // Factory method to create an Element node not associated with a given name space
  670. // // using String value parameters passed in from a content handler or application
  671. // /**
  672. // * Factory method; creates an Element node not associated with a given name space in this document.
  673. // *
  674. // * The node created will be chained according to its natural order of request
  675. // * received. %TBD% It can be rechained later via the optional DTM writable interface.
  676. // *
  677. // * <p>The XML content handler or application will invoke endElement() method after all
  678. // * of the element's content are processed in order to give DTM the indication
  679. // * to prepare and patch up parent and sibling node pointers.</p>
  680. // *
  681. // * <p>The following parameters for createElement contains raw string values for name
  682. // * symbols used in an Element node.</p>
  683. // *
  684. // * @param name String the element name, including the prefix if any.
  685. // * @param atts The attributes attached to the element, if any.
  686. // * @see #endElement
  687. // * @see org.xml.sax.Attributes
  688. // */
  689. // public int createElement(String name, Attributes atts)
  690. // {
  691. // // This method wraps around the index valued interface of the createElement interface.
  692. // // The raw string values are stored into the current DTM name symbol tables. The method
  693. // // method will then use the index values returned to invoke the other createElement()
  694. // // onverted to index values modified to match a
  695. // // method.
  696. // int nsIndex = NULL;
  697. // int nameIndex = m_localNames.stringToIndex(name);
  698. // // note - there should be no prefix separator in the name because it is not associated
  699. // // with a name space
  700. // return createElement(nsIndex, nameIndex, atts);
  701. // }
  702. // // Factory method to create an Element node associated with a given name space
  703. // // using String value parameters passed in from a content handler or application
  704. // /**
  705. // * Factory method; creates an Element node associated with a given name space in this document.
  706. // *
  707. // * The node created will be chained according to its natural order of request
  708. // * received. %TBD% It can be rechained later via the optional DTM writable interface.
  709. // *
  710. // * <p>The XML content handler or application will invoke endElement() method after all
  711. // * of the element's content are processed in order to give DTM the indication
  712. // * to prepare and patch up parent and sibling node pointers.</p>
  713. // *
  714. // * <p>The following parameters for createElementNS contains raw string values for name
  715. // * symbols used in an Element node.</p>
  716. // *
  717. // * @param ns String the namespace of the node
  718. // * @param name String the element name, including the prefix if any.
  719. // * @param atts The attributes attached to the element, if any.
  720. // * @see #endElement
  721. // * @see org.xml.sax.Attributes
  722. // */
  723. // public int createElementNS(String ns, String name, Attributes atts)
  724. // {
  725. // // This method wraps around the index valued interface of the createElement interface.
  726. // // The raw string values are stored into the current DTM name symbol tables. The method
  727. // // method will then use the index values returned to invoke the other createElement()
  728. // // onverted to index values modified to match a
  729. // // method.
  730. // int nsIndex = m_nsNames.stringToIndex(ns);
  731. // int nameIndex = m_localNames.stringToIndex(name);
  732. // // The prefixIndex is not needed by the indexed interface of the createElement method
  733. // int prefixSep = name.indexOf(":");
  734. // int prefixIndex = m_prefixNames.stringToIndex(name.substring(0, prefixSep));
  735. // return createElement(nsIndex, nameIndex, atts);
  736. // }
  737. // /**
  738. // * Receive an indication for the end of an element.
  739. // *
  740. // * <p>The XML content handler will invoke this method at the end of every
  741. // * element in the XML document to give hint its time to pop up the current
  742. // * element and parent and patch up parent and sibling pointers if necessary
  743. // *
  744. // * <p>%tbd% The following interface may need to be modified to match a
  745. // * coordinated access to the DTMDStringPool based symbol tables.</p>
  746. // *
  747. // * @param ns the namespace of the element
  748. // * @param localName The local part of the qualified name of the element
  749. // * @param name The element name
  750. // */
  751. // public void endElement(String ns, String name)
  752. // {
  753. // // pop up the stacks
  754. // //
  755. // if (previousSiblingWasParent)
  756. // nodes.writeEntry(previousSibling, 2, NULL);
  757. // // Pop parentage
  758. // previousSibling = currentParent;
  759. // nodes.readSlot(currentParent, gotslot);
  760. // currentParent = gotslot[1] & 0xFFFF;
  761. // // The element just being finished will be
  762. // // the previous sibling for the next operation
  763. // previousSiblingWasParent = true;
  764. // // Pop a level of namespace table
  765. // // namespaceTable.removeLastElem();
  766. // }
  767. // /**
  768. // * Creates attributes for the current node.
  769. // *
  770. // * @param atts Attributes to be created.
  771. // */
  772. // void setAttributes(Attributes atts) {
  773. // int atLength = (null == atts) ? 0 : atts.getLength();
  774. // for (int i=0; i < atLength; i++) {
  775. // String qname = atts.getQName(i);
  776. // createAttribute(atts.getQName(i), atts.getValue(i));
  777. // }
  778. // }
  779. // /**
  780. // * Appends an attribute to the document.
  781. // * @param qname Qualified Name of the attribute
  782. // * @param value Value of the attribute
  783. // * @return Handle of node
  784. // */
  785. // public int createAttribute(String qname, String value) {
  786. // int colonpos = qname.indexOf(":");
  787. // String attName = qname.substring(colonpos+1);
  788. // int w0 = 0;
  789. // if (colonpos > 0) {
  790. // String prefix = qname.substring(0, colonpos);
  791. // if (prefix.equals("xml")) {
  792. // //w0 = ATTRIBUTE_NODE |
  793. // // (org.apache.xalan.templates.Constants.S_XMLNAMESPACEURI << 16);
  794. // } else {
  795. // //w0 = ATTRIBUTE_NODE |
  796. // }
  797. // } else {
  798. // w0 = ATTRIBUTE_NODE;
  799. // }
  800. // // W1: Parent
  801. // int w1 = currentParent;
  802. // // W2: Next (not yet resolved)
  803. // int w2 = 0;
  804. // // W3: Tag name
  805. // int w3 = m_localNames.stringToIndex(attName);
  806. // // Add node
  807. // int ourslot = appendNode(w0, w1, w2, w3);
  808. // previousSibling = ourslot; // Should attributes be previous siblings
  809. // // W0: Node Type
  810. // w0 = TEXT_NODE;
  811. // // W1: Parent
  812. // w1 = ourslot;
  813. // // W2: Start Position within buffer
  814. // w2 = m_char.length();
  815. // m_char.append(value);
  816. // // W3: Length
  817. // w3 = m_char.length() - w2;
  818. // appendNode(w0, w1, w2, w3);
  819. // charStringStart=m_char.length();
  820. // charStringLength = 0;
  821. // //previousSibling = ourslot;
  822. // // Attrs are Parents
  823. // previousSiblingWasParent = true;
  824. // return (m_docHandle | ourslot);
  825. // }
  826. // /**
  827. // * Factory method; creates a Text node in this document.
  828. // *
  829. // * The node created will be chained according to its natural order of request
  830. // * received. %TBD% It can be rechained later via the optional DTM writable interface.
  831. // *
  832. // * @param text String The characters text string from the XML document.
  833. // * @return int DTM node-number of the text node created
  834. // */
  835. // public int createTextNode(String text)
  836. // throws DTMException
  837. // {
  838. // // wraps around the index value based createTextNode method
  839. // return createTextNode(text.toCharArray(), 0, text.length());
  840. // }
  841. // /**
  842. // * Factory method; creates a Text node in this document.
  843. // *
  844. // * The node created will be chained according to its natural order of request
  845. // * received. %TBD% It can be rechained later via the optional DTM writable interface.
  846. // *
  847. // * %REVIEW% for text normalization issues, unless we are willing to
  848. // * insist that all adjacent text must be merged before this method
  849. // * is called.
  850. // *
  851. // * @param ch The characters from the XML document.
  852. // * @param start The start position in the array.
  853. // * @param length The number of characters to read from the array.
  854. // */
  855. // public int createTextNode(char ch[], int start, int length)
  856. // throws DTMException
  857. // {
  858. // m_char.append(ch, start, length); // store the chunk to the text/comment string table
  859. // // create a Text Node
  860. // // %TBD% may be possible to combine with appendNode()to replace the next chunk of code
  861. // int w0 = TEXT_NODE;
  862. // // W1: Parent
  863. // int w1 = currentParent;
  864. // // W2: Start position within m_char
  865. // int w2 = charStringStart;
  866. // // W3: Length of the full string
  867. // int w3 = length;
  868. // int ourslot = appendNode(w0, w1, w2, w3);
  869. // previousSibling = ourslot;
  870. // charStringStart=m_char.length();
  871. // charStringLength = 0;
  872. // return (m_docHandle | ourslot);
  873. // }
  874. // /**
  875. // * Factory method; creates a Comment node in this document.
  876. // *
  877. // * The node created will be chained according to its natural order of request
  878. // * received. %TBD% It can be rechained later via the optional DTM writable interface.
  879. // *
  880. // * @param text String The characters text string from the XML document.
  881. // * @return int DTM node-number of the text node created
  882. // */
  883. // public int createComment(String text)
  884. // throws DTMException
  885. // {
  886. // // wraps around the index value based createTextNode method
  887. // return createComment(text.toCharArray(), 0, text.length());
  888. // }
  889. // /**
  890. // * Factory method; creates a Comment node in this document.
  891. // *
  892. // * The node created will be chained according to its natural order of request
  893. // * received. %TBD% It can be rechained later via the optional DTM writable interface.
  894. // *
  895. // * @param ch An array holding the characters in the comment.
  896. // * @param start The starting position in the array.
  897. // * @param length The number of characters to use from the array.
  898. // * @see DTMException
  899. // */
  900. // public int createComment(char ch[], int start, int length)
  901. // throws DTMException
  902. // {
  903. // m_char.append(ch, start, length); // store the comment string to the text/comment string table
  904. // // create a Comment Node
  905. // // %TBD% may be possible to combine with appendNode()to replace the next chunk of code
  906. // int w0 = COMMENT_NODE;
  907. // // W1: Parent
  908. // int w1 = currentParent;
  909. // // W2: Start position within m_char
  910. // int w2 = charStringStart;
  911. // // W3: Length of the full string
  912. // int w3 = length;
  913. // int ourslot = appendNode(w0, w1, w2, w3);
  914. // previousSibling = ourslot;
  915. // charStringStart=m_char.length();
  916. // charStringLength = 0;
  917. // return (m_docHandle | ourslot);
  918. // }
  919. // // Counters to keep track of the current text string being accumulated with respect
  920. // // to the text/comment string table: charStringStart should point to the starting
  921. // // offset of the string in the table and charStringLength the acccumulated length when
  922. // // appendAccumulatedText starts, and reset to the end of the table and 0 at the end
  923. // // of appendAccumulatedText for the next set of characters receives
  924. // int charStringStart=0,charStringLength=0;
  925. // ========= Document Navigation Functions =========
  926. /** Given a node handle, test if it has child nodes.
  927. * <p> %REVIEW% This is obviously useful at the DOM layer, where it
  928. * would permit testing this without having to create a proxy
  929. * node. It's less useful in the DTM API, where
  930. * (dtm.getFirstChild(nodeHandle)!=DTM.NULL) is just as fast and
  931. * almost as self-evident. But it's a convenience, and eases porting
  932. * of DOM code to DTM. </p>
  933. *
  934. * @param nodeHandle int Handle of the node.
  935. * @return int true if the given node has child nodes.
  936. */
  937. public boolean hasChildNodes(int nodeHandle) {
  938. return(getFirstChild(nodeHandle) != NULL);
  939. }
  940. /**
  941. * Given a node handle, get the handle of the node's first child.
  942. * If not yet resolved, waits for more nodes to be added to the document and
  943. * tries again.
  944. *
  945. * @param nodeHandle int Handle of the node.
  946. * @return int DTM node-number of first child, or DTM.NULL to indicate none exists.
  947. */
  948. public int getFirstChild(int nodeHandle) {
  949. // ###shs worry about tracing/debug later
  950. nodeHandle &= NODEHANDLE_MASK;
  951. // Read node into variable
  952. nodes.readSlot(nodeHandle, gotslot);
  953. // type is the last half of first slot
  954. short type = (short) (gotslot[0] & 0xFFFF);
  955. // Check to see if Element or Document node
  956. if ((type == ELEMENT_NODE) || (type == DOCUMENT_NODE) ||
  957. (type == ENTITY_REFERENCE_NODE)) {
  958. // In case when Document root is given
  959. // if (nodeHandle == 0) nodeHandle = 1;
  960. // %TBD% Probably was a mistake.
  961. // If someone explicitly asks for first child
  962. // of Document, I would expect them to want
  963. // that and only that.
  964. int kid = nodeHandle + 1;
  965. nodes.readSlot(kid, gotslot);
  966. while (ATTRIBUTE_NODE == (gotslot[0] & 0xFFFF)) {
  967. // points to next sibling
  968. kid = gotslot[2];
  969. // Return NULL if node has only attributes
  970. if (kid == NULL) return NULL;
  971. nodes.readSlot(kid, gotslot);
  972. }
  973. // If parent slot matches given parent, return kid
  974. if (gotslot[1] == nodeHandle)
  975. {
  976. int firstChild = kid | m_docHandle;
  977. return firstChild;
  978. }
  979. }
  980. // No child found
  981. return NULL;
  982. }
  983. /**
  984. * Given a node handle, advance to its last child.
  985. * If not yet resolved, waits for more nodes to be added to the document and
  986. * tries again.
  987. *
  988. * @param nodeHandle int Handle of the node.
  989. * @return int Node-number of last child,
  990. * or DTM.NULL to indicate none exists.
  991. */
  992. public int getLastChild(int nodeHandle) {
  993. // ###shs put trace/debug later
  994. nodeHandle &= NODEHANDLE_MASK;
  995. // do not need to test node type since getFirstChild does that
  996. int lastChild = NULL;
  997. for (int nextkid = getFirstChild(nodeHandle); nextkid != NULL;
  998. nextkid = getNextSibling(nextkid)) {
  999. lastChild = nextkid;
  1000. }
  1001. return lastChild | m_docHandle;
  1002. }
  1003. /**
  1004. * Retrieves an attribute node by by qualified name and namespace URI.
  1005. *
  1006. * @param nodeHandle int Handle of the node upon which to look up this attribute.
  1007. * @param namespaceURI The namespace URI of the attribute to
  1008. * retrieve, or null.
  1009. * @param name The local name of the attribute to
  1010. * retrieve.
  1011. * @return The attribute node handle with the specified name (
  1012. * <code>nodeName</code>) or <code>DTM.NULL</code> if there is no such
  1013. * attribute.
  1014. */
  1015. public int getAttributeNode(int nodeHandle, String namespaceURI, String name) {
  1016. int nsIndex = m_nsNames.stringToIndex(namespaceURI),
  1017. nameIndex = m_localNames.stringToIndex(name);
  1018. nodeHandle &= NODEHANDLE_MASK;
  1019. nodes.readSlot(nodeHandle, gotslot);
  1020. short type = (short) (gotslot[0] & 0xFFFF);
  1021. // If nodeHandle points to element next slot would be first attribute
  1022. if (type == ELEMENT_NODE)
  1023. nodeHandle++;
  1024. // Iterate through Attribute Nodes
  1025. while (type == ATTRIBUTE_NODE) {
  1026. if ((nsIndex == (gotslot[0] << 16)) && (gotslot[3] == nameIndex))
  1027. return nodeHandle | m_docHandle;
  1028. // Goto next sibling
  1029. nodeHandle = gotslot[2];
  1030. nodes.readSlot(nodeHandle, gotslot);
  1031. }
  1032. return NULL;
  1033. }
  1034. /**
  1035. * Given a node handle, get the index of the node's first attribute.
  1036. *
  1037. * @param nodeHandle int Handle of the Element node.
  1038. * @return Handle of first attribute, or DTM.NULL to indicate none exists.
  1039. */
  1040. public int getFirstAttribute(int nodeHandle) {
  1041. nodeHandle &= NODEHANDLE_MASK;
  1042. // %REVIEW% jjk: Just a quick observation: If you're going to
  1043. // call readEntry repeatedly on the same node, it may be
  1044. // more efficiently to do a readSlot to get the data locally,
  1045. // reducing the addressing and call-and-return overhead.
  1046. // Should we check if handle is element (do we want sanity checks?)
  1047. if (ELEMENT_NODE != (nodes.readEntry(nodeHandle, 0) & 0xFFFF))
  1048. return NULL;
  1049. // First Attribute (if any) should be at next position in table
  1050. nodeHandle++;
  1051. return(ATTRIBUTE_NODE == (nodes.readEntry(nodeHandle, 0) & 0xFFFF)) ?
  1052. nodeHandle | m_docHandle : NULL;
  1053. }
  1054. /**
  1055. * Given a node handle, get the index of the node's first child.
  1056. * If not yet resolved, waits for more nodes to be added to the document and
  1057. * tries again
  1058. *
  1059. * @param nodeHandle handle to node, which should probably be an element
  1060. * node, but need not be.
  1061. *
  1062. * @param inScope true if all namespaces in scope should be returned,
  1063. * false if only the namespace declarations should be
  1064. * returned.
  1065. * @return handle of first namespace, or DTM.NULL to indicate none exists.
  1066. */
  1067. public int getFirstNamespaceNode(int nodeHandle, boolean inScope) {
  1068. return NULL;
  1069. }
  1070. /**
  1071. * Given a node handle, advance to its next sibling.
  1072. *
  1073. * %TBD% This currently uses the DTM-internal definition of
  1074. * sibling; eg, the last attr's next sib is the first
  1075. * child. In the old DTM, the DOM proxy layer provided the
  1076. * additional logic for the public view. If we're rewriting
  1077. * for XPath emulation, that test must be done here.
  1078. *
  1079. * %TBD% CODE INTERACTION WITH INCREMENTAL PARSE - If not yet
  1080. * resolved, should wait for more nodes to be added to the document
  1081. * and tries again.
  1082. *
  1083. * @param nodeHandle int Handle of the node.
  1084. * @return int Node-number of next sibling,
  1085. * or DTM.NULL to indicate none exists.
  1086. * */
  1087. public int getNextSibling(int nodeHandle) {
  1088. nodeHandle &= NODEHANDLE_MASK;
  1089. // Document root has no next sibling
  1090. if (nodeHandle == 0)
  1091. return NULL;
  1092. short type = (short) (nodes.readEntry(nodeHandle, 0) & 0xFFFF);
  1093. if ((type == ELEMENT_NODE) || (type == ATTRIBUTE_NODE) ||
  1094. (type == ENTITY_REFERENCE_NODE)) {
  1095. int nextSib = nodes.readEntry(nodeHandle, 2);
  1096. if (nextSib == NULL)
  1097. return NULL;
  1098. if (nextSib != 0)
  1099. return (m_docHandle | nextSib);
  1100. // ###shs should cycle/wait if nextSib is 0? Working on threading next
  1101. }
  1102. // Next Sibling is in the next position if it shares the same parent
  1103. int thisParent = nodes.readEntry(nodeHandle, 1);
  1104. if (nodes.readEntry(++nodeHandle, 1) == thisParent)
  1105. return (m_docHandle | nodeHandle);
  1106. return NULL;
  1107. }
  1108. /**
  1109. * Given a node handle, find its preceeding sibling.
  1110. * WARNING: DTM is asymmetric; this operation is resolved by search, and is
  1111. * relatively expensive.
  1112. *
  1113. * @param nodeHandle the id of the node.
  1114. * @return int Node-number of the previous sib,
  1115. * or DTM.NULL to indicate none exists.
  1116. */
  1117. public int getPreviousSibling(int nodeHandle) {
  1118. nodeHandle &= NODEHANDLE_MASK;
  1119. // Document root has no previous sibling
  1120. if (nodeHandle == 0)
  1121. return NULL;
  1122. int parent = nodes.readEntry(nodeHandle, 1);
  1123. int kid = NULL;
  1124. for (int nextkid = getFirstChild(parent); nextkid != nodeHandle;
  1125. nextkid = getNextSibling(nextkid)) {
  1126. kid = nextkid;
  1127. }
  1128. return kid | m_docHandle;
  1129. }
  1130. /**
  1131. * Given a node handle, advance to the next attribute. If an
  1132. * element, we advance to its first attribute; if an attr, we advance to
  1133. * the next attr on the same node.
  1134. *
  1135. * @param nodeHandle int Handle of the node.
  1136. * @return int DTM node-number of the resolved attr,
  1137. * or DTM.NULL to indicate none exists.
  1138. */
  1139. public int getNextAttribute(int nodeHandle) {
  1140. nodeHandle &= NODEHANDLE_MASK;
  1141. nodes.readSlot(nodeHandle, gotslot);
  1142. //%REVIEW% Why are we using short here? There's no storage
  1143. //reduction for an automatic variable, especially one used
  1144. //so briefly, and it typically costs more cycles to process
  1145. //than an int would.
  1146. short type = (short) (gotslot[0] & 0xFFFF);
  1147. if (type == ELEMENT_NODE) {
  1148. return getFirstAttribute(nodeHandle);
  1149. } else if (type == ATTRIBUTE_NODE) {
  1150. if (gotslot[2] != NULL)
  1151. return (m_docHandle | gotslot[2]);
  1152. }
  1153. return NULL;
  1154. }
  1155. /**
  1156. * Given a namespace handle, advance to the next namespace.
  1157. *
  1158. * %TBD% THIS METHOD DOES NOT MATCH THE CURRENT SIGNATURE IN
  1159. * THE DTM INTERFACE. FIX IT, OR JUSTIFY CHANGING THE DTM
  1160. * API.
  1161. *
  1162. * @param namespaceHandle handle to node which must be of type NAMESPACE_NODE.
  1163. * @return handle of next namespace, or DTM.NULL to indicate none exists.
  1164. */
  1165. public int getNextNamespaceNode(int baseHandle,int namespaceHandle, boolean inScope) {
  1166. // ###shs need to work on namespace
  1167. return NULL;
  1168. }
  1169. /**
  1170. * Given a node handle, advance to its next descendant.
  1171. * If not yet resolved, waits for more nodes to be added to the document and
  1172. * tries again.
  1173. *
  1174. * @param subtreeRootNodeHandle
  1175. * @param nodeHandle int Handle of the node.
  1176. * @return handle of next descendant,
  1177. * or DTM.NULL to indicate none exists.
  1178. */
  1179. public int getNextDescendant(int subtreeRootHandle, int nodeHandle) {
  1180. subtreeRootHandle &= NODEHANDLE_MASK;
  1181. nodeHandle &= NODEHANDLE_MASK;
  1182. // Document root [Document Node? -- jjk] - no next-sib
  1183. if (nodeHandle == 0)
  1184. return NULL;
  1185. while (!m_isError) {
  1186. // Document done and node out of bounds
  1187. if (done && (nodeHandle > nodes.slotsUsed()))
  1188. break;
  1189. if (nodeHandle > subtreeRootHandle) {
  1190. nodes.readSlot(nodeHandle+1, gotslot);
  1191. if (gotslot[2] != 0) {
  1192. short type = (short) (gotslot[0] & 0xFFFF);
  1193. if (type == ATTRIBUTE_NODE) {
  1194. nodeHandle +=2;
  1195. } else {
  1196. int nextParentPos = gotslot[1];
  1197. if (nextParentPos >= subtreeRootHandle)
  1198. return (m_docHandle | (nodeHandle+1));
  1199. else
  1200. break;
  1201. }
  1202. } else if (!done) {
  1203. // Add wait logic here
  1204. } else
  1205. break;
  1206. } else {
  1207. nodeHandle++;
  1208. }
  1209. }
  1210. // Probably should throw error here like original instead of returning
  1211. return NULL;
  1212. }
  1213. /**
  1214. * Given a node handle, advance to the next node on the following axis.
  1215. *
  1216. * @param axisContextHandle the start of the axis that is being traversed.
  1217. * @param nodeHandle
  1218. * @return handle of next sibling,
  1219. * or DTM.NULL to indicate none exists.
  1220. */
  1221. public int getNextFollowing(int axisContextHandle, int nodeHandle) {
  1222. //###shs still working on
  1223. return NULL;
  1224. }
  1225. /**
  1226. * Given a node handle, advance to the next node on the preceding axis.
  1227. *
  1228. * @param axisContextHandle the start of the axis that is being traversed.
  1229. * @param nodeHandle the id of the node.
  1230. * @return int Node-number of preceding sibling,
  1231. * or DTM.NULL to indicate none exists.
  1232. */
  1233. public int getNextPreceding(int axisContextHandle, int nodeHandle) {
  1234. // ###shs copied from Xalan 1, what is this suppose to do?
  1235. nodeHandle &= NODEHANDLE_MASK;
  1236. while (nodeHandle > 1) {
  1237. nodeHandle--;
  1238. if (ATTRIBUTE_NODE == (nodes.readEntry(nodeHandle, 0) & 0xFFFF))
  1239. continue;
  1240. // if nodeHandle is _not_ an ancestor of
  1241. // axisContextHandle, specialFind will return it.
  1242. // If it _is_ an ancestor, specialFind will return -1
  1243. // %REVIEW% unconditional return defeats the
  1244. // purpose of the while loop -- does this
  1245. // logic make any sense?
  1246. return (m_docHandle | nodes.specialFind(axisContextHandle, nodeHandle));
  1247. }
  1248. return NULL;
  1249. }
  1250. /**
  1251. * Given a node handle, find its parent node.
  1252. *
  1253. * @param nodeHandle the id of the node.
  1254. * @return int Node-number of parent,
  1255. * or DTM.NULL to indicate none exists.
  1256. */
  1257. public int getParent(int nodeHandle) {
  1258. // Should check to see within range?
  1259. // Document Root should not have to be handled differently
  1260. return (m_docHandle | nodes.readEntry(nodeHandle, 1));
  1261. }
  1262. /**
  1263. * Returns the root element of the document.
  1264. * @return nodeHandle to the Document Root.
  1265. */
  1266. public int getDocumentRoot() {
  1267. return (m_docHandle | m_docElement);
  1268. }
  1269. /**
  1270. * Given a node handle, find the owning document node.
  1271. *
  1272. * @param nodeHandle the id of the node.
  1273. * @return int Node handle of document, which should always be valid.
  1274. */
  1275. public int getDocument() {
  1276. return m_docHandle;
  1277. }
  1278. /**
  1279. * Given a node handle, find the owning document node. This has the exact
  1280. * same semantics as the DOM Document method of the same name, in that if
  1281. * the nodeHandle is a document node, it will return NULL.
  1282. *
  1283. * <p>%REVIEW% Since this is DOM-specific, it may belong at the DOM
  1284. * binding layer. Included here as a convenience function and to
  1285. * aid porting of DOM code to DTM.</p>
  1286. *
  1287. * @param nodeHandle the id of the node.
  1288. * @return int Node handle of owning document, or NULL if the nodeHandle is
  1289. * a document.
  1290. */
  1291. public int getOwnerDocument(int nodeHandle) {
  1292. // Assumption that Document Node is always in 0 slot
  1293. if ((nodeHandle & NODEHANDLE_MASK) == 0)
  1294. return NULL;
  1295. return (nodeHandle & DOCHANDLE_MASK);
  1296. }
  1297. /**
  1298. * Given a node handle, find the owning document node. This has the DTM
  1299. * semantics; a Document node is its own owner.
  1300. *
  1301. * <p>%REVIEW% Since this is DOM-specific, it may belong at the DOM
  1302. * binding layer. Included here as a convenience function and to
  1303. * aid porting of DOM code to DTM.</p>
  1304. *
  1305. * @param nodeHandle the id of the node.
  1306. * @return int Node handle of owning document, or NULL if the nodeHandle is
  1307. * a document.
  1308. */
  1309. public int getDocumentRoot(int nodeHandle) {
  1310. // Assumption that Document Node is always in 0 slot
  1311. if ((nodeHandle & NODEHANDLE_MASK) == 0)
  1312. return NULL;
  1313. return (nodeHandle & DOCHANDLE_MASK);
  1314. }
  1315. /**
  1316. * Get the string-value of a node as a String object
  1317. * (see http://www.w3.org/TR/xpath#data-model
  1318. * for the definition of a node's string-value).
  1319. *
  1320. * @param nodeHandle The node ID.
  1321. *
  1322. * @return A string object that represents the string-value of the given node.
  1323. */
  1324. public XMLString getStringValue(int nodeHandle) {
  1325. // ###zaj - researching
  1326. nodes.readSlot(nodeHandle, gotslot);
  1327. int nodetype=gotslot[0] & 0xFF;
  1328. String value=null;
  1329. switch (nodetype) {
  1330. case TEXT_NODE:
  1331. case COMMENT_NODE:
  1332. case CDATA_SECTION_NODE:
  1333. value= m_char.getString(gotslot[2], gotslot[3]);
  1334. break;
  1335. case PROCESSING_INSTRUCTION_NODE:
  1336. case ATTRIBUTE_NODE:
  1337. case ELEMENT_NODE:
  1338. case ENTITY_REFERENCE_NODE:
  1339. default:
  1340. break;
  1341. }
  1342. return m_xsf.newstr( value );
  1343. }
  1344. /**
  1345. * Get number of character array chunks in
  1346. * the string-value of a node.
  1347. * (see http://www.w3.org/TR/xpath#data-model
  1348. * for the definition of a node's string-value).
  1349. * Note that a single text node may have multiple text chunks.
  1350. *
  1351. * EXPLANATION: This method is an artifact of the fact that the
  1352. * underlying m_chars object may not store characters in a
  1353. * single contiguous array -- for example,the current
  1354. * FastStringBuffer may split a single node's text across
  1355. * multiple allocation units. This call tells us how many
  1356. * separate accesses will be required to retrieve the entire
  1357. * content. PLEASE NOTE that this may not be the same as the
  1358. * number of SAX characters() events that caused the text node
  1359. * to be built in the first place, since m_chars buffering may
  1360. * be on different boundaries than the parser's buffers.
  1361. *
  1362. * @param nodeHandle The node ID.
  1363. *
  1364. * @return number of character array chunks in
  1365. * the string-value of a node.
  1366. * */
  1367. //###zaj - tbd
  1368. public int getStringValueChunkCount(int nodeHandle)
  1369. {
  1370. //###zaj return value
  1371. return 0;
  1372. }
  1373. /**
  1374. * Get a character array chunk in the string-value of a node.
  1375. * (see http://www.w3.org/TR/xpath#data-model
  1376. * for the definition of a node's string-value).
  1377. * Note that a single text node may have multiple text chunks.
  1378. *
  1379. * EXPLANATION: This method is an artifact of the fact that
  1380. * the underlying m_chars object may not store characters in a
  1381. * single contiguous array -- for example,the current
  1382. * FastStringBuffer may split a single node's text across
  1383. * multiple allocation units. This call retrieves a single
  1384. * contiguous portion of the text -- as much as m-chars was
  1385. * able to store in a single allocation unit. PLEASE NOTE
  1386. * that this may not be the same granularityas the SAX
  1387. * characters() events that caused the text node to be built
  1388. * in the first place, since m_chars buffering may be on
  1389. * different boundaries than the parser's buffers.
  1390. *
  1391. * @param nodeHandle The node ID.
  1392. * @param chunkIndex Which chunk to get.
  1393. * @param startAndLen An array of 2 where the start position and length of
  1394. * the chunk will be returned.
  1395. *
  1396. * @return The character array reference where the chunk occurs. */
  1397. //###zaj - tbd
  1398. public char[] getStringValueChunk(int nodeHandle, int chunkIndex,
  1399. int[] startAndLen) {return new char[0];}
  1400. /**
  1401. * Given a node handle, return an ID that represents the node's expanded name.
  1402. *
  1403. * @param nodeHandle The handle to the node in question.
  1404. *
  1405. * @return the expanded-name id of the node.
  1406. */
  1407. public int getExpandedTypeID(int nodeHandle) {
  1408. nodes.readSlot(nodeHandle, gotslot);
  1409. String qName = m_localNames.indexToString(gotslot[3]);
  1410. // Remove prefix from qName
  1411. // %TBD% jjk This is assuming the elementName is the qName.
  1412. int colonpos = qName.indexOf(":");
  1413. String localName = qName.substring(colonpos+1);
  1414. // Get NS
  1415. String namespace = m_nsNames.indexToString(gotslot[0] << 16);
  1416. // Create expanded name
  1417. String expandedName = namespace + ":" + localName;
  1418. int expandedNameID = m_nsNames.stringToIndex(expandedName);
  1419. return expandedNameID;
  1420. }
  1421. /**
  1422. * Given an expanded name, return an ID. If the expanded-name does not
  1423. * exist in the internal tables, the entry will be created, and the ID will
  1424. * be returned. Any additional nodes that are created that have this
  1425. * expanded name will use this ID.
  1426. *
  1427. * @param nodeHandle The handle to the node in question.
  1428. *
  1429. * @return the expanded-name id of the node.
  1430. */
  1431. public int getExpandedTypeID(String namespace, String localName, int type) {
  1432. // Create expanded name
  1433. // %TBD% jjk Expanded name is bitfield-encoded as
  1434. // typeID[6]nsuriID[10]localID[16]. Switch to that form, and to
  1435. // accessing the ns/local via their tables rather than confusing
  1436. // nsnames and expandednames.
  1437. String expandedName = namespace + ":" + localName;
  1438. int expandedNameID = m_nsNames.stringToIndex(expandedName);
  1439. return expandedNameID;
  1440. }
  1441. /**
  1442. * Given an expanded-name ID, return the local name part.
  1443. *
  1444. * @param ExpandedNameID an ID that represents an expanded-name.
  1445. * @return String Local name of this node.
  1446. */
  1447. public String getLocalNameFromExpandedNameID(int ExpandedNameID) {
  1448. // Get expanded name
  1449. String expandedName = m_localNames.indexToString(ExpandedNameID);
  1450. // Remove prefix from expanded name
  1451. int colonpos = expandedName.indexOf(":");
  1452. String localName = expandedName.substring(colonpos+1);
  1453. return localName;
  1454. }
  1455. /**
  1456. * Given an expanded-name ID, return the namespace URI part.
  1457. *
  1458. * @param ExpandedNameID an ID that represents an expanded-name.
  1459. * @return String URI value of this node's namespace, or null if no
  1460. * namespace was resolved.
  1461. */
  1462. public String getNamespaceFromExpandedNameID(int ExpandedNameID) {
  1463. String expandedName = m_localNames.indexToString(ExpandedNameID);
  1464. // Remove local name from expanded name
  1465. int colonpos = expandedName.indexOf(":");
  1466. String nsName = expandedName.substring(0, colonpos);
  1467. return nsName;
  1468. }
  1469. /**
  1470. * fixednames
  1471. */
  1472. static final String[] fixednames=
  1473. {
  1474. null,null, // nothing, Element
  1475. null,"#text", // Attr, Text
  1476. "#cdata_section",null, // CDATA, EntityReference
  1477. null,null, // Entity, PI
  1478. "#comment","#document", // Comment, Document
  1479. null,"#document-fragment", // Doctype, DocumentFragment
  1480. null}; // Notation
  1481. /**
  1482. * Given a node handle, return its DOM-style node name. This will
  1483. * include names such as #text or #document.
  1484. *
  1485. * @param nodeHandle the id of the node.
  1486. * @return String Name of this node, which may be an empty string.
  1487. * %REVIEW% Document when empty string is possible...
  1488. */
  1489. public String getNodeName(int nodeHandle) {
  1490. nodes.readSlot(nodeHandle, gotslot);
  1491. short type = (short) (gotslot[0] & 0xFFFF);
  1492. String name = fixednames[type];
  1493. if (null == name) {
  1494. int i=gotslot[3];
  1495. /**/System.out.println("got i="+i+" "+(i>>16)+"/"+(i&0xffff));
  1496. name=m_localNames.indexToString(i & 0xFFFF);
  1497. String prefix=m_prefixNames.indexToString(i >>16);
  1498. if(prefix!=null && prefix.length()>0)
  1499. name=prefix+":"+name;
  1500. }
  1501. return name;
  1502. }
  1503. /**
  1504. * Given a node handle, return the XPath node name. This should be
  1505. * the name as described by the XPath data model, NOT the DOM-style
  1506. * name.
  1507. *
  1508. * @param nodeHandle the id of the node.
  1509. * @return String Name of this node.
  1510. */
  1511. public String getNodeNameX(int nodeHandle) {return null;}
  1512. /**
  1513. * Given a node handle, return its DOM-style localname.
  1514. * (As defined in Namespaces, this is the portion of the name after any
  1515. * colon character)
  1516. *
  1517. * %REVIEW% What's the local name of something other than Element/Attr?
  1518. * Should this be DOM-style (undefined unless namespaced), or other?
  1519. *
  1520. * @param nodeHandle the id of the node.
  1521. * @return String Local name of this node.
  1522. */
  1523. public String getLocalName(int nodeHandle) {
  1524. nodes.readSlot(nodeHandle, gotslot);
  1525. short type = (short) (gotslot[0] & 0xFFFF);
  1526. String name = "";
  1527. if ((type==ELEMENT_NODE) || (type==ATTRIBUTE_NODE)) {
  1528. int i=gotslot[3];
  1529. name=m_localNames.indexToString(i & 0xFFFF);
  1530. if(name==null) name="";
  1531. }
  1532. return name;
  1533. }
  1534. /**
  1535. * Given a namespace handle, return the prefix that the namespace decl is
  1536. * mapping.
  1537. * Given a node handle, return the prefix used to map to the namespace.
  1538. *
  1539. * <p> %REVIEW% Are you sure you want "" for no prefix? </p>
  1540. *
  1541. * %REVIEW% Should this be DOM-style (undefined unless namespaced),
  1542. * or other?
  1543. *
  1544. * @param nodeHandle the id of the node.
  1545. * @return String prefix of this node's name, or "" if no explicit
  1546. * namespace prefix was given.
  1547. */
  1548. public String getPrefix(int nodeHandle) {
  1549. nodes.readSlot(nodeHandle, gotslot);
  1550. short type = (short) (gotslot[0] & 0xFFFF);
  1551. String name = "";
  1552. if((type==ELEMENT_NODE) || (type==ATTRIBUTE_NODE)) {
  1553. int i=gotslot[3];
  1554. name=m_prefixNames.indexToString(i >>16);
  1555. if(name==null) name="";
  1556. }
  1557. return name;
  1558. }
  1559. /**
  1560. * Given a node handle, return its DOM-style namespace URI
  1561. * (As defined in Namespaces, this is the declared URI which this node's
  1562. * prefix -- or default in lieu thereof -- was mapped to.)
  1563. *
  1564. * @param nodeHandle the id of the node.
  1565. * @return String URI value of this node's namespace, or null if no
  1566. * namespace was resolved.
  1567. */
  1568. public String getNamespaceURI(int nodeHandle) {return null;}
  1569. /**
  1570. * Given a node handle, return its node value. This is mostly
  1571. * as defined by the DOM, but may ignore some conveniences.
  1572. * <p>
  1573. *
  1574. * @param nodeHandle The node id.
  1575. * @return String Value of this node, or null if not
  1576. * meaningful for this node type.
  1577. */
  1578. public String getNodeValue(int nodeHandle)
  1579. {
  1580. nodes.readSlot(nodeHandle, gotslot);
  1581. int nodetype=gotslot[0] & 0xFF; // ###zaj use mask to get node type
  1582. String value=null;
  1583. switch (nodetype) { // ###zaj todo - document nodetypes
  1584. case ATTRIBUTE_NODE:
  1585. nodes.readSlot(nodeHandle+1, gotslot);
  1586. case TEXT_NODE:
  1587. case COMMENT_NODE:
  1588. case CDATA_SECTION_NODE:
  1589. value=m_char.getString(gotslot[2], gotslot[3]); //###zaj
  1590. break;
  1591. case PROCESSING_INSTRUCTION_NODE:
  1592. case ELEMENT_NODE:
  1593. case ENTITY_REFERENCE_NODE:
  1594. default:
  1595. break;
  1596. }
  1597. return value;
  1598. }
  1599. /**
  1600. * Given a node handle, return its DOM-style node type.
  1601. * <p>
  1602. * %REVIEW% Generally, returning short is false economy. Return int?
  1603. *
  1604. * @param nodeHandle The node id.
  1605. * @return int Node type, as per the DOM's Node._NODE constants.
  1606. */
  1607. public short getNodeType(int nodeHandle) {
  1608. return(short) (nodes.readEntry(nodeHandle, 0) & 0xFFFF);
  1609. }
  1610. /**
  1611. * <meta name="usage" content="internal"/>
  1612. * Get the depth level of this node in the tree (equals 1 for
  1613. * a parentless node).
  1614. *
  1615. * @param nodeHandle The node id.
  1616. * @return the number of ancestors, plus one
  1617. */
  1618. public short getLevel(int nodeHandle) {
  1619. short count = 0;
  1620. while (nodeHandle != 0) {
  1621. count++;
  1622. nodeHandle = nodes.readEntry(nodeHandle, 1);
  1623. }
  1624. return count;
  1625. }
  1626. // ============== Document query functions ==============
  1627. /**
  1628. * Tests whether DTM DOM implementation implements a specific feature and
  1629. * that feature is supported by this node.
  1630. *
  1631. * @param feature The name of the feature to test.
  1632. * @param versionThis is the version number of the feature to test.
  1633. * If the version is not
  1634. * specified, supporting any version of the feature will cause the
  1635. * method to return <code>true</code>.
  1636. * @return Returns <code>true</code> if the specified feature is
  1637. * supported on this node, <code>false</code> otherwise.
  1638. */
  1639. public boolean isSupported(String feature, String version) {return false;}
  1640. /**
  1641. * Return the base URI of the document entity. If it is not known
  1642. * (because the document was parsed from a socket connection or from
  1643. * standard input, for example), the value of this property is unknown.
  1644. *
  1645. * @return the document base URI String object or null if unknown.
  1646. */
  1647. public String getDocumentBaseURI()
  1648. {
  1649. return m_documentBaseURI;
  1650. }
  1651. /**
  1652. * Set the base URI of the document entity.
  1653. *
  1654. * @param baseURI the document base URI String object or null if unknown.
  1655. */
  1656. public void setDocumentBaseURI(String baseURI)
  1657. {
  1658. m_documentBaseURI = baseURI;
  1659. }
  1660. /**
  1661. * Return the system identifier of the document entity. If
  1662. * it is not known, the value of this property is unknown.
  1663. *
  1664. * @param nodeHandle The node id, which can be any valid node handle.
  1665. * @return the system identifier String object or null if unknown.
  1666. */
  1667. public String getDocumentSystemIdentifier(int nodeHandle) {return null;}
  1668. /**
  1669. * Return the name of the character encoding scheme
  1670. * in which the document entity is expressed.
  1671. *
  1672. * @param nodeHandle The node id, which can be any valid node handle.
  1673. * @return the document encoding String object.
  1674. */
  1675. public String getDocumentEncoding(int nodeHandle) {return null;}
  1676. /**
  1677. * Return an indication of the standalone status of the document,
  1678. * either "yes" or "no". This property is derived from the optional
  1679. * standalone document declaration in the XML declaration at the
  1680. * beginning of the document entity, and has no value if there is no
  1681. * standalone document declaration.
  1682. *
  1683. * @param nodeHandle The node id, which can be any valid node handle.
  1684. * @return the document standalone String object, either "yes", "no", or null.
  1685. */
  1686. public String getDocumentStandalone(int nodeHandle) {return null;}
  1687. /**
  1688. * Return a string representing the XML version of the document. This
  1689. * property is derived from the XML declaration optionally present at the
  1690. * beginning of the document entity, and has no value if there is no XML
  1691. * declaration.
  1692. *
  1693. * @param the document handle
  1694. *
  1695. * @return the document version String object
  1696. */
  1697. public String getDocumentVersion(int documentHandle) {return null;}
  1698. /**
  1699. * Return an indication of
  1700. * whether the processor has read the complete DTD. Its value is a
  1701. * boolean. If it is false, then certain properties (indicated in their
  1702. * descriptions below) may be unknown. If it is true, those properties
  1703. * are never unknown.
  1704. *
  1705. * @return <code>true</code> if all declarations were processed {};
  1706. * <code>false</code> otherwise.
  1707. */
  1708. public boolean getDocumentAllDeclarationsProcessed() {return false;}
  1709. /**
  1710. * A document type declaration information item has the following properties:
  1711. *
  1712. * 1. [system identifier] The system identifier of the external subset, if
  1713. * it exists. Otherwise this property has no value.
  1714. *
  1715. * @return the system identifier String object, or null if there is none.
  1716. */
  1717. public String getDocumentTypeDeclarationSystemIdentifier() {return null;}
  1718. /**
  1719. * Return the public identifier of the external subset,
  1720. * normalized as described in 4.2.2 External Entities [XML]. If there is
  1721. * no external subset or if it has no public identifier, this property
  1722. * has no value.
  1723. *
  1724. * @param the document type declaration handle
  1725. *
  1726. * @return the public identifier String object, or null if there is none.
  1727. */
  1728. public String getDocumentTypeDeclarationPublicIdentifier() {return null;}
  1729. /**
  1730. * Returns the <code>Element</code> whose <code>ID</code> is given by
  1731. * <code>elementId</code>. If no such element exists, returns
  1732. * <code>DTM.NULL</code>. Behavior is not defined if more than one element
  1733. * has this <code>ID</code>. Attributes (including those
  1734. * with the name "ID") are not of type ID unless so defined by DTD/Schema
  1735. * information available to the DTM implementation.
  1736. * Implementations that do not know whether attributes are of type ID or
  1737. * not are expected to return <code>DTM.NULL</code>.
  1738. *
  1739. * <p>%REVIEW% Presumably IDs are still scoped to a single document,
  1740. * and this operation searches only within a single document, right?
  1741. * Wouldn't want collisions between DTMs in the same process.</p>
  1742. *
  1743. * @param elementId The unique <code>id</code> value for an element.
  1744. * @return The handle of the matching element.
  1745. */
  1746. public int getElementById(String elementId) {return 0;}
  1747. /**
  1748. * The getUnparsedEntityURI function returns the URI of the unparsed
  1749. * entity with the specified name in the same document as the context
  1750. * node (see [3.3 Unparsed Entities]). It returns the empty string if
  1751. * there is no such entity.
  1752. * <p>
  1753. * XML processors may choose to use the System Identifier (if one
  1754. * is provided) to resolve the entity, rather than the URI in the
  1755. * Public Identifier. The details are dependent on the processor, and
  1756. * we would have to support some form of plug-in resolver to handle
  1757. * this properly. Currently, we simply return the System Identifier if
  1758. * present, and hope that it a usable URI or that our caller can
  1759. * map it to one.
  1760. * TODO: Resolve Public Identifiers... or consider changing function name.
  1761. * <p>
  1762. * If we find a relative URI
  1763. * reference, XML expects it to be resolved in terms of the base URI
  1764. * of the document. The DOM doesn't do that for us, and it isn't
  1765. * entirely clear whether that should be done here; currently that's
  1766. * pushed up to a higher level of our application. (Note that DOM Level
  1767. * 1 didn't store the document's base URI.)
  1768. * TODO: Consider resolving Relative URIs.
  1769. * <p>
  1770. * (The DOM's statement that "An XML processor may choose to
  1771. * completely expand entities before the structure model is passed
  1772. * to the DOM" refers only to parsed entities, not unparsed, and hence
  1773. * doesn't affect this function.)
  1774. *
  1775. * @param name A string containing the Entity Name of the unparsed
  1776. * entity.
  1777. *
  1778. * @return String containing the URI of the Unparsed Entity, or an
  1779. * empty string if no such entity exists.
  1780. */
  1781. public String getUnparsedEntityURI(String name) {return null;}
  1782. // ============== Boolean methods ================
  1783. /**
  1784. * Return true if the xsl:strip-space or xsl:preserve-space was processed
  1785. * during construction of the DTM document.
  1786. *
  1787. * <p>%REVEIW% Presumes a 1:1 mapping from DTM to Document, since
  1788. * we aren't saying which Document to query...?</p>
  1789. */
  1790. public boolean supportsPreStripping() {return false;}
  1791. /**
  1792. * Figure out whether nodeHandle2 should be considered as being later
  1793. * in the document than nodeHandle1, in Document Order as defined
  1794. * by the XPath model. This may not agree with the ordering defined
  1795. * by other XML applications.
  1796. * <p>
  1797. * There are some cases where ordering isn't defined, and neither are
  1798. * the results of this function -- though we'll generally return true.
  1799. *
  1800. * TODO: Make sure this does the right thing with attribute nodes!!!
  1801. *
  1802. * @param node1 DOM Node to perform position comparison on.
  1803. * @param node2 DOM Node to perform position comparison on .
  1804. *
  1805. * @return false if node2 comes before node1, otherwise return true.
  1806. * You can think of this as
  1807. * <code>(node1.documentOrderPosition <= node2.documentOrderPosition)</code>.
  1808. */
  1809. public boolean isNodeAfter(int nodeHandle1, int nodeHandle2) {return false;}
  1810. /**
  1811. * 2. [element content whitespace] A boolean indicating whether the
  1812. * character is white space appearing within element content (see [XML],
  1813. * 2.10 "White Space Handling"). Note that validating XML processors are
  1814. * required by XML 1.0 to provide this information. If there is no
  1815. * declaration for the containing element, this property has no value for
  1816. * white space characters. If no declaration has been read, but the [all
  1817. * declarations processed] property of the document information item is
  1818. * false (so there may be an unread declaration), then the value of this
  1819. * property is unknown for white space characters. It is always false for
  1820. * characters that are not white space.
  1821. *
  1822. * @param nodeHandle the node ID.
  1823. * @return <code>true</code> if the character data is whitespace;
  1824. * <code>false</code> otherwise.
  1825. */
  1826. public boolean isCharacterElementContentWhitespace(int nodeHandle) {return false;}
  1827. /**
  1828. * 10. [all declarations processed] This property is not strictly speaking
  1829. * part of the infoset of the document. Rather it is an indication of
  1830. * whether the processor has read the complete DTD. Its value is a
  1831. * boolean. If it is false, then certain properties (indicated in their
  1832. * descriptions below) may be unknown. If it is true, those properties
  1833. * are never unknown.
  1834. *
  1835. * @param the document handle
  1836. *
  1837. * @param documentHandle A node handle that must identify a document.
  1838. * @return <code>true</code> if all declarations were processed;
  1839. * <code>false</code> otherwise.
  1840. */
  1841. public boolean isDocumentAllDeclarationsProcessed(int documentHandle) {return false;}
  1842. /**
  1843. * 5. [specified] A flag indicating whether this attribute was actually
  1844. * specified in the start-tag of its element, or was defaulted from the
  1845. * DTD.
  1846. *
  1847. * @param the attribute handle
  1848. *
  1849. * NEEDSDOC @param attributeHandle
  1850. * @return <code>true</code> if the attribute was specified;
  1851. * <code>false</code> if it was defaulted.
  1852. */
  1853. public boolean isAttributeSpecified(int attributeHandle) {return false;}
  1854. // ========== Direct SAX Dispatch, for optimization purposes ========
  1855. /**
  1856. * Directly call the
  1857. * characters method on the passed ContentHandler for the
  1858. * string-value of the given node (see http://www.w3.org/TR/xpath#data-model
  1859. * for the definition of a node's string-value). Multiple calls to the
  1860. * ContentHandler's characters methods may well occur for a single call to
  1861. * this method.
  1862. *
  1863. * @param nodeHandle The node ID.
  1864. * @param ch A non-null reference to a ContentHandler.
  1865. *
  1866. * @throws org.xml.sax.SAXException
  1867. */
  1868. public void dispatchCharactersEvents(
  1869. int nodeHandle, org.xml.sax.ContentHandler ch, boolean normalize)
  1870. throws org.xml.sax.SAXException {}
  1871. /**
  1872. * Directly create SAX parser events from a subtree.
  1873. *
  1874. * @param nodeHandle The node ID.
  1875. * @param ch A non-null reference to a ContentHandler.
  1876. *
  1877. * @throws org.xml.sax.SAXException
  1878. */
  1879. public void dispatchToEvents(int nodeHandle, org.xml.sax.ContentHandler ch)
  1880. throws org.xml.sax.SAXException {}
  1881. /**
  1882. * Return an DOM node for the given node.
  1883. *
  1884. * @param nodeHandle The node ID.
  1885. *
  1886. * @return A node representation of the DTM node.
  1887. */
  1888. public org.w3c.dom.Node getNode(int nodeHandle)
  1889. {
  1890. return null;
  1891. }
  1892. // ==== Construction methods (may not be supported by some implementations!) =====
  1893. // %REVIEW% jjk: These probably aren't the right API. At the very least
  1894. // they need to deal with current-insertion-location and end-element
  1895. // issues.
  1896. /**
  1897. * Append a child to the end of the child list of the current node. Please note that the node
  1898. * is always cloned if it is owned by another document.
  1899. *
  1900. * <p>%REVIEW% "End of the document" needs to be defined more clearly.
  1901. * Does it become the last child of the Document? Of the root element?</p>
  1902. *
  1903. * @param newChild Must be a valid new node handle.
  1904. * @param clone true if the child should be cloned into the document.
  1905. * @param cloneDepth if the clone argument is true, specifies that the
  1906. * clone should include all it's children.
  1907. */
  1908. public void appendChild(int newChild, boolean clone, boolean cloneDepth) {
  1909. boolean sameDoc = ((newChild & DOCHANDLE_MASK) == m_docHandle);
  1910. if (clone || !sameDoc) {
  1911. } else {
  1912. }
  1913. }
  1914. /**
  1915. * Append a text node child that will be constructed from a string,
  1916. * to the end of the document.
  1917. *
  1918. * <p>%REVIEW% "End of the document" needs to be defined more clearly.
  1919. * Does it become the last child of the Document? Of the root element?</p>
  1920. *
  1921. * @param str Non-null reference to a string.
  1922. */
  1923. public void appendTextChild(String str) {
  1924. // ###shs Think more about how this differs from createTextNode
  1925. //%TBD%
  1926. }
  1927. //================================================================
  1928. // ==== BUILDER methods ====
  1929. // %TBD% jjk: SHOULD PROBABLY BE INLINED, unless we want to support
  1930. // both SAX1 and SAX2 and share this logic between them.
  1931. /** Append a text child at the current insertion point. Assumes that the
  1932. * actual content of the text has previously been appended to the m_char
  1933. * buffer (shared with the builder).
  1934. *
  1935. * @param m_char_current_start int Starting offset of node's content in m_char.
  1936. * @param contentLength int Length of node's content in m_char.
  1937. * */
  1938. void appendTextChild(int m_char_current_start,int contentLength)
  1939. {
  1940. // create a Text Node
  1941. // %TBD% may be possible to combine with appendNode()to replace the next chunk of code
  1942. int w0 = TEXT_NODE;
  1943. // W1: Parent
  1944. int w1 = currentParent;
  1945. // W2: Start position within m_char
  1946. int w2 = m_char_current_start;
  1947. // W3: Length of the full string
  1948. int w3 = contentLength;
  1949. int ourslot = appendNode(w0, w1, w2, w3);
  1950. previousSibling = ourslot;
  1951. }
  1952. /** Append a comment child at the current insertion point. Assumes that the
  1953. * actual content of the comment has previously been appended to the m_char
  1954. * buffer (shared with the builder).
  1955. *
  1956. * @param m_char_current_start int Starting offset of node's content in m_char.
  1957. * @param contentLength int Length of node's content in m_char.
  1958. * */
  1959. void appendComment(int m_char_current_start,int contentLength)
  1960. {
  1961. // create a Comment Node
  1962. // %TBD% may be possible to combine with appendNode()to replace the next chunk of code
  1963. int w0 = COMMENT_NODE;
  1964. // W1: Parent
  1965. int w1 = currentParent;
  1966. // W2: Start position within m_char
  1967. int w2 = m_char_current_start;
  1968. // W3: Length of the full string
  1969. int w3 = contentLength;
  1970. int ourslot = appendNode(w0, w1, w2, w3);
  1971. previousSibling = ourslot;
  1972. }
  1973. /** Append an Element child at the current insertion point. This
  1974. * Element then _becomes_ the insertion point; subsequent appends
  1975. * become its lastChild until an appendEndElement() call is made.
  1976. *
  1977. * Assumes that the symbols (local name, namespace URI and prefix)
  1978. * have already been added to the pools
  1979. *
  1980. * Note that this _only_ handles the Element node itself. Attrs and
  1981. * namespace nodes are unbundled in the ContentHandler layer
  1982. * and appended separately.
  1983. *
  1984. * @param namespaceIndex: Index within the namespaceURI string pool
  1985. * @param localNameIndex Index within the local name string pool
  1986. * @param prefixIndex: Index within the prefix string pool
  1987. * */
  1988. void appendStartElement(int namespaceIndex,int localNameIndex, int prefixIndex)
  1989. {
  1990. // do document root node creation here on the first element, create nodes for
  1991. // this element and its attributes, store the element, namespace, and attritute
  1992. // name indexes to the nodes array, keep track of the current node and parent
  1993. // element used
  1994. // W0 High: Namespace Low: Node Type
  1995. int w0 = (namespaceIndex << 16) | ELEMENT_NODE;
  1996. // W1: Parent
  1997. int w1 = currentParent;
  1998. // W2: Next (initialized as 0)
  1999. int w2 = 0;
  2000. // W3: Tagname high: prefix Low: local name
  2001. int w3 = localNameIndex | prefixIndex<<16;
  2002. /**/System.out.println("set w3="+w3+" "+(w3>>16)+"/"+(w3&0xffff));
  2003. //int ourslot = nodes.appendSlot(w0, w1, w2, w3);
  2004. int ourslot = appendNode(w0, w1, w2, w3);
  2005. currentParent = ourslot;
  2006. previousSibling = 0;
  2007. // set the root element pointer when creating the first element node
  2008. if (m_docElement == NULL)
  2009. m_docElement = ourslot;
  2010. }
  2011. /** Append a Namespace Declaration child at the current insertion point.
  2012. * Assumes that the symbols (namespace URI and prefix) have already been
  2013. * added to the pools
  2014. *
  2015. * @param prefixIndex: Index within the prefix string pool
  2016. * @param namespaceIndex: Index within the namespaceURI string pool
  2017. * @param isID: If someone really insists on writing a bad DTD, it is
  2018. * theoretically possible for a namespace declaration to also be declared
  2019. * as being a node ID. I don't really want to support that stupidity,
  2020. * but I'm not sure we can refuse to accept it.
  2021. * */
  2022. void appendNSDeclaration(int prefixIndex, int namespaceIndex,
  2023. boolean isID)
  2024. {
  2025. // %REVIEW% I'm assigning this node the "namespace for namespaces"
  2026. // which the DOM defined. It is expected that the Namespace spec will
  2027. // adopt this as official. It isn't strictly needed since it's implied
  2028. // by the nodetype, but for now...
  2029. // %REVIEW% Prefix need not be recorded; it's implied too. But
  2030. // recording it might simplify the design.
  2031. // %TBD% isID is not currently honored.
  2032. final int namespaceForNamespaces=m_nsNames.stringToIndex("http://www.w3.org/2000/xmlns/");
  2033. // W0 High: Namespace Low: Node Type
  2034. int w0 = NAMESPACE_NODE | (m_nsNames.stringToIndex("http://www.w3.org/2000/xmlns/")<<16);
  2035. // W1: Parent
  2036. int w1 = currentParent;
  2037. // W2: CURRENTLY UNUSED -- It's next-sib in attrs, but we have no kids.
  2038. int w2 = 0;
  2039. // W3: namespace name
  2040. int w3 = namespaceIndex;
  2041. // Add node
  2042. int ourslot = appendNode(w0, w1, w2, w3);
  2043. previousSibling = ourslot; // Should attributes be previous siblings
  2044. previousSiblingWasParent = false;
  2045. return ;//(m_docHandle | ourslot);
  2046. }
  2047. /** Append an Attribute child at the current insertion
  2048. * point. Assumes that the symbols (namespace URI, local name, and
  2049. * prefix) have already been added to the pools, and that the content has
  2050. * already been appended to m_char. Note that the attribute's content has
  2051. * been flattened into a single string; DTM does _NOT_ attempt to model
  2052. * the details of entity references within attribute values.
  2053. *
  2054. * @param namespaceIndex int Index within the namespaceURI string pool
  2055. * @param localNameIndex int Index within the local name string pool
  2056. * @param prefixIndex int Index within the prefix string pool
  2057. * @param isID boolean True if this attribute was declared as an ID
  2058. * (for use in supporting getElementByID).
  2059. * @param m_char_current_start int Starting offset of node's content in m_char.
  2060. * @param contentLength int Length of node's content in m_char.
  2061. * */
  2062. void appendAttribute(int namespaceIndex, int localNameIndex, int prefixIndex,
  2063. boolean isID,
  2064. int m_char_current_start, int contentLength)
  2065. {
  2066. // %TBD% isID is not currently honored.
  2067. // W0 High: Namespace Low: Node Type
  2068. int w0 = ATTRIBUTE_NODE | namespaceIndex<<16;
  2069. // W1: Parent
  2070. int w1 = currentParent;
  2071. // W2: Next (not yet resolved)
  2072. int w2 = 0;
  2073. // W3: Tagname high: prefix Low: local name
  2074. int w3 = localNameIndex | prefixIndex<<16;
  2075. /**/System.out.println("set w3="+w3+" "+(w3>>16)+"/"+(w3&0xffff));
  2076. // Add node
  2077. int ourslot = appendNode(w0, w1, w2, w3);
  2078. previousSibling = ourslot; // Should attributes be previous siblings
  2079. // Attribute's content is currently appended as a Text Node
  2080. // W0: Node Type
  2081. w0 = TEXT_NODE;
  2082. // W1: Parent
  2083. w1 = ourslot;
  2084. // W2: Start Position within buffer
  2085. w2 = m_char_current_start;
  2086. // W3: Length
  2087. w3 = contentLength;
  2088. appendNode(w0, w1, w2, w3);
  2089. // Attrs are Parents
  2090. previousSiblingWasParent = true;
  2091. return ;//(m_docHandle | ourslot);
  2092. }
  2093. /**
  2094. * This returns a stateless "traverser", that can navigate over an
  2095. * XPath axis, though not in document order.
  2096. *
  2097. * @param axis One of Axes.ANCESTORORSELF, etc.
  2098. *
  2099. * @return A DTMAxisIterator, or null if the given axis isn't supported.
  2100. */
  2101. public DTMAxisTraverser getAxisTraverser(final int axis)
  2102. {
  2103. return null;
  2104. }
  2105. /**
  2106. * This is a shortcut to the iterators that implement the
  2107. * supported XPath axes (only namespace::) is not supported.
  2108. * Returns a bare-bones iterator that must be initialized
  2109. * with a start node (using iterator.setStartNode()).
  2110. *
  2111. * @param axis One of Axes.ANCESTORORSELF, etc.
  2112. *
  2113. * @return A DTMAxisIterator, or null if the given axis isn't supported.
  2114. */
  2115. public DTMAxisIterator getAxisIterator(final int axis)
  2116. {
  2117. // %TBD%
  2118. return null;
  2119. }
  2120. /**
  2121. * Get an iterator that can navigate over an XPath Axis, predicated by
  2122. * the extended type ID.
  2123. *
  2124. *
  2125. * @param axis
  2126. * @param type An extended type ID.
  2127. *
  2128. * @return A DTMAxisIterator, or null if the given axis isn't supported.
  2129. */
  2130. public DTMAxisIterator getTypedAxisIterator(final int axis, final int type)
  2131. {
  2132. // %TBD%
  2133. return null;
  2134. }
  2135. /** Terminate the element currently acting as an insertion point. Subsequent
  2136. * insertions will occur as the last child of this element's parent.
  2137. * */
  2138. void appendEndElement()
  2139. {
  2140. // pop up the stacks
  2141. if (previousSiblingWasParent)
  2142. nodes.writeEntry(previousSibling, 2, NULL);
  2143. // Pop parentage
  2144. previousSibling = currentParent;
  2145. nodes.readSlot(currentParent, gotslot);
  2146. currentParent = gotslot[1] & 0xFFFF;
  2147. // The element just being finished will be
  2148. // the previous sibling for the next operation
  2149. previousSiblingWasParent = true;
  2150. // Pop a level of namespace table
  2151. // namespaceTable.removeLastElem();
  2152. }
  2153. /** Starting a new document. Perform any resets/initialization
  2154. * not already handled.
  2155. * */
  2156. void appendStartDocument()
  2157. {
  2158. // %TBD% reset slot 0 to indicate ChunkedIntArray reuse or wait for
  2159. // the next initDocument().
  2160. m_docElement = NULL; // reset nodeHandle to the root of the actual dtm doc content
  2161. initDocument(0);
  2162. }
  2163. /** All appends to this document have finished; do whatever final
  2164. * cleanup is needed.
  2165. * */
  2166. void appendEndDocument()
  2167. {
  2168. done = true;
  2169. // %TBD% may need to notice the last slot number and slot count to avoid
  2170. // residual data from provious use of this DTM
  2171. }
  2172. /**
  2173. * For the moment all the run time properties are ignored by this
  2174. * class.
  2175. *
  2176. * @param property a <code>String</code> value
  2177. * @param value an <code>Object</code> value
  2178. */
  2179. public void setProperty(String property, Object value)
  2180. {
  2181. }
  2182. /**
  2183. * Source information is not handled yet, so return
  2184. * <code>null</code> here.
  2185. *
  2186. * @param node an <code>int</code> value
  2187. * @return null
  2188. */
  2189. public SourceLocator getSourceLocatorFor(int node)
  2190. {
  2191. return null;
  2192. }
  2193. /**
  2194. * A dummy routine to satisify the abstract interface. If the DTM
  2195. * implememtation that extends the default base requires notification
  2196. * of registration, they can override this method.
  2197. */
  2198. public void documentRegistration()
  2199. {
  2200. }
  2201. /**
  2202. * A dummy routine to satisify the abstract interface. If the DTM
  2203. * implememtation that extends the default base requires notification
  2204. * when the document is being released, they can override this method
  2205. */
  2206. public void documentRelease()
  2207. {
  2208. }
  2209. }