KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xml > dtm > ref > DTMDefaultBase


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: DTMDefaultBase.java,v 1.39 2004/02/16 23:06:11 minchau Exp $
18  */

19 package org.apache.xml.dtm.ref;
20
21 import org.apache.xml.dtm.*;
22 import org.apache.xml.utils.SuballocatedIntVector;
23 import org.apache.xml.utils.BoolStack;
24
25 import java.util.Vector JavaDoc;
26
27 import javax.xml.transform.Source JavaDoc;
28
29 import org.apache.xml.utils.XMLString;
30 import org.apache.xml.utils.XMLStringFactory;
31
32 import org.apache.xml.res.XMLMessages;
33 import org.apache.xml.res.XMLErrorResources;
34
35 import java.io.*; // for dumpDTM
36

37 /**
38  * The <code>DTMDefaultBase</code> class serves as a helper base for DTMs.
39  * It sets up structures for navigation and type, while leaving data
40  * management and construction to the derived classes.
41  */

42 public abstract class DTMDefaultBase implements DTM
43 {
44     static boolean JJK_DEBUG=false;
45
46   // This constant is likely to be removed in the future. Use the
47
// getDocument() method instead of ROOTNODE to get at the root
48
// node of a DTM.
49
/** The identity of the root node. */
50   public static final int ROOTNODE = 0;
51     
52   /**
53    * The number of nodes, which is also used to determine the next
54    * node index.
55    */

56   protected int m_size = 0;
57
58   /** The expanded names, one array element for each node. */
59   protected SuballocatedIntVector m_exptype;
60
61   /** First child values, one array element for each node. */
62   protected SuballocatedIntVector m_firstch;
63
64   /** Next sibling values, one array element for each node. */
65   protected SuballocatedIntVector m_nextsib;
66
67   /** Previous sibling values, one array element for each node. */
68   protected SuballocatedIntVector m_prevsib;
69
70   /** Previous sibling values, one array element for each node. */
71   protected SuballocatedIntVector m_parent;
72
73   /** Vector of SuballocatedIntVectors of NS decl sets */
74   protected Vector m_namespaceDeclSets = null;
75
76   /** SuballocatedIntVector of elements at which corresponding
77    * namespaceDeclSets were defined */

78   protected SuballocatedIntVector m_namespaceDeclSetElements = null;
79
80   /**
81    * These hold indexes to elements based on namespace and local name.
82    * The base lookup is the the namespace. The second lookup is the local
83    * name, and the last array contains the the first free element
84    * at the start, and the list of element handles following.
85    */

86   protected int[][][] m_elemIndexes;
87
88   /** The default block size of the node arrays */
89   public static final int DEFAULT_BLOCKSIZE = 512; // favor small docs.
90

91   /** The number of blocks for the node arrays */
92   public static final int DEFAULT_NUMBLOCKS = 32;
93   
94   /** The number of blocks used for small documents & RTFs */
95   public static final int DEFAULT_NUMBLOCKS_SMALL = 4;
96   
97   /** The block size of the node arrays */
98   //protected final int m_blocksize;
99

100   /**
101    * The value to use when the information has not been built yet.
102    */

103   protected static final int NOTPROCESSED = DTM.NULL - 1;
104
105   /**
106    * The DTM manager who "owns" this DTM.
107    */

108
109   public DTMManager m_mgr;
110
111   /**
112    * m_mgr cast to DTMManagerDefault, or null if it isn't an instance
113    * (Efficiency hook)
114    */

115   protected DTMManagerDefault m_mgrDefault=null;
116
117
118   /** The document identity number(s). If we have overflowed the addressing
119    * range of the first that was assigned to us, we may add others. */

120   protected SuballocatedIntVector m_dtmIdent;
121
122   /** The mask for the identity.
123       %REVIEW% Should this really be set to the _DEFAULT? What if
124       a particular DTM wanted to use another value? */

125   //protected final static int m_mask = DTMManager.IDENT_NODE_DEFAULT;
126

127   /** The base URI for this document. */
128   protected String JavaDoc m_documentBaseURI;
129
130   /**
131    * The whitespace filter that enables elements to strip whitespace or not.
132    */

133   protected DTMWSFilter m_wsfilter;
134
135   /** Flag indicating whether to strip whitespace nodes */
136   protected boolean m_shouldStripWS = false;
137
138   /** Stack of flags indicating whether to strip whitespace nodes */
139   protected BoolStack m_shouldStripWhitespaceStack;
140
141   /** The XMLString factory for creating XMLStrings. */
142   protected XMLStringFactory m_xstrf;
143
144   /**
145    * The table for exandedNameID lookups. This may or may not be the same
146    * table as is contained in the DTMManagerDefault.
147    */

148   protected ExpandedNameTable m_expandedNameTable;
149
150   /** true if indexing is turned on. */
151   protected boolean m_indexing;
152
153   /**
154    * Construct a DTMDefaultBase object using the default block size.
155    *
156    * @param mgr The DTMManager who owns this DTM.
157    * @param domSource the DOM source that this DTM will wrap.
158    * @param source The object that is used to specify the construction source.
159    * @param dtmIdentity The DTM identity ID for this DTM.
160    * @param whiteSpaceFilter The white space filter for this DTM, which may
161    * be null.
162    * @param xstringfactory The factory to use for creating XMLStrings.
163    * @param doIndexing true if the caller considers it worth it to use
164    * indexing schemes.
165    */

166   public DTMDefaultBase(DTMManager mgr, Source JavaDoc source, int dtmIdentity,
167             DTMWSFilter whiteSpaceFilter,
168             XMLStringFactory xstringfactory, boolean doIndexing)
169   {
170     this(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory,
171          doIndexing, DEFAULT_BLOCKSIZE, true, false);
172   }
173
174   /**
175    * Construct a DTMDefaultBase object from a DOM node.
176    *
177    * @param mgr The DTMManager who owns this DTM.
178    * @param domSource the DOM source that this DTM will wrap.
179    * @param source The object that is used to specify the construction source.
180    * @param dtmIdentity The DTM identity ID for this DTM.
181    * @param whiteSpaceFilter The white space filter for this DTM, which may
182    * be null.
183    * @param xstringfactory The factory to use for creating XMLStrings.
184    * @param doIndexing true if the caller considers it worth it to use
185    * indexing schemes.
186    * @param blocksize The block size of the DTM.
187    * @param usePrevsib true if we want to build the previous sibling node array.
188    * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
189    */

190   public DTMDefaultBase(DTMManager mgr, Source JavaDoc source, int dtmIdentity,
191                         DTMWSFilter whiteSpaceFilter,
192                         XMLStringFactory xstringfactory, boolean doIndexing,
193                         int blocksize, boolean usePrevsib,
194                         boolean newNameTable)
195   {
196     // Use smaller sizes for the internal node arrays if the block size
197
// is small.
198
int numblocks;
199     if (blocksize <= 64)
200     {
201       numblocks = DEFAULT_NUMBLOCKS_SMALL;
202       m_dtmIdent= new SuballocatedIntVector(4, 1);
203     }
204     else
205     {
206       numblocks = DEFAULT_NUMBLOCKS;
207       m_dtmIdent= new SuballocatedIntVector(32);
208     }
209     
210     m_exptype = new SuballocatedIntVector(blocksize, numblocks);
211     m_firstch = new SuballocatedIntVector(blocksize, numblocks);
212     m_nextsib = new SuballocatedIntVector(blocksize, numblocks);
213     m_parent = new SuballocatedIntVector(blocksize, numblocks);
214     
215     // Only create the m_prevsib array if the usePrevsib flag is true.
216
// Some DTM implementations (e.g. SAXImpl) do not need this array.
217
// We can save the time to build it in those cases.
218
if (usePrevsib)
219       m_prevsib = new SuballocatedIntVector(blocksize, numblocks);
220
221     m_mgr = mgr;
222     if(mgr instanceof DTMManagerDefault)
223       m_mgrDefault=(DTMManagerDefault)mgr;
224     
225     m_documentBaseURI = (null != source) ? source.getSystemId() : null;
226     m_dtmIdent.setElementAt(dtmIdentity,0);
227     m_wsfilter = whiteSpaceFilter;
228     m_xstrf = xstringfactory;
229     m_indexing = doIndexing;
230
231     if (doIndexing)
232     {
233       m_expandedNameTable = new ExpandedNameTable();
234     }
235     else
236     {
237       // Note that this fails if we aren't talking to an instance of
238
// DTMManagerDefault
239
m_expandedNameTable = m_mgrDefault.getExpandedNameTable(this);
240     }
241
242     if (null != whiteSpaceFilter)
243     {
244       m_shouldStripWhitespaceStack = new BoolStack();
245
246       pushShouldStripWhitespace(false);
247     }
248   }
249
250   /**
251    * Ensure that the size of the element indexes can hold the information.
252    *
253    * @param namespaceID Namespace ID index.
254    * @param LocalNameID Local name ID.
255    */

256   protected void ensureSizeOfIndex(int namespaceID, int LocalNameID)
257   {
258
259     if (null == m_elemIndexes)
260     {
261       m_elemIndexes = new int[namespaceID + 20][][];
262     }
263     else if (m_elemIndexes.length <= namespaceID)
264     {
265       int[][][] indexes = m_elemIndexes;
266
267       m_elemIndexes = new int[namespaceID + 20][][];
268
269       System.arraycopy(indexes, 0, m_elemIndexes, 0, indexes.length);
270     }
271
272     int[][] localNameIndex = m_elemIndexes[namespaceID];
273
274     if (null == localNameIndex)
275     {
276       localNameIndex = new int[LocalNameID + 100][];
277       m_elemIndexes[namespaceID] = localNameIndex;
278     }
279     else if (localNameIndex.length <= LocalNameID)
280     {
281       int[][] indexes = localNameIndex;
282
283       localNameIndex = new int[LocalNameID + 100][];
284
285       System.arraycopy(indexes, 0, localNameIndex, 0, indexes.length);
286
287       m_elemIndexes[namespaceID] = localNameIndex;
288     }
289
290     int[] elemHandles = localNameIndex[LocalNameID];
291
292     if (null == elemHandles)
293     {
294       elemHandles = new int[128];
295       localNameIndex[LocalNameID] = elemHandles;
296       elemHandles[0] = 1;
297     }
298     else if (elemHandles.length <= elemHandles[0] + 1)
299     {
300       int[] indexes = elemHandles;
301
302       elemHandles = new int[elemHandles[0] + 1024];
303
304       System.arraycopy(indexes, 0, elemHandles, 0, indexes.length);
305
306       localNameIndex[LocalNameID] = elemHandles;
307     }
308   }
309
310   /**
311    * Add a node to the element indexes. The node will not be added unless
312    * it's an element.
313    *
314    * @param expandedTypeID The expanded type ID of the node.
315    * @param identity The node identity index.
316    */

317   protected void indexNode(int expandedTypeID, int identity)
318   {
319
320     ExpandedNameTable ent = m_expandedNameTable;
321     short type = ent.getType(expandedTypeID);
322
323     if (DTM.ELEMENT_NODE == type)
324     {
325       int namespaceID = ent.getNamespaceID(expandedTypeID);
326       int localNameID = ent.getLocalNameID(expandedTypeID);
327
328       ensureSizeOfIndex(namespaceID, localNameID);
329
330       int[] index = m_elemIndexes[namespaceID][localNameID];
331
332       index[index[0]] = identity;
333
334       index[0]++;
335     }
336   }
337
338   /**
339    * Find the first index that occurs in the list that is greater than or
340    * equal to the given value.
341    *
342    * @param list A list of integers.
343    * @param start The start index to begin the search.
344    * @param len The number of items to search.
345    * @param value Find the slot that has a value that is greater than or
346    * identical to this argument.
347    *
348    * @return The index in the list of the slot that is higher or identical
349    * to the identity argument, or -1 if no node is higher or equal.
350    */

351   protected int findGTE(int[] list, int start, int len, int value)
352   {
353
354     int low = start;
355     int high = start + (len - 1);
356     int end = high;
357
358     while (low <= high)
359     {
360       int mid = (low + high) / 2;
361       int c = list[mid];
362
363       if (c > value)
364         high = mid - 1;
365       else if (c < value)
366         low = mid + 1;
367       else
368         return mid;
369     }
370
371     return (low <= end && list[low] > value) ? low : -1;
372   }
373
374   /**
375    * Find the first matching element from the index at or after the
376    * given node.
377    *
378    * @param nsIndex The namespace index lookup.
379    * @param lnIndex The local name index lookup.
380    * @param firstPotential The first potential match that is worth looking at.
381    *
382    * @return The first node that is greater than or equal to the
383    * firstPotential argument, or DTM.NOTPROCESSED if not found.
384    */

385   int findElementFromIndex(int nsIndex, int lnIndex, int firstPotential)
386   {
387
388     int[][][] indexes = m_elemIndexes;
389
390     if (null != indexes && nsIndex < indexes.length)
391     {
392       int[][] lnIndexs = indexes[nsIndex];
393
394       if (null != lnIndexs && lnIndex < lnIndexs.length)
395       {
396         int[] elems = lnIndexs[lnIndex];
397
398         if (null != elems)
399         {
400           int pos = findGTE(elems, 1, elems[0], firstPotential);
401
402           if (pos > -1)
403           {
404             return elems[pos];
405           }
406         }
407       }
408     }
409
410     return NOTPROCESSED;
411   }
412
413   /**
414    * Get the next node identity value in the list, and call the iterator
415    * if it hasn't been added yet.
416    *
417    * @param identity The node identity (index).
418    * @return identity+1, or DTM.NULL.
419    */

420   protected abstract int getNextNodeIdentity(int identity);
421
422   /**
423    * This method should try and build one or more nodes in the table.
424    *
425    * @return The true if a next node is found or false if
426    * there are no more nodes.
427    */

428   protected abstract boolean nextNode();
429
430   /**
431    * Get the number of nodes that have been added.
432    *
433    * @return the number of nodes that have been mapped.
434    */

435   protected abstract int getNumberOfNodes();
436
437   /** Stateless axis traversers, lazely built. */
438   protected DTMAxisTraverser[] m_traversers;
439
440 // /**
441
// * Ensure that the size of the information arrays can hold another entry
442
// * at the given index.
443
// *
444
// * @param index On exit from this function, the information arrays sizes must be
445
// * at least index+1.
446
// */
447
// protected void ensureSize(int index)
448
// {
449
// // We've cut over to Suballocated*Vector, which are self-sizing.
450
// }
451

452   /**
453    * Get the simple type ID for the given node identity.
454    *
455    * @param identity The node identity.
456    *
457    * @return The simple type ID, or DTM.NULL.
458    */

459   protected short _type(int identity)
460   {
461
462     int info = _exptype(identity);
463
464     if (NULL != info)
465       return m_expandedNameTable.getType(info);
466     else
467       return NULL;
468   }
469
470   /**
471    * Get the expanded type ID for the given node identity.
472    *
473    * @param identity The node identity.
474    *
475    * @return The expanded type ID, or DTM.NULL.
476    */

477   protected int _exptype(int identity)
478   {
479     if (identity == DTM.NULL)
480     return NULL;
481     // Reorganized test and loop into single flow
482
// Tiny performance improvement, saves a few bytes of code, clearer.
483
// %OPT% Other internal getters could be treated simliarly
484
while (identity>=m_size)
485     {
486       if (!nextNode() && identity >= m_size)
487         return NULL;
488     }
489     return m_exptype.elementAt(identity);
490
491   }
492
493   /**
494    * Get the level in the tree for the given node identity.
495    *
496    * @param identity The node identity.
497    *
498    * @return The tree level, or DTM.NULL.
499    */

500   protected int _level(int identity)
501   {
502     while (identity>=m_size)
503     {
504       boolean isMore = nextNode();
505       if (!isMore && identity >= m_size)
506         return NULL;
507     }
508
509     int i=0;
510     while(NULL != (identity=_parent(identity)))
511       ++i;
512     return i;
513   }
514
515   /**
516    * Get the first child for the given node identity.
517    *
518    * @param identity The node identity.
519    *
520    * @return The first child identity, or DTM.NULL.
521    */

522   protected int _firstch(int identity)
523   {
524
525     // Boiler-plate code for each of the _xxx functions, except for the array.
526
int info = (identity >= m_size) ? NOTPROCESSED : m_firstch.elementAt(identity);
527
528     // Check to see if the information requested has been processed, and,
529
// if not, advance the iterator until we the information has been
530
// processed.
531
while (info == NOTPROCESSED)
532     {
533       boolean isMore = nextNode();
534
535       if (identity >= m_size &&!isMore)
536         return NULL;
537       else
538       {
539         info = m_firstch.elementAt(identity);
540         if(info == NOTPROCESSED && !isMore)
541           return NULL;
542       }
543     }
544
545     return info;
546   }
547
548   /**
549    * Get the next sibling for the given node identity.
550    *
551    * @param identity The node identity.
552    *
553    * @return The next sibling identity, or DTM.NULL.
554    */

555   protected int _nextsib(int identity)
556   {
557     // Boiler-plate code for each of the _xxx functions, except for the array.
558
int info = (identity >= m_size) ? NOTPROCESSED : m_nextsib.elementAt(identity);
559
560     // Check to see if the information requested has been processed, and,
561
// if not, advance the iterator until we the information has been
562
// processed.
563
while (info == NOTPROCESSED)
564     {
565       boolean isMore = nextNode();
566
567       if (identity >= m_size &&!isMore)
568         return NULL;
569       else
570       {
571         info = m_nextsib.elementAt(identity);
572         if(info == NOTPROCESSED && !isMore)
573           return NULL;
574       }
575     }
576
577     return info;
578   }
579
580   /**
581    * Get the previous sibling for the given node identity.
582    *
583    * @param identity The node identity.
584    *
585    * @return The previous sibling identity, or DTM.NULL.
586    */

587   protected int _prevsib(int identity)
588   {
589
590     if (identity < m_size)
591       return m_prevsib.elementAt(identity);
592
593     // Check to see if the information requested has been processed, and,
594
// if not, advance the iterator until we the information has been
595
// processed.
596
while (true)
597     {
598       boolean isMore = nextNode();
599
600       if (identity >= m_size && !isMore)
601         return NULL;
602       else if (identity < m_size)
603         return m_prevsib.elementAt(identity);
604     }
605   }
606
607   /**
608    * Get the parent for the given node identity.
609    *
610    * @param identity The node identity.
611    *
612    * @return The parent identity, or DTM.NULL.
613    */

614   protected int _parent(int identity)
615   {
616
617     if (identity < m_size)
618       return m_parent.elementAt(identity);
619
620     // Check to see if the information requested has been processed, and,
621
// if not, advance the iterator until we the information has been
622
// processed.
623
while (true)
624     {
625       boolean isMore = nextNode();
626
627       if (identity >= m_size && !isMore)
628         return NULL;
629       else if (identity < m_size)
630         return m_parent.elementAt(identity);
631     }
632   }
633
634   /**
635    * Diagnostics function to dump the DTM.
636    */

637   public void dumpDTM(OutputStream os)
638   {
639     try
640     {
641       if(os==null)
642       {
643           File f = new File("DTMDump"+((Object JavaDoc)this).hashCode()+".txt");
644           System.err.println("Dumping... "+f.getAbsolutePath());
645           os=new FileOutputStream(f);
646       }
647       PrintStream ps = new PrintStream(os);
648
649       while (nextNode()){}
650
651       int nRecords = m_size;
652
653       ps.println("Total nodes: " + nRecords);
654
655       for (int index = 0; index < nRecords; ++index)
656       {
657         int i=makeNodeHandle(index);
658         ps.println("=========== index=" + index + " handle=" + i + " ===========");
659         ps.println("NodeName: " + getNodeName(i));
660         ps.println("NodeNameX: " + getNodeNameX(i));
661         ps.println("LocalName: " + getLocalName(i));
662         ps.println("NamespaceURI: " + getNamespaceURI(i));
663         ps.println("Prefix: " + getPrefix(i));
664
665         int exTypeID = _exptype(index);
666
667         ps.println("Expanded Type ID: "
668                            + Integer.toHexString(exTypeID));
669
670         int type = _type(index);
671         String JavaDoc typestring;
672
673         switch (type)
674         {
675         case DTM.ATTRIBUTE_NODE :
676           typestring = "ATTRIBUTE_NODE";
677           break;
678         case DTM.CDATA_SECTION_NODE :
679           typestring = "CDATA_SECTION_NODE";
680           break;
681         case DTM.COMMENT_NODE :
682           typestring = "COMMENT_NODE";
683           break;
684         case DTM.DOCUMENT_FRAGMENT_NODE :
685           typestring = "DOCUMENT_FRAGMENT_NODE";
686           break;
687         case DTM.DOCUMENT_NODE :
688           typestring = "DOCUMENT_NODE";
689           break;
690         case DTM.DOCUMENT_TYPE_NODE :
691           typestring = "DOCUMENT_NODE";
692           break;
693         case DTM.ELEMENT_NODE :
694           typestring = "ELEMENT_NODE";
695           break;
696         case DTM.ENTITY_NODE :
697           typestring = "ENTITY_NODE";
698           break;
699         case DTM.ENTITY_REFERENCE_NODE :
700           typestring = "ENTITY_REFERENCE_NODE";
701           break;
702         case DTM.NAMESPACE_NODE :
703           typestring = "NAMESPACE_NODE";
704           break;
705         case DTM.NOTATION_NODE :
706           typestring = "NOTATION_NODE";
707           break;
708         case DTM.NULL :
709           typestring = "NULL";
710           break;
711         case DTM.PROCESSING_INSTRUCTION_NODE :
712           typestring = "PROCESSING_INSTRUCTION_NODE";
713           break;
714         case DTM.TEXT_NODE :
715           typestring = "TEXT_NODE";
716           break;
717         default :
718           typestring = "Unknown!";
719           break;
720         }
721
722         ps.println("Type: " + typestring);
723
724         int firstChild = _firstch(index);
725
726         if (DTM.NULL == firstChild)
727           ps.println("First child: DTM.NULL");
728         else if (NOTPROCESSED == firstChild)
729           ps.println("First child: NOTPROCESSED");
730         else
731           ps.println("First child: " + firstChild);
732
733         if (m_prevsib != null)
734         {
735           int prevSibling = _prevsib(index);
736
737           if (DTM.NULL == prevSibling)
738             ps.println("Prev sibling: DTM.NULL");
739           else if (NOTPROCESSED == prevSibling)
740             ps.println("Prev sibling: NOTPROCESSED");
741           else
742             ps.println("Prev sibling: " + prevSibling);
743         }
744
745         int nextSibling = _nextsib(index);
746
747         if (DTM.NULL == nextSibling)
748           ps.println("Next sibling: DTM.NULL");
749         else if (NOTPROCESSED == nextSibling)
750           ps.println("Next sibling: NOTPROCESSED");
751         else
752           ps.println("Next sibling: " + nextSibling);
753
754         int parent = _parent(index);
755
756         if (DTM.NULL == parent)
757           ps.println("Parent: DTM.NULL");
758         else if (NOTPROCESSED == parent)
759           ps.println("Parent: NOTPROCESSED");
760         else
761           ps.println("Parent: " + parent);
762
763         int level = _level(index);
764
765         ps.println("Level: " + level);
766         ps.println("Node Value: " + getNodeValue(i));
767         ps.println("String Value: " + getStringValue(i));
768       }
769     }
770     catch(IOException ioe)
771     {
772       ioe.printStackTrace(System.err);
773       System.exit(-1);
774     }
775   }
776   
777   /**
778    * Diagnostics function to dump a single node.
779    *
780    * %REVIEW% KNOWN GLITCH: If you pass it a node index rather than a
781    * node handle, it works just fine... but the displayed identity
782    * number before the colon is different, which complicates comparing
783    * it with nodes printed the other way. We could always OR the DTM ID
784    * into the value, to suppress that distinction...
785    *
786    * %REVIEW% This might want to be moved up to DTMDefaultBase, or possibly
787    * DTM itself, since it's a useful diagnostic and uses only DTM's public
788    * APIs.
789    */

790   public String JavaDoc dumpNode(int nodeHandle)
791   {
792       if(nodeHandle==DTM.NULL)
793           return "[null]";
794           
795         String JavaDoc typestring;
796         switch (getNodeType(nodeHandle))
797         {
798         case DTM.ATTRIBUTE_NODE :
799           typestring = "ATTR";
800           break;
801         case DTM.CDATA_SECTION_NODE :
802           typestring = "CDATA";
803           break;
804         case DTM.COMMENT_NODE :
805           typestring = "COMMENT";
806           break;
807         case DTM.DOCUMENT_FRAGMENT_NODE :
808           typestring = "DOC_FRAG";
809           break;
810         case DTM.DOCUMENT_NODE :
811           typestring = "DOC";
812           break;
813         case DTM.DOCUMENT_TYPE_NODE :
814           typestring = "DOC_TYPE";
815           break;
816         case DTM.ELEMENT_NODE :
817           typestring = "ELEMENT";
818           break;
819         case DTM.ENTITY_NODE :
820           typestring = "ENTITY";
821           break;
822         case DTM.ENTITY_REFERENCE_NODE :
823           typestring = "ENT_REF";
824           break;
825         case DTM.NAMESPACE_NODE :
826           typestring = "NAMESPACE";
827           break;
828         case DTM.NOTATION_NODE :
829           typestring = "NOTATION";
830           break;
831         case DTM.NULL :
832           typestring = "null";
833           break;
834         case DTM.PROCESSING_INSTRUCTION_NODE :
835           typestring = "PI";
836           break;
837         case DTM.TEXT_NODE :
838           typestring = "TEXT";
839           break;
840         default :
841           typestring = "Unknown!";
842           break;
843         }
844
845       StringBuffer JavaDoc sb=new StringBuffer JavaDoc();
846       sb.append("["+nodeHandle+": "+typestring+
847                 "(0x"+Integer.toHexString(getExpandedTypeID(nodeHandle))+") "+
848                 getNodeNameX(nodeHandle)+" {"+getNamespaceURI(nodeHandle)+"}"+
849                 "=\""+ getNodeValue(nodeHandle)+"\"]");
850       return sb.toString();
851   }
852
853   // ========= DTM Implementation Control Functions. ==============
854

855   /**
856    * Set an implementation dependent feature.
857    * <p>
858    * %REVIEW% Do we really expect to set features on DTMs?
859    *
860    * @param featureId A feature URL.
861    * @param state true if this feature should be on, false otherwise.
862    */

863   public void setFeature(String JavaDoc featureId, boolean state){}
864
865   // ========= Document Navigation Functions =========
866

867   /**
868    * Given a node handle, test if it has child nodes.
869    * <p> %REVIEW% This is obviously useful at the DOM layer, where it
870    * would permit testing this without having to create a proxy
871    * node. It's less useful in the DTM API, where
872    * (dtm.getFirstChild(nodeHandle)!=DTM.NULL) is just as fast and
873    * almost as self-evident. But it's a convenience, and eases porting
874    * of DOM code to DTM. </p>
875    *
876    * @param nodeHandle int Handle of the node.
877    * @return int true if the given node has child nodes.
878    */

879   public boolean hasChildNodes(int nodeHandle)
880   {
881
882     int identity = makeNodeIdentity(nodeHandle);
883     int firstChild = _firstch(identity);
884
885     return firstChild != DTM.NULL;
886   }
887     
888   /** Given a node identity, return a node handle. If extended addressing
889    * has been used (multiple DTM IDs), we need to map the high bits of the
890    * identity into the proper DTM ID.
891    *
892    * This has been made FINAL to facilitate inlining, since we do not expect
893    * any subclass of DTMDefaultBase to ever change the algorithm. (I don't
894    * really like doing so, and would love to have an excuse not to...)
895    *
896    * %REVIEW% Is it worth trying to specialcase small documents?
897    * %REVIEW% Should this be exposed at the package/public layers?
898    *
899    * @param nodeIdentity Internal offset to this node's records.
900    * @return NodeHandle (external representation of node)
901    * */

902   final public int makeNodeHandle(int nodeIdentity)
903   {
904     if(NULL==nodeIdentity) return NULL;
905         
906     if(JJK_DEBUG && nodeIdentity>DTMManager.IDENT_NODE_DEFAULT)
907       System.err.println("GONK! (only useful in limited situations)");
908
909     return m_dtmIdent.elementAt(nodeIdentity >>> DTMManager.IDENT_DTM_NODE_BITS)
910       + (nodeIdentity & DTMManager.IDENT_NODE_DEFAULT) ;
911   }
912     
913   /** Given a node handle, return a node identity. If extended addressing
914    * has been used (multiple DTM IDs), we need to map the high bits of the
915    * identity into the proper DTM ID and thence find the proper offset
916    * to add to the low bits of the identity
917    *
918    * This has been made FINAL to facilitate inlining, since we do not expect
919    * any subclass of DTMDefaultBase to ever change the algorithm. (I don't
920    * really like doing so, and would love to have an excuse not to...)
921    *
922    * %OPT% Performance is critical for this operation.
923    *
924    * %REVIEW% Should this be exposed at the package/public layers?
925    *
926    * @param NodeHandle (external representation of node)
927    * @return nodeIdentity Internal offset to this node's records.
928    * */

929   final public int makeNodeIdentity(int nodeHandle)
930   {
931     if(NULL==nodeHandle) return NULL;
932
933     if(m_mgrDefault!=null)
934     {
935       // Optimization: use the DTMManagerDefault's fast DTMID-to-offsets
936
// table. I'm not wild about this solution but this operation
937
// needs need extreme speed.
938

939       int whichDTMindex=nodeHandle>>>DTMManager.IDENT_DTM_NODE_BITS;
940
941       // %REVIEW% Wish I didn't have to perform the pre-test, but
942
// someone is apparently asking DTMs whether they contain nodes
943
// which really don't belong to them. That's probably a bug
944
// which should be fixed, but until it is:
945
if(m_mgrDefault.m_dtms[whichDTMindex]!=this)
946     return NULL;
947       else
948     return
949       m_mgrDefault.m_dtm_offsets[whichDTMindex]
950       | (nodeHandle & DTMManager.IDENT_NODE_DEFAULT);
951     }
952       
953     int whichDTMid=m_dtmIdent.indexOf(nodeHandle & DTMManager.IDENT_DTM_DEFAULT);
954     return (whichDTMid==NULL)
955       ? NULL
956       : (whichDTMid << DTMManager.IDENT_DTM_NODE_BITS)
957       + (nodeHandle & DTMManager.IDENT_NODE_DEFAULT);
958   }
959
960
961   /**
962    * Given a node handle, get the handle of the node's first child.
963    * If not yet resolved, waits for more nodes to be added to the document and
964    * tries again.
965    *
966    * @param nodeHandle int Handle of the node.
967    * @return int DTM node-number of first child, or DTM.NULL to indicate none exists.
968    */

969   public int getFirstChild(int nodeHandle)
970   {
971
972     int identity = makeNodeIdentity(nodeHandle);
973     int firstChild = _firstch(identity);
974
975     return makeNodeHandle(firstChild);
976   }
977   
978   /**
979    * Given a node handle, get the handle of the node's first child.
980    * If not yet resolved, waits for more nodes to be added to the document and
981    * tries again.
982    *
983    * @param nodeHandle int Handle of the node.
984    * @return int DTM node-number of first child, or DTM.NULL to indicate none exists.
985    */

986   public int getTypedFirstChild(int nodeHandle, int nodeType)
987   {
988
989     int firstChild, eType;
990     if (nodeType < DTM.NTYPES) {
991       for (firstChild = _firstch(makeNodeIdentity(nodeHandle));
992            firstChild != DTM.NULL;
993            firstChild = _nextsib(firstChild)) {
994         eType = _exptype(firstChild);
995         if (eType == nodeType
996                || (eType >= DTM.NTYPES
997                       && m_expandedNameTable.getType(eType) == nodeType)) {
998           return makeNodeHandle(firstChild);
999         }
1000      }
1001    } else {
1002      for (firstChild = _firstch(makeNodeIdentity(nodeHandle));
1003           firstChild != DTM.NULL;
1004           firstChild = _nextsib(firstChild)) {
1005        if (_exptype(firstChild) == nodeType) {
1006          return makeNodeHandle(firstChild);
1007        }
1008      }
1009    }
1010    return DTM.NULL;
1011  }
1012
1013  /**
1014   * Given a node handle, advance to its last child.
1015   * If not yet resolved, waits for more nodes to be added to the document and
1016   * tries again.
1017   *
1018   * @param nodeHandle int Handle of the node.
1019   * @return int Node-number of last child,
1020   * or DTM.NULL to indicate none exists.
1021   */

1022  public int getLastChild(int nodeHandle)
1023  {
1024
1025    int identity = makeNodeIdentity(nodeHandle);
1026    int child = _firstch(identity);
1027    int lastChild = DTM.NULL;
1028
1029    while (child != DTM.NULL)
1030    {
1031      lastChild = child;
1032      child = _nextsib(child);
1033    }
1034
1035    return makeNodeHandle(lastChild);
1036  }
1037
1038  /**
1039   * Retrieves an attribute node by by qualified name and namespace URI.
1040   *
1041   * @param nodeHandle int Handle of the node upon which to look up this attribute..
1042   * @param namespaceURI The namespace URI of the attribute to
1043   * retrieve, or null.
1044   * @param name The local name of the attribute to
1045   * retrieve.
1046   * @return The attribute node handle with the specified name (
1047   * <code>nodeName</code>) or <code>DTM.NULL</code> if there is no such
1048   * attribute.
1049   */

1050  public abstract int getAttributeNode(int nodeHandle, String JavaDoc namespaceURI,
1051                                       String JavaDoc name);
1052
1053  /**
1054   * Given a node handle, get the index of the node's first attribute.
1055   *
1056   * @param nodeHandle int Handle of the node.
1057   * @return Handle of first attribute, or DTM.NULL to indicate none exists.
1058   */

1059  public int getFirstAttribute(int nodeHandle)
1060  {
1061    int nodeID = makeNodeIdentity(nodeHandle);
1062
1063    return makeNodeHandle(getFirstAttributeIdentity(nodeID));
1064  }
1065
1066  /**
1067   * Given a node identity, get the index of the node's first attribute.
1068   *
1069   * @param identity int identity of the node.
1070   * @return Identity of first attribute, or DTM.NULL to indicate none exists.
1071   */

1072  protected int getFirstAttributeIdentity(int identity) {
1073    int type = _type(identity);
1074
1075    if (DTM.ELEMENT_NODE == type)
1076    {
1077      // Assume that attributes and namespaces immediately follow the element.
1078
while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
1079      {
1080
1081        // Assume this can not be null.
1082
type = _type(identity);
1083
1084        if (type == DTM.ATTRIBUTE_NODE)
1085        {
1086          return identity;
1087        }
1088        else if (DTM.NAMESPACE_NODE != type)
1089        {
1090          break;
1091        }
1092      }
1093    }
1094
1095    return DTM.NULL;
1096  }
1097
1098  /**
1099   * Given a node handle and an expanded type ID, get the index of the node's
1100   * attribute of that type, if any.
1101   *
1102   * @param nodeHandle int Handle of the node.
1103   * @param attType int expanded type ID of the required attribute.
1104   * @return Handle of attribute of the required type, or DTM.NULL to indicate
1105   * none exists.
1106   */

1107  protected int getTypedAttribute(int nodeHandle, int attType) {
1108    int type = getNodeType(nodeHandle);
1109    if (DTM.ELEMENT_NODE == type) {
1110      int identity = makeNodeIdentity(nodeHandle);
1111
1112      while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
1113      {
1114        type = _type(identity);
1115
1116        if (type == DTM.ATTRIBUTE_NODE)
1117        {
1118          if (_exptype(identity) == attType) return makeNodeHandle(identity);
1119        }
1120        else if (DTM.NAMESPACE_NODE != type)
1121        {
1122          break;
1123        }
1124      }
1125    }
1126
1127    return DTM.NULL;
1128  }
1129
1130  /**
1131   * Given a node handle, advance to its next sibling.
1132   * If not yet resolved, waits for more nodes to be added to the document and
1133   * tries again.
1134   * @param nodeHandle int Handle of the node.
1135   * @return int Node-number of next sibling,
1136   * or DTM.NULL to indicate none exists.
1137   */

1138  public int getNextSibling(int nodeHandle)
1139  {
1140    if (nodeHandle == DTM.NULL)
1141    return DTM.NULL;
1142    return makeNodeHandle(_nextsib(makeNodeIdentity(nodeHandle)));
1143  }
1144  
1145  /**
1146   * Given a node handle, advance to its next sibling.
1147   * If not yet resolved, waits for more nodes to be added to the document and
1148   * tries again.
1149   * @param nodeHandle int Handle of the node.
1150   * @return int Node-number of next sibling,
1151   * or DTM.NULL to indicate none exists.
1152   */

1153  public int getTypedNextSibling(int nodeHandle, int nodeType)
1154  {
1155    if (nodeHandle == DTM.NULL)
1156    return DTM.NULL;
1157    int node = makeNodeIdentity(nodeHandle);
1158    int eType;
1159    while ((node = _nextsib(node)) != DTM.NULL &&
1160    ((eType = _exptype(node)) != nodeType &&
1161    m_expandedNameTable.getType(eType)!= nodeType));
1162    //_type(node) != nodeType));
1163

1164    return (node == DTM.NULL ? DTM.NULL : makeNodeHandle(node));
1165  }
1166
1167  /**
1168   * Given a node handle, find its preceeding sibling.
1169   * WARNING: DTM is asymmetric; this operation is resolved by search, and is
1170   * relatively expensive.
1171   *
1172   * @param nodeHandle the id of the node.
1173   * @return int Node-number of the previous sib,
1174   * or DTM.NULL to indicate none exists.
1175   */

1176  public int getPreviousSibling(int nodeHandle)
1177  {
1178    if (nodeHandle == DTM.NULL)
1179      return DTM.NULL;
1180    
1181    if (m_prevsib != null)
1182      return makeNodeHandle(_prevsib(makeNodeIdentity(nodeHandle)));
1183    else
1184    {
1185      // If the previous sibling array is not built, we get at
1186
// the previous sibling using the parent, firstch and
1187
// nextsib arrays.
1188
int nodeID = makeNodeIdentity(nodeHandle);
1189      int parent = _parent(nodeID);
1190      int node = _firstch(parent);
1191      int result = DTM.NULL;
1192      while (node != nodeID)
1193      {
1194        result = node;
1195        node = _nextsib(node);
1196      }
1197      return makeNodeHandle(result);
1198    }
1199  }
1200
1201  /**
1202   * Given a node handle, advance to the next attribute.
1203   * If an attr, we advance to
1204   * the next attr on the same node. If not an attribute, we return NULL.
1205   *
1206   * @param nodeHandle int Handle of the node.
1207   * @return int DTM node-number of the resolved attr,
1208   * or DTM.NULL to indicate none exists.
1209   */

1210  public int getNextAttribute(int nodeHandle) {
1211    int nodeID = makeNodeIdentity(nodeHandle);
1212
1213    if (_type(nodeID) == DTM.ATTRIBUTE_NODE) {
1214      return makeNodeHandle(getNextAttributeIdentity(nodeID));
1215    }
1216
1217    return DTM.NULL;
1218  }
1219
1220  /**
1221   * Given a node identity for an attribute, advance to the next attribute.
1222   *
1223   * @param identity int identity of the attribute node. This
1224   * <strong>must</strong> be an attribute node.
1225   *
1226   * @return int DTM node-identity of the resolved attr,
1227   * or DTM.NULL to indicate none exists.
1228   *
1229   */

1230  protected int getNextAttributeIdentity(int identity) {
1231    // Assume that attributes and namespace nodes immediately follow the element
1232
while (DTM.NULL != (identity = getNextNodeIdentity(identity))) {
1233      int type = _type(identity);
1234
1235      if (type == DTM.ATTRIBUTE_NODE) {
1236        return identity;
1237      } else if (type != DTM.NAMESPACE_NODE) {
1238        break;
1239      }
1240    }
1241
1242    return DTM.NULL;
1243  }
1244
1245  /** Lazily created namespace lists. */
1246  private Vector m_namespaceLists = null; // on demand
1247

1248
1249  /** Build table of namespace declaration
1250   * locations during DTM construction. Table is a Vector of
1251   * SuballocatedIntVectors containing the namespace node HANDLES declared at
1252   * that ID, plus an SuballocatedIntVector of the element node INDEXES at which
1253   * these declarations appeared.
1254   *
1255   * NOTE: Since this occurs during model build, nodes will be encountered
1256   * in doucment order and thus the table will be ordered by element,
1257   * permitting binary-search as a possible retrieval optimization.
1258   *
1259   * %REVIEW% Directly managed arrays rather than vectors?
1260   * %REVIEW% Handles or IDs? Given usage, I think handles.
1261   * */

1262  protected void declareNamespaceInContext(int elementNodeIndex,int namespaceNodeIndex)
1263  {
1264    SuballocatedIntVector nsList=null;
1265    if(m_namespaceDeclSets==null)
1266      {
1267
1268        // First
1269
m_namespaceDeclSetElements=new SuballocatedIntVector(32);
1270        m_namespaceDeclSetElements.addElement(elementNodeIndex);
1271        m_namespaceDeclSets=new Vector();
1272        nsList=new SuballocatedIntVector(32);
1273        m_namespaceDeclSets.addElement(nsList);
1274      }
1275    else
1276      {
1277        // Most recent. May be -1 (none) if DTM was pruned.
1278
// %OPT% Is there a lastElement() method? Should there be?
1279
int last=m_namespaceDeclSetElements.size()-1;
1280            
1281        if(last>=0 && elementNodeIndex==m_namespaceDeclSetElements.elementAt(last))
1282          {
1283            nsList=(SuballocatedIntVector)m_namespaceDeclSets.elementAt(last);
1284          }
1285      }
1286    if(nsList==null)
1287      {
1288        m_namespaceDeclSetElements.addElement(elementNodeIndex);
1289
1290        SuballocatedIntVector inherited =
1291                                findNamespaceContext(_parent(elementNodeIndex));
1292
1293        if (inherited!=null) {
1294            // %OPT% Count-down might be faster, but debuggability may
1295
// be better this way, and if we ever decide we want to
1296
// keep this ordered by expanded-type...
1297
int isize=inherited.size();
1298
1299            // Base the size of a new namespace list on the
1300
// size of the inherited list - but within reason!
1301
nsList=new SuballocatedIntVector(Math.max(Math.min(isize+16,2048),
1302                                                      32));
1303
1304            for(int i=0;i<isize;++i)
1305              {
1306                nsList.addElement(inherited.elementAt(i));
1307              }
1308        } else {
1309            nsList=new SuballocatedIntVector(32);
1310        }
1311
1312        m_namespaceDeclSets.addElement(nsList);
1313      }
1314
1315    // Handle overwriting inherited.
1316
// %OPT% Keep sorted? (By expanded-name rather than by doc order...)
1317
// Downside: Would require insertElementAt if not found,
1318
// which has recopying costs. But these are generally short lists...
1319
int newEType=_exptype(namespaceNodeIndex);
1320
1321    for(int i=nsList.size()-1;i>=0;--i)
1322      {
1323        if(newEType==getExpandedTypeID(nsList.elementAt(i)))
1324          {
1325            nsList.setElementAt(makeNodeHandle(namespaceNodeIndex),i);
1326            return;
1327          }
1328      }
1329    nsList.addElement(makeNodeHandle(namespaceNodeIndex));
1330  }
1331
1332  /** Retrieve list of namespace declaration locations
1333     * active at this node. List is an SuballocatedIntVector whose
1334     * entries are the namespace node HANDLES declared at that ID.
1335     *
1336     * %REVIEW% Directly managed arrays rather than vectors?
1337     * %REVIEW% Handles or IDs? Given usage, I think handles.
1338     * */

1339  protected SuballocatedIntVector findNamespaceContext(int elementNodeIndex)
1340  {
1341    if (null!=m_namespaceDeclSetElements)
1342      {
1343        // %OPT% Is binary-search really saving us a lot versus linear?
1344
// (... It may be, in large docs with many NS decls.)
1345
int wouldBeAt=findInSortedSuballocatedIntVector(m_namespaceDeclSetElements,
1346                                            elementNodeIndex);
1347        if(wouldBeAt>=0) // Found it
1348
return (SuballocatedIntVector) m_namespaceDeclSets.elementAt(wouldBeAt);
1349        if(wouldBeAt == -1) // -1-wouldbeat == 0
1350
return null; // Not after anything; definitely not found
1351

1352        // Not found, but we know where it should have been.
1353
// Search back until we find an ancestor or run out.
1354
wouldBeAt=-1-wouldBeAt;
1355
1356        // Decrement wouldBeAt to find last possible ancestor
1357
int candidate=m_namespaceDeclSetElements.elementAt(-- wouldBeAt);
1358        int ancestor=_parent(elementNodeIndex);
1359
1360        // Special case: if the candidate is before the given node, and
1361
// is in the earliest possible position in the document, it
1362
// must have the namespace declarations we're interested in.
1363
if (wouldBeAt == 0 && candidate < ancestor) {
1364          int rootHandle = getDocumentRoot(makeNodeHandle(elementNodeIndex));
1365          int rootID = makeNodeIdentity(rootHandle);
1366          int uppermostNSCandidateID;
1367
1368          if (getNodeType(rootHandle) == DTM.DOCUMENT_NODE) {
1369            int ch = _firstch(rootID);
1370            uppermostNSCandidateID = (ch != DTM.NULL) ? ch : rootID;
1371          } else {
1372            uppermostNSCandidateID = rootID;
1373          }
1374
1375          if (candidate == uppermostNSCandidateID) {
1376            return (SuballocatedIntVector)m_namespaceDeclSets.elementAt(wouldBeAt);
1377          }
1378        }
1379
1380        while(wouldBeAt>=0 && ancestor>0)
1381          {
1382            if (candidate==ancestor) {
1383                // Found ancestor in list
1384
return (SuballocatedIntVector)m_namespaceDeclSets.elementAt(wouldBeAt);
1385            } else if (candidate<ancestor) {
1386                // Too deep in tree
1387
do {
1388                  ancestor=_parent(ancestor);
1389                } while (candidate < ancestor);
1390            } else if(wouldBeAt > 0){
1391              // Too late in list
1392
candidate=m_namespaceDeclSetElements.elementAt(--wouldBeAt);
1393            }
1394            else
1395                break;
1396          }
1397      }
1398
1399    return null; // No namespaces known at this node
1400
}
1401
1402  /**
1403     * Subroutine: Locate the specified node within
1404     * m_namespaceDeclSetElements, or the last element which
1405     * preceeds it in document order
1406     *
1407     * %REVIEW% Inlne this into findNamespaceContext? Create SortedSuballocatedIntVector type?
1408     *
1409     * @param elementNodeIndex Index of a node to look up.
1410     *
1411     * @return If positive or zero, the index of the found item.
1412     * If negative, index of the point at which it would have appeared,
1413     * encoded as -1-index and hence reconvertable by subtracting
1414     * it from -1. (Encoding because I don't want to recompare the strings
1415     * but don't want to burn bytes on a datatype to hold a flagged value.)
1416     */

1417  protected int findInSortedSuballocatedIntVector(SuballocatedIntVector vector, int lookfor)
1418  {
1419    // Binary search
1420
int i = 0;
1421    if(vector != null) {
1422      int first = 0;
1423      int last = vector.size() - 1;
1424
1425      while (first <= last) {
1426        i = (first + last) / 2;
1427        int test = lookfor-vector.elementAt(i);
1428        if(test == 0) {
1429          return i; // Name found
1430
}
1431        else if (test < 0) {
1432          last = i - 1; // looked too late
1433
}
1434        else {
1435          first = i + 1; // looked ot early
1436
}
1437      }
1438
1439      if (first > i) {
1440        i = first; // Clean up at loop end
1441
}
1442    }
1443
1444    return -1 - i; // not-found has to be encoded.
1445
}
1446
1447
1448  /**
1449   * Given a node handle, get the index of the node's first child.
1450   * If not yet resolved, waits for more nodes to be added to the document and
1451   * tries again
1452   *
1453   * @param nodeHandle handle to node, which should probably be an element
1454   * node, but need not be.
1455   *
1456   * @param inScope true if all namespaces in scope should be returned,
1457   * false if only the namespace declarations should be
1458   * returned.
1459   * @return handle of first namespace, or DTM.NULL to indicate none exists.
1460   */

1461  public int getFirstNamespaceNode(int nodeHandle, boolean inScope)
1462  {
1463        if(inScope)
1464        {
1465            int identity = makeNodeIdentity(nodeHandle);
1466            if (_type(identity) == DTM.ELEMENT_NODE)
1467            {
1468              SuballocatedIntVector nsContext=findNamespaceContext(identity);
1469              if(nsContext==null || nsContext.size()<1)
1470                return NULL;
1471
1472              return nsContext.elementAt(0);
1473            }
1474            else
1475              return NULL;
1476          }
1477        else
1478          {
1479            // Assume that attributes and namespaces immediately
1480
// follow the element.
1481
//
1482
// %OPT% Would things be faster if all NS nodes were built
1483
// before all Attr nodes? Some costs at build time for 2nd
1484
// pass...
1485
int identity = makeNodeIdentity(nodeHandle);
1486            if (_type(identity) == DTM.ELEMENT_NODE)
1487            {
1488              while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
1489              {
1490                int type = _type(identity);
1491                if (type == DTM.NAMESPACE_NODE)
1492                    return makeNodeHandle(identity);
1493                else if (DTM.ATTRIBUTE_NODE != type)
1494                    break;
1495              }
1496              return NULL;
1497            }
1498            else
1499              return NULL;
1500          }
1501  }
1502
1503  /**
1504   * Given a namespace handle, advance to the next namespace.
1505   *
1506   * @param baseHandle handle to original node from where the first namespace
1507   * was relative to (needed to return nodes in document order).
1508   * @param namespaceHandle handle to node which must be of type
1509   * NAMESPACE_NODE.
1510   * @param nodeHandle A namespace handle for which we will find the next node.
1511   * @param inScope true if all namespaces that are in scope should be processed,
1512   * otherwise just process the nodes in the given element handle.
1513   * @return handle of next namespace, or DTM.NULL to indicate none exists.
1514   */

1515  public int getNextNamespaceNode(int baseHandle, int nodeHandle,
1516                                  boolean inScope)
1517  {
1518        if(inScope)
1519          {
1520            //Since we've been given the base, try direct lookup
1521
//(could look from nodeHandle but this is at least one
1522
//comparison/get-parent faster)
1523
//SuballocatedIntVector nsContext=findNamespaceContext(nodeHandle & m_mask);
1524

1525                SuballocatedIntVector nsContext=findNamespaceContext(makeNodeIdentity(baseHandle));
1526
1527            if(nsContext==null)
1528              return NULL;
1529            int i=1 + nsContext.indexOf(nodeHandle);
1530            if(i<=0 || i==nsContext.size())
1531              return NULL;
1532
1533            return nsContext.elementAt(i);
1534          }
1535        else
1536          {
1537            // Assume that attributes and namespace nodes immediately follow the element.
1538
int identity = makeNodeIdentity(nodeHandle);
1539            while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
1540              {
1541                int type = _type(identity);
1542                if (type == DTM.NAMESPACE_NODE)
1543                  {
1544                    return makeNodeHandle(identity);
1545                  }
1546                else if (type != DTM.ATTRIBUTE_NODE)
1547                  {
1548                    break;
1549                  }
1550              }
1551          }
1552     return DTM.NULL;
1553  }
1554
1555  /**
1556   * Given a node handle, find its parent node.
1557   *
1558   * @param nodeHandle the id of the node.
1559   * @return int Node-number of parent,
1560   * or DTM.NULL to indicate none exists.
1561   */

1562  public int getParent(int nodeHandle)
1563  {
1564
1565    int identity = makeNodeIdentity(nodeHandle);
1566
1567    if (identity > 0)
1568      return makeNodeHandle(_parent(identity));
1569    else
1570      return DTM.NULL;
1571  }
1572
1573  /**
1574   * Find the Document node handle for the document currently under construction.
1575   * PLEASE NOTE that most people should use getOwnerDocument(nodeHandle) instead;
1576   * this version of the operation is primarily intended for use during negotiation
1577   * with the DTM Manager.
1578   *
1579   * @param nodeHandle the id of the node.
1580   * @return int Node handle of document, which should always be valid.
1581   */

1582  public int getDocument()
1583  {
1584    return m_dtmIdent.elementAt(0); // makeNodeHandle(0)
1585
}
1586
1587  /**
1588   * Given a node handle, find the owning document node. This has the exact
1589   * same semantics as the DOM Document method of the same name, in that if
1590   * the nodeHandle is a document node, it will return NULL.
1591   *
1592   * <p>%REVIEW% Since this is DOM-specific, it may belong at the DOM
1593   * binding layer. Included here as a convenience function and to
1594   * aid porting of DOM code to DTM.</p>
1595   *
1596   * @param nodeHandle the id of the node.
1597   * @return int Node handle of owning document, or -1 if the node was a Docment
1598   */

1599  public int getOwnerDocument(int nodeHandle)
1600  {
1601
1602    if (DTM.DOCUMENT_NODE == getNodeType(nodeHandle))
1603        return DTM.NULL;
1604
1605    return getDocumentRoot(nodeHandle);
1606  }
1607
1608  /**
1609   * Given a node handle, find the owning document node. Unlike the DOM,
1610   * this considers the owningDocument of a Document to be itself.
1611   *
1612   * @param nodeHandle the id of the node.
1613   * @return int Node handle of owning document, or the nodeHandle if it is
1614   * a Document.
1615   */

1616  public int getDocumentRoot(int nodeHandle)
1617  {
1618    return getDocument();
1619  }
1620
1621  /**
1622   * Get the string-value of a node as a String object
1623   * (see http://www.w3.org/TR/xpath#data-model
1624   * for the definition of a node's string-value).
1625   *
1626   * @param nodeHandle The node ID.
1627   *
1628   * @return A string object that represents the string-value of the given node.
1629   */

1630  public abstract XMLString getStringValue(int nodeHandle);
1631
1632  /**
1633   * Get number of character array chunks in
1634   * the string-value of a node.
1635   * (see http://www.w3.org/TR/xpath#data-model
1636   * for the definition of a node's string-value).
1637   * Note that a single text node may have multiple text chunks.
1638   *
1639   * @param nodeHandle The node ID.
1640   *
1641   * @return number of character array chunks in
1642   * the string-value of a node.
1643   */

1644  public int getStringValueChunkCount(int nodeHandle)
1645  {
1646
1647    // %TBD%
1648
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//("getStringValueChunkCount not yet supported!");
1649

1650    return 0;
1651  }
1652
1653  /**
1654   * Get a character array chunk in the string-value of a node.
1655   * (see http://www.w3.org/TR/xpath#data-model
1656   * for the definition of a node's string-value).
1657   * Note that a single text node may have multiple text chunks.
1658   *
1659   * @param nodeHandle The node ID.
1660   * @param chunkIndex Which chunk to get.
1661   * @param startAndLen An array of 2 where the start position and length of
1662   * the chunk will be returned.
1663   *
1664   * @return The character array reference where the chunk occurs.
1665   */

1666  public char[] getStringValueChunk(int nodeHandle, int chunkIndex,
1667                                    int[] startAndLen)
1668  {
1669
1670    // %TBD%
1671
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"getStringValueChunk not yet supported!");
1672

1673    return null;
1674  }
1675
1676  /**
1677   * Given a node handle, return an ID that represents the node's expanded name.
1678   *
1679   * @param nodeHandle The handle to the node in question.
1680   *
1681   * @return the expanded-name id of the node.
1682   */

1683  public int getExpandedTypeID(int nodeHandle)
1684  {
1685    // %REVIEW% This _should_ only be null if someone asked the wrong DTM about the node...
1686
// which one would hope would never happen...
1687
int id=makeNodeIdentity(nodeHandle);
1688    if(id==NULL)
1689      return NULL;
1690    return _exptype(id);
1691  }
1692
1693  /**
1694   * Given an expanded name, return an ID. If the expanded-name does not
1695   * exist in the internal tables, the entry will be created, and the ID will
1696   * be returned. Any additional nodes that are created that have this
1697   * expanded name will use this ID.
1698   *
1699   * @param nodeHandle The handle to the node in question.
1700   * @param type The simple type, i.e. one of ELEMENT, ATTRIBUTE, etc.
1701   *
1702   * @param namespace The namespace URI, which may be null, may be an empty
1703   * string (which will be the same as null), or may be a
1704   * namespace URI.
1705   * @param localName The local name string, which must be a valid
1706   * <a HREF="http://www.w3.org/TR/REC-xml-names/">NCName</a>.
1707   *
1708   * @return the expanded-name id of the node.
1709   */

1710  public int getExpandedTypeID(String JavaDoc namespace, String JavaDoc localName, int type)
1711  {
1712
1713    ExpandedNameTable ent = m_expandedNameTable;
1714
1715    return ent.getExpandedTypeID(namespace, localName, type);
1716  }
1717
1718  /**
1719   * Given an expanded-name ID, return the local name part.
1720   *
1721   * @param ExpandedNameID an ID that represents an expanded-name.
1722   * @return String Local name of this node.
1723   */

1724  public String JavaDoc getLocalNameFromExpandedNameID(int expandedNameID)
1725  {
1726    return m_expandedNameTable.getLocalName(expandedNameID);
1727  }
1728
1729  /**
1730   * Given an expanded-name ID, return the namespace URI part.
1731   *
1732   * @param ExpandedNameID an ID that represents an expanded-name.
1733   * @return String URI value of this node's namespace, or null if no
1734   * namespace was resolved.
1735   */

1736  public String JavaDoc getNamespaceFromExpandedNameID(int expandedNameID)
1737  {
1738    return m_expandedNameTable.getNamespace(expandedNameID);
1739  }
1740
1741  /**
1742   * Returns the namespace type of a specific node
1743   * @param nodeHandle the id of the node.
1744   * @return the ID of the namespace.
1745   */

1746  public int getNamespaceType(final int nodeHandle)
1747  {
1748
1749    int identity = makeNodeIdentity(nodeHandle);
1750    int expandedNameID = _exptype(identity);
1751
1752    return m_expandedNameTable.getNamespaceID(expandedNameID);
1753  }
1754
1755  /**
1756   * Given a node handle, return its DOM-style node name. This will
1757   * include names such as #text or #document.
1758   *
1759   * @param nodeHandle the id of the node.
1760   * @return String Name of this node, which may be an empty string.
1761   * %REVIEW% Document when empty string is possible...
1762   * %REVIEW-COMMENT% It should never be empty, should it?
1763   */

1764  public abstract String JavaDoc getNodeName(int nodeHandle);
1765
1766  /**
1767   * Given a node handle, return the XPath node name. This should be
1768   * the name as described by the XPath data model, NOT the DOM-style
1769   * name.
1770   *
1771   * @param nodeHandle the id of the node.
1772   * @return String Name of this node, which may be an empty string.
1773   */

1774  public String JavaDoc getNodeNameX(int nodeHandle)
1775  {
1776
1777    /** @todo: implement this org.apache.xml.dtm.DTMDefaultBase abstract method */
1778    error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");
1779

1780    return null;
1781  }
1782
1783  /**
1784   * Given a node handle, return its XPath-style localname.
1785   * (As defined in Namespaces, this is the portion of the name after any
1786   * colon character).
1787   *
1788   * @param nodeHandle the id of the node.
1789   * @return String Local name of this node.
1790   */

1791  public abstract String JavaDoc getLocalName(int nodeHandle);
1792
1793  /**
1794   * Given a namespace handle, return the prefix that the namespace decl is
1795   * mapping.
1796   * Given a node handle, return the prefix used to map to the namespace.
1797   *
1798   * <p> %REVIEW% Are you sure you want "" for no prefix? </p>
1799   * <p> %REVIEW-COMMENT% I think so... not totally sure. -sb </p>
1800   *
1801   * @param nodeHandle the id of the node.
1802   * @return String prefix of this node's name, or "" if no explicit
1803   * namespace prefix was given.
1804   */

1805  public abstract String JavaDoc getPrefix(int nodeHandle);
1806
1807  /**
1808   * Given a node handle, return its DOM-style namespace URI
1809   * (As defined in Namespaces, this is the declared URI which this node's
1810   * prefix -- or default in lieu thereof -- was mapped to.)
1811   *
1812   * <p>%REVIEW% Null or ""? -sb</p>
1813   *
1814   * @param nodeHandle the id of the node.
1815   * @return String URI value of this node's namespace, or null if no
1816   * namespace was resolved.
1817   */

1818  public abstract String JavaDoc getNamespaceURI(int nodeHandle);
1819
1820  /**
1821   * Given a node handle, return its node value. This is mostly
1822   * as defined by the DOM, but may ignore some conveniences.
1823   * <p>
1824   *
1825   * @param nodeHandle The node id.
1826   * @return String Value of this node, or null if not
1827   * meaningful for this node type.
1828   */

1829  public abstract String JavaDoc getNodeValue(int nodeHandle);
1830
1831  /**
1832   * Given a node handle, return its DOM-style node type.
1833   * <p>
1834   * %REVIEW% Generally, returning short is false economy. Return int?
1835   * %REVIEW% Make assumption that node has already arrived. Is OK?
1836   *
1837   * @param nodeHandle The node id.
1838   * @return int Node type, as per the DOM's Node._NODE constants.
1839   */

1840  public short getNodeType(int nodeHandle)
1841  {
1842    if (nodeHandle == DTM.NULL)
1843    return DTM.NULL;
1844    return m_expandedNameTable.getType(_exptype(makeNodeIdentity(nodeHandle)));
1845  }
1846
1847  /**
1848   * Get the depth level of this node in the tree (equals 1 for
1849   * a parentless node).
1850   *
1851   * @param nodeHandle The node id.
1852   * @return the number of ancestors, plus one
1853   * @xsl.usage internal
1854   */

1855  public short getLevel(int nodeHandle)
1856  {
1857    // Apparently, the axis walker stuff requires levels to count from 1.
1858
int identity = makeNodeIdentity(nodeHandle);
1859    return (short) (_level(identity) + 1);
1860  }
1861  
1862  /**
1863   * Get the identity of this node in the tree
1864   *
1865   * @param nodeHandle The node handle.
1866   * @return the node identity
1867   * @xsl.usage internal
1868   */

1869  public int getNodeIdent(int nodeHandle)
1870  {
1871    /*if (nodeHandle != DTM.NULL)
1872      return nodeHandle & m_mask;
1873    else
1874      return DTM.NULL;*/

1875      
1876      return makeNodeIdentity(nodeHandle);
1877  }
1878  
1879  /**
1880   * Get the handle of this node in the tree
1881   *
1882   * @param nodeId The node identity.
1883   * @return the node handle
1884   * @xsl.usage internal
1885   */

1886  public int getNodeHandle(int nodeId)
1887  {
1888    /*if (nodeId != DTM.NULL)
1889      return nodeId | m_dtmIdent;
1890    else
1891      return DTM.NULL;*/

1892      
1893      return makeNodeHandle(nodeId);
1894  }
1895
1896  // ============== Document query functions ==============
1897

1898  /**
1899   * Tests whether DTM DOM implementation implements a specific feature and
1900   * that feature is supported by this node.
1901   *
1902   * @param feature The name of the feature to test.
1903   * @param versionThis is the version number of the feature to test.
1904   * If the version is not
1905   * specified, supporting any version of the feature will cause the
1906   * method to return <code>true</code>.
1907   * @param version The version string of the feature requested, may be null.
1908   * @return Returns <code>true</code> if the specified feature is
1909   * supported on this node, <code>false</code> otherwise.
1910   */

1911  public boolean isSupported(String JavaDoc feature, String JavaDoc version)
1912  {
1913
1914    // %TBD%
1915
return false;
1916  }
1917
1918  /**
1919   * Return the base URI of the document entity. If it is not known
1920   * (because the document was parsed from a socket connection or from
1921   * standard input, for example), the value of this property is unknown.
1922   *
1923   * @return the document base URI String object or null if unknown.
1924   */

1925  public String JavaDoc getDocumentBaseURI()
1926  {
1927    return m_documentBaseURI;
1928  }
1929
1930  /**
1931   * Set the base URI of the document entity.
1932   *
1933   * @param baseURI the document base URI String object or null if unknown.
1934   */

1935  public void setDocumentBaseURI(String JavaDoc baseURI)
1936  {
1937    m_documentBaseURI = baseURI;
1938  }
1939
1940  /**
1941   * Return the system identifier of the document entity. If
1942   * it is not known, the value of this property is unknown.
1943   *
1944   * @param nodeHandle The node id, which can be any valid node handle.
1945   * @return the system identifier String object or null if unknown.
1946   */

1947  public String JavaDoc getDocumentSystemIdentifier(int nodeHandle)
1948  {
1949
1950    // %REVIEW% OK? -sb
1951
return m_documentBaseURI;
1952  }
1953
1954  /**
1955   * Return the name of the character encoding scheme
1956   * in which the document entity is expressed.
1957   *
1958   * @param nodeHandle The node id, which can be any valid node handle.
1959   * @return the document encoding String object.
1960   * @xsl.usage internal
1961   */

1962  public String JavaDoc getDocumentEncoding(int nodeHandle)
1963  {
1964
1965    // %REVIEW% OK?? -sb
1966
return "UTF-8";
1967  }
1968
1969  /**
1970   * Return an indication of the standalone status of the document,
1971   * either "yes" or "no". This property is derived from the optional
1972   * standalone document declaration in the XML declaration at the
1973   * beginning of the document entity, and has no value if there is no
1974   * standalone document declaration.
1975   *
1976   * @param nodeHandle The node id, which can be any valid node handle.
1977   * @return the document standalone String object, either "yes", "no", or null.
1978   */

1979  public String JavaDoc getDocumentStandalone(int nodeHandle)
1980  {
1981    return null;
1982  }
1983
1984  /**
1985   * Return a string representing the XML version of the document. This
1986   * property is derived from the XML declaration optionally present at the
1987   * beginning of the document entity, and has no value if there is no XML
1988   * declaration.
1989   *
1990   * @param documentHandle The document handle
1991   *
1992   * @return the document version String object.
1993   */

1994  public String JavaDoc getDocumentVersion(int documentHandle)
1995  {
1996    return null;
1997  }
1998
1999  /**
2000   * Return an indication of
2001   * whether the processor has read the complete DTD. Its value is a
2002   * boolean. If it is false, then certain properties (indicated in their
2003   * descriptions below) may be unknown. If it is true, those properties
2004   * are never unknown.
2005   *
2006   * @return <code>true</code> if all declarations were processed;
2007   * <code>false</code> otherwise.
2008   */

2009  public boolean getDocumentAllDeclarationsProcessed()
2010  {
2011
2012    // %REVIEW% OK?
2013
return true;
2014  }
2015
2016  /**
2017   * A document type declaration information item has the following properties:
2018   *
2019   * 1. [system identifier] The system identifier of the external subset, if
2020   * it exists. Otherwise this property has no value.
2021   *
2022   * @return the system identifier String object, or null if there is none.
2023   */

2024  public abstract String JavaDoc getDocumentTypeDeclarationSystemIdentifier();
2025
2026  /**
2027   * Return the public identifier of the external subset,
2028   * normalized as described in 4.2.2 External Entities [XML]. If there is
2029   * no external subset or if it has no public identifier, this property
2030   * has no value.
2031   *
2032   * @param the document type declaration handle
2033   *
2034   * @return the public identifier String object, or null if there is none.
2035   */

2036  public abstract String JavaDoc getDocumentTypeDeclarationPublicIdentifier();
2037
2038  /**
2039   * Returns the <code>Element</code> whose <code>ID</code> is given by
2040   * <code>elementId</code>. If no such element exists, returns
2041   * <code>DTM.NULL</code>. Behavior is not defined if more than one element
2042   * has this <code>ID</code>. Attributes (including those
2043   * with the name "ID") are not of type ID unless so defined by DTD/Schema
2044   * information available to the DTM implementation.
2045   * Implementations that do not know whether attributes are of type ID or
2046   * not are expected to return <code>DTM.NULL</code>.
2047   *
2048   * <p>%REVIEW% Presumably IDs are still scoped to a single document,
2049   * and this operation searches only within a single document, right?
2050   * Wouldn't want collisions between DTMs in the same process.</p>
2051   *
2052   * @param elementId The unique <code>id</code> value for an element.
2053   * @return The handle of the matching element.
2054   */

2055  public abstract int getElementById(String JavaDoc elementId);
2056
2057  /**
2058   * The getUnparsedEntityURI function returns the URI of the unparsed
2059   * entity with the specified name in the same document as the context
2060   * node (see [3.3 Unparsed Entities]). It returns the empty string if
2061   * there is no such entity.
2062   * <p>
2063   * XML processors may choose to use the System Identifier (if one
2064   * is provided) to resolve the entity, rather than the URI in the
2065   * Public Identifier. The details are dependent on the processor, and
2066   * we would have to support some form of plug-in resolver to handle
2067   * this properly. Currently, we simply return the System Identifier if
2068   * present, and hope that it a usable URI or that our caller can
2069   * map it to one.
2070   * TODO: Resolve Public Identifiers... or consider changing function name.
2071   * <p>
2072   * If we find a relative URI
2073   * reference, XML expects it to be resolved in terms of the base URI
2074   * of the document. The DOM doesn't do that for us, and it isn't
2075   * entirely clear whether that should be done here; currently that's
2076   * pushed up to a higher level of our application. (Note that DOM Level
2077   * 1 didn't store the document's base URI.)
2078   * TODO: Consider resolving Relative URIs.
2079   * <p>
2080   * (The DOM's statement that "An XML processor may choose to
2081   * completely expand entities before the structure model is passed
2082   * to the DOM" refers only to parsed entities, not unparsed, and hence
2083   * doesn't affect this function.)
2084   *
2085   * @param name A string containing the Entity Name of the unparsed
2086   * entity.
2087   *
2088   * @return String containing the URI of the Unparsed Entity, or an
2089   * empty string if no such entity exists.
2090   */

2091  public abstract String JavaDoc getUnparsedEntityURI(String JavaDoc name);
2092
2093  // ============== Boolean methods ================
2094

2095  /**
2096   * Return true if the xsl:strip-space or xsl:preserve-space was processed
2097   * during construction of the DTM document.
2098   *
2099   * @return true if this DTM supports prestripping.
2100   */

2101  public boolean supportsPreStripping()
2102  {
2103    return true;
2104  }
2105
2106  /**
2107   * Figure out whether nodeHandle2 should be considered as being later
2108   * in the document than nodeHandle1, in Document Order as defined
2109   * by the XPath model. This may not agree with the ordering defined
2110   * by other XML applications.
2111   * <p>
2112   * There are some cases where ordering isn't defined, and neither are
2113   * the results of this function -- though we'll generally return false.
2114   *
2115   * @param nodeHandle1 Node handle to perform position comparison on.
2116   * @param nodeHandle2 Second Node handle to perform position comparison on .
2117   *
2118   * @return true if node1 comes before node2, otherwise return false.
2119   * You can think of this as
2120   * <code>(node1.documentOrderPosition &lt;= node2.documentOrderPosition)</code>.
2121   */

2122  public boolean isNodeAfter(int nodeHandle1, int nodeHandle2)
2123  {
2124        // These return NULL if the node doesn't belong to this document.
2125
int index1 = makeNodeIdentity(nodeHandle1);
2126    int index2 = makeNodeIdentity(nodeHandle2);
2127
2128    return index1!=NULL & index2!=NULL & index1 <= index2;
2129  }
2130
2131  /**
2132   * 2. [element content whitespace] A boolean indicating whether the
2133   * character is white space appearing within element content (see [XML],
2134   * 2.10 "White Space Handling"). Note that validating XML processors are
2135   * required by XML 1.0 to provide this information. If there is no
2136   * declaration for the containing element, this property has no value for
2137   * white space characters. If no declaration has been read, but the [all
2138   * declarations processed] property of the document information item is
2139   * false (so there may be an unread declaration), then the value of this
2140   * property is unknown for white space characters. It is always false for
2141   * characters that are not white space.
2142   *
2143   * @param nodeHandle the node ID.
2144   * @return <code>true</code> if the character data is whitespace;
2145   * <code>false</code> otherwise.
2146   */

2147  public boolean isCharacterElementContentWhitespace(int nodeHandle)
2148  {
2149
2150    // %TBD%
2151
return false;
2152  }
2153
2154  /**
2155   * 10. [all declarations processed] This property is not strictly speaking
2156   * part of the infoset of the document. Rather it is an indication of
2157   * whether the processor has read the complete DTD. Its value is a
2158   * boolean. If it is false, then certain properties (indicated in their
2159   * descriptions below) may be unknown. If it is true, those properties
2160   * are never unknown.
2161   *
2162   * @param the document handle
2163   *
2164   * @param documentHandle A node handle that must identify a document.
2165   * @return <code>true</code> if all declarations were processed;
2166   * <code>false</code> otherwise.
2167   */

2168  public boolean isDocumentAllDeclarationsProcessed(int documentHandle)
2169  {
2170    return true;
2171  }
2172
2173  /**
2174   * 5. [specified] A flag indicating whether this attribute was actually
2175   * specified in the start-tag of its element, or was defaulted from the
2176   * DTD.
2177   *
2178   * @param attributeHandle The attribute handle in question.
2179   *
2180   * @return <code>true</code> if the attribute was specified;
2181   * <code>false</code> if it was defaulted.
2182   */

2183  public abstract boolean isAttributeSpecified(int attributeHandle);
2184
2185  // ========== Direct SAX Dispatch, for optimization purposes ========
2186

2187  /**
2188   * Directly call the
2189   * characters method on the passed ContentHandler for the
2190   * string-value of the given node (see http://www.w3.org/TR/xpath#data-model
2191   * for the definition of a node's string-value). Multiple calls to the
2192   * ContentHandler's characters methods may well occur for a single call to
2193   * this method.
2194   *
2195   * @param nodeHandle The node ID.
2196   * @param ch A non-null reference to a ContentHandler.
2197   * @param normalize true if the content should be normalized according to
2198   * the rules for the XPath
2199   * <a HREF="http://www.w3.org/TR/xpath#function-normalize-space">normalize-space</a>
2200   * function.
2201   *
2202   * @throws org.xml.sax.SAXException
2203   */

2204  public abstract void dispatchCharactersEvents(
2205    int nodeHandle, org.xml.sax.ContentHandler JavaDoc ch, boolean normalize)
2206      throws org.xml.sax.SAXException JavaDoc;
2207
2208  /**
2209   * Directly create SAX parser events from a subtree.
2210   *
2211   * @param nodeHandle The node ID.
2212   * @param ch A non-null reference to a ContentHandler.
2213   *
2214   * @throws org.xml.sax.SAXException
2215   */

2216  public abstract void dispatchToEvents(
2217    int nodeHandle, org.xml.sax.ContentHandler JavaDoc ch)
2218      throws org.xml.sax.SAXException JavaDoc;
2219
2220  /**
2221   * Return an DOM node for the given node.
2222   *
2223   * @param nodeHandle The node ID.
2224   *
2225   * @return A node representation of the DTM node.
2226   */

2227  public org.w3c.dom.Node JavaDoc getNode(int nodeHandle)
2228  {
2229    return new DTMNodeProxy(this, nodeHandle);
2230  }
2231
2232  // ==== Construction methods (may not be supported by some implementations!) =====
2233

2234  /**
2235   * Append a child to the end of the document. Please note that the node
2236   * is always cloned if it is owned by another document.
2237   *
2238   * <p>%REVIEW% "End of the document" needs to be defined more clearly.
2239   * Does it become the last child of the Document? Of the root element?</p>
2240   *
2241   * @param newChild Must be a valid new node handle.
2242   * @param clone true if the child should be cloned into the document.
2243   * @param cloneDepth if the clone argument is true, specifies that the
2244   * clone should include all it's children.
2245   */

2246  public void appendChild(int newChild, boolean clone, boolean cloneDepth)
2247  {
2248    error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"appendChild not yet supported!");
2249
}
2250
2251  /**
2252   * Append a text node child that will be constructed from a string,
2253   * to the end of the document.
2254   *
2255   * <p>%REVIEW% "End of the document" needs to be defined more clearly.
2256   * Does it become the last child of the Document? Of the root element?</p>
2257   *
2258   * @param str Non-null reverence to a string.
2259   */

2260  public void appendTextChild(String JavaDoc str)
2261  {
2262    error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"appendTextChild not yet supported!");
2263
}
2264
2265  /**
2266   * Simple error for asserts and the like.
2267   *
2268   * @param msg Error message to report.
2269   */

2270  protected void error(String JavaDoc msg)
2271  {
2272    throw new DTMException(msg);
2273  }
2274
2275  /**
2276   * Find out whether or not to strip whispace nodes.
2277   *
2278   *
2279   * @return whether or not to strip whispace nodes.
2280   */

2281  protected boolean getShouldStripWhitespace()
2282  {
2283    return m_shouldStripWS;
2284  }
2285
2286  /**
2287   * Set whether to strip whitespaces and push in current value of
2288   * m_shouldStripWS in m_shouldStripWhitespaceStack.
2289   *
2290   * @param shouldStrip Flag indicating whether to strip whitespace nodes
2291   */

2292  protected void pushShouldStripWhitespace(boolean shouldStrip)
2293  {
2294
2295    m_shouldStripWS = shouldStrip;
2296
2297    if (null != m_shouldStripWhitespaceStack)
2298      m_shouldStripWhitespaceStack.push(shouldStrip);
2299  }
2300
2301  /**
2302   * Set whether to strip whitespaces at this point by popping out
2303   * m_shouldStripWhitespaceStack.
2304   *
2305   */

2306  protected void popShouldStripWhitespace()
2307  {
2308    if (null != m_shouldStripWhitespaceStack)
2309      m_shouldStripWS = m_shouldStripWhitespaceStack.popAndTop();
2310  }
2311
2312  /**
2313   * Set whether to strip whitespaces and set the top of the stack to
2314   * the current value of m_shouldStripWS.
2315   *
2316   *
2317   * @param shouldStrip Flag indicating whether to strip whitespace nodes
2318   */

2319  protected void setShouldStripWhitespace(boolean shouldStrip)
2320  {
2321
2322    m_shouldStripWS = shouldStrip;
2323
2324    if (null != m_shouldStripWhitespaceStack)
2325      m_shouldStripWhitespaceStack.setTop(shouldStrip);
2326  }
2327
2328  /**
2329   * A dummy routine to satisify the abstract interface. If the DTM
2330   * implememtation that extends the default base requires notification
2331   * of registration, they can override this method.
2332   */

2333   public void documentRegistration()
2334   {
2335   }
2336
2337  /**
2338   * A dummy routine to satisify the abstract interface. If the DTM
2339   * implememtation that extends the default base requires notification
2340   * when the document is being released, they can override this method
2341   */

2342   public void documentRelease()
2343   {
2344   }
2345
2346   /**
2347    * Migrate a DTM built with an old DTMManager to a new DTMManager.
2348    * After the migration, the new DTMManager will treat the DTM as
2349    * one that is built by itself.
2350    * This is used to support DTM sharing between multiple transformations.
2351    * @param manager the DTMManager
2352    */

2353   public void migrateTo(DTMManager mgr)
2354   {
2355     m_mgr = mgr;
2356     if(mgr instanceof DTMManagerDefault)
2357       m_mgrDefault=(DTMManagerDefault)mgr;
2358   }
2359
2360     /** Query which DTMManager this DTM is currently being handled by.
2361      *
2362      * %REVEW% Should this become part of the base DTM API?
2363      *
2364      * @return a DTMManager, or null if this is a "stand-alone" DTM.
2365      */

2366     public DTMManager getManager()
2367     {
2368         return m_mgr;
2369     }
2370
2371     /** Query which DTMIDs this DTM is currently using within the DTMManager.
2372      *
2373      * %REVEW% Should this become part of the base DTM API?
2374      *
2375      * @return an IntVector, or null if this is a "stand-alone" DTM.
2376      */

2377     public SuballocatedIntVector getDTMIDs()
2378     {
2379         if(m_mgr==null) return null;
2380         return m_dtmIdent;
2381     }
2382}
2383
Popular Tags