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