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