KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > dtm > ref > DTMDocumentImpl


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: DTMDocumentImpl.java,v 1.13 2004/02/16 23:06:11 minchau Exp $
18  */

19 package com.sun.org.apache.xml.internal.dtm.ref;
20
21 import javax.xml.transform.SourceLocator JavaDoc;
22
23 import com.sun.org.apache.xml.internal.dtm.DTM;
24 import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
25 import com.sun.org.apache.xml.internal.dtm.DTMAxisTraverser;
26 import com.sun.org.apache.xml.internal.dtm.DTMManager;
27 import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;
28 import com.sun.org.apache.xml.internal.utils.FastStringBuffer;
29 import com.sun.org.apache.xml.internal.utils.XMLString;
30 import com.sun.org.apache.xml.internal.utils.XMLStringFactory;
31
32 import org.xml.sax.Attributes JavaDoc;
33 import org.xml.sax.ContentHandler JavaDoc;
34 import org.xml.sax.Locator JavaDoc;
35 import org.xml.sax.ext.LexicalHandler JavaDoc;
36
37 /**
38  * This is the implementation of the DTM document interface. It receives
39  * requests from an XML content handler similar to that of an XML DOM or SAX parser
40  * to store information from the xml document in an array based
41  * dtm table structure. This informtion is used later for document navigation,
42  * query, and SAX event dispatch functions. The DTM can also be used directly as a
43  * document composition model for an application. The requests received are:
44  * <ul>
45  * <li>initiating DTM to set the doc handle</li>
46  * <li>resetting DTM for data structure reuse</li>
47  * <li>hinting the end of document to adjust the end of data structure pointers</li>
48  * <li>createnodes (element, comment, text, attribute, ....)</li>
49  * <li>hinting the end of an element to patch parent and siblings<li>
50  * <li>setting application provided symbol name stringpool data structures</li>
51  * </ul>
52  * <p>State: In progress!!</p>
53  *
54  * %REVIEW% I _think_ the SAX convention is that "no namespace" is expressed
55  * as "" rather than as null (which is the DOM's convention). What should
56  * DTM expect? What should it do with the other?
57  *
58  * <p>Origin: the implemention is a composite logic based on the DTM of XalanJ1 and
59  * DocImpl, DocumentImpl, ElementImpl, TextImpl, etc. of XalanJ2</p>
60  */

61 public class DTMDocumentImpl
62 implements DTM, org.xml.sax.ContentHandler JavaDoc, org.xml.sax.ext.LexicalHandler JavaDoc
63 {
64
65         // Number of lower bits used to represent node index.
66
protected static final byte DOCHANDLE_SHIFT = 22;
67         // Masks the lower order of node handle.
68
// Same as {@link DTMConstructor.IDENT_NODE_DEFAULT}
69
protected static final int NODEHANDLE_MASK = (1 << (DOCHANDLE_SHIFT + 1)) - 1;
70         // Masks the higher order Document handle
71
// Same as {@link DTMConstructor.IDENT_DOC_DEFAULT}
72
protected static final int DOCHANDLE_MASK = -1 - NODEHANDLE_MASK;
73
74         int m_docHandle = NULL; // masked document handle for this dtm document
75
int m_docElement = NULL; // nodeHandle to the root of the actual dtm doc content
76

77         // Context for parse-and-append operations
78
int currentParent = 0; // current parent - default is document root
79
int previousSibling = 0; // previous sibling - no previous sibling
80
protected int m_currentNode = -1; // current node
81

82         // The tree under construction can itself be used as
83
// the element stack, so m_elemStack isn't needed.
84
//protected Stack m_elemStack = new Stack(); // element stack
85

86         private boolean previousSiblingWasParent = false;
87         // Local cache for record-at-a-time fetch
88
int gotslot[] = new int[4];
89
90         // endDocument recieved?
91
private boolean done = false;
92         boolean m_isError = false;
93
94         private final boolean DEBUG = false;
95
96         /** The document base URI. */
97         protected String JavaDoc m_documentBaseURI;
98
99   /** If we're building the model incrementally on demand, we need to
100    * be able to tell the source when to send us more data.
101    *
102    * Note that if this has not been set, and you attempt to read ahead
103    * of the current build point, we'll probably throw a null-pointer
104    * exception. We could try to wait-and-retry instead, as a very poor
105    * fallback, but that has all the known problems with multithreading
106    * on multiprocessors and we Don't Want to Go There.
107    *
108    * @see setIncrementalSAXSource
109    */

110   private IncrementalSAXSource m_incrSAXSource=null;
111
112
113         // ========= DTM data structure declarations. ==============
114

115         // nodes array: integer array blocks to hold the first level reference of the nodes,
116
// each reference slot is addressed by a nodeHandle index value.
117
// Assumes indices are not larger than {@link NODEHANDLE_MASK}
118
// ({@link DOCHANDLE_SHIFT} bits).
119
ChunkedIntArray nodes = new ChunkedIntArray(4);
120
121         // text/comment table: string buffer to hold the text string values of the document,
122
// each of which is addressed by the absolute offset and length in the buffer
123
private FastStringBuffer m_char = new FastStringBuffer();
124         // Start of string currently being accumulated into m_char;
125
// needed because the string may be appended in several chunks.
126
private int m_char_current_start=0;
127
128         // %TBD% INITIALIZATION/STARTUP ISSUES
129
// -- Should we really be creating these, or should they be
130
// passed in from outside? Scott want to be able to share
131
// pools across multiple documents, so setting them here is
132
// probably not the right default.
133
private DTMStringPool m_localNames = new DTMStringPool();
134         private DTMStringPool m_nsNames = new DTMStringPool();
135         private DTMStringPool m_prefixNames = new DTMStringPool();
136
137         // %TBD% If we use the current ExpandedNameTable mapper, it
138
// needs to be bound to the NS and local name pools. Which
139
// means it needs to attach to them AFTER we've resolved their
140
// startup. Or it needs to attach to this document and
141
// retrieve them each time. Or this needs to be
142
// an interface _implemented_ by this class... which might be simplest!
143
private ExpandedNameTable m_expandedNames=
144                 new ExpandedNameTable();
145
146         private XMLStringFactory m_xsf;
147
148
149         /**
150          * Construct a DTM.
151          *
152          * @param documentNumber the ID number assigned to this document.
153          * It will be shifted up into the high bits and returned as part of
154          * all node ID numbers, so those IDs indicate which document they
155          * came from as well as a location within the document. It is the
156          * DTMManager's responsibility to assign a unique number to each
157          * document.
158          */

159         public DTMDocumentImpl(DTMManager mgr, int documentNumber,
160                                DTMWSFilter whiteSpaceFilter,
161                                XMLStringFactory xstringfactory){
162                 initDocument(documentNumber); // clear nodes and document handle
163
m_xsf = xstringfactory;
164         }
165
166   /** Bind a IncrementalSAXSource to this DTM. If we discover we need nodes
167    * that have not yet been built, we will ask this object to send us more
168    * events, and it will manage interactions with its data sources.
169    *
170    * Note that we do not actually build the IncrementalSAXSource, since we don't
171    * know what source it's reading from, what thread that source will run in,
172    * or when it will run.
173    *
174    * @param source The IncrementalSAXSource that we want to recieve events from
175    * on demand.
176    */

177   public void setIncrementalSAXSource(IncrementalSAXSource source)
178   {
179     m_incrSAXSource=source;
180
181     // Establish SAX-stream link so we can receive the requested data
182
source.setContentHandler(this);
183     source.setLexicalHandler(this);
184
185     // Are the following really needed? IncrementalSAXSource doesn't yet
186
// support them, and they're mostly no-ops here...
187
//source.setErrorHandler(this);
188
//source.setDTDHandler(this);
189
//source.setDeclHandler(this);
190
}
191
192         /**
193          * Wrapper for ChunkedIntArray.append, to automatically update the
194          * previous sibling's "next" reference (if necessary) and periodically
195          * wake a reader who may have encountered incomplete data and entered
196          * a wait state.
197          * @param w0 int As in ChunkedIntArray.append
198          * @param w1 int As in ChunkedIntArray.append
199          * @param w2 int As in ChunkedIntArray.append
200          * @param w3 int As in ChunkedIntArray.append
201          * @return int As in ChunkedIntArray.append
202          * @see ChunkedIntArray.append
203          */

204         private final int appendNode(int w0, int w1, int w2, int w3)
205         {
206                 // A decent compiler may inline this.
207
int slotnumber = nodes.appendSlot(w0, w1, w2, w3);
208
209                 if (DEBUG) System.out.println(slotnumber+": "+w0+" "+w1+" "+w2+" "+w3);
210
211                 if (previousSiblingWasParent)
212                         nodes.writeEntry(previousSibling,2,slotnumber);
213
214                 previousSiblingWasParent = false; // Set the default; endElement overrides
215

216                 return slotnumber;
217         }
218
219         // ========= DTM Implementation Control Functions. ==============
220

221         /**
222          * Set an implementation dependent feature.
223          * <p>
224          * %REVIEW% Do we really expect to set features on DTMs?
225          *
226          * @param featureId A feature URL.
227          * @param state true if this feature should be on, false otherwise.
228          */

229         public void setFeature(String JavaDoc featureId, boolean state) {};
230
231         /**
232          * Set a reference pointer to the element name symbol table.
233          * %REVIEW% Should this really be Public? Changing it while
234          * DTM is in use would be a disaster.
235          *
236          * @param poolRef DTMStringPool reference to an instance of table.
237          */

238         public void setLocalNameTable(DTMStringPool poolRef) {
239                 m_localNames = poolRef;
240         }
241
242         /**
243          * Get a reference pointer to the element name symbol table.
244          *
245          * @return DTMStringPool reference to an instance of table.
246          */

247         public DTMStringPool getLocalNameTable() {
248                  return m_localNames;
249          }
250
251         /**
252          * Set a reference pointer to the namespace URI symbol table.
253          * %REVIEW% Should this really be Public? Changing it while
254          * DTM is in use would be a disaster.
255          *
256          * @param poolRef DTMStringPool reference to an instance of table.
257          */

258         public void setNsNameTable(DTMStringPool poolRef) {
259                 m_nsNames = poolRef;
260         }
261
262         /**
263          * Get a reference pointer to the namespace URI symbol table.
264          *
265          * @return DTMStringPool reference to an instance of table.
266          */

267         public DTMStringPool getNsNameTable() {
268                  return m_nsNames;
269          }
270
271         /**
272          * Set a reference pointer to the prefix name symbol table.
273          * %REVIEW% Should this really be Public? Changing it while
274          * DTM is in use would be a disaster.
275          *
276          * @param poolRef DTMStringPool reference to an instance of table.
277          */

278         public void setPrefixNameTable(DTMStringPool poolRef) {
279                 m_prefixNames = poolRef;
280         }
281
282         /**
283          * Get a reference pointer to the prefix name symbol table.
284          *
285          * @return DTMStringPool reference to an instance of table.
286          */

287         public DTMStringPool getPrefixNameTable() {
288                 return m_prefixNames;
289         }
290
291          /**
292           * Set a reference pointer to the content-text repository
293           *
294           * @param bufferRef FastStringBuffer reference to an instance of
295           * buffer
296           */

297          void setContentBuffer(FastStringBuffer buffer) {
298                  m_char = buffer;
299          }
300
301          /**
302           * Get a reference pointer to the content-text repository
303           *
304           * @return FastStringBuffer reference to an instance of buffer
305           */

306          FastStringBuffer getContentBuffer() {
307                  return m_char;
308          }
309
310   /** getContentHandler returns "our SAX builder" -- the thing that
311    * someone else should send SAX events to in order to extend this
312    * DTM model.
313    *
314    * @return null if this model doesn't respond to SAX events,
315    * "this" if the DTM object has a built-in SAX ContentHandler,
316    * the IncrementalSAXSource if we're bound to one and should receive
317    * the SAX stream via it for incremental build purposes...
318    * */

319   public org.xml.sax.ContentHandler JavaDoc getContentHandler()
320   {
321     if (m_incrSAXSource instanceof IncrementalSAXSource_Filter)
322       return (ContentHandler JavaDoc) m_incrSAXSource;
323     else
324       return this;
325   }
326
327   /**
328    * Return this DTM's lexical handler.
329    *
330    * %REVIEW% Should this return null if constrution already done/begun?
331    *
332    * @return null if this model doesn't respond to lexical SAX events,
333    * "this" if the DTM object has a built-in SAX ContentHandler,
334    * the IncrementalSAXSource if we're bound to one and should receive
335    * the SAX stream via it for incremental build purposes...
336    */

337   public LexicalHandler JavaDoc getLexicalHandler()
338   {
339
340     if (m_incrSAXSource instanceof IncrementalSAXSource_Filter)
341       return (LexicalHandler JavaDoc) m_incrSAXSource;
342     else
343       return this;
344   }
345
346   /**
347    * Return this DTM's EntityResolver.
348    *
349    * @return null if this model doesn't respond to SAX entity ref events.
350    */

351   public org.xml.sax.EntityResolver JavaDoc getEntityResolver()
352   {
353
354     return null;
355   }
356
357   /**
358    * Return this DTM's DTDHandler.
359    *
360    * @return null if this model doesn't respond to SAX dtd events.
361    */

362   public org.xml.sax.DTDHandler JavaDoc getDTDHandler()
363   {
364
365     return null;
366   }
367
368   /**
369    * Return this DTM's ErrorHandler.
370    *
371    * @return null if this model doesn't respond to SAX error events.
372    */

373   public org.xml.sax.ErrorHandler JavaDoc getErrorHandler()
374   {
375
376     return null;
377   }
378
379   /**
380    * Return this DTM's DeclHandler.
381    *
382    * @return null if this model doesn't respond to SAX Decl events.
383    */

384   public org.xml.sax.ext.DeclHandler JavaDoc getDeclHandler()
385   {
386
387     return null;
388   }
389
390   /** @return true iff we're building this model incrementally (eg
391    * we're partnered with a IncrementalSAXSource) and thus require that the
392    * transformation and the parse run simultaneously. Guidance to the
393    * DTMManager.
394    * */

395   public boolean needsTwoThreads()
396   {
397     return null!=m_incrSAXSource;
398   }
399
400   //================================================================
401
// ========= SAX2 ContentHandler methods =========
402
// Accept SAX events, use them to build/extend the DTM tree.
403
// Replaces the deprecated DocumentHandler interface.
404

405   public void characters(char[] ch, int start, int length)
406        throws org.xml.sax.SAXException JavaDoc
407   {
408     // Actually creating the text node is handled by
409
// processAccumulatedText(); here we just accumulate the
410
// characters into the buffer.
411
m_char.append(ch,start,length);
412   }
413
414   // Flush string accumulation into a text node
415
private void processAccumulatedText()
416   {
417     int len=m_char.length();
418     if(len!=m_char_current_start)
419       {
420         // The FastStringBuffer has been previously agreed upon
421
appendTextChild(m_char_current_start,len-m_char_current_start);
422         m_char_current_start=len;
423       }
424   }
425   public void endDocument()
426        throws org.xml.sax.SAXException JavaDoc
427   {
428     // May need to tell the low-level builder code to pop up a level.
429
// There _should't_ be any significant pending text at this point.
430
appendEndDocument();
431   }
432   public void endElement(java.lang.String JavaDoc namespaceURI, java.lang.String JavaDoc localName,
433       java.lang.String JavaDoc qName)
434        throws org.xml.sax.SAXException JavaDoc
435   {
436     processAccumulatedText();
437     // No args but we do need to tell the low-level builder code to
438
// pop up a level.
439
appendEndElement();
440   }
441   public void endPrefixMapping(java.lang.String JavaDoc prefix)
442        throws org.xml.sax.SAXException JavaDoc
443   {
444     // No-op
445
}
446   public void ignorableWhitespace(char[] ch, int start, int length)
447        throws org.xml.sax.SAXException JavaDoc
448   {
449     // %TBD% I believe ignorable text isn't part of the DTM model...?
450
}
451   public void processingInstruction(java.lang.String JavaDoc target, java.lang.String JavaDoc data)
452        throws org.xml.sax.SAXException JavaDoc
453   {
454     processAccumulatedText();
455     // %TBD% Which pools do target and data go into?
456
}
457   public void setDocumentLocator(Locator JavaDoc locator)
458   {
459     // No-op for DTM
460
}
461   public void skippedEntity(java.lang.String JavaDoc name)
462        throws org.xml.sax.SAXException JavaDoc
463   {
464     processAccumulatedText();
465     //%TBD%
466
}
467   public void startDocument()
468        throws org.xml.sax.SAXException JavaDoc
469   {
470     appendStartDocument();
471   }
472   public void startElement(java.lang.String JavaDoc namespaceURI, java.lang.String JavaDoc localName,
473       java.lang.String JavaDoc qName, Attributes JavaDoc atts)
474        throws org.xml.sax.SAXException JavaDoc
475   {
476     processAccumulatedText();
477
478     // %TBD% Split prefix off qname
479
String JavaDoc prefix=null;
480     int colon=qName.indexOf(':');
481     if(colon>0)
482       prefix=qName.substring(0,colon);
483
484     // %TBD% Where do we pool expandedName, or is it just the union, or...
485
/**/System.out.println("Prefix="+prefix+" index="+m_prefixNames.stringToIndex(prefix));
486     appendStartElement(m_nsNames.stringToIndex(namespaceURI),
487                      m_localNames.stringToIndex(localName),
488                      m_prefixNames.stringToIndex(prefix)); /////// %TBD%
489

490     // %TBD% I'm assuming that DTM will require resequencing of
491
// NS decls before other attrs, hence two passes are taken.
492
// %TBD% Is there an easier way to test for NSDecl?
493
int nAtts=(atts==null) ? 0 : atts.getLength();
494     // %TBD% Countdown is more efficient if nobody cares about sequence.
495
for(int i=nAtts-1;i>=0;--i)
496       {
497         qName=atts.getQName(i);
498         if(qName.startsWith("xmlns:") || "xmlns".equals(qName))
499           {
500             prefix=null;
501             colon=qName.indexOf(':');
502             if(colon>0)
503               {
504                 prefix=qName.substring(0,colon);
505               }
506             else
507               {
508                 // %REVEIW% Null or ""?
509
prefix=null; // Default prefix
510
}
511
512
513             appendNSDeclaration(
514                                     m_prefixNames.stringToIndex(prefix),
515                                     m_nsNames.stringToIndex(atts.getValue(i)),
516                                     atts.getType(i).equalsIgnoreCase("ID"));
517           }
518       }
519
520     for(int i=nAtts-1;i>=0;--i)
521       {
522         qName=atts.getQName(i);
523         if(!(qName.startsWith("xmlns:") || "xmlns".equals(qName)))
524           {
525             // %TBD% I hate having to extract the prefix into a new
526
// string when we may never use it. Consider pooling whole
527
// qNames, which are already strings?
528
prefix=null;
529             colon=qName.indexOf(':');
530             if(colon>0)
531               {
532                 prefix=qName.substring(0,colon);
533                 localName=qName.substring(colon+1);
534               }
535             else
536               {
537                 prefix=""; // Default prefix
538
localName=qName;
539               }
540
541
542             m_char.append(atts.getValue(i)); // Single-string value
543
int contentEnd=m_char.length();
544
545             if(!("xmlns".equals(prefix) || "xmlns".equals(qName)))
546               appendAttribute(m_nsNames.stringToIndex(atts.getURI(i)),
547                                   m_localNames.stringToIndex(localName),
548                                   m_prefixNames.stringToIndex(prefix),
549                                   atts.getType(i).equalsIgnoreCase("ID"),
550                                   m_char_current_start, contentEnd-m_char_current_start);
551             m_char_current_start=contentEnd;
552           }
553       }
554   }
555   public void startPrefixMapping(java.lang.String JavaDoc prefix, java.lang.String JavaDoc uri)
556        throws org.xml.sax.SAXException JavaDoc
557   {
558     // No-op in DTM, handled during element/attr processing?
559
}
560
561   //
562
// LexicalHandler support. Not all SAX2 parsers support these events
563
// but we may want to pass them through when they exist...
564
//
565
public void comment(char[] ch, int start, int length)
566        throws org.xml.sax.SAXException JavaDoc
567   {
568     processAccumulatedText();
569
570     m_char.append(ch,start,length); // Single-string value
571
appendComment(m_char_current_start,length);
572     m_char_current_start+=length;
573   }
574   public void endCDATA()
575        throws org.xml.sax.SAXException JavaDoc
576   {
577     // No-op in DTM
578
}
579   public void endDTD()
580        throws org.xml.sax.SAXException JavaDoc
581   {
582     // No-op in DTM
583
}
584   public void endEntity(java.lang.String JavaDoc name)
585        throws org.xml.sax.SAXException JavaDoc
586   {
587     // No-op in DTM
588
}
589   public void startCDATA()
590        throws org.xml.sax.SAXException JavaDoc
591   {
592     // No-op in DTM
593
}
594   public void startDTD(java.lang.String JavaDoc name, java.lang.String JavaDoc publicId,
595       java.lang.String JavaDoc systemId)
596        throws org.xml.sax.SAXException JavaDoc
597   {
598     // No-op in DTM
599
}
600   public void startEntity(java.lang.String JavaDoc name)
601        throws org.xml.sax.SAXException JavaDoc
602   {
603     // No-op in DTM
604
}
605
606
607   //================================================================
608
// ========= Document Handler Functions =========
609
// %REVIEW% jjk -- DocumentHandler is SAX Level 1, and deprecated....
610
// and this wasn't a fully compliant or declared implementation of that API
611
// in any case. Phase out in favor of SAX2 ContentHandler/LexicalHandler
612

613         /**
614          * Reset a dtm document to its initial (empty) state.
615          *
616          * The DTMManager will invoke this method when the dtm is created.
617          *
618          * @param docHandle int the handle for the DTM document.
619          */

620         final void initDocument(int documentNumber)
621         {
622                 // save masked DTM document handle
623
m_docHandle = documentNumber<<DOCHANDLE_SHIFT;
624
625                 // Initialize the doc -- no parent, no next-sib
626
nodes.writeSlot(0,DOCUMENT_NODE,-1,-1,0);
627                 // wait for the first startElement to create the doc root node
628
done = false;
629         }
630
631 // /**
632
// * Receive hint of the end of a document.
633
// *
634
// * <p>The content handler will invoke this method only once, and it will
635
// * be the last method invoked during the parse. The handler shall not
636
// * not invoke this method until it has either abandoned parsing
637
// * (because of an unrecoverable error) or reached the end of
638
// * input.</p>
639
// */
640
// public void documentEnd()
641
// {
642
// done = true;
643
// // %TBD% may need to notice the last slot number and slot count to avoid
644
// // residual data from provious use of this DTM
645
// }
646

647 // /**
648
// * Receive notification of the beginning of a document.
649
// *
650
// * <p>The SAX parser will invoke this method only once, before any
651
// * other methods in this interface.</p>
652
// */
653
// public void reset()
654
// {
655

656 // // %TBD% reset slot 0 to indicate ChunkedIntArray reuse or wait for
657
// // the next initDocument().
658
// m_docElement = NULL; // reset nodeHandle to the root of the actual dtm doc content
659
// initDocument(0);
660
// }
661

662 // /**
663
// * Factory method; creates an Element node in this document.
664
// *
665
// * The node created will be chained according to its natural order of request
666
// * received. %TBD% It can be rechained later via the optional DTM writable interface.
667
// *
668
// * <p>The XML content handler will invoke endElement() method after all
669
// * of the element's content are processed in order to give DTM the indication
670
// * to prepare and patch up parent and sibling node pointers.</p>
671
// *
672
// * <p>The following interface for createElement will use an index value corresponds
673
// * to the symbol entry in the DTMDStringPool based symbol tables.</p>
674
// *
675
// * @param nsIndex The namespace of the node
676
// * @param nameIndex The element name.
677
// * @see #endElement
678
// * @see org.xml.sax.Attributes
679
// * @return nodeHandle int of the element created
680
// */
681
// public int createElement(int nsIndex, int nameIndex, Attributes atts)
682
// {
683
// // do document root node creation here on the first element, create nodes for
684
// // this element and its attributes, store the element, namespace, and attritute
685
// // name indexes to the nodes array, keep track of the current node and parent
686
// // element used
687

688 // // W0 High: Namespace Low: Node Type
689
// int w0 = (nsIndex << 16) | ELEMENT_NODE;
690
// // W1: Parent
691
// int w1 = currentParent;
692
// // W2: Next (initialized as 0)
693
// int w2 = 0;
694
// // W3: Tagname
695
// int w3 = nameIndex;
696
// //int ourslot = nodes.appendSlot(w0, w1, w2, w3);
697
// int ourslot = appendNode(w0, w1, w2, w3);
698
// currentParent = ourslot;
699
// previousSibling = 0;
700
// setAttributes(atts);
701

702 // // set the root element pointer when creating the first element node
703
// if (m_docElement == NULL)
704
// m_docElement = ourslot;
705
// return (m_docHandle | ourslot);
706
// }
707

708 // // Factory method to create an Element node not associated with a given name space
709
// // using String value parameters passed in from a content handler or application
710
// /**
711
// * Factory method; creates an Element node not associated with a given name space in this document.
712
// *
713
// * The node created will be chained according to its natural order of request
714
// * received. %TBD% It can be rechained later via the optional DTM writable interface.
715
// *
716
// * <p>The XML content handler or application will invoke endElement() method after all
717
// * of the element's content are processed in order to give DTM the indication
718
// * to prepare and patch up parent and sibling node pointers.</p>
719
// *
720
// * <p>The following parameters for createElement contains raw string values for name
721
// * symbols used in an Element node.</p>
722
// *
723
// * @param name String the element name, including the prefix if any.
724
// * @param atts The attributes attached to the element, if any.
725
// * @see #endElement
726
// * @see org.xml.sax.Attributes
727
// */
728
// public int createElement(String name, Attributes atts)
729
// {
730
// // This method wraps around the index valued interface of the createElement interface.
731
// // The raw string values are stored into the current DTM name symbol tables. The method
732
// // method will then use the index values returned to invoke the other createElement()
733
// // onverted to index values modified to match a
734
// // method.
735
// int nsIndex = NULL;
736
// int nameIndex = m_localNames.stringToIndex(name);
737
// // note - there should be no prefix separator in the name because it is not associated
738
// // with a name space
739

740 // return createElement(nsIndex, nameIndex, atts);
741
// }
742

743 // // Factory method to create an Element node associated with a given name space
744
// // using String value parameters passed in from a content handler or application
745
// /**
746
// * Factory method; creates an Element node associated with a given name space in this document.
747
// *
748
// * The node created will be chained according to its natural order of request
749
// * received. %TBD% It can be rechained later via the optional DTM writable interface.
750
// *
751
// * <p>The XML content handler or application will invoke endElement() method after all
752
// * of the element's content are processed in order to give DTM the indication
753
// * to prepare and patch up parent and sibling node pointers.</p>
754
// *
755
// * <p>The following parameters for createElementNS contains raw string values for name
756
// * symbols used in an Element node.</p>
757
// *
758
// * @param ns String the namespace of the node
759
// * @param name String the element name, including the prefix if any.
760
// * @param atts The attributes attached to the element, if any.
761
// * @see #endElement
762
// * @see org.xml.sax.Attributes
763
// */
764
// public int createElementNS(String ns, String name, Attributes atts)
765
// {
766
// // This method wraps around the index valued interface of the createElement interface.
767
// // The raw string values are stored into the current DTM name symbol tables. The method
768
// // method will then use the index values returned to invoke the other createElement()
769
// // onverted to index values modified to match a
770
// // method.
771
// int nsIndex = m_nsNames.stringToIndex(ns);
772
// int nameIndex = m_localNames.stringToIndex(name);
773
// // The prefixIndex is not needed by the indexed interface of the createElement method
774
// int prefixSep = name.indexOf(":");
775
// int prefixIndex = m_prefixNames.stringToIndex(name.substring(0, prefixSep));
776
// return createElement(nsIndex, nameIndex, atts);
777
// }
778

779 // /**
780
// * Receive an indication for the end of an element.
781
// *
782
// * <p>The XML content handler will invoke this method at the end of every
783
// * element in the XML document to give hint its time to pop up the current
784
// * element and parent and patch up parent and sibling pointers if necessary
785
// *
786
// * <p>%tbd% The following interface may need to be modified to match a
787
// * coordinated access to the DTMDStringPool based symbol tables.</p>
788
// *
789
// * @param ns the namespace of the element
790
// * @param localName The local part of the qualified name of the element
791
// * @param name The element name
792
// */
793
// public void endElement(String ns, String name)
794
// {
795
// // pop up the stacks
796

797 // //
798
// if (previousSiblingWasParent)
799
// nodes.writeEntry(previousSibling, 2, NULL);
800

801 // // Pop parentage
802
// previousSibling = currentParent;
803
// nodes.readSlot(currentParent, gotslot);
804
// currentParent = gotslot[1] & 0xFFFF;
805

806 // // The element just being finished will be
807
// // the previous sibling for the next operation
808
// previousSiblingWasParent = true;
809

810 // // Pop a level of namespace table
811
// // namespaceTable.removeLastElem();
812
// }
813

814 // /**
815
// * Creates attributes for the current node.
816
// *
817
// * @param atts Attributes to be created.
818
// */
819
// void setAttributes(Attributes atts) {
820
// int atLength = (null == atts) ? 0 : atts.getLength();
821
// for (int i=0; i < atLength; i++) {
822
// String qname = atts.getQName(i);
823
// createAttribute(atts.getQName(i), atts.getValue(i));
824
// }
825
// }
826

827 // /**
828
// * Appends an attribute to the document.
829
// * @param qname Qualified Name of the attribute
830
// * @param value Value of the attribute
831
// * @return Handle of node
832
// */
833
// public int createAttribute(String qname, String value) {
834
// int colonpos = qname.indexOf(":");
835
// String attName = qname.substring(colonpos+1);
836
// int w0 = 0;
837
// if (colonpos > 0) {
838
// String prefix = qname.substring(0, colonpos);
839
// if (prefix.equals("xml")) {
840
// //w0 = ATTRIBUTE_NODE |
841
// // (com.sun.org.apache.xalan.internal.templates.Constants.S_XMLNAMESPACEURI << 16);
842
// } else {
843
// //w0 = ATTRIBUTE_NODE |
844
// }
845
// } else {
846
// w0 = ATTRIBUTE_NODE;
847
// }
848
// // W1: Parent
849
// int w1 = currentParent;
850
// // W2: Next (not yet resolved)
851
// int w2 = 0;
852
// // W3: Tag name
853
// int w3 = m_localNames.stringToIndex(attName);
854
// // Add node
855
// int ourslot = appendNode(w0, w1, w2, w3);
856
// previousSibling = ourslot; // Should attributes be previous siblings
857

858 // // W0: Node Type
859
// w0 = TEXT_NODE;
860
// // W1: Parent
861
// w1 = ourslot;
862
// // W2: Start Position within buffer
863
// w2 = m_char.length();
864
// m_char.append(value);
865
// // W3: Length
866
// w3 = m_char.length() - w2;
867
// appendNode(w0, w1, w2, w3);
868
// charStringStart=m_char.length();
869
// charStringLength = 0;
870
// //previousSibling = ourslot;
871
// // Attrs are Parents
872
// previousSiblingWasParent = true;
873
// return (m_docHandle | ourslot);
874
// }
875

876 // /**
877
// * Factory method; creates a Text node in this document.
878
// *
879
// * The node created will be chained according to its natural order of request
880
// * received. %TBD% It can be rechained later via the optional DTM writable interface.
881
// *
882
// * @param text String The characters text string from the XML document.
883
// * @return int DTM node-number of the text node created
884
// */
885
// public int createTextNode(String text)
886
// throws DTMException
887
// {
888
// // wraps around the index value based createTextNode method
889
// return createTextNode(text.toCharArray(), 0, text.length());
890
// }
891

892 // /**
893
// * Factory method; creates a Text node in this document.
894
// *
895
// * The node created will be chained according to its natural order of request
896
// * received. %TBD% It can be rechained later via the optional DTM writable interface.
897
// *
898
// * %REVIEW% for text normalization issues, unless we are willing to
899
// * insist that all adjacent text must be merged before this method
900
// * is called.
901
// *
902
// * @param ch The characters from the XML document.
903
// * @param start The start position in the array.
904
// * @param length The number of characters to read from the array.
905
// */
906
// public int createTextNode(char ch[], int start, int length)
907
// throws DTMException
908
// {
909
// m_char.append(ch, start, length); // store the chunk to the text/comment string table
910

911 // // create a Text Node
912
// // %TBD% may be possible to combine with appendNode()to replace the next chunk of code
913
// int w0 = TEXT_NODE;
914
// // W1: Parent
915
// int w1 = currentParent;
916
// // W2: Start position within m_char
917
// int w2 = charStringStart;
918
// // W3: Length of the full string
919
// int w3 = length;
920
// int ourslot = appendNode(w0, w1, w2, w3);
921
// previousSibling = ourslot;
922

923 // charStringStart=m_char.length();
924
// charStringLength = 0;
925
// return (m_docHandle | ourslot);
926
// }
927

928 // /**
929
// * Factory method; creates a Comment node in this document.
930
// *
931
// * The node created will be chained according to its natural order of request
932
// * received. %TBD% It can be rechained later via the optional DTM writable interface.
933
// *
934
// * @param text String The characters text string from the XML document.
935
// * @return int DTM node-number of the text node created
936
// */
937
// public int createComment(String text)
938
// throws DTMException
939
// {
940
// // wraps around the index value based createTextNode method
941
// return createComment(text.toCharArray(), 0, text.length());
942
// }
943

944 // /**
945
// * Factory method; creates a Comment node in this document.
946
// *
947
// * The node created will be chained according to its natural order of request
948
// * received. %TBD% It can be rechained later via the optional DTM writable interface.
949
// *
950
// * @param ch An array holding the characters in the comment.
951
// * @param start The starting position in the array.
952
// * @param length The number of characters to use from the array.
953
// * @see DTMException
954
// */
955
// public int createComment(char ch[], int start, int length)
956
// throws DTMException
957
// {
958
// m_char.append(ch, start, length); // store the comment string to the text/comment string table
959

960 // // create a Comment Node
961
// // %TBD% may be possible to combine with appendNode()to replace the next chunk of code
962
// int w0 = COMMENT_NODE;
963
// // W1: Parent
964
// int w1 = currentParent;
965
// // W2: Start position within m_char
966
// int w2 = charStringStart;
967
// // W3: Length of the full string
968
// int w3 = length;
969
// int ourslot = appendNode(w0, w1, w2, w3);
970
// previousSibling = ourslot;
971

972 // charStringStart=m_char.length();
973
// charStringLength = 0;
974
// return (m_docHandle | ourslot);
975
// }
976

977 // // Counters to keep track of the current text string being accumulated with respect
978
// // to the text/comment string table: charStringStart should point to the starting
979
// // offset of the string in the table and charStringLength the acccumulated length when
980
// // appendAccumulatedText starts, and reset to the end of the table and 0 at the end
981
// // of appendAccumulatedText for the next set of characters receives
982
// int charStringStart=0,charStringLength=0;
983

984         // ========= Document Navigation Functions =========
985

986         /** Given a node handle, test if it has child nodes.
987          * <p> %REVIEW% This is obviously useful at the DOM layer, where it
988          * would permit testing this without having to create a proxy
989          * node. It's less useful in the DTM API, where
990          * (dtm.getFirstChild(nodeHandle)!=DTM.NULL) is just as fast and
991          * almost as self-evident. But it's a convenience, and eases porting
992          * of DOM code to DTM. </p>
993          *
994          * @param nodeHandle int Handle of the node.
995          * @return int true if the given node has child nodes.
996          */

997         public boolean hasChildNodes(int nodeHandle) {
998                 return(getFirstChild(nodeHandle) != NULL);
999         }
1000
1001        /**
1002         * Given a node handle, get the handle of the node's first child.
1003         * If not yet resolved, waits for more nodes to be added to the document and
1004         * tries again.
1005         *
1006         * @param nodeHandle int Handle of the node.
1007         * @return int DTM node-number of first child, or DTM.NULL to indicate none exists.
1008         */

1009        public int getFirstChild(int nodeHandle) {
1010
1011                // ###shs worry about tracing/debug later
1012
nodeHandle &= NODEHANDLE_MASK;
1013                // Read node into variable
1014
nodes.readSlot(nodeHandle, gotslot);
1015
1016                // type is the last half of first slot
1017
short type = (short) (gotslot[0] & 0xFFFF);
1018
1019                // Check to see if Element or Document node
1020
if ((type == ELEMENT_NODE) || (type == DOCUMENT_NODE) ||
1021                                (type == ENTITY_REFERENCE_NODE)) {
1022
1023                        // In case when Document root is given
1024
// if (nodeHandle == 0) nodeHandle = 1;
1025
// %TBD% Probably was a mistake.
1026
// If someone explicitly asks for first child
1027
// of Document, I would expect them to want
1028
// that and only that.
1029

1030                        int kid = nodeHandle + 1;
1031                        nodes.readSlot(kid, gotslot);
1032                        while (ATTRIBUTE_NODE == (gotslot[0] & 0xFFFF)) {
1033                                // points to next sibling
1034
kid = gotslot[2];
1035                                // Return NULL if node has only attributes
1036
if (kid == NULL) return NULL;
1037                                nodes.readSlot(kid, gotslot);
1038                        }
1039                        // If parent slot matches given parent, return kid
1040
if (gotslot[1] == nodeHandle)
1041                        {
1042                          int firstChild = kid | m_docHandle;
1043
1044                          return firstChild;
1045                        }
1046                }
1047                // No child found
1048

1049                return NULL;
1050        }
1051
1052        /**
1053        * Given a node handle, advance to its last child.
1054        * If not yet resolved, waits for more nodes to be added to the document and
1055        * tries again.
1056        *
1057        * @param nodeHandle int Handle of the node.
1058        * @return int Node-number of last child,
1059        * or DTM.NULL to indicate none exists.
1060        */

1061        public int getLastChild(int nodeHandle) {
1062                // ###shs put trace/debug later
1063
nodeHandle &= NODEHANDLE_MASK;
1064                // do not need to test node type since getFirstChild does that
1065
int lastChild = NULL;
1066                for (int nextkid = getFirstChild(nodeHandle); nextkid != NULL;
1067                                nextkid = getNextSibling(nextkid)) {
1068                        lastChild = nextkid;
1069                }
1070                return lastChild | m_docHandle;
1071        }
1072
1073        /**
1074         * Retrieves an attribute node by by qualified name and namespace URI.
1075         *
1076         * @param nodeHandle int Handle of the node upon which to look up this attribute.
1077         * @param namespaceURI The namespace URI of the attribute to
1078         * retrieve, or null.
1079         * @param name The local name of the attribute to
1080         * retrieve.
1081         * @return The attribute node handle with the specified name (
1082         * <code>nodeName</code>) or <code>DTM.NULL</code> if there is no such
1083         * attribute.
1084         */

1085        public int getAttributeNode(int nodeHandle, String JavaDoc namespaceURI, String JavaDoc name) {
1086                int nsIndex = m_nsNames.stringToIndex(namespaceURI),
1087                                                                        nameIndex = m_localNames.stringToIndex(name);
1088                nodeHandle &= NODEHANDLE_MASK;
1089                nodes.readSlot(nodeHandle, gotslot);
1090                short type = (short) (gotslot[0] & 0xFFFF);
1091                // If nodeHandle points to element next slot would be first attribute
1092
if (type == ELEMENT_NODE)
1093                        nodeHandle++;
1094                // Iterate through Attribute Nodes
1095
while (type == ATTRIBUTE_NODE) {
1096                        if ((nsIndex == (gotslot[0] << 16)) && (gotslot[3] == nameIndex))
1097                                return nodeHandle | m_docHandle;
1098                        // Goto next sibling
1099
nodeHandle = gotslot[2];
1100                        nodes.readSlot(nodeHandle, gotslot);
1101                }
1102                return NULL;
1103        }
1104
1105        /**
1106         * Given a node handle, get the index of the node's first attribute.
1107         *
1108         * @param nodeHandle int Handle of the Element node.
1109         * @return Handle of first attribute, or DTM.NULL to indicate none exists.
1110         */

1111        public int getFirstAttribute(int nodeHandle) {
1112                nodeHandle &= NODEHANDLE_MASK;
1113
1114                // %REVIEW% jjk: Just a quick observation: If you're going to
1115
// call readEntry repeatedly on the same node, it may be
1116
// more efficiently to do a readSlot to get the data locally,
1117
// reducing the addressing and call-and-return overhead.
1118

1119                // Should we check if handle is element (do we want sanity checks?)
1120
if (ELEMENT_NODE != (nodes.readEntry(nodeHandle, 0) & 0xFFFF))
1121                        return NULL;
1122                // First Attribute (if any) should be at next position in table
1123
nodeHandle++;
1124                return(ATTRIBUTE_NODE == (nodes.readEntry(nodeHandle, 0) & 0xFFFF)) ?
1125                nodeHandle | m_docHandle : NULL;
1126        }
1127
1128        /**
1129         * Given a node handle, get the index of the node's first child.
1130         * If not yet resolved, waits for more nodes to be added to the document and
1131         * tries again
1132         *
1133         * @param nodeHandle handle to node, which should probably be an element
1134         * node, but need not be.
1135         *
1136         * @param inScope true if all namespaces in scope should be returned,
1137         * false if only the namespace declarations should be
1138         * returned.
1139         * @return handle of first namespace, or DTM.NULL to indicate none exists.
1140         */

1141        public int getFirstNamespaceNode(int nodeHandle, boolean inScope) {
1142
1143                return NULL;
1144        }
1145
1146        /**
1147         * Given a node handle, advance to its next sibling.
1148         *
1149         * %TBD% This currently uses the DTM-internal definition of
1150         * sibling; eg, the last attr's next sib is the first
1151         * child. In the old DTM, the DOM proxy layer provided the
1152         * additional logic for the public view. If we're rewriting
1153         * for XPath emulation, that test must be done here.
1154         *
1155         * %TBD% CODE INTERACTION WITH INCREMENTAL PARSE - If not yet
1156         * resolved, should wait for more nodes to be added to the document
1157         * and tries again.
1158         *
1159         * @param nodeHandle int Handle of the node.
1160         * @return int Node-number of next sibling,
1161         * or DTM.NULL to indicate none exists.
1162         * */

1163        public int getNextSibling(int nodeHandle) {
1164                nodeHandle &= NODEHANDLE_MASK;
1165                // Document root has no next sibling
1166
if (nodeHandle == 0)
1167                        return NULL;
1168
1169                short type = (short) (nodes.readEntry(nodeHandle, 0) & 0xFFFF);
1170                if ((type == ELEMENT_NODE) || (type == ATTRIBUTE_NODE) ||
1171                                (type == ENTITY_REFERENCE_NODE)) {
1172                        int nextSib = nodes.readEntry(nodeHandle, 2);
1173                        if (nextSib == NULL)
1174                                return NULL;
1175                        if (nextSib != 0)
1176                                return (m_docHandle | nextSib);
1177                        // ###shs should cycle/wait if nextSib is 0? Working on threading next
1178
}
1179                // Next Sibling is in the next position if it shares the same parent
1180
int thisParent = nodes.readEntry(nodeHandle, 1);
1181
1182                if (nodes.readEntry(++nodeHandle, 1) == thisParent)
1183                        return (m_docHandle | nodeHandle);
1184
1185                return NULL;
1186        }
1187
1188        /**
1189         * Given a node handle, find its preceeding sibling.
1190         * WARNING: DTM is asymmetric; this operation is resolved by search, and is
1191         * relatively expensive.
1192         *
1193         * @param nodeHandle the id of the node.
1194         * @return int Node-number of the previous sib,
1195         * or DTM.NULL to indicate none exists.
1196         */

1197        public int getPreviousSibling(int nodeHandle) {
1198                nodeHandle &= NODEHANDLE_MASK;
1199                // Document root has no previous sibling
1200
if (nodeHandle == 0)
1201                        return NULL;
1202
1203                int parent = nodes.readEntry(nodeHandle, 1);
1204                int kid = NULL;
1205                for (int nextkid = getFirstChild(parent); nextkid != nodeHandle;
1206                                nextkid = getNextSibling(nextkid)) {
1207                        kid = nextkid;
1208                }
1209                return kid | m_docHandle;
1210        }
1211
1212        /**
1213         * Given a node handle, advance to the next attribute. If an
1214         * element, we advance to its first attribute; if an attr, we advance to
1215         * the next attr on the same node.
1216         *
1217         * @param nodeHandle int Handle of the node.
1218         * @return int DTM node-number of the resolved attr,
1219         * or DTM.NULL to indicate none exists.
1220         */

1221        public int getNextAttribute(int nodeHandle) {
1222                nodeHandle &= NODEHANDLE_MASK;
1223                nodes.readSlot(nodeHandle, gotslot);
1224
1225                //%REVIEW% Why are we using short here? There's no storage
1226
//reduction for an automatic variable, especially one used
1227
//so briefly, and it typically costs more cycles to process
1228
//than an int would.
1229
short type = (short) (gotslot[0] & 0xFFFF);
1230
1231                if (type == ELEMENT_NODE) {
1232                        return getFirstAttribute(nodeHandle);
1233                } else if (type == ATTRIBUTE_NODE) {
1234                        if (gotslot[2] != NULL)
1235                                return (m_docHandle | gotslot[2]);
1236                }
1237                return NULL;
1238        }
1239
1240        /**
1241         * Given a namespace handle, advance to the next namespace.
1242         *
1243         * %TBD% THIS METHOD DOES NOT MATCH THE CURRENT SIGNATURE IN
1244         * THE DTM INTERFACE. FIX IT, OR JUSTIFY CHANGING THE DTM
1245         * API.
1246         *
1247         * @param namespaceHandle handle to node which must be of type NAMESPACE_NODE.
1248         * @return handle of next namespace, or DTM.NULL to indicate none exists.
1249         */

1250        public int getNextNamespaceNode(int baseHandle,int namespaceHandle, boolean inScope) {
1251                // ###shs need to work on namespace
1252
return NULL;
1253        }
1254
1255        /**
1256         * Given a node handle, advance to its next descendant.
1257         * If not yet resolved, waits for more nodes to be added to the document and
1258         * tries again.
1259         *
1260         * @param subtreeRootNodeHandle
1261         * @param nodeHandle int Handle of the node.
1262         * @return handle of next descendant,
1263         * or DTM.NULL to indicate none exists.
1264         */

1265        public int getNextDescendant(int subtreeRootHandle, int nodeHandle) {
1266                subtreeRootHandle &= NODEHANDLE_MASK;
1267                nodeHandle &= NODEHANDLE_MASK;
1268                // Document root [Document Node? -- jjk] - no next-sib
1269
if (nodeHandle == 0)
1270                        return NULL;
1271                while (!m_isError) {
1272                        // Document done and node out of bounds
1273
if (done && (nodeHandle > nodes.slotsUsed()))
1274                                break;
1275                        if (nodeHandle > subtreeRootHandle) {
1276                                nodes.readSlot(nodeHandle+1, gotslot);
1277                                if (gotslot[2] != 0) {
1278                                        short type = (short) (gotslot[0] & 0xFFFF);
1279                                        if (type == ATTRIBUTE_NODE) {
1280                                                nodeHandle +=2;
1281                                        } else {
1282                                                int nextParentPos = gotslot[1];
1283                                                if (nextParentPos >= subtreeRootHandle)
1284                                                        return (m_docHandle | (nodeHandle+1));
1285                                                else
1286                                                        break;
1287                                        }
1288                                } else if (!done) {
1289                                        // Add wait logic here
1290
} else
1291                                        break;
1292                        } else {
1293                                nodeHandle++;
1294                        }
1295                }
1296                // Probably should throw error here like original instead of returning
1297
return NULL;
1298        }
1299
1300        /**
1301         * Given a node handle, advance to the next node on the following axis.
1302         *
1303         * @param axisContextHandle the start of the axis that is being traversed.
1304         * @param nodeHandle
1305         * @return handle of next sibling,
1306         * or DTM.NULL to indicate none exists.
1307         */

1308        public int getNextFollowing(int axisContextHandle, int nodeHandle) {
1309                //###shs still working on
1310
return NULL;
1311        }
1312
1313        /**
1314         * Given a node handle, advance to the next node on the preceding axis.
1315         *
1316         * @param axisContextHandle the start of the axis that is being traversed.
1317         * @param nodeHandle the id of the node.
1318         * @return int Node-number of preceding sibling,
1319         * or DTM.NULL to indicate none exists.
1320         */

1321        public int getNextPreceding(int axisContextHandle, int nodeHandle) {
1322                // ###shs copied from Xalan 1, what is this suppose to do?
1323
nodeHandle &= NODEHANDLE_MASK;
1324                while (nodeHandle > 1) {
1325                        nodeHandle--;
1326                        if (ATTRIBUTE_NODE == (nodes.readEntry(nodeHandle, 0) & 0xFFFF))
1327                                continue;
1328
1329                        // if nodeHandle is _not_ an ancestor of
1330
// axisContextHandle, specialFind will return it.
1331
// If it _is_ an ancestor, specialFind will return -1
1332

1333                        // %REVIEW% unconditional return defeats the
1334
// purpose of the while loop -- does this
1335
// logic make any sense?
1336

1337                        return (m_docHandle | nodes.specialFind(axisContextHandle, nodeHandle));
1338                }
1339                return NULL;
1340        }
1341
1342        /**
1343         * Given a node handle, find its parent node.
1344         *
1345         * @param nodeHandle the id of the node.
1346         * @return int Node-number of parent,
1347         * or DTM.NULL to indicate none exists.
1348         */

1349        public int getParent(int nodeHandle) {
1350                // Should check to see within range?
1351

1352                // Document Root should not have to be handled differently
1353
return (m_docHandle | nodes.readEntry(nodeHandle, 1));
1354        }
1355
1356        /**
1357         * Returns the root element of the document.
1358         * @return nodeHandle to the Document Root.
1359         */

1360        public int getDocumentRoot() {
1361                return (m_docHandle | m_docElement);
1362        }
1363
1364        /**
1365                * Given a node handle, find the owning document node.
1366                *
1367                * @param nodeHandle the id of the node.
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 JavaDoc 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 JavaDoc 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 JavaDoc localName = qName.substring(colonpos+1);
1517           // Get NS
1518
String JavaDoc namespace = m_nsNames.indexToString(gotslot[0] << 16);
1519           // Create expanded name
1520
String JavaDoc 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         * @param nodeHandle The handle to the node in question.
1534         *
1535         * @return the expanded-name id of the node.
1536         */

1537        public int getExpandedTypeID(String JavaDoc namespace, String JavaDoc localName, int type) {
1538           // Create expanded name
1539
// %TBD% jjk Expanded name is bitfield-encoded as
1540
// typeID[6]nsuriID[10]localID[16]. Switch to that form, and to
1541
// accessing the ns/local via their tables rather than confusing
1542
// nsnames and expandednames.
1543
String JavaDoc expandedName = namespace + ":" + localName;
1544           int expandedNameID = m_nsNames.stringToIndex(expandedName);
1545
1546           return expandedNameID;
1547        }
1548
1549
1550        /**
1551         * Given an expanded-name ID, return the local name part.
1552         *
1553         * @param ExpandedNameID an ID that represents an expanded-name.
1554         * @return String Local name of this node.
1555         */

1556        public String JavaDoc getLocalNameFromExpandedNameID(int ExpandedNameID) {
1557
1558           // Get expanded name
1559
String JavaDoc expandedName = m_localNames.indexToString(ExpandedNameID);
1560           // Remove prefix from expanded name
1561
int colonpos = expandedName.indexOf(":");
1562           String JavaDoc localName = expandedName.substring(colonpos+1);
1563           return localName;
1564        }
1565
1566
1567        /**
1568         * Given an expanded-name ID, return the namespace URI part.
1569         *
1570         * @param ExpandedNameID an ID that represents an expanded-name.
1571         * @return String URI value of this node's namespace, or null if no
1572         * namespace was resolved.
1573        */

1574        public String JavaDoc getNamespaceFromExpandedNameID(int ExpandedNameID) {
1575
1576           String JavaDoc expandedName = m_localNames.indexToString(ExpandedNameID);
1577           // Remove local name from expanded name
1578
int colonpos = expandedName.indexOf(":");
1579           String JavaDoc nsName = expandedName.substring(0, colonpos);
1580
1581        return nsName;
1582        }
1583
1584
1585        /**
1586         * fixednames
1587        */

1588        static final String JavaDoc[] fixednames=
1589        {
1590                null,null, // nothing, Element
1591
null,"#text", // Attr, Text
1592
"#cdata_section",null, // CDATA, EntityReference
1593
null,null, // Entity, PI
1594
"#comment","#document", // Comment, Document
1595
null,"#document-fragment", // Doctype, DocumentFragment
1596
null}; // Notation
1597

1598        /**
1599         * Given a node handle, return its DOM-style node name. This will
1600         * include names such as #text or #document.
1601         *
1602         * @param nodeHandle the id of the node.
1603         * @return String Name of this node, which may be an empty string.
1604         * %REVIEW% Document when empty string is possible...
1605         */

1606        public String JavaDoc getNodeName(int nodeHandle) {
1607                nodes.readSlot(nodeHandle, gotslot);
1608                short type = (short) (gotslot[0] & 0xFFFF);
1609                String JavaDoc name = fixednames[type];
1610                if (null == name) {
1611                  int i=gotslot[3];
1612                  /**/System.out.println("got i="+i+" "+(i>>16)+"/"+(i&0xffff));
1613
1614                  name=m_localNames.indexToString(i & 0xFFFF);
1615                  String JavaDoc prefix=m_prefixNames.indexToString(i >>16);
1616                  if(prefix!=null && prefix.length()>0)
1617                    name=prefix+":"+name;
1618                }
1619                return name;
1620        }
1621
1622        /**
1623         * Given a node handle, return the XPath node name. This should be
1624         * the name as described by the XPath data model, NOT the DOM-style
1625         * name.
1626         *
1627         * @param nodeHandle the id of the node.
1628         * @return String Name of this node.
1629         */

1630        public String JavaDoc getNodeNameX(int nodeHandle) {return null;}
1631
1632        /**
1633         * Given a node handle, return its DOM-style localname.
1634         * (As defined in Namespaces, this is the portion of the name after any
1635         * colon character)
1636         *
1637         * %REVIEW% What's the local name of something other than Element/Attr?
1638         * Should this be DOM-style (undefined unless namespaced), or other?
1639         *
1640         * @param nodeHandle the id of the node.
1641         * @return String Local name of this node.
1642         */

1643        public String JavaDoc getLocalName(int nodeHandle) {
1644                nodes.readSlot(nodeHandle, gotslot);
1645                short type = (short) (gotslot[0] & 0xFFFF);
1646                String JavaDoc name = "";
1647                if ((type==ELEMENT_NODE) || (type==ATTRIBUTE_NODE)) {
1648                  int i=gotslot[3];
1649                  name=m_localNames.indexToString(i & 0xFFFF);
1650                  if(name==null) name="";
1651                }
1652                return name;
1653        }
1654
1655        /**
1656         * Given a namespace handle, return the prefix that the namespace decl is
1657         * mapping.
1658         * Given a node handle, return the prefix used to map to the namespace.
1659         *
1660         * <p> %REVIEW% Are you sure you want "" for no prefix? </p>
1661         *
1662         * %REVIEW% Should this be DOM-style (undefined unless namespaced),
1663         * or other?
1664         *
1665         * @param nodeHandle the id of the node.
1666         * @return String prefix of this node's name, or "" if no explicit
1667         * namespace prefix was given.
1668         */

1669        public String JavaDoc getPrefix(int nodeHandle) {
1670                nodes.readSlot(nodeHandle, gotslot);
1671                short type = (short) (gotslot[0] & 0xFFFF);
1672                String JavaDoc name = "";
1673                if((type==ELEMENT_NODE) || (type==ATTRIBUTE_NODE)) {
1674                  int i=gotslot[3];
1675                  name=m_prefixNames.indexToString(i >>16);
1676                  if(name==null) name="";
1677                }
1678                return name;
1679        }
1680
1681        /**
1682         * Given a node handle, return its DOM-style namespace URI
1683         * (As defined in Namespaces, this is the declared URI which this node's
1684         * prefix -- or default in lieu thereof -- was mapped to.)
1685         *
1686         * @param nodeHandle the id of the node.
1687         * @return String URI value of this node's namespace, or null if no
1688         * namespace was resolved.
1689         */

1690        public String JavaDoc getNamespaceURI(int nodeHandle) {return null;}
1691
1692        /**
1693         * Given a node handle, return its node value. This is mostly
1694         * as defined by the DOM, but may ignore some conveniences.
1695         * <p>
1696         *
1697         * @param nodeHandle The node id.
1698         * @return String Value of this node, or null if not
1699         * meaningful for this node type.
1700         */

1701        public String JavaDoc getNodeValue(int nodeHandle)
1702        {
1703                nodes.readSlot(nodeHandle, gotslot);
1704                int nodetype=gotslot[0] & 0xFF; // ###zaj use mask to get node type
1705
String JavaDoc value=null;
1706
1707                switch (nodetype) { // ###zaj todo - document nodetypes
1708
case ATTRIBUTE_NODE:
1709                        nodes.readSlot(nodeHandle+1, gotslot);
1710                case TEXT_NODE:
1711                case COMMENT_NODE:
1712                case CDATA_SECTION_NODE:
1713                        value=m_char.getString(gotslot[2], gotslot[3]); //###zaj
1714
break;
1715                case PROCESSING_INSTRUCTION_NODE:
1716                case ELEMENT_NODE:
1717                case ENTITY_REFERENCE_NODE:
1718                default:
1719                        break;
1720                }
1721                return value;
1722        }
1723
1724        /**
1725         * Given a node handle, return its DOM-style node type.
1726         * <p>
1727         * %REVIEW% Generally, returning short is false economy. Return int?
1728         *
1729         * @param nodeHandle The node id.
1730         * @return int Node type, as per the DOM's Node._NODE constants.
1731         */

1732        public short getNodeType(int nodeHandle) {
1733                return(short) (nodes.readEntry(nodeHandle, 0) & 0xFFFF);
1734        }
1735
1736        /**
1737         * Get the depth level of this node in the tree (equals 1 for
1738         * a parentless node).
1739         *
1740         * @param nodeHandle The node id.
1741         * @return the number of ancestors, plus one
1742         * @xsl.usage internal
1743         */

1744        public short getLevel(int nodeHandle) {
1745                short count = 0;
1746                while (nodeHandle != 0) {
1747                        count++;
1748                        nodeHandle = nodes.readEntry(nodeHandle, 1);
1749                }
1750                return count;
1751        }
1752
1753        // ============== Document query functions ==============
1754

1755        /**
1756         * Tests whether DTM DOM implementation implements a specific feature and
1757         * that feature is supported by this node.
1758         *
1759         * @param feature The name of the feature to test.
1760         * @param versionThis is the version number of the feature to test.
1761         * If the version is not
1762         * specified, supporting any version of the feature will cause the
1763         * method to return <code>true</code>.
1764         * @return Returns <code>true</code> if the specified feature is
1765         * supported on this node, <code>false</code> otherwise.
1766         */

1767        public boolean isSupported(String JavaDoc feature, String JavaDoc version) {return false;}
1768
1769        /**
1770         * Return the base URI of the document entity. If it is not known
1771         * (because the document was parsed from a socket connection or from
1772         * standard input, for example), the value of this property is unknown.
1773         *
1774         * @return the document base URI String object or null if unknown.
1775         */

1776        public String JavaDoc getDocumentBaseURI()
1777        {
1778
1779          return m_documentBaseURI;
1780        }
1781
1782        /**
1783         * Set the base URI of the document entity.
1784         *
1785         * @param baseURI the document base URI String object or null if unknown.
1786         */

1787        public void setDocumentBaseURI(String JavaDoc baseURI)
1788        {
1789
1790          m_documentBaseURI = baseURI;
1791        }
1792
1793        /**
1794         * Return the system identifier of the document entity. If
1795         * it is not known, the value of this property is unknown.
1796         *
1797         * @param nodeHandle The node id, which can be any valid node handle.
1798         * @return the system identifier String object or null if unknown.
1799         */

1800        public String JavaDoc getDocumentSystemIdentifier(int nodeHandle) {return null;}
1801
1802        /**
1803         * Return the name of the character encoding scheme
1804         * in which the document entity is expressed.
1805         *
1806         * @param nodeHandle The node id, which can be any valid node handle.
1807         * @return the document encoding String object.
1808         */

1809        public String JavaDoc getDocumentEncoding(int nodeHandle) {return null;}
1810
1811        /**
1812         * Return an indication of the standalone status of the document,
1813         * either "yes" or "no". This property is derived from the optional
1814         * standalone document declaration in the XML declaration at the
1815         * beginning of the document entity, and has no value if there is no
1816         * standalone document declaration.
1817         *
1818         * @param nodeHandle The node id, which can be any valid node handle.
1819         * @return the document standalone String object, either "yes", "no", or null.
1820         */

1821        public String JavaDoc getDocumentStandalone(int nodeHandle) {return null;}
1822
1823        /**
1824         * Return a string representing the XML version of the document. This
1825         * property is derived from the XML declaration optionally present at the
1826         * beginning of the document entity, and has no value if there is no XML
1827         * declaration.
1828         *
1829         * @param the document handle
1830         *
1831         * @return the document version String object
1832         */

1833        public String JavaDoc getDocumentVersion(int documentHandle) {return null;}
1834
1835        /**
1836         * Return an indication of
1837         * whether the processor has read the complete DTD. Its value is a
1838         * boolean. If it is false, then certain properties (indicated in their
1839         * descriptions below) may be unknown. If it is true, those properties
1840         * are never unknown.
1841         *
1842         * @return <code>true</code> if all declarations were processed {};
1843         * <code>false</code> otherwise.
1844         */

1845        public boolean getDocumentAllDeclarationsProcessed() {return false;}
1846
1847        /**
1848         * A document type declaration information item has the following properties:
1849         *
1850         * 1. [system identifier] The system identifier of the external subset, if
1851         * it exists. Otherwise this property has no value.
1852         *
1853         * @return the system identifier String object, or null if there is none.
1854         */

1855        public String JavaDoc getDocumentTypeDeclarationSystemIdentifier() {return null;}
1856
1857        /**
1858         * Return the public identifier of the external subset,
1859         * normalized as described in 4.2.2 External Entities [XML]. If there is
1860         * no external subset or if it has no public identifier, this property
1861         * has no value.
1862         *
1863         * @param the document type declaration handle
1864         *
1865         * @return the public identifier String object, or null if there is none.
1866         */

1867        public String JavaDoc getDocumentTypeDeclarationPublicIdentifier() {return null;}
1868
1869        /**
1870         * Returns the <code>Element</code> whose <code>ID</code> is given by
1871         * <code>elementId</code>. If no such element exists, returns
1872         * <code>DTM.NULL</code>. Behavior is not defined if more than one element
1873         * has this <code>ID</code>. Attributes (including those
1874         * with the name "ID") are not of type ID unless so defined by DTD/Schema
1875         * information available to the DTM implementation.
1876         * Implementations that do not know whether attributes are of type ID or
1877         * not are expected to return <code>DTM.NULL</code>.
1878         *
1879         * <p>%REVIEW% Presumably IDs are still scoped to a single document,
1880         * and this operation searches only within a single document, right?
1881         * Wouldn't want collisions between DTMs in the same process.</p>
1882         *
1883         * @param elementId The unique <code>id</code> value for an element.
1884         * @return The handle of the matching element.
1885         */

1886        public int getElementById(String JavaDoc elementId) {return 0;}
1887
1888        /**
1889         * The getUnparsedEntityURI function returns the URI of the unparsed
1890         * entity with the specified name in the same document as the context
1891         * node (see [3.3 Unparsed Entities]). It returns the empty string if
1892         * there is no such entity.
1893         * <p>
1894         * XML processors may choose to use the System Identifier (if one
1895         * is provided) to resolve the entity, rather than the URI in the
1896         * Public Identifier. The details are dependent on the processor, and
1897         * we would have to support some form of plug-in resolver to handle
1898         * this properly. Currently, we simply return the System Identifier if
1899         * present, and hope that it a usable URI or that our caller can
1900         * map it to one.
1901         * TODO: Resolve Public Identifiers... or consider changing function name.
1902         * <p>
1903         * If we find a relative URI
1904         * reference, XML expects it to be resolved in terms of the base URI
1905         * of the document. The DOM doesn't do that for us, and it isn't
1906         * entirely clear whether that should be done here; currently that's
1907         * pushed up to a higher level of our application. (Note that DOM Level
1908         * 1 didn't store the document's base URI.)
1909         * TODO: Consider resolving Relative URIs.
1910         * <p>
1911         * (The DOM's statement that "An XML processor may choose to
1912         * completely expand entities before the structure model is passed
1913         * to the DOM" refers only to parsed entities, not unparsed, and hence
1914         * doesn't affect this function.)
1915         *
1916         * @param name A string containing the Entity Name of the unparsed
1917         * entity.
1918         *
1919         * @return String containing the URI of the Unparsed Entity, or an
1920         * empty string if no such entity exists.
1921         */

1922        public String JavaDoc getUnparsedEntityURI(String JavaDoc name) {return null;}
1923
1924
1925        // ============== Boolean methods ================
1926

1927        /**
1928         * Return true if the xsl:strip-space or xsl:preserve-space was processed
1929         * during construction of the DTM document.
1930         *
1931         * <p>%REVEIW% Presumes a 1:1 mapping from DTM to Document, since
1932         * we aren't saying which Document to query...?</p>
1933         */

1934        public boolean supportsPreStripping() {return false;}
1935
1936        /**
1937         * Figure out whether nodeHandle2 should be considered as being later
1938         * in the document than nodeHandle1, in Document Order as defined
1939         * by the XPath model. This may not agree with the ordering defined
1940         * by other XML applications.
1941         * <p>
1942         * There are some cases where ordering isn't defined, and neither are
1943         * the results of this function -- though we'll generally return true.
1944         *
1945         * TODO: Make sure this does the right thing with attribute nodes!!!
1946         *
1947         * @param node1 DOM Node to perform position comparison on.
1948         * @param node2 DOM Node to perform position comparison on .
1949         *
1950         * @return false if node2 comes before node1, otherwise return true.
1951         * You can think of this as
1952         * <code>(node1.documentOrderPosition &lt;= node2.documentOrderPosition)</code>.
1953         */

1954        public boolean isNodeAfter(int nodeHandle1, int nodeHandle2) {return false;}
1955
1956        /**
1957         * 2. [element content whitespace] A boolean indicating whether the
1958         * character is white space appearing within element content (see [XML],
1959         * 2.10 "White Space Handling"). Note that validating XML processors are
1960         * required by XML 1.0 to provide this information. If there is no
1961         * declaration for the containing element, this property has no value for
1962         * white space characters. If no declaration has been read, but the [all
1963         * declarations processed] property of the document information item is
1964         * false (so there may be an unread declaration), then the value of this
1965         * property is unknown for white space characters. It is always false for
1966         * characters that are not white space.
1967         *
1968         * @param nodeHandle the node ID.
1969         * @return <code>true</code> if the character data is whitespace;
1970         * <code>false</code> otherwise.
1971         */

1972        public boolean isCharacterElementContentWhitespace(int nodeHandle) {return false;}
1973
1974        /**
1975         * 10. [all declarations processed] This property is not strictly speaking
1976         * part of the infoset of the document. Rather it is an indication of
1977         * whether the processor has read the complete DTD. Its value is a
1978         * boolean. If it is false, then certain properties (indicated in their
1979         * descriptions below) may be unknown. If it is true, those properties
1980         * are never unknown.
1981         *
1982         * @param the document handle
1983         *
1984         * @param documentHandle A node handle that must identify a document.
1985         * @return <code>true</code> if all declarations were processed;
1986         * <code>false</code> otherwise.
1987         */

1988        public boolean isDocumentAllDeclarationsProcessed(int documentHandle) {return false;}
1989
1990        /**
1991         * 5. [specified] A flag indicating whether this attribute was actually
1992         * specified in the start-tag of its element, or was defaulted from the
1993         * DTD.
1994         *
1995         * @param the attribute handle
1996         *
1997         * NEEDSDOC @param attributeHandle
1998         * @return <code>true</code> if the attribute was specified;
1999         * <code>false</code> if it was defaulted.
2000         */

2001        public boolean isAttributeSpecified(int attributeHandle) {return false;}
2002
2003        // ========== Direct SAX Dispatch, for optimization purposes ========
2004

2005        /**
2006         * Directly call the
2007         * characters method on the passed ContentHandler for the
2008         * string-value of the given node (see http://www.w3.org/TR/xpath#data-model
2009         * for the definition of a node's string-value). Multiple calls to the
2010         * ContentHandler's characters methods may well occur for a single call to
2011         * this method.
2012         *
2013         * @param nodeHandle The node ID.
2014         * @param ch A non-null reference to a ContentHandler.
2015         *
2016         * @throws org.xml.sax.SAXException
2017         */

2018        public void dispatchCharactersEvents(
2019                                                                                                                                                        int nodeHandle, org.xml.sax.ContentHandler JavaDoc ch, boolean normalize)
2020        throws org.xml.sax.SAXException JavaDoc {}
2021
2022        /**
2023         * Directly create SAX parser events from a subtree.
2024         *
2025         * @param nodeHandle The node ID.
2026         * @param ch A non-null reference to a ContentHandler.
2027         *
2028         * @throws org.xml.sax.SAXException
2029         */

2030
2031        public void dispatchToEvents(int nodeHandle, org.xml.sax.ContentHandler JavaDoc ch)
2032        throws org.xml.sax.SAXException JavaDoc {}
2033
2034        /**
2035         * Return an DOM node for the given node.
2036         *
2037         * @param nodeHandle The node ID.
2038         *
2039         * @return A node representation of the DTM node.
2040         */

2041        public org.w3c.dom.Node JavaDoc getNode(int nodeHandle)
2042        {
2043          return null;
2044        }
2045
2046        // ==== Construction methods (may not be supported by some implementations!) =====
2047
// %REVIEW% jjk: These probably aren't the right API. At the very least
2048
// they need to deal with current-insertion-location and end-element
2049
// issues.
2050

2051        /**
2052         * Append a child to the end of the child list of the current node. Please note that the node
2053         * is always cloned if it is owned by another document.
2054         *
2055         * <p>%REVIEW% "End of the document" needs to be defined more clearly.
2056         * Does it become the last child of the Document? Of the root element?</p>
2057         *
2058         * @param newChild Must be a valid new node handle.
2059         * @param clone true if the child should be cloned into the document.
2060         * @param cloneDepth if the clone argument is true, specifies that the
2061         * clone should include all it's children.
2062         */

2063        public void appendChild(int newChild, boolean clone, boolean cloneDepth) {
2064                boolean sameDoc = ((newChild & DOCHANDLE_MASK) == m_docHandle);
2065                if (clone || !sameDoc) {
2066
2067                } else {
2068
2069                }
2070        }
2071
2072        /**
2073         * Append a text node child that will be constructed from a string,
2074         * to the end of the document.
2075         *
2076         * <p>%REVIEW% "End of the document" needs to be defined more clearly.
2077         * Does it become the last child of the Document? Of the root element?</p>
2078         *
2079         * @param str Non-null reference to a string.
2080         */

2081        public void appendTextChild(String JavaDoc str) {
2082                // ###shs Think more about how this differs from createTextNode
2083
//%TBD%
2084
}
2085
2086
2087  //================================================================
2088
// ==== BUILDER methods ====
2089
// %TBD% jjk: SHOULD PROBABLY BE INLINED, unless we want to support
2090
// both SAX1 and SAX2 and share this logic between them.
2091

2092  /** Append a text child at the current insertion point. Assumes that the
2093   * actual content of the text has previously been appended to the m_char
2094   * buffer (shared with the builder).
2095   *
2096   * @param m_char_current_start int Starting offset of node's content in m_char.
2097   * @param contentLength int Length of node's content in m_char.
2098   * */

2099  void appendTextChild(int m_char_current_start,int contentLength)
2100  {
2101    // create a Text Node
2102
// %TBD% may be possible to combine with appendNode()to replace the next chunk of code
2103
int w0 = TEXT_NODE;
2104    // W1: Parent
2105
int w1 = currentParent;
2106    // W2: Start position within m_char
2107
int w2 = m_char_current_start;
2108    // W3: Length of the full string
2109
int w3 = contentLength;
2110
2111    int ourslot = appendNode(w0, w1, w2, w3);
2112    previousSibling = ourslot;
2113  }
2114
2115  /** Append a comment child at the current insertion point. Assumes that the
2116   * actual content of the comment has previously been appended to the m_char
2117   * buffer (shared with the builder).
2118   *
2119   * @param m_char_current_start int Starting offset of node's content in m_char.
2120   * @param contentLength int Length of node's content in m_char.
2121   * */

2122  void appendComment(int m_char_current_start,int contentLength)
2123  {
2124    // create a Comment Node
2125
// %TBD% may be possible to combine with appendNode()to replace the next chunk of code
2126
int w0 = COMMENT_NODE;
2127    // W1: Parent
2128
int w1 = currentParent;
2129    // W2: Start position within m_char
2130
int w2 = m_char_current_start;
2131    // W3: Length of the full string
2132
int w3 = contentLength;
2133
2134    int ourslot = appendNode(w0, w1, w2, w3);
2135    previousSibling = ourslot;
2136  }
2137
2138
2139  /** Append an Element child at the current insertion point. This
2140   * Element then _becomes_ the insertion point; subsequent appends
2141   * become its lastChild until an appendEndElement() call is made.
2142   *
2143   * Assumes that the symbols (local name, namespace URI and prefix)
2144   * have already been added to the pools
2145   *
2146   * Note that this _only_ handles the Element node itself. Attrs and
2147   * namespace nodes are unbundled in the ContentHandler layer
2148   * and appended separately.
2149   *
2150   * @param namespaceIndex: Index within the namespaceURI string pool
2151   * @param localNameIndex Index within the local name string pool
2152   * @param prefixIndex: Index within the prefix string pool
2153   * */

2154  void appendStartElement(int namespaceIndex,int localNameIndex, int prefixIndex)
2155  {
2156                // do document root node creation here on the first element, create nodes for
2157
// this element and its attributes, store the element, namespace, and attritute
2158
// name indexes to the nodes array, keep track of the current node and parent
2159
// element used
2160

2161                // W0 High: Namespace Low: Node Type
2162
int w0 = (namespaceIndex << 16) | ELEMENT_NODE;
2163                // W1: Parent
2164
int w1 = currentParent;
2165                // W2: Next (initialized as 0)
2166
int w2 = 0;
2167                // W3: Tagname high: prefix Low: local name
2168
int w3 = localNameIndex | prefixIndex<<16;
2169                /**/System.out.println("set w3="+w3+" "+(w3>>16)+"/"+(w3&0xffff));
2170
2171                //int ourslot = nodes.appendSlot(w0, w1, w2, w3);
2172
int ourslot = appendNode(w0, w1, w2, w3);
2173                currentParent = ourslot;
2174                previousSibling = 0;
2175
2176                // set the root element pointer when creating the first element node
2177
if (m_docElement == NULL)
2178                        m_docElement = ourslot;
2179  }
2180
2181  /** Append a Namespace Declaration child at the current insertion point.
2182   * Assumes that the symbols (namespace URI and prefix) have already been
2183   * added to the pools
2184   *
2185   * @param prefixIndex: Index within the prefix string pool
2186   * @param namespaceIndex: Index within the namespaceURI string pool
2187   * @param isID: If someone really insists on writing a bad DTD, it is
2188   * theoretically possible for a namespace declaration to also be declared
2189   * as being a node ID. I don't really want to support that stupidity,
2190   * but I'm not sure we can refuse to accept it.
2191   * */

2192  void appendNSDeclaration(int prefixIndex, int namespaceIndex,
2193                           boolean isID)
2194  {
2195    // %REVIEW% I'm assigning this node the "namespace for namespaces"
2196
// which the DOM defined. It is expected that the Namespace spec will
2197
// adopt this as official. It isn't strictly needed since it's implied
2198
// by the nodetype, but for now...
2199

2200    // %REVIEW% Prefix need not be recorded; it's implied too. But
2201
// recording it might simplify the design.
2202

2203    // %TBD% isID is not currently honored.
2204

2205    final int namespaceForNamespaces=m_nsNames.stringToIndex("http://www.w3.org/2000/xmlns/");
2206
2207    // W0 High: Namespace Low: Node Type
2208
int w0 = NAMESPACE_NODE | (m_nsNames.stringToIndex("http://www.w3.org/2000/xmlns/")<<16);
2209
2210    // W1: Parent
2211
int w1 = currentParent;
2212    // W2: CURRENTLY UNUSED -- It's next-sib in attrs, but we have no kids.
2213
int w2 = 0;
2214    // W3: namespace name
2215
int w3 = namespaceIndex;
2216    // Add node
2217
int ourslot = appendNode(w0, w1, w2, w3);
2218    previousSibling = ourslot; // Should attributes be previous siblings
2219
previousSiblingWasParent = false;
2220    return ;//(m_docHandle | ourslot);
2221
}
2222
2223  /** Append an Attribute child at the current insertion
2224   * point. Assumes that the symbols (namespace URI, local name, and
2225   * prefix) have already been added to the pools, and that the content has
2226   * already been appended to m_char. Note that the attribute's content has
2227   * been flattened into a single string; DTM does _NOT_ attempt to model
2228   * the details of entity references within attribute values.
2229   *
2230   * @param namespaceIndex int Index within the namespaceURI string pool
2231   * @param localNameIndex int Index within the local name string pool
2232   * @param prefixIndex int Index within the prefix string pool
2233   * @param isID boolean True if this attribute was declared as an ID
2234   * (for use in supporting getElementByID).
2235   * @param m_char_current_start int Starting offset of node's content in m_char.
2236   * @param contentLength int Length of node's content in m_char.
2237   * */

2238  void appendAttribute(int namespaceIndex, int localNameIndex, int prefixIndex,
2239                       boolean isID,
2240                       int m_char_current_start, int contentLength)
2241  {
2242    // %TBD% isID is not currently honored.
2243

2244    // W0 High: Namespace Low: Node Type
2245
int w0 = ATTRIBUTE_NODE | namespaceIndex<<16;
2246
2247    // W1: Parent
2248
int w1 = currentParent;
2249    // W2: Next (not yet resolved)
2250
int w2 = 0;
2251    // W3: Tagname high: prefix Low: local name
2252
int w3 = localNameIndex | prefixIndex<<16;
2253    /**/System.out.println("set w3="+w3+" "+(w3>>16)+"/"+(w3&0xffff));
2254    // Add node
2255
int ourslot = appendNode(w0, w1, w2, w3);
2256    previousSibling = ourslot; // Should attributes be previous siblings
2257

2258    // Attribute's content is currently appended as a Text Node
2259

2260    // W0: Node Type
2261
w0 = TEXT_NODE;
2262    // W1: Parent
2263
w1 = ourslot;
2264    // W2: Start Position within buffer
2265
w2 = m_char_current_start;
2266    // W3: Length
2267
w3 = contentLength;
2268    appendNode(w0, w1, w2, w3);
2269
2270    // Attrs are Parents
2271
previousSiblingWasParent = true;
2272    return ;//(m_docHandle | ourslot);
2273
}
2274
2275  /**
2276   * This returns a stateless "traverser", that can navigate over an
2277   * XPath axis, though not in document order.
2278   *
2279   * @param axis One of Axes.ANCESTORORSELF, etc.
2280   *
2281   * @return A DTMAxisIterator, or null if the given axis isn't supported.
2282   */

2283  public DTMAxisTraverser getAxisTraverser(final int axis)
2284  {
2285    return null;
2286  }
2287
2288  /**
2289   * This is a shortcut to the iterators that implement the
2290   * supported XPath axes (only namespace::) is not supported.
2291   * Returns a bare-bones iterator that must be initialized
2292   * with a start node (using iterator.setStartNode()).
2293   *
2294   * @param axis One of Axes.ANCESTORORSELF, etc.
2295   *
2296   * @return A DTMAxisIterator, or null if the given axis isn't supported.
2297   */

2298  public DTMAxisIterator getAxisIterator(final int axis)
2299  {
2300    // %TBD%
2301
return null;
2302  }
2303
2304  /**
2305   * Get an iterator that can navigate over an XPath Axis, predicated by
2306   * the extended type ID.
2307   *
2308   *
2309   * @param axis
2310   * @param type An extended type ID.
2311   *
2312   * @return A DTMAxisIterator, or null if the given axis isn't supported.
2313   */

2314  public DTMAxisIterator getTypedAxisIterator(final int axis, final int type)
2315  {
2316    // %TBD%
2317
return null;
2318  }
2319
2320
2321  /** Terminate the element currently acting as an insertion point. Subsequent
2322   * insertions will occur as the last child of this element's parent.
2323   * */

2324  void appendEndElement()
2325  {
2326    // pop up the stacks
2327

2328    if (previousSiblingWasParent)
2329      nodes.writeEntry(previousSibling, 2, NULL);
2330
2331    // Pop parentage
2332
previousSibling = currentParent;
2333    nodes.readSlot(currentParent, gotslot);
2334    currentParent = gotslot[1] & 0xFFFF;
2335
2336    // The element just being finished will be
2337
// the previous sibling for the next operation
2338
previousSiblingWasParent = true;
2339
2340    // Pop a level of namespace table
2341
// namespaceTable.removeLastElem();
2342
}
2343
2344  /** Starting a new document. Perform any resets/initialization
2345   * not already handled.
2346   * */

2347  void appendStartDocument()
2348  {
2349
2350    // %TBD% reset slot 0 to indicate ChunkedIntArray reuse or wait for
2351
// the next initDocument().
2352
m_docElement = NULL; // reset nodeHandle to the root of the actual dtm doc content
2353
initDocument(0);
2354  }
2355
2356  /** All appends to this document have finished; do whatever final
2357   * cleanup is needed.
2358   * */

2359  void appendEndDocument()
2360  {
2361    done = true;
2362    // %TBD% may need to notice the last slot number and slot count to avoid
2363
// residual data from provious use of this DTM
2364
}
2365
2366  /**
2367   * For the moment all the run time properties are ignored by this
2368   * class.
2369   *
2370   * @param property a <code>String</code> value
2371   * @param value an <code>Object</code> value
2372   */

2373  public void setProperty(String JavaDoc property, Object JavaDoc value)
2374  {
2375  }
2376
2377  /**
2378   * Source information is not handled yet, so return
2379   * <code>null</code> here.
2380   *
2381   * @param node an <code>int</code> value
2382   * @return null
2383   */

2384  public SourceLocator JavaDoc getSourceLocatorFor(int node)
2385  {
2386    return null;
2387  }
2388
2389
2390  /**
2391   * A dummy routine to satisify the abstract interface. If the DTM
2392   * implememtation that extends the default base requires notification
2393   * of registration, they can override this method.
2394   */

2395   public void documentRegistration()
2396   {
2397   }
2398
2399  /**
2400   * A dummy routine to satisify the abstract interface. If the DTM
2401   * implememtation that extends the default base requires notification
2402   * when the document is being released, they can override this method
2403   */

2404   public void documentRelease()
2405   {
2406   }
2407
2408   /**
2409    * Migrate a DTM built with an old DTMManager to a new DTMManager.
2410    * After the migration, the new DTMManager will treat the DTM as
2411    * one that is built by itself.
2412    * This is used to support DTM sharing between multiple transformations.
2413    * @param manager the DTMManager
2414    */

2415   public void migrateTo(DTMManager manager)
2416   {
2417   }
2418
2419}
2420
Popular Tags