KickJava   Java API By Example, From Geeks To Geeks.

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


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: SAX2DTM.java,v 1.36 2004/02/17 04:07:37 minchau Exp $
18  */

19 package com.sun.org.apache.xml.internal.dtm.ref.sax2dtm;
20
21 import java.util.Hashtable JavaDoc;
22 import java.util.Vector JavaDoc;
23 import javax.xml.transform.Source JavaDoc;
24 import javax.xml.transform.SourceLocator JavaDoc;
25
26 import com.sun.org.apache.xml.internal.dtm.*;
27 import com.sun.org.apache.xml.internal.dtm.ref.*;
28 import com.sun.org.apache.xml.internal.utils.StringVector;
29 import com.sun.org.apache.xml.internal.utils.IntVector;
30 import com.sun.org.apache.xml.internal.utils.FastStringBuffer;
31 import com.sun.org.apache.xml.internal.utils.IntStack;
32 import com.sun.org.apache.xml.internal.utils.SuballocatedIntVector;
33 import com.sun.org.apache.xml.internal.utils.SystemIDResolver;
34 import com.sun.org.apache.xml.internal.utils.WrappedRuntimeException;
35 import com.sun.org.apache.xml.internal.utils.XMLString;
36 import com.sun.org.apache.xml.internal.utils.XMLStringFactory;
37 import com.sun.org.apache.xml.internal.res.XMLErrorResources;
38 import com.sun.org.apache.xml.internal.res.XMLMessages;
39 import org.xml.sax.*;
40 import org.xml.sax.ext.*;
41
42 /**
43  * This class implements a DTM that tends to be optimized more for speed than
44  * for compactness, that is constructed via SAX2 ContentHandler events.
45  */

46 public class SAX2DTM extends DTMDefaultBaseIterators
47         implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler,
48                    DeclHandler, LexicalHandler
49 {
50   /** Set true to monitor SAX events and similar diagnostic info. */
51   private static final boolean DEBUG = false;
52
53   /**
54    * If we're building the model incrementally on demand, we need to
55    * be able to tell the source when to send us more data.
56    *
57    * Note that if this has not been set, and you attempt to read ahead
58    * of the current build point, we'll probably throw a null-pointer
59    * exception. We could try to wait-and-retry instead, as a very poor
60    * fallback, but that has all the known problems with multithreading
61    * on multiprocessors and we Don't Want to Go There.
62    *
63    * @see setIncrementalSAXSource
64    */

65   private IncrementalSAXSource m_incrementalSAXSource = null;
66
67   /**
68    * All the character content, including attribute values, are stored in
69    * this buffer.
70    *
71    * %REVIEW% Should this have an option of being shared across DTMs?
72    * Sequentially only; not threadsafe... Currently, I think not.
73    *
74    * %REVIEW% Initial size was pushed way down to reduce weight of RTFs.
75    * pending reduction in number of RTF DTMs. Now that we're sharing a DTM
76    * between RTFs, and tail-pruning... consider going back to the larger/faster.
77    *
78    * Made protected rather than private so SAX2RTFDTM can access it.
79    */

80   //private FastStringBuffer m_chars = new FastStringBuffer(13, 13);
81
protected FastStringBuffer m_chars;
82
83   /** This vector holds offset and length data.
84    */

85   protected SuballocatedIntVector m_data;
86
87   /** The parent stack, needed only for construction.
88    * Made protected rather than private so SAX2RTFDTM can access it.
89    */

90   transient protected IntStack m_parents;
91
92   /** The current previous node, needed only for construction time.
93    * Made protected rather than private so SAX2RTFDTM can access it.
94    */

95   transient protected int m_previous = 0;
96
97   /** Namespace support, only relevent at construction time.
98    * Made protected rather than private so SAX2RTFDTM can access it.
99    */

100   transient protected java.util.Vector JavaDoc m_prefixMappings =
101     new java.util.Vector JavaDoc();
102
103   /** Namespace support, only relevent at construction time.
104    * Made protected rather than private so SAX2RTFDTM can access it.
105    */

106   transient protected IntStack m_contextIndexes;
107
108   /** Type of next characters() event within text block in prgress. */
109   transient protected int m_textType = DTM.TEXT_NODE;
110
111   /**
112    * Type of coalesced text block. See logic in the characters()
113    * method.
114    */

115   transient protected int m_coalescedTextType = DTM.TEXT_NODE;
116
117   /** The SAX Document locator */
118   transient protected Locator JavaDoc m_locator = null;
119
120   /** The SAX Document system-id */
121   transient private String JavaDoc m_systemId = null;
122
123   /** We are inside the DTD. This is used for ignoring comments. */
124   transient protected boolean m_insideDTD = false;
125
126   /** Tree Walker for dispatchToEvents. */
127   protected DTMTreeWalker m_walker = new DTMTreeWalker();
128
129   /** pool of string values that come as strings. */
130   protected DTMStringPool m_valuesOrPrefixes;
131
132   /** End document has been reached.
133    * Made protected rather than private so SAX2RTFDTM can access it.
134    */

135   protected boolean m_endDocumentOccured = false;
136
137   /** Data or qualified name values, one array element for each node. */
138   protected SuballocatedIntVector m_dataOrQName;
139
140   /**
141    * This table holds the ID string to node associations, for
142    * XML IDs.
143    */

144   protected Hashtable JavaDoc m_idAttributes = new Hashtable JavaDoc();
145
146   /**
147    * fixed dom-style names.
148    */

149   static final String JavaDoc[] m_fixednames = { null, null, // nothing, Element
150
null, "#text", // Attr, Text
151
"#cdata_section", null, // CDATA, EntityReference
152
null, null, // Entity, PI
153
"#comment", "#document", // Comment, Document
154
null, "#document-fragment", // Doctype, DocumentFragment
155
null }; // Notation
156

157   /**
158    * Vector of entities. Each record is composed of four Strings:
159    * publicId, systemID, notationName, and name.
160    */

161   private Vector JavaDoc m_entities = null;
162
163   /** m_entities public ID offset. */
164   private static final int ENTITY_FIELD_PUBLICID = 0;
165
166   /** m_entities system ID offset. */
167   private static final int ENTITY_FIELD_SYSTEMID = 1;
168
169   /** m_entities notation name offset. */
170   private static final int ENTITY_FIELD_NOTATIONNAME = 2;
171
172   /** m_entities name offset. */
173   private static final int ENTITY_FIELD_NAME = 3;
174
175   /** Number of entries per record for m_entities. */
176   private static final int ENTITY_FIELDS_PER = 4;
177
178   /**
179    * The starting offset within m_chars for the text or
180    * CDATA_SECTION node currently being acumulated,
181    * or -1 if there is no text node in progress
182    */

183   protected int m_textPendingStart = -1;
184
185   /**
186    * Describes whether information about document source location
187    * should be maintained or not.
188    *
189    * Made protected for access by SAX2RTFDTM.
190    */

191   protected boolean m_useSourceLocationProperty = false;
192
193   /**
194    * Describes whether information about document source location
195    * should be maintained or not. This static flag is set by TransformerFactoryImpl.
196    */

197   protected static boolean m_source_location = false;
198
199    /** Made protected for access by SAX2RTFDTM.
200    */

201   protected StringVector m_sourceSystemId;
202    /** Made protected for access by SAX2RTFDTM.
203    */

204   protected IntVector m_sourceLine;
205    /** Made protected for access by SAX2RTFDTM.
206    */

207   protected IntVector m_sourceColumn;
208   
209   /**
210    * Construct a SAX2DTM object using the default block size.
211    *
212    * @param mgr The DTMManager who owns this DTM.
213    * @param source the JAXP 1.1 Source object for this DTM.
214    * @param dtmIdentity The DTM identity ID for this DTM.
215    * @param whiteSpaceFilter The white space filter for this DTM, which may
216    * be null.
217    * @param xstringfactory XMLString factory for creating character content.
218    * @param doIndexing true if the caller considers it worth it to use
219    * indexing schemes.
220    */

221   public SAX2DTM(DTMManager mgr, Source JavaDoc source, int dtmIdentity,
222                  DTMWSFilter whiteSpaceFilter,
223                  XMLStringFactory xstringfactory,
224                  boolean doIndexing)
225   {
226
227     this(mgr, source, dtmIdentity, whiteSpaceFilter,
228           xstringfactory, doIndexing, DEFAULT_BLOCKSIZE, true, false);
229   }
230   
231   /**
232    * Construct a SAX2DTM object ready to be constructed from SAX2
233    * ContentHandler events.
234    *
235    * @param mgr The DTMManager who owns this DTM.
236    * @param source the JAXP 1.1 Source object for this DTM.
237    * @param dtmIdentity The DTM identity ID for this DTM.
238    * @param whiteSpaceFilter The white space filter for this DTM, which may
239    * be null.
240    * @param xstringfactory XMLString factory for creating character content.
241    * @param doIndexing true if the caller considers it worth it to use
242    * indexing schemes.
243    * @param blocksize The block size of the DTM.
244    * @param usePrevsib true if we want to build the previous sibling node array.
245    * @param newNameTable true if we want to use a new ExpandedNameTable for this DTM.
246    */

247   public SAX2DTM(DTMManager mgr, Source JavaDoc source, int dtmIdentity,
248                  DTMWSFilter whiteSpaceFilter,
249                  XMLStringFactory xstringfactory,
250                  boolean doIndexing,
251                  int blocksize,
252                  boolean usePrevsib,
253                  boolean newNameTable)
254   {
255
256     super(mgr, source, dtmIdentity, whiteSpaceFilter,
257           xstringfactory, doIndexing, blocksize, usePrevsib, newNameTable);
258
259     // %OPT% Use smaller sizes for all internal storage units when
260
// the blocksize is small. This reduces the cost of creating an RTF.
261
if (blocksize <= 64)
262     {
263       m_data = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS_SMALL);
264       m_dataOrQName = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS_SMALL);
265       m_valuesOrPrefixes = new DTMStringPool(16);
266       m_chars = new FastStringBuffer(7, 10);
267       m_contextIndexes = new IntStack(4);
268       m_parents = new IntStack(4);
269     }
270     else
271     {
272       m_data = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS);
273       m_dataOrQName = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS);
274       m_valuesOrPrefixes = new DTMStringPool();
275       m_chars = new FastStringBuffer(10, 13);
276       m_contextIndexes = new IntStack();
277       m_parents = new IntStack();
278     }
279          
280     // %REVIEW% Initial size pushed way down to reduce weight of RTFs
281
// (I'm not entirely sure 0 would work, so I'm playing it safe for now.)
282
//m_data = new SuballocatedIntVector(doIndexing ? (1024*2) : 512, 1024);
283
//m_data = new SuballocatedIntVector(blocksize);
284

285     m_data.addElement(0); // Need placeholder in case index into here must be <0.
286

287     //m_dataOrQName = new SuballocatedIntVector(blocksize);
288

289     // m_useSourceLocationProperty=com.sun.org.apache.xalan.internal.processor.TransformerFactoryImpl.m_source_location;
290
m_useSourceLocationProperty = m_source_location;
291     m_sourceSystemId = (m_useSourceLocationProperty) ? new StringVector() : null;
292     m_sourceLine = (m_useSourceLocationProperty) ? new IntVector() : null;
293     m_sourceColumn = (m_useSourceLocationProperty) ? new IntVector() : null;
294   }
295
296   /**
297    * Set whether information about document source location
298    * should be maintained or not.
299    */

300   public static void setUseSourceLocation(boolean useSourceLocation)
301   {
302     m_source_location = useSourceLocation;
303   }
304
305   /**
306    * Get the data or qualified name for the given node identity.
307    *
308    * @param identity The node identity.
309    *
310    * @return The data or qualified name, or DTM.NULL.
311    */

312   protected int _dataOrQName(int identity)
313   {
314
315     if (identity < m_size)
316       return m_dataOrQName.elementAt(identity);
317
318     // Check to see if the information requested has been processed, and,
319
// if not, advance the iterator until we the information has been
320
// processed.
321
while (true)
322     {
323       boolean isMore = nextNode();
324
325       if (!isMore)
326         return NULL;
327       else if (identity < m_size)
328         return m_dataOrQName.elementAt(identity);
329     }
330   }
331
332   /**
333    * Ask the CoRoutine parser to doTerminate and clear the reference.
334    */

335   public void clearCoRoutine()
336   {
337     clearCoRoutine(true);
338   }
339
340   /**
341    * Ask the CoRoutine parser to doTerminate and clear the reference. If
342    * the CoRoutine parser has already been cleared, this will have no effect.
343    *
344    * @param callDoTerminate true of doTerminate should be called on the
345    * coRoutine parser.
346    */

347   public void clearCoRoutine(boolean callDoTerminate)
348   {
349
350     if (null != m_incrementalSAXSource)
351     {
352       if (callDoTerminate)
353         m_incrementalSAXSource.deliverMoreNodes(false);
354
355       m_incrementalSAXSource = null;
356     }
357   }
358
359   /**
360    * Bind a IncrementalSAXSource to this DTM. If we discover we need nodes
361    * that have not yet been built, we will ask this object to send us more
362    * events, and it will manage interactions with its data sources.
363    *
364    * Note that we do not actually build the IncrementalSAXSource, since we don't
365    * know what source it's reading from, what thread that source will run in,
366    * or when it will run.
367    *
368    * @param incrementalSAXSource The parser that we want to recieve events from
369    * on demand.
370    * @param appCoRID The CoRoutine ID for the application.
371    */

372   public void setIncrementalSAXSource(IncrementalSAXSource incrementalSAXSource)
373   {
374
375     // Establish coroutine link so we can request more data
376
//
377
// Note: It's possible that some versions of IncrementalSAXSource may
378
// not actually use a CoroutineManager, and hence may not require
379
// that we obtain an Application Coroutine ID. (This relies on the
380
// coroutine transaction details having been encapsulated in the
381
// IncrementalSAXSource.do...() methods.)
382
m_incrementalSAXSource = incrementalSAXSource;
383
384     // Establish SAX-stream link so we can receive the requested data
385
incrementalSAXSource.setContentHandler(this);
386     incrementalSAXSource.setLexicalHandler(this);
387     incrementalSAXSource.setDTDHandler(this);
388
389     // Are the following really needed? incrementalSAXSource doesn't yet
390
// support them, and they're mostly no-ops here...
391
//incrementalSAXSource.setErrorHandler(this);
392
//incrementalSAXSource.setDeclHandler(this);
393
}
394
395   /**
396    * getContentHandler returns "our SAX builder" -- the thing that
397    * someone else should send SAX events to in order to extend this
398    * DTM model.
399    *
400    * %REVIEW% Should this return null if constrution already done/begun?
401    *
402    * @return null if this model doesn't respond to SAX events,
403    * "this" if the DTM object has a built-in SAX ContentHandler,
404    * the IncrementalSAXSource if we're bound to one and should receive
405    * the SAX stream via it for incremental build purposes...
406    *
407    * Note that IncrementalSAXSource_Filter is package private, hence
408    * it can't be statically referenced using instanceof (CR 6537912).
409    */

410   public ContentHandler getContentHandler()
411   {
412
413     if (m_incrementalSAXSource.getClass().getName().equals("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter"))
414       return (ContentHandler) m_incrementalSAXSource;
415     else
416       return this;
417   }
418
419   /**
420    * Return this DTM's lexical handler.
421    *
422    * %REVIEW% Should this return null if constrution already done/begun?
423    *
424    * @return null if this model doesn't respond to lexical SAX events,
425    * "this" if the DTM object has a built-in SAX ContentHandler,
426    * the IncrementalSAXSource if we're bound to one and should receive
427    * the SAX stream via it for incremental build purposes...
428    *
429    * Note that IncrementalSAXSource_Filter is package private, hence
430    * it can't be statically referenced using instanceof (CR 6537912).
431    */

432   public LexicalHandler getLexicalHandler()
433   {
434
435     if (m_incrementalSAXSource.getClass().getName().equals("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter"))
436       return (LexicalHandler) m_incrementalSAXSource;
437     else
438       return this;
439   }
440
441   /**
442    * Return this DTM's EntityResolver.
443    *
444    * @return null if this model doesn't respond to SAX entity ref events.
445    */

446   public EntityResolver getEntityResolver()
447   {
448     return this;
449   }
450
451   /**
452    * Return this DTM's DTDHandler.
453    *
454    * @return null if this model doesn't respond to SAX dtd events.
455    */

456   public DTDHandler getDTDHandler()
457   {
458     return this;
459   }
460
461   /**
462    * Return this DTM's ErrorHandler.
463    *
464    * @return null if this model doesn't respond to SAX error events.
465    */

466   public ErrorHandler getErrorHandler()
467   {
468     return this;
469   }
470
471   /**
472    * Return this DTM's DeclHandler.
473    *
474    * @return null if this model doesn't respond to SAX Decl events.
475    */

476   public DeclHandler getDeclHandler()
477   {
478     return this;
479   }
480
481   /**
482    * @return true iff we're building this model incrementally (eg
483    * we're partnered with a IncrementalSAXSource) and thus require that the
484    * transformation and the parse run simultaneously. Guidance to the
485    * DTMManager.
486    */

487   public boolean needsTwoThreads()
488   {
489     return null != m_incrementalSAXSource;
490   }
491
492   /**
493    * Directly call the
494    * characters method on the passed ContentHandler for the
495    * string-value of the given node (see http://www.w3.org/TR/xpath#data-model
496    * for the definition of a node's string-value). Multiple calls to the
497    * ContentHandler's characters methods may well occur for a single call to
498    * this method.
499    *
500    * @param nodeHandle The node ID.
501    * @param ch A non-null reference to a ContentHandler.
502    * @param normalize true if the content should be normalized according to
503    * the rules for the XPath
504    * <a HREF="http://www.w3.org/TR/xpath#function-normalize-space">normalize-space</a>
505    * function.
506    *
507    * @throws SAXException
508    */

509   public void dispatchCharactersEvents(int nodeHandle, ContentHandler ch,
510                                        boolean normalize)
511           throws SAXException
512   {
513
514     int identity = makeNodeIdentity(nodeHandle);
515     
516     if (identity == DTM.NULL)
517       return;
518     
519     int type = _type(identity);
520
521     if (isTextType(type))
522     {
523       int dataIndex = m_dataOrQName.elementAt(identity);
524       int offset = m_data.elementAt(dataIndex);
525       int length = m_data.elementAt(dataIndex + 1);
526
527       if(normalize)
528         m_chars.sendNormalizedSAXcharacters(ch, offset, length);
529       else
530         m_chars.sendSAXcharacters(ch, offset, length);
531     }
532     else
533     {
534       int firstChild = _firstch(identity);
535
536       if (DTM.NULL != firstChild)
537       {
538         int offset = -1;
539         int length = 0;
540         int startNode = identity;
541
542         identity = firstChild;
543
544         do {
545           type = _type(identity);
546
547           if (isTextType(type))
548           {
549             int dataIndex = _dataOrQName(identity);
550
551             if (-1 == offset)
552             {
553               offset = m_data.elementAt(dataIndex);
554             }
555
556             length += m_data.elementAt(dataIndex + 1);
557           }
558
559           identity = getNextNodeIdentity(identity);
560         } while (DTM.NULL != identity && (_parent(identity) >= startNode));
561
562         if (length > 0)
563         {
564           if(normalize)
565             m_chars.sendNormalizedSAXcharacters(ch, offset, length);
566           else
567             m_chars.sendSAXcharacters(ch, offset, length);
568         }
569       }
570       else if(type != DTM.ELEMENT_NODE)
571       {
572         int dataIndex = _dataOrQName(identity);
573
574         if (dataIndex < 0)
575         {
576           dataIndex = -dataIndex;
577           dataIndex = m_data.elementAt(dataIndex + 1);
578         }
579
580         String JavaDoc str = m_valuesOrPrefixes.indexToString(dataIndex);
581
582           if(normalize)
583             FastStringBuffer.sendNormalizedSAXcharacters(str.toCharArray(),
584                                                          0, str.length(), ch);
585           else
586             ch.characters(str.toCharArray(), 0, str.length());
587       }
588     }
589   }
590
591
592   /**
593    * Given a node handle, return its DOM-style node name. This will
594    * include names such as #text or #document.
595    *
596    * @param nodeHandle the id of the node.
597    * @return String Name of this node, which may be an empty string.
598    * %REVIEW% Document when empty string is possible...
599    * %REVIEW-COMMENT% It should never be empty, should it?
600    */

601   public String JavaDoc getNodeName(int nodeHandle)
602   {
603
604     int expandedTypeID = getExpandedTypeID(nodeHandle);
605     // If just testing nonzero, no need to shift...
606
int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
607
608     if (0 == namespaceID)
609     {
610       // Don't retrieve name until/unless needed
611
// String name = m_expandedNameTable.getLocalName(expandedTypeID);
612
int type = getNodeType(nodeHandle);
613
614       if (type == DTM.NAMESPACE_NODE)
615       {
616         if (null == m_expandedNameTable.getLocalName(expandedTypeID))
617           return "xmlns";
618         else
619           return "xmlns:" + m_expandedNameTable.getLocalName(expandedTypeID);
620       }
621       else if (0 == m_expandedNameTable.getLocalNameID(expandedTypeID))
622       {
623         return m_fixednames[type];
624       }
625       else
626         return m_expandedNameTable.getLocalName(expandedTypeID);
627     }
628     else
629     {
630       int qnameIndex = m_dataOrQName.elementAt(makeNodeIdentity(nodeHandle));
631
632       if (qnameIndex < 0)
633       {
634         qnameIndex = -qnameIndex;
635         qnameIndex = m_data.elementAt(qnameIndex);
636       }
637
638       return m_valuesOrPrefixes.indexToString(qnameIndex);
639     }
640   }
641
642   /**
643    * Given a node handle, return the XPath node name. This should be
644    * the name as described by the XPath data model, NOT the DOM-style
645    * name.
646    *
647    * @param nodeHandle the id of the node.
648    * @return String Name of this node, which may be an empty string.
649    */

650   public String JavaDoc getNodeNameX(int nodeHandle)
651   {
652
653     int expandedTypeID = getExpandedTypeID(nodeHandle);
654     int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
655
656     if (0 == namespaceID)
657     {
658       String JavaDoc name = m_expandedNameTable.getLocalName(expandedTypeID);
659
660       if (name == null)
661         return "";
662       else
663         return name;
664     }
665     else
666     {
667       int qnameIndex = m_dataOrQName.elementAt(makeNodeIdentity(nodeHandle));
668
669       if (qnameIndex < 0)
670       {
671         qnameIndex = -qnameIndex;
672         qnameIndex = m_data.elementAt(qnameIndex);
673       }
674
675       return m_valuesOrPrefixes.indexToString(qnameIndex);
676     }
677   }
678
679   /**
680    * 5. [specified] A flag indicating whether this attribute was actually
681    * specified in the start-tag of its element, or was defaulted from the
682    * DTD.
683    *
684    * @param the attribute handle
685    *
686    * @param attributeHandle Must be a valid handle to an attribute node.
687    * @return <code>true</code> if the attribute was specified;
688    * <code>false</code> if it was defaulted.
689    */

690   public boolean isAttributeSpecified(int attributeHandle)
691   {
692
693     // I'm not sure if I want to do anything with this...
694
return true; // ??
695
}
696
697   /**
698    * A document type declaration information item has the following properties:
699    *
700    * 1. [system identifier] The system identifier of the external subset, if
701    * it exists. Otherwise this property has no value.
702    *
703    * @return the system identifier String object, or null if there is none.
704    */

705   public String JavaDoc getDocumentTypeDeclarationSystemIdentifier()
706   {
707
708     /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */
709     error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");
710

711     return null;
712   }
713
714   /**
715    * Get the next node identity value in the list, and call the iterator
716    * if it hasn't been added yet.
717    *
718    * @param identity The node identity (index).
719    * @return identity+1, or DTM.NULL.
720    */

721   protected int getNextNodeIdentity(int identity)
722   {
723
724     identity += 1;
725
726     while (identity >= m_size)
727     {
728       if (null == m_incrementalSAXSource)
729         return DTM.NULL;
730
731       nextNode();
732     }
733
734     return identity;
735   }
736
737   /**
738    * Directly create SAX parser events from a subtree.
739    *
740    * @param nodeHandle The node ID.
741    * @param ch A non-null reference to a ContentHandler.
742    *
743    * @throws org.xml.sax.SAXException
744    */

745   public void dispatchToEvents(int nodeHandle, org.xml.sax.ContentHandler JavaDoc ch)
746           throws org.xml.sax.SAXException JavaDoc
747   {
748
749     DTMTreeWalker treeWalker = m_walker;
750     ContentHandler prevCH = treeWalker.getcontentHandler();
751
752     if (null != prevCH)
753     {
754       treeWalker = new DTMTreeWalker();
755     }
756
757     treeWalker.setcontentHandler(ch);
758     treeWalker.setDTM(this);
759
760     try
761     {
762       treeWalker.traverse(nodeHandle);
763     }
764     finally
765     {
766       treeWalker.setcontentHandler(null);
767     }
768   }
769
770   /**
771    * Get the number of nodes that have been added.
772    *
773    * @return The number of that are currently in the tree.
774    */

775   public int getNumberOfNodes()
776   {
777     return m_size;
778   }
779
780   /**
781    * This method should try and build one or more nodes in the table.
782    *
783    * @return The true if a next node is found or false if
784    * there are no more nodes.
785    */

786   protected boolean nextNode()
787   {
788
789     if (null == m_incrementalSAXSource)
790       return false;
791
792     if (m_endDocumentOccured)
793     {
794       clearCoRoutine();
795
796       return false;
797     }
798
799     Object JavaDoc gotMore = m_incrementalSAXSource.deliverMoreNodes(true);
800
801     // gotMore may be a Boolean (TRUE if still parsing, FALSE if
802
// EOF) or an exception if IncrementalSAXSource malfunctioned
803
// (code error rather than user error).
804
//
805
// %REVIEW% Currently the ErrorHandlers sketched herein are
806
// no-ops, so I'm going to initially leave this also as a
807
// no-op.
808
if (!(gotMore instanceof Boolean JavaDoc))
809     {
810       if(gotMore instanceof RuntimeException JavaDoc)
811       {
812         throw (RuntimeException JavaDoc)gotMore;
813       }
814       else if(gotMore instanceof Exception JavaDoc)
815       {
816         throw new WrappedRuntimeException((Exception JavaDoc)gotMore);
817       }
818       // for now...
819
clearCoRoutine();
820
821       return false;
822
823       // %TBD%
824
}
825
826     if (gotMore != Boolean.TRUE)
827     {
828
829       // EOF reached without satisfying the request
830
clearCoRoutine(); // Drop connection, stop trying
831

832       // %TBD% deregister as its listener?
833
}
834
835     return true;
836   }
837
838   /**
839    * Bottleneck determination of text type.
840    *
841    * @param type oneof DTM.XXX_NODE.
842    *
843    * @return true if this is a text or cdata section.
844    */

845   private final boolean isTextType(int type)
846   {
847     return (DTM.TEXT_NODE == type || DTM.CDATA_SECTION_NODE == type);
848   }
849
850 // /**
851
// * Ensure that the size of the information arrays can hold another entry
852
// * at the given index.
853
// *
854
// * @param on exit from this function, the information arrays sizes must be
855
// * at least index+1.
856
// *
857
// * NEEDSDOC @param index
858
// */
859
// protected void ensureSize(int index)
860
// {
861
// // dataOrQName is an SuballocatedIntVector and hence self-sizing.
862
// // But DTMDefaultBase may need fixup.
863
// super.ensureSize(index);
864
// }
865

866   /**
867    * Construct the node map from the node.
868    *
869    * @param type raw type ID, one of DTM.XXX_NODE.
870    * @param expandedTypeID The expended type ID.
871    * @param parentIndex The current parent index.
872    * @param previousSibling The previous sibling index.
873    * @param dataOrPrefix index into m_data table, or string handle.
874    * @param canHaveFirstChild true if the node can have a first child, false
875    * if it is atomic.
876    *
877    * @return The index identity of the node that was added.
878    */

879   protected int addNode(int type, int expandedTypeID,
880                         int parentIndex, int previousSibling,
881                         int dataOrPrefix, boolean canHaveFirstChild)
882   {
883     // Common to all nodes:
884
int nodeIndex = m_size++;
885
886     // Have we overflowed a DTM Identity's addressing range?
887
if(m_dtmIdent.size() == (nodeIndex>>>DTMManager.IDENT_DTM_NODE_BITS))
888     {
889       addNewDTMID(nodeIndex);
890     }
891
892     m_firstch.addElement(canHaveFirstChild ? NOTPROCESSED : DTM.NULL);
893     m_nextsib.addElement(NOTPROCESSED);
894     m_parent.addElement(parentIndex);
895     m_exptype.addElement(expandedTypeID);
896     m_dataOrQName.addElement(dataOrPrefix);
897
898     if (m_prevsib != null) {
899       m_prevsib.addElement(previousSibling);
900     }
901
902     if (DTM.NULL != previousSibling) {
903       m_nextsib.setElementAt(nodeIndex,previousSibling);
904     }
905
906     if (m_locator != null && m_useSourceLocationProperty) {
907       setSourceLocation();
908     }
909
910     // Note that nextSibling is not processed until charactersFlush()
911
// is called, to handle successive characters() events.
912

913     // Special handling by type: Declare namespaces, attach first child
914
switch(type)
915     {
916     case DTM.NAMESPACE_NODE:
917       declareNamespaceInContext(parentIndex,nodeIndex);
918       break;
919     case DTM.ATTRIBUTE_NODE:
920       break;
921     default:
922       if (DTM.NULL == previousSibling && DTM.NULL != parentIndex) {
923         m_firstch.setElementAt(nodeIndex,parentIndex);
924       }
925       break;
926     }
927
928     return nodeIndex;
929   }
930
931   /**
932    * Get a new DTM ID beginning at the specified node index.
933    * @param nodeIndex The node identity at which the new DTM ID will begin
934    * addressing.
935    */

936   protected void addNewDTMID(int nodeIndex) {
937     try
938     {
939       if(m_mgr==null)
940         throw new ClassCastException JavaDoc();
941                               
942                               // Handle as Extended Addressing
943
DTMManagerDefault mgrD=(DTMManagerDefault)m_mgr;
944       int id=mgrD.getFirstFreeDTMID();
945       mgrD.addDTM(this,id,nodeIndex);
946       m_dtmIdent.addElement(id<<DTMManager.IDENT_DTM_NODE_BITS);
947     }
948     catch(ClassCastException JavaDoc e)
949     {
950       // %REVIEW% Wrong error message, but I've been told we're trying
951
// not to add messages right not for I18N reasons.
952
// %REVIEW% Should this be a Fatal Error?
953
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_NO_DTMIDS_AVAIL, null));//"No more DTM IDs are available";
954
}
955   }
956
957   /**
958     * Migrate a DTM built with an old DTMManager to a new DTMManager.
959     * After the migration, the new DTMManager will treat the DTM as
960     * one that is built by itself.
961     * This is used to support DTM sharing between multiple transformations.
962     * @param manager the DTMManager
963     */

964   public void migrateTo(DTMManager manager) {
965     super.migrateTo(manager);
966     
967     // We have to reset the information in m_dtmIdent and
968
// register the DTM with the new manager.
969
int numDTMs = m_dtmIdent.size();
970     int dtmId = m_mgrDefault.getFirstFreeDTMID();
971     int nodeIndex = 0;
972     for (int i = 0; i < numDTMs; i++)
973     {
974       m_dtmIdent.setElementAt(dtmId << DTMManager.IDENT_DTM_NODE_BITS, i);
975       m_mgrDefault.addDTM(this, dtmId, nodeIndex);
976       dtmId++;
977       nodeIndex += (1 << DTMManager.IDENT_DTM_NODE_BITS);
978     }
979   }
980
981   /**
982    * Store the source location of the current node. This method must be called
983    * as every node is added to the DTM or for no node.
984    */

985   protected void setSourceLocation() {
986     m_sourceSystemId.addElement(m_locator.getSystemId());
987     m_sourceLine.addElement(m_locator.getLineNumber());
988     m_sourceColumn.addElement(m_locator.getColumnNumber());
989
990     //%REVIEW% %BUG% Prevent this from arising in the first place
991
// by not allowing the enabling conditions to change after we start
992
// building the document.
993
if (m_sourceSystemId.size() != m_size) {
994         System.err.println("CODING ERROR in Source Location: " + m_size
995                            + " != "
996                             + m_sourceSystemId.size());
997         System.exit(1);
998     }
999   }
1000
1001  /**
1002   * Given a node handle, return its node value. This is mostly
1003   * as defined by the DOM, but may ignore some conveniences.
1004   * <p>
1005   *
1006   * @param nodeHandle The node id.
1007   * @return String Value of this node, or null if not
1008   * meaningful for this node type.
1009   */

1010  public String JavaDoc getNodeValue(int nodeHandle)
1011  {
1012
1013    int identity = makeNodeIdentity(nodeHandle);
1014    int type = _type(identity);
1015
1016    if (isTextType(type))
1017    {
1018      int dataIndex = _dataOrQName(identity);
1019      int offset = m_data.elementAt(dataIndex);
1020      int length = m_data.elementAt(dataIndex + 1);
1021
1022      // %OPT% We should cache this, I guess.
1023
return m_chars.getString(offset, length);
1024    }
1025    else if (DTM.ELEMENT_NODE == type || DTM.DOCUMENT_FRAGMENT_NODE == type
1026             || DTM.DOCUMENT_NODE == type)
1027    {
1028      return null;
1029    }
1030    else
1031    {
1032      int dataIndex = _dataOrQName(identity);
1033
1034      if (dataIndex < 0)
1035      {
1036        dataIndex = -dataIndex;
1037        dataIndex = m_data.elementAt(dataIndex + 1);
1038      }
1039
1040      return m_valuesOrPrefixes.indexToString(dataIndex);
1041    }
1042  }
1043
1044  /**
1045   * Given a node handle, return its XPath-style localname.
1046   * (As defined in Namespaces, this is the portion of the name after any
1047   * colon character).
1048   *
1049   * @param nodeHandle the id of the node.
1050   * @return String Local name of this node.
1051   */

1052  public String JavaDoc getLocalName(int nodeHandle)
1053  {
1054    return m_expandedNameTable.getLocalName(_exptype(makeNodeIdentity(nodeHandle)));
1055  }
1056
1057  /**
1058   * The getUnparsedEntityURI function returns the URI of the unparsed
1059   * entity with the specified name in the same document as the context
1060   * node (see [3.3 Unparsed Entities]). It returns the empty string if
1061   * there is no such entity.
1062   * <p>
1063   * XML processors may choose to use the System Identifier (if one
1064   * is provided) to resolve the entity, rather than the URI in the
1065   * Public Identifier. The details are dependent on the processor, and
1066   * we would have to support some form of plug-in resolver to handle
1067   * this properly. Currently, we simply return the System Identifier if
1068   * present, and hope that it a usable URI or that our caller can
1069   * map it to one.
1070   * TODO: Resolve Public Identifiers... or consider changing function name.
1071   * <p>
1072   * If we find a relative URI
1073   * reference, XML expects it to be resolved in terms of the base URI
1074   * of the document. The DOM doesn't do that for us, and it isn't
1075   * entirely clear whether that should be done here; currently that's
1076   * pushed up to a higher level of our application. (Note that DOM Level
1077   * 1 didn't store the document's base URI.)
1078   * TODO: Consider resolving Relative URIs.
1079   * <p>
1080   * (The DOM's statement that "An XML processor may choose to
1081   * completely expand entities before the structure model is passed
1082   * to the DOM" refers only to parsed entities, not unparsed, and hence
1083   * doesn't affect this function.)
1084   *
1085   * @param name A string containing the Entity Name of the unparsed
1086   * entity.
1087   *
1088   * @return String containing the URI of the Unparsed Entity, or an
1089   * empty string if no such entity exists.
1090   */

1091  public String JavaDoc getUnparsedEntityURI(String JavaDoc name)
1092  {
1093
1094    String JavaDoc url = "";
1095
1096    if (null == m_entities)
1097      return url;
1098
1099    int n = m_entities.size();
1100
1101    for (int i = 0; i < n; i += ENTITY_FIELDS_PER)
1102    {
1103      String JavaDoc ename = (String JavaDoc) m_entities.elementAt(i + ENTITY_FIELD_NAME);
1104
1105      if (null != ename && ename.equals(name))
1106      {
1107        String JavaDoc nname = (String JavaDoc) m_entities.elementAt(i
1108                         + ENTITY_FIELD_NOTATIONNAME);
1109
1110        if (null != nname)
1111        {
1112
1113          // The draft says: "The XSLT processor may use the public
1114
// identifier to generate a URI for the entity instead of the URI
1115
// specified in the system identifier. If the XSLT processor does
1116
// not use the public identifier to generate the URI, it must use
1117
// the system identifier; if the system identifier is a relative
1118
// URI, it must be resolved into an absolute URI using the URI of
1119
// the resource containing the entity declaration as the base
1120
// URI [RFC2396]."
1121
// So I'm falling a bit short here.
1122
url = (String JavaDoc) m_entities.elementAt(i + ENTITY_FIELD_SYSTEMID);
1123
1124          if (null == url)
1125          {
1126            url = (String JavaDoc) m_entities.elementAt(i + ENTITY_FIELD_PUBLICID);
1127          }
1128        }
1129
1130        break;
1131      }
1132    }
1133
1134    return url;
1135  }
1136
1137  /**
1138   * Given a namespace handle, return the prefix that the namespace decl is
1139   * mapping.
1140   * Given a node handle, return the prefix used to map to the namespace.
1141   *
1142   * <p> %REVIEW% Are you sure you want "" for no prefix? </p>
1143   * <p> %REVIEW-COMMENT% I think so... not totally sure. -sb </p>
1144   *
1145   * @param nodeHandle the id of the node.
1146   * @return String prefix of this node's name, or "" if no explicit
1147   * namespace prefix was given.
1148   */

1149  public String JavaDoc getPrefix(int nodeHandle)
1150  {
1151
1152    int identity = makeNodeIdentity(nodeHandle);
1153    int type = _type(identity);
1154
1155    if (DTM.ELEMENT_NODE == type)
1156    {
1157      int prefixIndex = _dataOrQName(identity);
1158
1159      if (0 == prefixIndex)
1160        return "";
1161      else
1162      {
1163        String JavaDoc qname = m_valuesOrPrefixes.indexToString(prefixIndex);
1164
1165        return getPrefix(qname, null);
1166      }
1167    }
1168    else if (DTM.ATTRIBUTE_NODE == type)
1169    {
1170      int prefixIndex = _dataOrQName(identity);
1171
1172      if (prefixIndex < 0)
1173      {
1174        prefixIndex = m_data.elementAt(-prefixIndex);
1175
1176        String JavaDoc qname = m_valuesOrPrefixes.indexToString(prefixIndex);
1177
1178        return getPrefix(qname, null);
1179      }
1180    }
1181
1182    return "";
1183  }
1184
1185  /**
1186   * Retrieves an attribute node by by qualified name and namespace URI.
1187   *
1188   * @param nodeHandle int Handle of the node upon which to look up this attribute..
1189   * @param namespaceURI The namespace URI of the attribute to
1190   * retrieve, or null.
1191   * @param name The local name of the attribute to
1192   * retrieve.
1193   * @return The attribute node handle with the specified name (
1194   * <code>nodeName</code>) or <code>DTM.NULL</code> if there is no such
1195   * attribute.
1196   */

1197  public int getAttributeNode(int nodeHandle, String JavaDoc namespaceURI,
1198                              String JavaDoc name)
1199  {
1200
1201    for (int attrH = getFirstAttribute(nodeHandle); DTM.NULL != attrH;
1202            attrH = getNextAttribute(attrH))
1203    {
1204      String JavaDoc attrNS = getNamespaceURI(attrH);
1205      String JavaDoc attrName = getLocalName(attrH);
1206      boolean nsMatch = namespaceURI == attrNS
1207                        || (namespaceURI != null
1208                            && namespaceURI.equals(attrNS));
1209
1210      if (nsMatch && name.equals(attrName))
1211        return attrH;
1212    }
1213
1214    return DTM.NULL;
1215  }
1216
1217  /**
1218   * Return the public identifier of the external subset,
1219   * normalized as described in 4.2.2 External Entities [XML]. If there is
1220   * no external subset or if it has no public identifier, this property
1221   * has no value.
1222   *
1223   * @param the document type declaration handle
1224   *
1225   * @return the public identifier String object, or null if there is none.
1226   */

1227  public String JavaDoc getDocumentTypeDeclarationPublicIdentifier()
1228  {
1229
1230    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */
1231    error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");
1232

1233    return null;
1234  }
1235
1236  /**
1237   * Given a node handle, return its DOM-style namespace URI
1238   * (As defined in Namespaces, this is the declared URI which this node's
1239   * prefix -- or default in lieu thereof -- was mapped to.)
1240   *
1241   * <p>%REVIEW% Null or ""? -sb</p>
1242   *
1243   * @param nodeHandle the id of the node.
1244   * @return String URI value of this node's namespace, or null if no
1245   * namespace was resolved.
1246   */

1247  public String JavaDoc getNamespaceURI(int nodeHandle)
1248  {
1249
1250    return m_expandedNameTable.getNamespace(_exptype(makeNodeIdentity(nodeHandle)));
1251  }
1252
1253  /**
1254   * Get the string-value of a node as a String object
1255   * (see http://www.w3.org/TR/xpath#data-model
1256   * for the definition of a node's string-value).
1257   *
1258   * @param nodeHandle The node ID.
1259   *
1260   * @return A string object that represents the string-value of the given node.
1261   */

1262  public XMLString getStringValue(int nodeHandle)
1263  {
1264    int identity = makeNodeIdentity(nodeHandle);
1265    int type;
1266    if(identity==DTM.NULL) // Separate lines because I wanted to breakpoint it
1267
type = DTM.NULL;
1268    else
1269      type= _type(identity);
1270
1271    if (isTextType(type))
1272    {
1273      int dataIndex = _dataOrQName(identity);
1274      int offset = m_data.elementAt(dataIndex);
1275      int length = m_data.elementAt(dataIndex + 1);
1276
1277      return m_xstrf.newstr(m_chars, offset, length);
1278    }
1279    else
1280    {
1281      int firstChild = _firstch(identity);
1282
1283      if (DTM.NULL != firstChild)
1284      {
1285        int offset = -1;
1286        int length = 0;
1287        int startNode = identity;
1288
1289        identity = firstChild;
1290
1291        do {
1292          type = _type(identity);
1293
1294          if (isTextType(type))
1295          {
1296            int dataIndex = _dataOrQName(identity);
1297
1298            if (-1 == offset)
1299            {
1300              offset = m_data.elementAt(dataIndex);
1301            }
1302
1303            length += m_data.elementAt(dataIndex + 1);
1304          }
1305
1306          identity = getNextNodeIdentity(identity);
1307        } while (DTM.NULL != identity && (_parent(identity) >= startNode));
1308
1309        if (length > 0)
1310        {
1311          return m_xstrf.newstr(m_chars, offset, length);
1312        }
1313      }
1314      else if(type != DTM.ELEMENT_NODE)
1315      {
1316        int dataIndex = _dataOrQName(identity);
1317
1318        if (dataIndex < 0)
1319        {
1320          dataIndex = -dataIndex;
1321          dataIndex = m_data.elementAt(dataIndex + 1);
1322        }
1323        return m_xstrf.newstr(m_valuesOrPrefixes.indexToString(dataIndex));
1324      }
1325    }
1326
1327    return m_xstrf.emptystr();
1328  }
1329  
1330  /**
1331   * Determine if the string-value of a node is whitespace
1332   *
1333   * @param nodeHandle The node Handle.
1334   *
1335   * @return Return true if the given node is whitespace.
1336   */

1337  public boolean isWhitespace(int nodeHandle)
1338  {
1339    int identity = makeNodeIdentity(nodeHandle);
1340    int type;
1341    if(identity==DTM.NULL) // Separate lines because I wanted to breakpoint it
1342
type = DTM.NULL;
1343    else
1344      type= _type(identity);
1345
1346    if (isTextType(type))
1347    {
1348      int dataIndex = _dataOrQName(identity);
1349      int offset = m_data.elementAt(dataIndex);
1350      int length = m_data.elementAt(dataIndex + 1);
1351
1352      return m_chars.isWhitespace(offset, length);
1353    }
1354    return false;
1355  }
1356
1357  /**
1358   * Returns the <code>Element</code> whose <code>ID</code> is given by
1359   * <code>elementId</code>. If no such element exists, returns
1360   * <code>DTM.NULL</code>. Behavior is not defined if more than one element
1361   * has this <code>ID</code>. Attributes (including those
1362   * with the name "ID") are not of type ID unless so defined by DTD/Schema
1363   * information available to the DTM implementation.
1364   * Implementations that do not know whether attributes are of type ID or
1365   * not are expected to return <code>DTM.NULL</code>.
1366   *
1367   * <p>%REVIEW% Presumably IDs are still scoped to a single document,
1368   * and this operation searches only within a single document, right?
1369   * Wouldn't want collisions between DTMs in the same process.</p>
1370   *
1371   * @param elementId The unique <code>id</code> value for an element.
1372   * @return The handle of the matching element.
1373   */

1374  public int getElementById(String JavaDoc elementId)
1375  {
1376
1377    Integer JavaDoc intObj;
1378    boolean isMore = true;
1379
1380    do
1381    {
1382      intObj = (Integer JavaDoc) m_idAttributes.get(elementId);
1383
1384      if (null != intObj)
1385        return makeNodeHandle(intObj.intValue());
1386
1387      if (!isMore || m_endDocumentOccured)
1388        break;
1389
1390      isMore = nextNode();
1391    }
1392    while (null == intObj);
1393
1394    return DTM.NULL;
1395  }
1396
1397  /**
1398   * Get a prefix either from the qname or from the uri mapping, or just make
1399   * one up!
1400   *
1401   * @param qname The qualified name, which may be null.
1402   * @param uri The namespace URI, which may be null.
1403   *
1404   * @return The prefix if there is one, or null.
1405   */

1406  public String JavaDoc getPrefix(String JavaDoc qname, String JavaDoc uri)
1407  {
1408
1409    String JavaDoc prefix;
1410    int uriIndex = -1;
1411
1412    if (null != uri && uri.length() > 0)
1413    {
1414
1415      do
1416      {
1417        uriIndex = m_prefixMappings.indexOf(uri, ++uriIndex);
1418      } while ( (uriIndex & 0x01) == 0);
1419
1420      if (uriIndex >= 0)
1421      {
1422        prefix = (String JavaDoc) m_prefixMappings.elementAt(uriIndex - 1);
1423      }
1424      else if (null != qname)
1425      {
1426        int indexOfNSSep = qname.indexOf(':');
1427
1428        if (qname.equals("xmlns"))
1429          prefix = "";
1430        else if (qname.startsWith("xmlns:"))
1431          prefix = qname.substring(indexOfNSSep + 1);
1432        else
1433          prefix = (indexOfNSSep > 0)
1434                   ? qname.substring(0, indexOfNSSep) : null;
1435      }
1436      else
1437      {
1438        prefix = null;
1439      }
1440    }
1441    else if (null != qname)
1442    {
1443      int indexOfNSSep = qname.indexOf(':');
1444
1445      if (indexOfNSSep > 0)
1446      {
1447        if (qname.startsWith("xmlns:"))
1448          prefix = qname.substring(indexOfNSSep + 1);
1449        else
1450          prefix = qname.substring(0, indexOfNSSep);
1451      }
1452      else
1453      {
1454        if (qname.equals("xmlns"))
1455          prefix = "";
1456        else
1457          prefix = null;
1458      }
1459    }
1460    else
1461    {
1462      prefix = null;
1463    }
1464
1465    return prefix;
1466  }
1467  
1468  /**
1469   * Get a prefix either from the uri mapping, or just make
1470   * one up!
1471   *
1472   * @param uri The namespace URI, which may be null.
1473   *
1474   * @return The prefix if there is one, or null.
1475   */

1476  public int getIdForNamespace(String JavaDoc uri)
1477  {
1478
1479     return m_valuesOrPrefixes.stringToIndex(uri);
1480    
1481  }
1482
1483    /**
1484   * Get a prefix either from the qname or from the uri mapping, or just make
1485   * one up!
1486   *
1487   * @param qname The qualified name, which may be null.
1488   * @param uri The namespace URI, which may be null.
1489   *
1490   * @return The prefix if there is one, or null.
1491   */

1492  public String JavaDoc getNamespaceURI(String JavaDoc prefix)
1493  {
1494
1495    String JavaDoc uri = "";
1496    int prefixIndex = m_contextIndexes.peek() - 1 ;
1497
1498    if(null == prefix)
1499      prefix = "";
1500
1501      do
1502      {
1503        prefixIndex = m_prefixMappings.indexOf(prefix, ++prefixIndex);
1504      } while ( (prefixIndex >= 0) && (prefixIndex & 0x01) == 0x01);
1505
1506      if (prefixIndex > -1)
1507      {
1508        uri = (String JavaDoc) m_prefixMappings.elementAt(prefixIndex + 1);
1509      }
1510
1511
1512    return uri;
1513  }
1514
1515  /**
1516   * Set an ID string to node association in the ID table.
1517   *
1518   * @param id The ID string.
1519   * @param elem The associated element handle.
1520   */

1521  public void setIDAttribute(String JavaDoc id, int elem)
1522  {
1523    m_idAttributes.put(id, new Integer JavaDoc(elem));
1524  }
1525
1526  /**
1527   * Check whether accumulated text should be stripped; if not,
1528   * append the appropriate flavor of text/cdata node.
1529   */

1530  protected void charactersFlush()
1531  {
1532
1533    if (m_textPendingStart >= 0) // -1 indicates no-text-in-progress
1534
{
1535      int length = m_chars.size() - m_textPendingStart;
1536      boolean doStrip = false;
1537
1538      if (getShouldStripWhitespace())
1539      {
1540        doStrip = m_chars.isWhitespace(m_textPendingStart, length);
1541      }
1542
1543      if (doStrip)
1544        m_chars.setLength(m_textPendingStart); // Discard accumulated text
1545
else
1546      {
1547        int exName = m_expandedNameTable.getExpandedTypeID(DTM.TEXT_NODE);
1548        int dataIndex = m_data.size();
1549
1550        m_previous = addNode(m_coalescedTextType, exName,
1551                             m_parents.peek(), m_previous, dataIndex, false);
1552
1553        m_data.addElement(m_textPendingStart);
1554        m_data.addElement(length);
1555      }
1556
1557      // Reset for next text block
1558
m_textPendingStart = -1;
1559      m_textType = m_coalescedTextType = DTM.TEXT_NODE;
1560    }
1561  }
1562
1563  ////////////////////////////////////////////////////////////////////
1564
// Implementation of the EntityResolver interface.
1565
////////////////////////////////////////////////////////////////////
1566

1567  /**
1568   * Resolve an external entity.
1569   *
1570   * <p>Always return null, so that the parser will use the system
1571   * identifier provided in the XML document. This method implements
1572   * the SAX default behaviour: application writers can override it
1573   * in a subclass to do special translations such as catalog lookups
1574   * or URI redirection.</p>
1575   *
1576   * @param publicId The public identifer, or null if none is
1577   * available.
1578   * @param systemId The system identifier provided in the XML
1579   * document.
1580   * @return The new input source, or null to require the
1581   * default behaviour.
1582   * @throws SAXException Any SAX exception, possibly
1583   * wrapping another exception.
1584   * @see org.xml.sax.EntityResolver#resolveEntity
1585   *
1586   * @throws SAXException
1587   */

1588  public InputSource resolveEntity(String JavaDoc publicId, String JavaDoc systemId)
1589          throws SAXException
1590  {
1591    return null;
1592  }
1593
1594  ////////////////////////////////////////////////////////////////////
1595
// Implementation of DTDHandler interface.
1596
////////////////////////////////////////////////////////////////////
1597

1598  /**
1599   * Receive notification of a notation declaration.
1600   *
1601   * <p>By default, do nothing. Application writers may override this
1602   * method in a subclass if they wish to keep track of the notations
1603   * declared in a document.</p>
1604   *
1605   * @param name The notation name.
1606   * @param publicId The notation public identifier, or null if not
1607   * available.
1608   * @param systemId The notation system identifier.
1609   * @throws SAXException Any SAX exception, possibly
1610   * wrapping another exception.
1611   * @see org.xml.sax.DTDHandler#notationDecl
1612   *
1613   * @throws SAXException
1614   */

1615  public void notationDecl(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId)
1616          throws SAXException
1617  {
1618
1619    // no op
1620
}
1621
1622  /**
1623   * Receive notification of an unparsed entity declaration.
1624   *
1625   * <p>By default, do nothing. Application writers may override this
1626   * method in a subclass to keep track of the unparsed entities
1627   * declared in a document.</p>
1628   *
1629   * @param name The entity name.
1630   * @param publicId The entity public identifier, or null if not
1631   * available.
1632   * @param systemId The entity system identifier.
1633   * @param notationName The name of the associated notation.
1634   * @throws SAXException Any SAX exception, possibly
1635   * wrapping another exception.
1636   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
1637   *
1638   * @throws SAXException
1639   */

1640  public void unparsedEntityDecl(
1641          String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId, String JavaDoc notationName)
1642            throws SAXException
1643  {
1644
1645    if (null == m_entities)
1646    {
1647      m_entities = new Vector JavaDoc();
1648    }
1649
1650    try
1651    {
1652      systemId = SystemIDResolver.getAbsoluteURI(systemId,
1653                                                 getDocumentBaseURI());
1654    }
1655    catch (Exception JavaDoc e)
1656    {
1657      throw new org.xml.sax.SAXException JavaDoc(e);
1658    }
1659
1660    // private static final int ENTITY_FIELD_PUBLICID = 0;
1661
m_entities.addElement(publicId);
1662
1663    // private static final int ENTITY_FIELD_SYSTEMID = 1;
1664
m_entities.addElement(systemId);
1665
1666    // private static final int ENTITY_FIELD_NOTATIONNAME = 2;
1667
m_entities.addElement(notationName);
1668
1669    // private static final int ENTITY_FIELD_NAME = 3;
1670
m_entities.addElement(name);
1671  }
1672
1673  ////////////////////////////////////////////////////////////////////
1674
// Implementation of ContentHandler interface.
1675
////////////////////////////////////////////////////////////////////
1676

1677  /**
1678   * Receive a Locator object for document events.
1679   *
1680   * <p>By default, do nothing. Application writers may override this
1681   * method in a subclass if they wish to store the locator for use
1682   * with other document events.</p>
1683   *
1684   * @param locator A locator for all SAX document events.
1685   * @see org.xml.sax.ContentHandler#setDocumentLocator
1686   * @see org.xml.sax.Locator
1687   */

1688  public void setDocumentLocator(Locator JavaDoc locator)
1689  {
1690    m_locator = locator;
1691    m_systemId = locator.getSystemId();
1692  }
1693
1694  /**
1695   * Receive notification of the beginning of the document.
1696   *
1697   * @throws SAXException Any SAX exception, possibly
1698   * wrapping another exception.
1699   * @see org.xml.sax.ContentHandler#startDocument
1700   */

1701  public void startDocument() throws SAXException
1702  {
1703    if (DEBUG)
1704      System.out.println("startDocument");
1705
1706        
1707    int doc = addNode(DTM.DOCUMENT_NODE,
1708                      m_expandedNameTable.getExpandedTypeID(DTM.DOCUMENT_NODE),
1709                      DTM.NULL, DTM.NULL, 0, true);
1710
1711    m_parents.push(doc);
1712    m_previous = DTM.NULL;
1713
1714    m_contextIndexes.push(m_prefixMappings.size()); // for the next element.
1715
}
1716
1717  /**
1718   * Receive notification of the end of the document.
1719   *
1720   * @throws SAXException Any SAX exception, possibly
1721   * wrapping another exception.
1722   * @see org.xml.sax.ContentHandler#endDocument
1723   */

1724  public void endDocument() throws SAXException
1725  {
1726    if (DEBUG)
1727      System.out.println("endDocument");
1728
1729        charactersFlush();
1730
1731    m_nextsib.setElementAt(NULL,0);
1732
1733    if (m_firstch.elementAt(0) == NOTPROCESSED)
1734      m_firstch.setElementAt(NULL,0);
1735
1736    if (DTM.NULL != m_previous)
1737      m_nextsib.setElementAt(DTM.NULL,m_previous);
1738
1739    m_parents = null;
1740    m_prefixMappings = null;
1741    m_contextIndexes = null;
1742
1743    m_endDocumentOccured = true;
1744    
1745    // Bugzilla 4858: throw away m_locator. we cache m_systemId
1746
m_locator = null;
1747  }
1748
1749  /**
1750   * Receive notification of the start of a Namespace mapping.
1751   *
1752   * <p>By default, do nothing. Application writers may override this
1753   * method in a subclass to take specific actions at the start of
1754   * each Namespace prefix scope (such as storing the prefix mapping).</p>
1755   *
1756   * @param prefix The Namespace prefix being declared.
1757   * @param uri The Namespace URI mapped to the prefix.
1758   * @throws SAXException Any SAX exception, possibly
1759   * wrapping another exception.
1760   * @see org.xml.sax.ContentHandler#startPrefixMapping
1761   */

1762  public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri)
1763          throws SAXException
1764  {
1765
1766    if (DEBUG)
1767      System.out.println("startPrefixMapping: prefix: " + prefix + ", uri: "
1768                         + uri);
1769
1770    if(null == prefix)
1771      prefix = "";
1772    m_prefixMappings.addElement(prefix); // JDK 1.1.x compat -sc
1773
m_prefixMappings.addElement(uri); // JDK 1.1.x compat -sc
1774
}
1775
1776  /**
1777   * Receive notification of the end of a Namespace mapping.
1778   *
1779   * <p>By default, do nothing. Application writers may override this
1780   * method in a subclass to take specific actions at the end of
1781   * each prefix mapping.</p>
1782   *
1783   * @param prefix The Namespace prefix being declared.
1784   * @throws SAXException Any SAX exception, possibly
1785   * wrapping another exception.
1786   * @see org.xml.sax.ContentHandler#endPrefixMapping
1787   */

1788  public void endPrefixMapping(String JavaDoc prefix) throws SAXException
1789  {
1790    if (DEBUG)
1791      System.out.println("endPrefixMapping: prefix: " + prefix);
1792
1793    if(null == prefix)
1794      prefix = "";
1795
1796    int index = m_contextIndexes.peek() - 1;
1797
1798    do
1799    {
1800      index = m_prefixMappings.indexOf(prefix, ++index);
1801    } while ( (index >= 0) && ((index & 0x01) == 0x01) );
1802
1803
1804    if (index > -1)
1805    {
1806      m_prefixMappings.setElementAt("%@$#^@#", index);
1807      m_prefixMappings.setElementAt("%@$#^@#", index + 1);
1808    }
1809
1810    // no op
1811
}
1812
1813  /**
1814   * Check if a declaration has already been made for a given prefix.
1815   *
1816   * @param prefix non-null prefix string.
1817   *
1818   * @return true if the declaration has already been declared in the
1819   * current context.
1820   */

1821  protected boolean declAlreadyDeclared(String JavaDoc prefix)
1822  {
1823
1824    int startDecls = m_contextIndexes.peek();
1825    java.util.Vector JavaDoc prefixMappings = m_prefixMappings;
1826    int nDecls = prefixMappings.size();
1827
1828    for (int i = startDecls; i < nDecls; i += 2)
1829    {
1830      String JavaDoc prefixDecl = (String JavaDoc) prefixMappings.elementAt(i);
1831
1832      if (prefixDecl == null)
1833        continue;
1834
1835      if (prefixDecl.equals(prefix))
1836        return true;
1837    }
1838
1839    return false;
1840  }
1841
1842    boolean m_pastFirstElement=false;
1843
1844  /**
1845   * Receive notification of the start of an element.
1846   *
1847   * <p>By default, do nothing. Application writers may override this
1848   * method in a subclass to take specific actions at the start of
1849   * each element (such as allocating a new tree node or writing
1850   * output to a file).</p>
1851   *
1852   * @param name The element type name.
1853   *
1854   * @param uri The Namespace URI, or the empty string if the
1855   * element has no Namespace URI or if Namespace
1856   * processing is not being performed.
1857   * @param localName The local name (without prefix), or the
1858   * empty string if Namespace processing is not being
1859   * performed.
1860   * @param qName The qualified name (with prefix), or the
1861   * empty string if qualified names are not available.
1862   * @param attributes The specified or defaulted attributes.
1863   * @throws SAXException Any SAX exception, possibly
1864   * wrapping another exception.
1865   * @see org.xml.sax.ContentHandler#startElement
1866   */

1867  public void startElement(
1868          String JavaDoc uri, String JavaDoc localName, String JavaDoc qName, Attributes attributes)
1869            throws SAXException
1870  {
1871   if (DEBUG)
1872     {
1873      System.out.println("startElement: uri: " + uri + ", localname: "
1874                                                 + localName + ", qname: "+qName+", atts: " + attributes);
1875
1876            boolean DEBUG_ATTRS=true;
1877            if(DEBUG_ATTRS & attributes!=null)
1878            {
1879                int n = attributes.getLength();
1880                if(n==0)
1881                    System.out.println("\tempty attribute list");
1882                else for (int i = 0; i < n; i++)
1883                    System.out.println("\t attr: uri: " + attributes.getURI(i) +
1884                                                         ", localname: " + attributes.getLocalName(i) +
1885                                                         ", qname: " + attributes.getQName(i) +
1886                                                         ", type: " + attributes.getType(i) +
1887                                                         ", value: " + attributes.getValue(i)
1888                                                         );
1889            }
1890     }
1891        
1892    charactersFlush();
1893
1894    int exName = m_expandedNameTable.getExpandedTypeID(uri, localName, DTM.ELEMENT_NODE);
1895    String JavaDoc prefix = getPrefix(qName, uri);
1896    int prefixIndex = (null != prefix)
1897                      ? m_valuesOrPrefixes.stringToIndex(qName) : 0;
1898
1899    int elemNode = addNode(DTM.ELEMENT_NODE, exName,
1900                           m_parents.peek(), m_previous, prefixIndex, true);
1901
1902    if(m_indexing)
1903      indexNode(exName, elemNode);
1904    
1905
1906    m_parents.push(elemNode);
1907
1908    int startDecls = m_contextIndexes.peek();
1909    int nDecls = m_prefixMappings.size();
1910    int prev = DTM.NULL;
1911
1912    if(!m_pastFirstElement)
1913    {
1914      // SPECIAL CASE: Implied declaration at root element
1915
prefix="xml";
1916      String JavaDoc declURL = "http://www.w3.org/XML/1998/namespace";
1917      exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
1918      int val = m_valuesOrPrefixes.stringToIndex(declURL);
1919      prev = addNode(DTM.NAMESPACE_NODE, exName, elemNode,
1920                     prev, val, false);
1921      m_pastFirstElement=true;
1922    }
1923
1924    for (int i = startDecls; i < nDecls; i += 2)
1925    {
1926      prefix = (String JavaDoc) m_prefixMappings.elementAt(i);
1927
1928      if (prefix == null)
1929        continue;
1930
1931      String JavaDoc declURL = (String JavaDoc) m_prefixMappings.elementAt(i + 1);
1932
1933      exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
1934
1935      int val = m_valuesOrPrefixes.stringToIndex(declURL);
1936
1937      prev = addNode(DTM.NAMESPACE_NODE, exName, elemNode,
1938                     prev, val, false);
1939    }
1940
1941    int n = attributes.getLength();
1942
1943    for (int i = 0; i < n; i++)
1944    {
1945      String JavaDoc attrUri = attributes.getURI(i);
1946      String JavaDoc attrQName = attributes.getQName(i);
1947      String JavaDoc valString = attributes.getValue(i);
1948
1949      prefix = getPrefix(attrQName, attrUri);
1950
1951      int nodeType;
1952      
1953       String JavaDoc attrLocalName = attributes.getLocalName(i);
1954
1955      if ((null != attrQName)
1956              && (attrQName.equals("xmlns")
1957                  || attrQName.startsWith("xmlns:")))
1958      {
1959        if (declAlreadyDeclared(prefix))
1960          continue; // go to the next attribute.
1961

1962        nodeType = DTM.NAMESPACE_NODE;
1963      }
1964      else
1965      {
1966        nodeType = DTM.ATTRIBUTE_NODE;
1967
1968        if (attributes.getType(i).equalsIgnoreCase("ID"))
1969          setIDAttribute(valString, elemNode);
1970      }
1971
1972      // Bit of a hack... if somehow valString is null, stringToIndex will
1973
// return -1, which will make things very unhappy.
1974
if(null == valString)
1975        valString = "";
1976
1977      int val = m_valuesOrPrefixes.stringToIndex(valString);
1978      //String attrLocalName = attributes.getLocalName(i);
1979

1980      if (null != prefix)
1981      {
1982
1983        prefixIndex = m_valuesOrPrefixes.stringToIndex(attrQName);
1984
1985        int dataIndex = m_data.size();
1986
1987        m_data.addElement(prefixIndex);
1988        m_data.addElement(val);
1989
1990        val = -dataIndex;
1991      }
1992
1993      exName = m_expandedNameTable.getExpandedTypeID(attrUri, attrLocalName, nodeType);
1994      prev = addNode(nodeType, exName, elemNode, prev, val,
1995                     false);
1996    }
1997
1998    if (DTM.NULL != prev)
1999      m_nextsib.setElementAt(DTM.NULL,prev);
2000
2001    if (null != m_wsfilter)
2002    {
2003      short wsv = m_wsfilter.getShouldStripSpace(makeNodeHandle(elemNode), this);
2004      boolean shouldStrip = (DTMWSFilter.INHERIT == wsv)
2005                            ? getShouldStripWhitespace()
2006                            : (DTMWSFilter.STRIP == wsv);
2007
2008      pushShouldStripWhitespace(shouldStrip);
2009    }
2010
2011    m_previous = DTM.NULL;
2012
2013    m_contextIndexes.push(m_prefixMappings.size()); // for the children.
2014
}
2015
2016  /**
2017   * Receive notification of the end of an element.
2018   *
2019   * <p>By default, do nothing. Application writers may override this
2020   * method in a subclass to take specific actions at the end of
2021   * each element (such as finalising a tree node or writing
2022   * output to a file).</p>
2023   *
2024   * @param name The element type name.
2025   * @param attributes The specified or defaulted attributes.
2026   *
2027   * @param uri The Namespace URI, or the empty string if the
2028   * element has no Namespace URI or if Namespace
2029   * processing is not being performed.
2030   * @param localName The local name (without prefix), or the
2031   * empty string if Namespace processing is not being
2032   * performed.
2033   * @param qName The qualified XML 1.0 name (with prefix), or the
2034   * empty string if qualified names are not available.
2035   * @throws SAXException Any SAX exception, possibly
2036   * wrapping another exception.
2037   * @see org.xml.sax.ContentHandler#endElement
2038   */

2039  public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName)
2040          throws SAXException
2041  {
2042   if (DEBUG)
2043      System.out.println("endElement: uri: " + uri + ", localname: "
2044                                                 + localName + ", qname: "+qName);
2045
2046    charactersFlush();
2047
2048    // If no one noticed, startPrefixMapping is a drag.
2049
// Pop the context for the last child (the one pushed by startElement)
2050
m_contextIndexes.quickPop(1);
2051
2052    // Do it again for this one (the one pushed by the last endElement).
2053
int topContextIndex = m_contextIndexes.peek();
2054    if (topContextIndex != m_prefixMappings.size()) {
2055      m_prefixMappings.setSize(topContextIndex);
2056    }
2057
2058    int lastNode = m_previous;
2059
2060    m_previous = m_parents.pop();
2061
2062    // If lastNode is still DTM.NULL, this element had no children
2063
if (DTM.NULL == lastNode)
2064      m_firstch.setElementAt(DTM.NULL,m_previous);
2065    else
2066      m_nextsib.setElementAt(DTM.NULL,lastNode);
2067
2068    popShouldStripWhitespace();
2069  }
2070
2071  /**
2072   * Receive notification of character data inside an element.
2073   *
2074   * <p>By default, do nothing. Application writers may override this
2075   * method to take specific actions for each chunk of character data
2076   * (such as adding the data to a node or buffer, or printing it to
2077   * a file).</p>
2078   *
2079   * @param ch The characters.
2080   * @param start The start position in the character array.
2081   * @param length The number of characters to use from the
2082   * character array.
2083   * @throws SAXException Any SAX exception, possibly
2084   * wrapping another exception.
2085   * @see org.xml.sax.ContentHandler#characters
2086   */

2087  public void characters(char ch[], int start, int length) throws SAXException
2088  {
2089    if (m_textPendingStart == -1) // First one in this block
2090
{
2091      m_textPendingStart = m_chars.size();
2092      m_coalescedTextType = m_textType;
2093    }
2094    // Type logic: If all adjacent text is CDATASections, the
2095
// concatentated text is treated as a single CDATASection (see
2096
// initialization above). If any were ordinary Text, the whole
2097
// thing is treated as Text. This may be worth %REVIEW%ing.
2098
else if (m_textType == DTM.TEXT_NODE)
2099    {
2100      m_coalescedTextType = DTM.TEXT_NODE;
2101    }
2102
2103    m_chars.append(ch, start, length);
2104  }
2105
2106  /**
2107   * Receive notification of ignorable whitespace in element content.
2108   *
2109   * <p>By default, do nothing. Application writers may override this
2110   * method to take specific actions for each chunk of ignorable
2111   * whitespace (such as adding data to a node or buffer, or printing
2112   * it to a file).</p>
2113   *
2114   * @param ch The whitespace characters.
2115   * @param start The start position in the character array.
2116   * @param length The number of characters to use from the
2117   * character array.
2118   * @throws SAXException Any SAX exception, possibly
2119   * wrapping another exception.
2120   * @see org.xml.sax.ContentHandler#ignorableWhitespace
2121   */

2122  public void ignorableWhitespace(char ch[], int start, int length)
2123          throws SAXException
2124  {
2125
2126    // %OPT% We can probably take advantage of the fact that we know this
2127
// is whitespace.
2128
characters(ch, start, length);
2129  }
2130
2131  /**
2132   * Receive notification of a processing instruction.
2133   *
2134   * <p>By default, do nothing. Application writers may override this
2135   * method in a subclass to take specific actions for each
2136   * processing instruction, such as setting status variables or
2137   * invoking other methods.</p>
2138   *
2139   * @param target The processing instruction target.
2140   * @param data The processing instruction data, or null if
2141   * none is supplied.
2142   * @throws SAXException Any SAX exception, possibly
2143   * wrapping another exception.
2144   * @see org.xml.sax.ContentHandler#processingInstruction
2145   */

2146  public void processingInstruction(String JavaDoc target, String JavaDoc data)
2147          throws SAXException
2148  {
2149    if (DEBUG)
2150         System.out.println("processingInstruction: target: " + target +", data: "+data);
2151
2152    charactersFlush();
2153
2154    int exName = m_expandedNameTable.getExpandedTypeID(null, target,
2155                                         DTM.PROCESSING_INSTRUCTION_NODE);
2156    int dataIndex = m_valuesOrPrefixes.stringToIndex(data);
2157
2158    m_previous = addNode(DTM.PROCESSING_INSTRUCTION_NODE, exName,
2159                         m_parents.peek(), m_previous,
2160                         dataIndex, false);
2161  }
2162
2163  /**
2164   * Receive notification of a skipped entity.
2165   *
2166   * <p>By default, do nothing. Application writers may override this
2167   * method in a subclass to take specific actions for each
2168   * processing instruction, such as setting status variables or
2169   * invoking other methods.</p>
2170   *
2171   * @param name The name of the skipped entity.
2172   * @throws SAXException Any SAX exception, possibly
2173   * wrapping another exception.
2174   * @see org.xml.sax.ContentHandler#processingInstruction
2175   */

2176  public void skippedEntity(String JavaDoc name) throws SAXException
2177  {
2178
2179    // %REVIEW% What should be done here?
2180
// no op
2181
}
2182
2183  ////////////////////////////////////////////////////////////////////
2184
// Implementation of the ErrorHandler interface.
2185
////////////////////////////////////////////////////////////////////
2186

2187  /**
2188   * Receive notification of a parser warning.
2189   *
2190   * <p>The default implementation does nothing. Application writers
2191   * may override this method in a subclass to take specific actions
2192   * for each warning, such as inserting the message in a log file or
2193   * printing it to the console.</p>
2194   *
2195   * @param e The warning information encoded as an exception.
2196   * @throws SAXException Any SAX exception, possibly
2197   * wrapping another exception.
2198   * @see org.xml.sax.ErrorHandler#warning
2199   * @see org.xml.sax.SAXParseException
2200   */

2201  public void warning(SAXParseException e) throws SAXException
2202  {
2203
2204    // %REVIEW% Is there anyway to get the JAXP error listener here?
2205
System.err.println(e.getMessage());
2206  }
2207
2208  /**
2209   * Receive notification of a recoverable parser error.
2210   *
2211   * <p>The default implementation does nothing. Application writers
2212   * may override this method in a subclass to take specific actions
2213   * for each error, such as inserting the message in a log file or
2214   * printing it to the console.</p>
2215   *
2216   * @param e The warning information encoded as an exception.
2217   * @throws SAXException Any SAX exception, possibly
2218   * wrapping another exception.
2219   * @see org.xml.sax.ErrorHandler#warning
2220   * @see org.xml.sax.SAXParseException
2221   */

2222  public void error(SAXParseException e) throws SAXException
2223  {
2224    throw e;
2225  }
2226
2227  /**
2228   * Report a fatal XML parsing error.
2229   *
2230   * <p>The default implementation throws a SAXParseException.
2231   * Application writers may override this method in a subclass if
2232   * they need to take specific actions for each fatal error (such as
2233   * collecting all of the errors into a single report): in any case,
2234   * the application must stop all regular processing when this
2235   * method is invoked, since the document is no longer reliable, and
2236   * the parser may no longer report parsing events.</p>
2237   *
2238   * @param e The error information encoded as an exception.
2239   * @throws SAXException Any SAX exception, possibly
2240   * wrapping another exception.
2241   * @see org.xml.sax.ErrorHandler#fatalError
2242   * @see org.xml.sax.SAXParseException
2243   */

2244  public void fatalError(SAXParseException e) throws SAXException
2245  {
2246    throw e;
2247  }
2248
2249  ////////////////////////////////////////////////////////////////////
2250
// Implementation of the DeclHandler interface.
2251
////////////////////////////////////////////////////////////////////
2252

2253  /**
2254   * Report an element type declaration.
2255   *
2256   * <p>The content model will consist of the string "EMPTY", the
2257   * string "ANY", or a parenthesised group, optionally followed
2258   * by an occurrence indicator. The model will be normalized so
2259   * that all whitespace is removed,and will include the enclosing
2260   * parentheses.</p>
2261   *
2262   * @param name The element type name.
2263   * @param model The content model as a normalized string.
2264   * @throws SAXException The application may raise an exception.
2265   */

2266  public void elementDecl(String JavaDoc name, String JavaDoc model) throws SAXException
2267  {
2268
2269    // no op
2270
}
2271
2272  /**
2273   * Report an attribute type declaration.
2274   *
2275   * <p>Only the effective (first) declaration for an attribute will
2276   * be reported. The type will be one of the strings "CDATA",
2277   * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
2278   * "ENTITIES", or "NOTATION", or a parenthesized token group with
2279   * the separator "|" and all whitespace removed.</p>
2280   *
2281   * @param eName The name of the associated element.
2282   * @param aName The name of the attribute.
2283   * @param type A string representing the attribute type.
2284   * @param valueDefault A string representing the attribute default
2285   * ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if
2286   * none of these applies.
2287   * @param value A string representing the attribute's default value,
2288   * or null if there is none.
2289   * @throws SAXException The application may raise an exception.
2290   */

2291  public void attributeDecl(
2292          String JavaDoc eName, String JavaDoc aName, String JavaDoc type, String JavaDoc valueDefault, String JavaDoc value)
2293            throws SAXException
2294  {
2295
2296    // no op
2297
}
2298
2299  /**
2300   * Report an internal entity declaration.
2301   *
2302   * <p>Only the effective (first) declaration for each entity
2303   * will be reported.</p>
2304   *
2305   * @param name The name of the entity. If it is a parameter
2306   * entity, the name will begin with '%'.
2307   * @param value The replacement text of the entity.
2308   * @throws SAXException The application may raise an exception.
2309   * @see #externalEntityDecl
2310   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
2311   */

2312  public void internalEntityDecl(String JavaDoc name, String JavaDoc value)
2313          throws SAXException
2314  {
2315
2316    // no op
2317
}
2318
2319  /**
2320   * Report a parsed external entity declaration.
2321   *
2322   * <p>Only the effective (first) declaration for each entity
2323   * will be reported.</p>
2324   *
2325   * @param name The name of the entity. If it is a parameter
2326   * entity, the name will begin with '%'.
2327   * @param publicId The declared public identifier of the entity, or
2328   * null if none was declared.
2329   * @param systemId The declared system identifier of the entity.
2330   * @throws SAXException The application may raise an exception.
2331   * @see #internalEntityDecl
2332   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
2333   */

2334  public void externalEntityDecl(
2335          String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId) throws SAXException
2336  {
2337
2338    // no op
2339
}
2340
2341  ////////////////////////////////////////////////////////////////////
2342
// Implementation of the LexicalHandler interface.
2343
////////////////////////////////////////////////////////////////////
2344

2345  /**
2346   * Report the start of DTD declarations, if any.
2347   *
2348   * <p>Any declarations are assumed to be in the internal subset
2349   * unless otherwise indicated by a {@link #startEntity startEntity}
2350   * event.</p>
2351   *
2352   * <p>Note that the start/endDTD events will appear within
2353   * the start/endDocument events from ContentHandler and
2354   * before the first startElement event.</p>
2355   *
2356   * @param name The document type name.
2357   * @param publicId The declared public identifier for the
2358   * external DTD subset, or null if none was declared.
2359   * @param systemId The declared system identifier for the
2360   * external DTD subset, or null if none was declared.
2361   * @throws SAXException The application may raise an
2362   * exception.
2363   * @see #endDTD
2364   * @see #startEntity
2365   */

2366  public void startDTD(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId)
2367          throws SAXException
2368  {
2369
2370    m_insideDTD = true;
2371  }
2372
2373  /**
2374   * Report the end of DTD declarations.
2375   *
2376   * @throws SAXException The application may raise an exception.
2377   * @see #startDTD
2378   */

2379  public void endDTD() throws SAXException
2380  {
2381
2382    m_insideDTD = false;
2383  }
2384
2385  /**
2386   * Report the beginning of an entity in content.
2387   *
2388   * <p><strong>NOTE:</entity> entity references in attribute
2389   * values -- and the start and end of the document entity --
2390   * are never reported.</p>
2391   *
2392   * <p>The start and end of the external DTD subset are reported
2393   * using the pseudo-name "[dtd]". All other events must be
2394   * properly nested within start/end entity events.</p>
2395   *
2396   * <p>Note that skipped entities will be reported through the
2397   * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}
2398   * event, which is part of the ContentHandler interface.</p>
2399   *
2400   * @param name The name of the entity. If it is a parameter
2401   * entity, the name will begin with '%'.
2402   * @throws SAXException The application may raise an exception.
2403   * @see #endEntity
2404   * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
2405   * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
2406   */

2407  public void startEntity(String JavaDoc name) throws SAXException
2408  {
2409
2410    // no op
2411
}
2412
2413  /**
2414   * Report the end of an entity.
2415   *
2416   * @param name The name of the entity that is ending.
2417   * @throws SAXException The application may raise an exception.
2418   * @see #startEntity
2419   */

2420  public void endEntity(String JavaDoc name) throws SAXException
2421  {
2422
2423    // no op
2424
}
2425
2426  /**
2427   * Report the start of a CDATA section.
2428   *
2429   * <p>The contents of the CDATA section will be reported through
2430   * the regular {@link org.xml.sax.ContentHandler#characters
2431   * characters} event.</p>
2432   *
2433   * @throws SAXException The application may raise an exception.
2434   * @see #endCDATA
2435   */

2436  public void startCDATA() throws SAXException
2437  {
2438    m_textType = DTM.CDATA_SECTION_NODE;
2439  }
2440
2441  /**
2442   * Report the end of a CDATA section.
2443   *
2444   * @throws SAXException The application may raise an exception.
2445   * @see #startCDATA
2446   */

2447  public void endCDATA() throws SAXException
2448  {
2449    m_textType = DTM.TEXT_NODE;
2450  }
2451
2452  /**
2453   * Report an XML comment anywhere in the document.
2454   *
2455   * <p>This callback will be used for comments inside or outside the
2456   * document element, including comments in the external DTD
2457   * subset (if read).</p>
2458   *
2459   * @param ch An array holding the characters in the comment.
2460   * @param start The starting position in the array.
2461   * @param length The number of characters to use from the array.
2462   * @throws SAXException The application may raise an exception.
2463   */

2464  public void comment(char ch[], int start, int length) throws SAXException
2465  {
2466
2467    if (m_insideDTD) // ignore comments if we're inside the DTD
2468
return;
2469
2470    charactersFlush();
2471
2472    int exName = m_expandedNameTable.getExpandedTypeID(DTM.COMMENT_NODE);
2473
2474    // For now, treat comments as strings... I guess we should do a
2475
// seperate FSB buffer instead.
2476
int dataIndex = m_valuesOrPrefixes.stringToIndex(new String JavaDoc(ch, start,
2477                      length));
2478
2479
2480    m_previous = addNode(DTM.COMMENT_NODE, exName,
2481                         m_parents.peek(), m_previous, dataIndex, false);
2482  }
2483
2484  /**
2485   * Set a run time property for this DTM instance.
2486   *
2487   * %REVIEW% Now that we no longer use this method to support
2488   * getSourceLocatorFor, can we remove it?
2489   *
2490   * @param property a <code>String</code> value
2491   * @param value an <code>Object</code> value
2492   */

2493  public void setProperty(String JavaDoc property, Object JavaDoc value)
2494  {
2495  }
2496
2497  /** Retrieve the SourceLocator associated with a specific node.
2498   * This is only meaningful if the XalanProperties.SOURCE_LOCATION flag was
2499   * set True using setProperty; if it was never set, or was set false, we
2500   * will return null.
2501   *
2502   * (We _could_ return a locator with the document's base URI and bogus
2503   * line/column information. Trying that; see the else clause.)
2504   * */

2505  public SourceLocator JavaDoc getSourceLocatorFor(int node)
2506  {
2507    if (m_useSourceLocationProperty)
2508    {
2509
2510      node = makeNodeIdentity(node);
2511      
2512
2513      return new NodeLocator(null,
2514                             m_sourceSystemId.elementAt(node),
2515                             m_sourceLine.elementAt(node),
2516                             m_sourceColumn.elementAt(node));
2517    }
2518    else if(m_locator!=null)
2519    {
2520        return new NodeLocator(null,m_locator.getSystemId(),-1,-1);
2521    }
2522    else if(m_systemId!=null)
2523    {
2524        return new NodeLocator(null,m_systemId,-1,-1);
2525    }
2526    return null;
2527  }
2528}
2529
Popular Tags