KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > parsers > AbstractDOMParser


1 /*
2  * Copyright 2001-2005 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 package org.apache.xerces.parsers;
18
19 import java.util.Locale JavaDoc;
20 import java.util.Stack JavaDoc;
21
22 import org.apache.xerces.dom.AttrImpl;
23 import org.apache.xerces.dom.CoreDocumentImpl;
24 import org.apache.xerces.dom.DOMErrorImpl;
25 import org.apache.xerces.dom.DOMMessageFormatter;
26 import org.apache.xerces.dom.DeferredDocumentImpl;
27 import org.apache.xerces.dom.DocumentImpl;
28 import org.apache.xerces.dom.DocumentTypeImpl;
29 import org.apache.xerces.dom.ElementDefinitionImpl;
30 import org.apache.xerces.dom.ElementImpl;
31 import org.apache.xerces.dom.ElementNSImpl;
32 import org.apache.xerces.dom.EntityImpl;
33 import org.apache.xerces.dom.EntityReferenceImpl;
34 import org.apache.xerces.dom.NodeImpl;
35 import org.apache.xerces.dom.NotationImpl;
36 import org.apache.xerces.dom.PSVIAttrNSImpl;
37 import org.apache.xerces.dom.PSVIDocumentImpl;
38 import org.apache.xerces.dom.PSVIElementNSImpl;
39 import org.apache.xerces.dom.TextImpl;
40 import org.apache.xerces.impl.Constants;
41 import org.apache.xerces.impl.dv.XSSimpleType;
42 import org.apache.xerces.util.DOMErrorHandlerWrapper;
43 import org.apache.xerces.xni.Augmentations;
44 import org.apache.xerces.xni.NamespaceContext;
45 import org.apache.xerces.xni.QName;
46 import org.apache.xerces.xni.XMLAttributes;
47 import org.apache.xerces.xni.XMLLocator;
48 import org.apache.xerces.xni.XMLResourceIdentifier;
49 import org.apache.xerces.xni.XMLString;
50 import org.apache.xerces.xni.XNIException;
51 import org.apache.xerces.xni.parser.XMLParserConfiguration;
52 import org.apache.xerces.xs.AttributePSVI;
53 import org.apache.xerces.xs.ElementPSVI;
54 import org.apache.xerces.xs.XSTypeDefinition;
55 import org.w3c.dom.Attr JavaDoc;
56 import org.w3c.dom.CDATASection JavaDoc;
57 import org.w3c.dom.Comment JavaDoc;
58 import org.w3c.dom.Document JavaDoc;
59 import org.w3c.dom.DocumentType JavaDoc;
60 import org.w3c.dom.DOMError JavaDoc;
61 import org.w3c.dom.Element JavaDoc;
62 import org.w3c.dom.EntityReference JavaDoc;
63 import org.w3c.dom.NamedNodeMap JavaDoc;
64 import org.w3c.dom.Node JavaDoc;
65 import org.w3c.dom.NodeList JavaDoc;
66 import org.w3c.dom.ProcessingInstruction JavaDoc;
67 import org.w3c.dom.Text JavaDoc;
68 import org.w3c.dom.ls.LSParserFilter JavaDoc;
69 import org.w3c.dom.traversal.NodeFilter;
70 import org.xml.sax.SAXException JavaDoc;
71
72 /**
73  * This is the base class of all DOM parsers. It implements the XNI
74  * callback methods to create the DOM tree. After a successful parse of
75  * an XML document, the DOM Document object can be queried using the
76  * <code>getDocument</code> method. The actual pipeline is defined in
77  * parser configuration.
78  *
79  * @author Arnaud Le Hors, IBM
80  * @author Andy Clark, IBM
81  * @author Elena Litani, IBM
82  *
83  * @version $Id: AbstractDOMParser.java,v 1.116 2005/05/09 19:46:17 ankitp Exp $
84  */

85 public class AbstractDOMParser extends AbstractXMLDocumentParser {
86
87     //
88
// Constants
89
//
90

91     // feature ids
92

93     /** Feature id: namespace. */
94     protected static final String JavaDoc NAMESPACES =
95     Constants.SAX_FEATURE_PREFIX+Constants.NAMESPACES_FEATURE;
96
97     /** Feature id: create entity ref nodes. */
98     protected static final String JavaDoc CREATE_ENTITY_REF_NODES =
99     Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
100
101     /** Feature id: include comments. */
102     protected static final String JavaDoc INCLUDE_COMMENTS_FEATURE =
103     Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_COMMENTS_FEATURE;
104
105     /** Feature id: create cdata nodes. */
106     protected static final String JavaDoc CREATE_CDATA_NODES_FEATURE =
107     Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_CDATA_NODES_FEATURE;
108
109     /** Feature id: include ignorable whitespace. */
110     protected static final String JavaDoc INCLUDE_IGNORABLE_WHITESPACE =
111     Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_IGNORABLE_WHITESPACE;
112
113     /** Feature id: defer node expansion. */
114     protected static final String JavaDoc DEFER_NODE_EXPANSION =
115     Constants.XERCES_FEATURE_PREFIX + Constants.DEFER_NODE_EXPANSION_FEATURE;
116
117
118     /** Recognized features. */
119     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
120         NAMESPACES,
121         CREATE_ENTITY_REF_NODES,
122         INCLUDE_COMMENTS_FEATURE,
123         CREATE_CDATA_NODES_FEATURE,
124         INCLUDE_IGNORABLE_WHITESPACE,
125         DEFER_NODE_EXPANSION
126     };
127
128     // property ids
129

130     /** Property id: document class name. */
131     protected static final String JavaDoc DOCUMENT_CLASS_NAME =
132     Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_CLASS_NAME_PROPERTY;
133
134     protected static final String JavaDoc CURRENT_ELEMENT_NODE=
135     Constants.XERCES_PROPERTY_PREFIX + Constants.CURRENT_ELEMENT_NODE_PROPERTY;
136
137     // protected static final String GRAMMAR_POOL =
138
// Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
139

140     /** Recognized properties. */
141     private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
142         DOCUMENT_CLASS_NAME,
143         CURRENT_ELEMENT_NODE,
144     };
145
146     // other
147

148     /** Default document class name. */
149     protected static final String JavaDoc DEFAULT_DOCUMENT_CLASS_NAME =
150     "org.apache.xerces.dom.DocumentImpl";
151
152     protected static final String JavaDoc CORE_DOCUMENT_CLASS_NAME =
153     "org.apache.xerces.dom.CoreDocumentImpl";
154
155     protected static final String JavaDoc PSVI_DOCUMENT_CLASS_NAME =
156     "org.apache.xerces.dom.PSVIDocumentImpl";
157
158     /**
159      * If the user stops the process, this exception will be thrown.
160      */

161     public static final RuntimeException JavaDoc abort = new RuntimeException JavaDoc();
162
163     // debugging
164

165     private static final boolean DEBUG_EVENTS = false;
166     private static final boolean DEBUG_BASEURI = false;
167
168     //
169
// Data
170
//
171

172     /** DOM L3 error handler */
173     protected DOMErrorHandlerWrapper fErrorHandler = null;
174
175     /** True if inside DTD. */
176     protected boolean fInDTD;
177
178     // features
179

180     /** Create entity reference nodes. */
181     protected boolean fCreateEntityRefNodes;
182
183     /** Include ignorable whitespace. */
184     protected boolean fIncludeIgnorableWhitespace;
185
186     /** Include Comments. */
187     protected boolean fIncludeComments;
188
189     /** Create cdata nodes. */
190     protected boolean fCreateCDATANodes;
191
192     // dom information
193

194     /** The document. */
195     protected Document JavaDoc fDocument;
196
197     /** The default Xerces document implementation, if used. */
198     protected CoreDocumentImpl fDocumentImpl;
199
200     /** Whether to store PSVI information in DOM tree. */
201     protected boolean fStorePSVI;
202
203     /** The document class name to use. */
204     protected String JavaDoc fDocumentClassName;
205
206     /** The document type node. */
207     protected DocumentType JavaDoc fDocumentType;
208
209     /** Current node. */
210     protected Node JavaDoc fCurrentNode;
211     protected CDATASection JavaDoc fCurrentCDATASection;
212     protected EntityImpl fCurrentEntityDecl;
213     protected int fDeferredEntityDecl;
214
215     /** Character buffer */
216     protected final StringBuffer JavaDoc fStringBuffer = new StringBuffer JavaDoc (50);
217
218     // internal subset
219

220     /** Internal subset buffer. */
221     protected StringBuffer JavaDoc fInternalSubset;
222
223     // deferred expansion data
224

225     protected boolean fDeferNodeExpansion;
226     protected boolean fNamespaceAware;
227     protected DeferredDocumentImpl fDeferredDocumentImpl;
228     protected int fDocumentIndex;
229     protected int fDocumentTypeIndex;
230     protected int fCurrentNodeIndex;
231     protected int fCurrentCDATASectionIndex;
232
233     // state
234

235     /** True if inside DTD external subset. */
236     protected boolean fInDTDExternalSubset;
237
238     /** Root element name */
239     protected QName fRoot = new QName();
240
241     /** True if inside CDATA section. */
242     protected boolean fInCDATASection;
243
244     /** True if saw the first chunk of characters*/
245     protected boolean fFirstChunk = false;
246
247
248     /** LSParserFilter: specifies that element with given QNAME and all its children
249      * must be rejected */

250     protected boolean fFilterReject = false;
251
252     // data
253

254     /** Base uri stack*/
255     protected Stack JavaDoc fBaseURIStack = new Stack JavaDoc ();
256
257
258     /** LSParserFilter: the QNAME of rejected element*/
259     protected final QName fRejectedElement = new QName ();
260
261     /** LSParserFilter: store qnames of skipped elements*/
262     protected Stack JavaDoc fSkippedElemStack = null;
263
264     /** LSParserFilter: true if inside entity reference */
265     protected boolean fInEntityRef = false;
266
267     /** Attribute QName. */
268     private QName fAttrQName = new QName ();
269
270     // handlers
271

272     protected LSParserFilter JavaDoc fDOMFilter = null;
273
274     //
275
// Constructors
276
//
277

278     /** Default constructor. */
279     protected AbstractDOMParser (XMLParserConfiguration config) {
280
281         super (config);
282
283
284         // add recognized features
285
fConfiguration.addRecognizedFeatures (RECOGNIZED_FEATURES);
286
287         // set default values
288
fConfiguration.setFeature (CREATE_ENTITY_REF_NODES, true);
289         fConfiguration.setFeature (INCLUDE_IGNORABLE_WHITESPACE, true);
290         fConfiguration.setFeature (DEFER_NODE_EXPANSION, true);
291         fConfiguration.setFeature (INCLUDE_COMMENTS_FEATURE, true);
292         fConfiguration.setFeature (CREATE_CDATA_NODES_FEATURE, true);
293
294         // add recognized properties
295
fConfiguration.addRecognizedProperties (RECOGNIZED_PROPERTIES);
296
297         // set default values
298
fConfiguration.setProperty (DOCUMENT_CLASS_NAME,
299         DEFAULT_DOCUMENT_CLASS_NAME);
300
301     } // <init>(XMLParserConfiguration)
302

303     /**
304      * This method retreives the name of current document class.
305      */

306     protected String JavaDoc getDocumentClassName () {
307         return fDocumentClassName;
308     }
309
310     /**
311      * This method allows the programmer to decide which document
312      * factory to use when constructing the DOM tree. However, doing
313      * so will lose the functionality of the default factory. Also,
314      * a document class other than the default will lose the ability
315      * to defer node expansion on the DOM tree produced.
316      *
317      * @param documentClassName The fully qualified class name of the
318      * document factory to use when constructing
319      * the DOM tree.
320      *
321      * @see #getDocumentClassName
322      * @see #DEFAULT_DOCUMENT_CLASS_NAME
323      */

324     protected void setDocumentClassName (String JavaDoc documentClassName) {
325
326         // normalize class name
327
if (documentClassName == null) {
328             documentClassName = DEFAULT_DOCUMENT_CLASS_NAME;
329         }
330
331         if (!documentClassName.equals(DEFAULT_DOCUMENT_CLASS_NAME) &&
332             !documentClassName.equals(PSVI_DOCUMENT_CLASS_NAME)) {
333             // verify that this class exists and is of the right type
334
try {
335                 Class JavaDoc _class = ObjectFactory.findProviderClass (documentClassName,
336                 ObjectFactory.findClassLoader (), true);
337                 //if (!_class.isAssignableFrom(Document.class)) {
338
if (!Document JavaDoc.class.isAssignableFrom (_class)) {
339                     throw new IllegalArgumentException JavaDoc (
340                         DOMMessageFormatter.formatMessage(
341                         DOMMessageFormatter.DOM_DOMAIN,
342                         "InvalidDocumentClassName", new Object JavaDoc [] {documentClassName}));
343                 }
344             }
345             catch (ClassNotFoundException JavaDoc e) {
346                 throw new IllegalArgumentException JavaDoc (
347                     DOMMessageFormatter.formatMessage(
348                     DOMMessageFormatter.DOM_DOMAIN,
349                     "MissingDocumentClassName", new Object JavaDoc [] {documentClassName}));
350             }
351         }
352
353         // set document class name
354
fDocumentClassName = documentClassName;
355         if (!documentClassName.equals (DEFAULT_DOCUMENT_CLASS_NAME)) {
356             fDeferNodeExpansion = false;
357         }
358
359     } // setDocumentClassName(String)
360

361     //
362
// Public methods
363
//
364

365     /** Returns the DOM document object. */
366     public Document JavaDoc getDocument () {
367         return fDocument;
368     } // getDocument():Document
369

370     //
371
// XMLDocumentParser methods
372
//
373

374     /**
375      * Resets the parser state.
376      *
377      * @throws SAXException Thrown on initialization error.
378      */

379     public void reset () throws XNIException {
380         super.reset ();
381
382
383         // get feature state
384
fCreateEntityRefNodes =
385         fConfiguration.getFeature (CREATE_ENTITY_REF_NODES);
386
387         fIncludeIgnorableWhitespace =
388         fConfiguration.getFeature (INCLUDE_IGNORABLE_WHITESPACE);
389
390         fDeferNodeExpansion =
391         fConfiguration.getFeature (DEFER_NODE_EXPANSION);
392
393         fNamespaceAware = fConfiguration.getFeature (NAMESPACES);
394
395         fIncludeComments = fConfiguration.getFeature (INCLUDE_COMMENTS_FEATURE);
396
397         fCreateCDATANodes = fConfiguration.getFeature (CREATE_CDATA_NODES_FEATURE);
398
399         // get property
400
setDocumentClassName ((String JavaDoc)
401         fConfiguration.getProperty (DOCUMENT_CLASS_NAME));
402
403         // reset dom information
404
fDocument = null;
405         fDocumentImpl = null;
406         fStorePSVI = false;
407         fDocumentType = null;
408         fDocumentTypeIndex = -1;
409         fDeferredDocumentImpl = null;
410         fCurrentNode = null;
411
412         // reset string buffer
413
fStringBuffer.setLength (0);
414
415         // reset state information
416
fRoot.clear();
417         fInDTD = false;
418         fInDTDExternalSubset = false;
419         fInCDATASection = false;
420         fFirstChunk = false;
421         fCurrentCDATASection = null;
422         fCurrentCDATASectionIndex = -1;
423
424         fBaseURIStack.removeAllElements ();
425
426
427     } // reset()
428

429     /**
430      * Set the locale to use for messages.
431      *
432      * @param locale The locale object to use for localization of messages.
433      *
434      */

435     public void setLocale (Locale JavaDoc locale) {
436         fConfiguration.setLocale (locale);
437
438     } // setLocale(Locale)
439

440     //
441
// XMLDocumentHandler methods
442
//
443

444     /**
445      * This method notifies the start of a general entity.
446      * <p>
447      * <strong>Note:</strong> This method is not called for entity references
448      * appearing as part of attribute values.
449      *
450      * @param name The name of the general entity.
451      * @param identifier The resource identifier.
452      * @param encoding The auto-detected IANA encoding name of the entity
453      * stream. This value will be null in those situations
454      * where the entity encoding is not auto-detected (e.g.
455      * internal entities or a document entity that is
456      * parsed from a java.io.Reader).
457      * @param augs Additional information that may include infoset augmentations
458      *
459      * @exception XNIException Thrown by handler to signal an error.
460      */

461     public void startGeneralEntity (String JavaDoc name,
462     XMLResourceIdentifier identifier,
463     String JavaDoc encoding, Augmentations augs)
464     throws XNIException {
465         if (DEBUG_EVENTS) {
466             System.out.println ("==>startGeneralEntity ("+name+")");
467             if (DEBUG_BASEURI) {
468                 System.out.println (" expandedSystemId( **baseURI): "+identifier.getExpandedSystemId ());
469                 System.out.println (" baseURI:"+ identifier.getBaseSystemId ());
470             }
471         }
472
473         // Always create entity reference nodes to be able to recreate
474
// entity as a part of doctype
475
if (!fDeferNodeExpansion) {
476             if (fFilterReject) {
477                 return;
478             }
479             setCharacterData (true);
480             EntityReference JavaDoc er = fDocument.createEntityReference (name);
481             if (fDocumentImpl != null) {
482                 // REVISIT: baseURI/actualEncoding
483
// remove dependency on our implementation when DOM L3 is REC
484
//
485

486                 EntityReferenceImpl erImpl =(EntityReferenceImpl)er;
487
488                 // set base uri
489
erImpl.setBaseURI (identifier.getExpandedSystemId ());
490                 if (fDocumentType != null) {
491                     // set actual encoding
492
NamedNodeMap JavaDoc entities = fDocumentType.getEntities ();
493                     fCurrentEntityDecl = (EntityImpl) entities.getNamedItem (name);
494                     if (fCurrentEntityDecl != null) {
495                         fCurrentEntityDecl.setInputEncoding (encoding);
496                     }
497
498                 }
499                 // we don't need synchronization now, because entity ref will be
500
// expanded anyway. Synch only needed when user creates entityRef node
501
erImpl.needsSyncChildren (false);
502             }
503             fInEntityRef = true;
504             fCurrentNode.appendChild (er);
505             fCurrentNode = er;
506         }
507         else {
508
509             int er =
510             fDeferredDocumentImpl.createDeferredEntityReference (name, identifier.getExpandedSystemId ());
511             if (fDocumentTypeIndex != -1) {
512                 // find corresponding Entity decl
513
int node = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
514                 while (node != -1) {
515                     short nodeType = fDeferredDocumentImpl.getNodeType (node, false);
516                     if (nodeType == Node.ENTITY_NODE) {
517                         String JavaDoc nodeName =
518                         fDeferredDocumentImpl.getNodeName (node, false);
519                         if (nodeName.equals (name)) {
520                             fDeferredEntityDecl = node;
521                             fDeferredDocumentImpl.setInputEncoding (node, encoding);
522                             break;
523                         }
524                     }
525                     node = fDeferredDocumentImpl.getRealPrevSibling (node, false);
526                 }
527             }
528             fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, er);
529             fCurrentNodeIndex = er;
530         }
531
532     } // startGeneralEntity(String,XMLResourceIdentifier, Augmentations)
533

534     /**
535      * Notifies of the presence of a TextDecl line in an entity. If present,
536      * this method will be called immediately following the startEntity call.
537      * <p>
538      * <strong>Note:</strong> This method will never be called for the
539      * document entity; it is only called for external general entities
540      * referenced in document content.
541      * <p>
542      * <strong>Note:</strong> This method is not called for entity references
543      * appearing as part of attribute values.
544      *
545      * @param version The XML version, or null if not specified.
546      * @param encoding The IANA encoding name of the entity.
547      * @param augs Additional information that may include infoset augmentations
548      *
549      * @throws XNIException Thrown by handler to signal an error.
550      */

551     public void textDecl (String JavaDoc version, String JavaDoc encoding, Augmentations augs) throws XNIException {
552         if (fInDTD){
553             return;
554         }
555         if (!fDeferNodeExpansion) {
556             if (fCurrentEntityDecl != null && !fFilterReject) {
557                 fCurrentEntityDecl.setXmlEncoding (encoding);
558                 if (version != null)
559                     fCurrentEntityDecl.setXmlVersion (version);
560             }
561         }
562         else {
563             if (fDeferredEntityDecl !=-1) {
564                 fDeferredDocumentImpl.setEntityInfo (fDeferredEntityDecl, version, encoding);
565             }
566         }
567     } // textDecl(String,String)
568

569     /**
570      * A comment.
571      *
572      * @param text The text in the comment.
573      * @param augs Additional information that may include infoset augmentations
574      *
575      * @throws XNIException Thrown by application to signal an error.
576      */

577     public void comment (XMLString text, Augmentations augs) throws XNIException {
578         if (fInDTD) {
579             if (fInternalSubset != null && !fInDTDExternalSubset) {
580                 fInternalSubset.append ("<!-- ");
581                 fInternalSubset.append (text.toString ());
582                 fInternalSubset.append (" -->");
583             }
584             return;
585         }
586         if (!fIncludeComments || fFilterReject) {
587             return;
588         }
589         if (!fDeferNodeExpansion) {
590             Comment JavaDoc comment = fDocument.createComment (text.toString ());
591
592             setCharacterData (false);
593             fCurrentNode.appendChild (comment);
594             if (fDOMFilter !=null && !fInEntityRef &&
595             (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_COMMENT)!= 0) {
596                 short code = fDOMFilter.acceptNode (comment);
597                 switch (code) {
598                     case LSParserFilter.FILTER_INTERRUPT:{
599                         throw abort;
600                     }
601                     case LSParserFilter.FILTER_REJECT:{
602                         // REVISIT: the constant FILTER_REJECT should be changed when new
603
// DOM LS specs gets published
604

605                         // fall through to SKIP since comment has no children.
606
}
607                     case LSParserFilter.FILTER_SKIP: {
608                         // REVISIT: the constant FILTER_SKIP should be changed when new
609
// DOM LS specs gets published
610
fCurrentNode.removeChild (comment);
611                         // make sure we don't loose chars if next event is characters()
612
fFirstChunk = true;
613                         return;
614                     }
615
616                     default: {
617                         // accept node
618
}
619                 }
620             }
621
622         }
623         else {
624             int comment =
625             fDeferredDocumentImpl.createDeferredComment (text.toString ());
626             fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, comment);
627         }
628
629     } // comment(XMLString)
630

631     /**
632      * A processing instruction. Processing instructions consist of a
633      * target name and, optionally, text data. The data is only meaningful
634      * to the application.
635      * <p>
636      * Typically, a processing instruction's data will contain a series
637      * of pseudo-attributes. These pseudo-attributes follow the form of
638      * element attributes but are <strong>not</strong> parsed or presented
639      * to the application as anything other than text. The application is
640      * responsible for parsing the data.
641      *
642      * @param target The target.
643      * @param data The data or null if none specified.
644      * @param augs Additional information that may include infoset augmentations
645      *
646      * @throws XNIException Thrown by handler to signal an error.
647      */

648     public void processingInstruction (String JavaDoc target, XMLString data, Augmentations augs)
649     throws XNIException {
650
651         if (fInDTD) {
652             if (fInternalSubset != null && !fInDTDExternalSubset) {
653                 fInternalSubset.append ("<?");
654                 fInternalSubset.append (target);
655                 fInternalSubset.append (' ');
656                 fInternalSubset.append (data.toString ());
657                 fInternalSubset.append ("?>");
658
659             }
660             return;
661         }
662
663         if (DEBUG_EVENTS) {
664             System.out.println ("==>processingInstruction ("+target+")");
665         }
666         if (!fDeferNodeExpansion) {
667             if (fFilterReject) {
668                 return;
669             }
670             ProcessingInstruction JavaDoc pi =
671             fDocument.createProcessingInstruction (target, data.toString ());
672
673
674             setCharacterData (false);
675             fCurrentNode.appendChild (pi);
676             if (fDOMFilter !=null && !fInEntityRef &&
677             (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_PROCESSING_INSTRUCTION)!= 0) {
678                 short code = fDOMFilter.acceptNode (pi);
679                 switch (code) {
680                     case LSParserFilter.FILTER_INTERRUPT:{
681                         throw abort;
682                     }
683                     case LSParserFilter.FILTER_REJECT:{
684                         // fall through to SKIP since PI has no children.
685
}
686                     case LSParserFilter.FILTER_SKIP: {
687                         fCurrentNode.removeChild (pi);
688                         // fFirstChunk must be set to true so that data
689
// won't be lost in the case where the child before PI is
690
// a text node and the next event is characters.
691
fFirstChunk = true;
692                         return;
693                     }
694                     default: {
695                     }
696                 }
697             }
698         }
699         else {
700             int pi = fDeferredDocumentImpl.
701             createDeferredProcessingInstruction (target, data.toString ());
702             fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, pi);
703         }
704
705     } // processingInstruction(String,XMLString)
706

707     /**
708      * The start of the document.
709      *
710      * @param locator The system identifier of the entity if the entity
711      * is external, null otherwise.
712      * @param encoding The auto-detected IANA encoding name of the entity
713      * stream. This value will be null in those situations
714      * where the entity encoding is not auto-detected (e.g.
715      * internal entities or a document entity that is
716      * parsed from a java.io.Reader).
717      * @param namespaceContext
718      * The namespace context in effect at the
719      * start of this document.
720      * This object represents the current context.
721      * Implementors of this class are responsible
722      * for copying the namespace bindings from the
723      * the current context (and its parent contexts)
724      * if that information is important.
725      * @param augs Additional information that may include infoset augmentations
726      *
727      * @throws XNIException Thrown by handler to signal an error.
728      */

729     public void startDocument (XMLLocator locator, String JavaDoc encoding,
730     NamespaceContext namespaceContext, Augmentations augs)
731     throws XNIException {
732
733         if (!fDeferNodeExpansion) {
734             if (fDocumentClassName.equals (DEFAULT_DOCUMENT_CLASS_NAME)) {
735                 fDocument = new DocumentImpl ();
736                 fDocumentImpl = (CoreDocumentImpl)fDocument;
737                 // REVISIT: when DOM Level 3 is REC rely on Document.support
738
// instead of specific class
739
// set DOM error checking off
740
fDocumentImpl.setStrictErrorChecking (false);
741                 // set actual encoding
742
fDocumentImpl.setInputEncoding (encoding);
743                 // set documentURI
744
fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
745             }
746             else if (fDocumentClassName.equals (PSVI_DOCUMENT_CLASS_NAME)) {
747                 fDocument = new PSVIDocumentImpl();
748                 fDocumentImpl = (CoreDocumentImpl)fDocument;
749                 fStorePSVI = true;
750                 // REVISIT: when DOM Level 3 is REC rely on Document.support
751
// instead of specific class
752
// set DOM error checking off
753
fDocumentImpl.setStrictErrorChecking (false);
754                 // set actual encoding
755
fDocumentImpl.setInputEncoding (encoding);
756                 // set documentURI
757
fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
758             }
759             else {
760                 // use specified document class
761
try {
762                     ClassLoader JavaDoc cl = ObjectFactory.findClassLoader();
763                     Class JavaDoc documentClass = ObjectFactory.findProviderClass (fDocumentClassName,
764                         cl, true);
765                     fDocument = (Document JavaDoc)documentClass.newInstance ();
766
767                     // if subclass of our own class that's cool too
768
Class JavaDoc defaultDocClass =
769                     ObjectFactory.findProviderClass (CORE_DOCUMENT_CLASS_NAME,
770                         cl, true);
771                     if (defaultDocClass.isAssignableFrom (documentClass)) {
772                         fDocumentImpl = (CoreDocumentImpl)fDocument;
773
774                         Class JavaDoc psviDocClass = ObjectFactory.findProviderClass (PSVI_DOCUMENT_CLASS_NAME,
775                             cl, true);
776                         if (psviDocClass.isAssignableFrom (documentClass)) {
777                             fStorePSVI = true;
778                         }
779
780                         // REVISIT: when DOM Level 3 is REC rely on
781
// Document.support instead of specific class
782
// set DOM error checking off
783
fDocumentImpl.setStrictErrorChecking (false);
784                         // set actual encoding
785
fDocumentImpl.setInputEncoding (encoding);
786                         // set documentURI
787
if (locator != null) {
788                             fDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
789                         }
790                     }
791                 }
792                 catch (ClassNotFoundException JavaDoc e) {
793                     // won't happen we already checked that earlier
794
}
795                 catch (Exception JavaDoc e) {
796                     throw new RuntimeException JavaDoc (
797                         DOMMessageFormatter.formatMessage(
798                         DOMMessageFormatter.DOM_DOMAIN,
799                         "CannotCreateDocumentClass",
800                         new Object JavaDoc [] {fDocumentClassName}));
801                 }
802             }
803             fCurrentNode = fDocument;
804         }
805         else {
806             fDeferredDocumentImpl = new DeferredDocumentImpl (fNamespaceAware);
807             fDocument = fDeferredDocumentImpl;
808             fDocumentIndex = fDeferredDocumentImpl.createDeferredDocument ();
809             // REVISIT: strict error checking is not implemented in deferred dom.
810
// Document.support instead of specific class
811

812             // set actual encoding
813
fDeferredDocumentImpl.setInputEncoding (encoding);
814             // set documentURI
815
fDeferredDocumentImpl.setDocumentURI (locator.getExpandedSystemId ());
816             fCurrentNodeIndex = fDocumentIndex;
817
818         }
819
820     } // startDocument(String,String)
821

822     /**
823      * Notifies of the presence of an XMLDecl line in the document. If
824      * present, this method will be called immediately following the
825      * startDocument call.
826      *
827      * @param version The XML version.
828      * @param encoding The IANA encoding name of the document, or null if
829      * not specified.
830      * @param standalone The standalone value, or null if not specified.
831      * @param augs Additional information that may include infoset augmentations
832      *
833      * @throws XNIException Thrown by handler to signal an error.
834      */

835     public void xmlDecl (String JavaDoc version, String JavaDoc encoding, String JavaDoc standalone,
836     Augmentations augs)
837     throws XNIException {
838         if (!fDeferNodeExpansion) {
839             // REVISIT: when DOM Level 3 is REC rely on Document.support
840
// instead of specific class
841
if (fDocumentImpl != null) {
842                 if (version != null)
843                     fDocumentImpl.setXmlVersion (version);
844                 fDocumentImpl.setXmlEncoding (encoding);
845                 fDocumentImpl.setXmlStandalone ("yes".equals (standalone));
846             }
847         }
848         else {
849             if (version != null)
850                 fDeferredDocumentImpl.setXmlVersion (version);
851             fDeferredDocumentImpl.setXmlEncoding (encoding);
852             fDeferredDocumentImpl.setXmlStandalone ("yes".equals (standalone));
853         }
854     } // xmlDecl(String,String,String)
855

856     /**
857      * Notifies of the presence of the DOCTYPE line in the document.
858      *
859      * @param rootElement The name of the root element.
860      * @param publicId The public identifier if an external DTD or null
861      * if the external DTD is specified using SYSTEM.
862      * @param systemId The system identifier if an external DTD, null
863      * otherwise.
864      * @param augs Additional information that may include infoset augmentations
865      *
866      * @throws XNIException Thrown by handler to signal an error.
867      */

868     public void doctypeDecl (String JavaDoc rootElement,
869     String JavaDoc publicId, String JavaDoc systemId, Augmentations augs)
870     throws XNIException {
871
872         if (!fDeferNodeExpansion) {
873             if (fDocumentImpl != null) {
874                 fDocumentType = fDocumentImpl.createDocumentType (
875                 rootElement, publicId, systemId);
876                 fCurrentNode.appendChild (fDocumentType);
877             }
878         }
879         else {
880             fDocumentTypeIndex = fDeferredDocumentImpl.
881             createDeferredDocumentType (rootElement, publicId, systemId);
882             fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, fDocumentTypeIndex);
883         }
884
885     } // doctypeDecl(String,String,String)
886

887     /**
888      * The start of an element. If the document specifies the start element
889      * by using an empty tag, then the startElement method will immediately
890      * be followed by the endElement method, with no intervening methods.
891      *
892      * @param element The name of the element.
893      * @param attributes The element attributes.
894      * @param augs Additional information that may include infoset augmentations
895      *
896      * @throws XNIException Thrown by handler to signal an error.
897      */

898     public void startElement (QName element, XMLAttributes attributes, Augmentations augs)
899     throws XNIException {
900         if (DEBUG_EVENTS) {
901             System.out.println ("==>startElement ("+element.rawname+")");
902         }
903         if (!fDeferNodeExpansion) {
904             if (fFilterReject) {
905                 return;
906             }
907             Element JavaDoc el = createElementNode (element);
908             int attrCount = attributes.getLength ();
909             for (int i = 0; i < attrCount; i++) {
910                 attributes.getName (i, fAttrQName);
911                 Attr JavaDoc attr = createAttrNode (fAttrQName);
912
913                 String JavaDoc attrValue = attributes.getValue (i);
914
915                 AttributePSVI attrPSVI =(AttributePSVI) attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_PSVI);
916                 if (fStorePSVI && attrPSVI != null){
917                     ((PSVIAttrNSImpl) attr).setPSVI (attrPSVI);
918                 }
919
920
921                 attr.setValue (attrValue);
922                 el.setAttributeNode (attr);
923                 // NOTE: The specified value MUST be set after you set
924
// the node value because that turns the "specified"
925
// flag to "true" which may overwrite a "false"
926
// value from the attribute list. -Ac
927
if (fDocumentImpl != null) {
928                     AttrImpl attrImpl = (AttrImpl) attr;
929                     Object JavaDoc type = null;
930                     boolean id = false;
931
932                     // REVISIT: currently it is possible that someone turns off
933
// namespaces and turns on xml schema validation
934
// To avoid classcast exception in AttrImpl check for namespaces
935
// however the correct solution should probably disallow setting
936
// namespaces to false when schema processing is turned on.
937
if (attrPSVI != null && fNamespaceAware) {
938                         // XML Schema
939
type = attrPSVI.getMemberTypeDefinition ();
940                         if (type == null) {
941                             type = attrPSVI.getTypeDefinition ();
942                             if (type != null) {
943                                 id = ((XSSimpleType) type).isIDType ();
944                                 attrImpl.setType (type);
945                             }
946                         }
947                         else {
948                             id = ((XSSimpleType) type).isIDType ();
949                             attrImpl.setType (type);
950                         }
951                     }
952                     else {
953                         // DTD
954
boolean isDeclared = Boolean.TRUE.equals (attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_DECLARED));
955                         // For DOM Level 3 TypeInfo, the type name must
956
// be null if this attribute has not been declared
957
// in the DTD.
958
if (isDeclared) {
959                             type = attributes.getType (i);
960                             id = "ID".equals (type);
961                         }
962                         attrImpl.setType (type);
963                     }
964
965                     if (id) {
966                         ((ElementImpl) el).setIdAttributeNode (attr, true);
967                     }
968
969                     attrImpl.setSpecified (attributes.isSpecified (i));
970                     // REVISIT: Handle entities in attribute value.
971
}
972             }
973             setCharacterData (false);
974
975             if (augs != null) {
976                 ElementPSVI elementPSVI = (ElementPSVI)augs.getItem (Constants.ELEMENT_PSVI);
977                 if (elementPSVI != null && fNamespaceAware) {
978                     XSTypeDefinition type = elementPSVI.getMemberTypeDefinition ();
979                     if (type == null) {
980                         type = elementPSVI.getTypeDefinition ();
981                     }
982                     ((ElementNSImpl)el).setType (type);
983                 }
984             }
985
986
987             // filter nodes
988
if (fDOMFilter != null && !fInEntityRef) {
989                 if (fRoot.rawname == null) {
990                     // fill value of the root element
991
fRoot.setValues(element);
992                 } else {
993                     short code = fDOMFilter.startElement(el);
994                     switch (code) {
995                         case LSParserFilter.FILTER_INTERRUPT :
996                             {
997                                 throw abort;
998                             }
999                         case LSParserFilter.FILTER_REJECT :
1000                            {
1001                                fFilterReject = true;
1002                                fRejectedElement.setValues(element);
1003                                return;
1004                            }
1005                        case LSParserFilter.FILTER_SKIP :
1006                            {
1007                                fSkippedElemStack.push(element.clone());
1008                                return;
1009                            }
1010                        default : {}
1011                    }
1012                }
1013            }
1014            fCurrentNode.appendChild (el);
1015            fCurrentNode = el;
1016        }
1017        else {
1018            Object JavaDoc type = null;
1019            if (augs != null) {
1020                ElementPSVI elementPSVI = (ElementPSVI)augs.getItem (Constants.ELEMENT_PSVI);
1021                if (elementPSVI != null) {
1022                    type = elementPSVI.getMemberTypeDefinition ();
1023                    if (type == null) {
1024                        type = elementPSVI.getTypeDefinition ();
1025                    }
1026                }
1027            }
1028
1029            int el =
1030            fDeferredDocumentImpl.createDeferredElement (fNamespaceAware ?
1031            element.uri : null,
1032            element.rawname,
1033            type);
1034            int attrCount = attributes.getLength ();
1035            for (int i = 0; i < attrCount; i++) {
1036                // set type information
1037
AttributePSVI attrPSVI = (AttributePSVI)attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_PSVI);
1038                boolean id = false;
1039
1040                // REVISIT: currently it is possible that someone turns off
1041
// namespaces and turns on xml schema validation
1042
// To avoid classcast exception in AttrImpl check for namespaces
1043
// however the correct solution should probably disallow setting
1044
// namespaces to false when schema processing is turned on.
1045
if (attrPSVI != null && fNamespaceAware) {
1046                    // XML Schema
1047
type = attrPSVI.getMemberTypeDefinition ();
1048                    if (type == null) {
1049                        type = attrPSVI.getTypeDefinition ();
1050                        if (type != null){
1051                            id = ((XSSimpleType) type).isIDType ();
1052                        }
1053                    }
1054                    else {
1055                        id = ((XSSimpleType) type).isIDType ();
1056                    }
1057                }
1058                else {
1059                    // DTD
1060
boolean isDeclared = Boolean.TRUE.equals (attributes.getAugmentations (i).getItem (Constants.ATTRIBUTE_DECLARED));
1061                    // For DOM Level 3 TypeInfo, the type name must
1062
// be null if this attribute has not been declared
1063
// in the DTD.
1064
if (isDeclared) {
1065                        type = attributes.getType (i);
1066                        id = "ID".equals (type);
1067                    }
1068                }
1069
1070                // create attribute
1071
fDeferredDocumentImpl.setDeferredAttribute (
1072                el,
1073                attributes.getQName (i),
1074                attributes.getURI (i),
1075                attributes.getValue (i),
1076                attributes.isSpecified (i),
1077                id,
1078                type);
1079            }
1080
1081            fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, el);
1082            fCurrentNodeIndex = el;
1083        }
1084    } // startElement(QName,XMLAttributes)
1085

1086
1087    /**
1088     * An empty element.
1089     *
1090     * @param element The name of the element.
1091     * @param attributes The element attributes.
1092     * @param augs Additional information that may include infoset augmentations
1093     *
1094     * @throws XNIException Thrown by handler to signal an error.
1095     */

1096    public void emptyElement (QName element, XMLAttributes attributes, Augmentations augs)
1097    throws XNIException {
1098
1099        startElement (element, attributes, augs);
1100        endElement (element, augs);
1101
1102    } // emptyElement(QName,XMLAttributes)
1103

1104    /**
1105     * Character content.
1106     *
1107     * @param text The content.
1108     * @param augs Additional information that may include infoset augmentations
1109     *
1110     * @throws XNIException Thrown by handler to signal an error.
1111     */

1112    public void characters (XMLString text, Augmentations augs) throws XNIException {
1113
1114        if (DEBUG_EVENTS) {
1115            System.out.println ("==>characters(): "+text.toString ());
1116        }
1117
1118        if (!fDeferNodeExpansion) {
1119
1120            if (fFilterReject) {
1121                return;
1122            }
1123            if (fInCDATASection && fCreateCDATANodes) {
1124                if (fCurrentCDATASection == null) {
1125                    fCurrentCDATASection =
1126                    fDocument.createCDATASection (text.toString ());
1127                    fCurrentNode.appendChild (fCurrentCDATASection);
1128                    fCurrentNode = fCurrentCDATASection;
1129                }
1130                else {
1131                    fCurrentCDATASection.appendData (text.toString ());
1132                }
1133            }
1134            else if (!fInDTD) {
1135                // if type is union (XML Schema) it is possible that we receive
1136
// character call with empty data
1137
if (text.length == 0) {
1138                    return;
1139                }
1140
1141                String JavaDoc value = text.toString ();
1142                Node JavaDoc child = fCurrentNode.getLastChild ();
1143                if (child != null && child.getNodeType () == Node.TEXT_NODE) {
1144                    // collect all the data into the string buffer.
1145
if (fFirstChunk) {
1146                        if (fDocumentImpl != null) {
1147                            fStringBuffer.append (((TextImpl)child).removeData ());
1148                        } else {
1149                            fStringBuffer.append (((Text JavaDoc)child).getData ());
1150                            ((Text JavaDoc)child).setNodeValue (null);
1151                        }
1152                        fFirstChunk = false;
1153                    }
1154                    fStringBuffer.append (value);
1155                }
1156                else {
1157                    fFirstChunk = true;
1158                    Text JavaDoc textNode = fDocument.createTextNode (value);
1159                    fCurrentNode.appendChild (textNode);
1160                }
1161
1162            }
1163        }
1164        else {
1165            // The Text and CDATASection normalization is taken care of within
1166
// the DOM in the deferred case.
1167
if (fInCDATASection && fCreateCDATANodes) {
1168                if (fCurrentCDATASectionIndex == -1) {
1169                    int cs = fDeferredDocumentImpl.
1170                    createDeferredCDATASection (text.toString ());
1171
1172                    fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, cs);
1173                    fCurrentCDATASectionIndex = cs;
1174                    fCurrentNodeIndex = cs;
1175                }
1176                else {
1177                    int txt = fDeferredDocumentImpl.
1178                    createDeferredTextNode (text.toString (), false);
1179                    fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, txt);
1180                }
1181            } else if (!fInDTD) {
1182                // if type is union (XML Schema) it is possible that we receive
1183
// character call with empty data
1184
if (text.length == 0) {
1185                    return;
1186                }
1187
1188                String JavaDoc value = text.toString ();
1189                int txt = fDeferredDocumentImpl.
1190                createDeferredTextNode (value, false);
1191                fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, txt);
1192
1193            }
1194        }
1195    } // characters(XMLString)
1196

1197    /**
1198     * Ignorable whitespace. For this method to be called, the document
1199     * source must have some way of determining that the text containing
1200     * only whitespace characters should be considered ignorable. For
1201     * example, the validator can determine if a length of whitespace
1202     * characters in the document are ignorable based on the element
1203     * content model.
1204     *
1205     * @param text The ignorable whitespace.
1206     * @param augs Additional information that may include infoset augmentations
1207     *
1208     * @throws XNIException Thrown by handler to signal an error.
1209     */

1210    public void ignorableWhitespace (XMLString text, Augmentations augs) throws XNIException {
1211
1212        if (!fIncludeIgnorableWhitespace || fFilterReject) {
1213            return;
1214        }
1215        if (!fDeferNodeExpansion) {
1216            Node JavaDoc child = fCurrentNode.getLastChild ();
1217            if (child != null && child.getNodeType () == Node.TEXT_NODE) {
1218                Text JavaDoc textNode = (Text JavaDoc)child;
1219                textNode.appendData (text.toString ());
1220            }
1221            else {
1222                Text JavaDoc textNode = fDocument.createTextNode (text.toString ());
1223                if (fDocumentImpl != null) {
1224                    TextImpl textNodeImpl = (TextImpl)textNode;
1225                    textNodeImpl.setIgnorableWhitespace (true);
1226                }
1227                fCurrentNode.appendChild (textNode);
1228            }
1229        }
1230        else {
1231            // The Text normalization is taken care of within the DOM in the
1232
// deferred case.
1233
int txt = fDeferredDocumentImpl.
1234            createDeferredTextNode (text.toString (), true);
1235            fDeferredDocumentImpl.appendChild (fCurrentNodeIndex, txt);
1236        }
1237
1238    } // ignorableWhitespace(XMLString)
1239

1240    /**
1241     * The end of an element.
1242     *
1243     * @param element The name of the element.
1244     * @param augs Additional information that may include infoset augmentations
1245     *
1246     * @throws XNIException Thrown by handler to signal an error.
1247     */

1248    public void endElement (QName element, Augmentations augs) throws XNIException {
1249        if (DEBUG_EVENTS) {
1250            System.out.println ("==>endElement ("+element.rawname+")");
1251        }
1252        if (!fDeferNodeExpansion) {
1253
1254            // REVISIT: Should this happen after we call the filter?
1255
if (augs != null && fDocumentImpl != null && (fNamespaceAware || fStorePSVI)) {
1256                ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI);
1257                if (elementPSVI != null) {
1258                    // Updating TypeInfo. If the declared type is a union the
1259
// [member type definition] will only be available at the
1260
// end of an element.
1261
if (fNamespaceAware) {
1262                        XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
1263                        if (type == null) {
1264                            type = elementPSVI.getTypeDefinition();
1265                        }
1266                        ((ElementNSImpl)fCurrentNode).setType(type);
1267                    }
1268                    if (fStorePSVI) {
1269                        ((PSVIElementNSImpl)fCurrentNode).setPSVI (elementPSVI);
1270                    }
1271                }
1272            }
1273
1274            if (fDOMFilter != null) {
1275                if (fFilterReject) {
1276                    if (element.equals (fRejectedElement)) {
1277                        fFilterReject = false;
1278                    }
1279                    return;
1280                }
1281                if (!fSkippedElemStack.isEmpty ()) {
1282                    if (fSkippedElemStack.peek ().equals (element)) {
1283                        fSkippedElemStack.pop ();
1284                        return;
1285                    }
1286                }
1287                setCharacterData (false);
1288                if (!fRoot.equals(element) && !fInEntityRef && (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_ELEMENT)!=0) {
1289                    short code = fDOMFilter.acceptNode (fCurrentNode);
1290                    switch (code) {
1291                        case LSParserFilter.FILTER_INTERRUPT:{
1292                            throw abort;
1293                        }
1294                        case LSParserFilter.FILTER_REJECT:{
1295                            Node JavaDoc parent = fCurrentNode.getParentNode ();
1296                            parent.removeChild (fCurrentNode);
1297                            fCurrentNode = parent;
1298                            return;
1299                        }
1300                        case LSParserFilter.FILTER_SKIP: {
1301                            // make sure that if any char data is available
1302
// the fFirstChunk is true, so that if the next event
1303
// is characters(), and the last node is text, we will copy
1304
// the value already in the text node to fStringBuffer
1305
// (not to loose it).
1306
fFirstChunk = true;
1307
1308                            // replace children
1309
Node JavaDoc parent = fCurrentNode.getParentNode ();
1310                            NodeList JavaDoc ls = fCurrentNode.getChildNodes ();
1311                            int length = ls.getLength ();
1312
1313                            for (int i=0;i<length;i++) {
1314                                parent.appendChild (ls.item (0));
1315                            }
1316                            parent.removeChild (fCurrentNode);
1317                            fCurrentNode = parent;
1318
1319                            return;
1320                        }
1321
1322                        default: { }
1323                    }
1324                }
1325                fCurrentNode = fCurrentNode.getParentNode ();
1326
1327            } // end-if DOMFilter
1328
else {
1329                setCharacterData (false);
1330                fCurrentNode = fCurrentNode.getParentNode ();
1331            }
1332
1333        }
1334        else {
1335            fCurrentNodeIndex =
1336            fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex, false);
1337        }
1338
1339
1340    } // endElement(QName)
1341

1342
1343    /**
1344     * The start of a CDATA section.
1345     * @param augs Additional information that may include infoset augmentations
1346     *
1347     * @throws XNIException Thrown by handler to signal an error.
1348     */

1349    public void startCDATA (Augmentations augs) throws XNIException {
1350
1351        fInCDATASection = true;
1352        if (!fDeferNodeExpansion) {
1353            if (fFilterReject) {
1354                return;
1355            }
1356            if (fCreateCDATANodes) {
1357                setCharacterData (false);
1358            }
1359        }
1360    } // startCDATA()
1361

1362    /**
1363     * The end of a CDATA section.
1364     * @param augs Additional information that may include infoset augmentations
1365     *
1366     * @throws XNIException Thrown by handler to signal an error.
1367     */

1368    public void endCDATA (Augmentations augs) throws XNIException {
1369
1370        fInCDATASection = false;
1371        if (!fDeferNodeExpansion) {
1372
1373            if (fFilterReject) {
1374                return;
1375            }
1376
1377            if (fCurrentCDATASection !=null) {
1378
1379                if (fDOMFilter !=null && !fInEntityRef &&
1380                (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_CDATA_SECTION)!= 0) {
1381                    short code = fDOMFilter.acceptNode (fCurrentCDATASection);
1382                    switch (code) {
1383                        case LSParserFilter.FILTER_INTERRUPT:{
1384                            throw abort;
1385                        }
1386                        case LSParserFilter.FILTER_REJECT:{
1387                            // fall through to SKIP since CDATA section has no children.
1388
}
1389                        case LSParserFilter.FILTER_SKIP: {
1390                            Node JavaDoc parent = fCurrentNode.getParentNode ();
1391                            parent.removeChild (fCurrentCDATASection);
1392                            fCurrentNode = parent;
1393                            return;
1394                        }
1395
1396                        default: {
1397                            // accept node
1398
}
1399                    }
1400                }
1401
1402                fCurrentNode = fCurrentNode.getParentNode ();
1403                fCurrentCDATASection = null;
1404            }
1405        }
1406        else {
1407            if (fCurrentCDATASectionIndex !=-1) {
1408                fCurrentNodeIndex =
1409                fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex, false);
1410                fCurrentCDATASectionIndex = -1;
1411            }
1412        }
1413
1414    } // endCDATA()
1415

1416    /**
1417     * The end of the document.
1418     * @param augs Additional information that may include infoset augmentations
1419     *
1420     * @throws XNIException Thrown by handler to signal an error.
1421     */

1422    public void endDocument (Augmentations augs) throws XNIException {
1423
1424        if (!fDeferNodeExpansion) {
1425            // REVISIT: when DOM Level 3 is REC rely on Document.support
1426
// instead of specific class
1427
// set DOM error checking back on
1428
if (fDocumentImpl != null) {
1429                fDocumentImpl.setStrictErrorChecking (true);
1430            }
1431            fCurrentNode = null;
1432        }
1433        else {
1434            fCurrentNodeIndex = -1;
1435        }
1436
1437    } // endDocument()
1438

1439    /**
1440     * This method notifies the end of a general entity.
1441     * <p>
1442     * <strong>Note:</strong> This method is not called for entity references
1443     * appearing as part of attribute values.
1444     *
1445     * @param name The name of the entity.
1446     * @param augs Additional information that may include infoset augmentations
1447     *
1448     * @exception XNIException
1449     * Thrown by handler to signal an error.
1450     */

1451    public void endGeneralEntity (String JavaDoc name, Augmentations augs) throws XNIException {
1452        if (DEBUG_EVENTS) {
1453            System.out.println ("==>endGeneralEntity: ("+name+")");
1454        }
1455        if (!fDeferNodeExpansion) {
1456
1457            if (fFilterReject) {
1458                return;
1459            }
1460            setCharacterData (true);
1461
1462            if (fDocumentType != null) {
1463                // get current entity declaration
1464
NamedNodeMap JavaDoc entities = fDocumentType.getEntities ();
1465                fCurrentEntityDecl = (EntityImpl) entities.getNamedItem (name);
1466                if (fCurrentEntityDecl != null) {
1467                    if (fCurrentEntityDecl != null && fCurrentEntityDecl.getFirstChild () == null) {
1468                        fCurrentEntityDecl.setReadOnly (false, true);
1469                        Node JavaDoc child = fCurrentNode.getFirstChild ();
1470                        while (child != null) {
1471                            Node JavaDoc copy = child.cloneNode (true);
1472                            fCurrentEntityDecl.appendChild (copy);
1473                            child = child.getNextSibling ();
1474                        }
1475                        fCurrentEntityDecl.setReadOnly (true, true);
1476
1477                        //entities.setNamedItem(fCurrentEntityDecl);
1478
}
1479                    fCurrentEntityDecl = null;
1480                }
1481
1482            }
1483            fInEntityRef = false;
1484            boolean removeEntityRef = false;
1485            if (fCreateEntityRefNodes) {
1486                if (fDocumentImpl != null) {
1487                    // Make entity ref node read only
1488
((NodeImpl)fCurrentNode).setReadOnly (true, true);
1489                }
1490
1491                if (fDOMFilter !=null &&
1492                (fDOMFilter.getWhatToShow () & NodeFilter.SHOW_ENTITY_REFERENCE)!= 0) {
1493                    short code = fDOMFilter.acceptNode (fCurrentNode);
1494                    switch (code) {
1495                        case LSParserFilter.FILTER_INTERRUPT:{
1496                            throw abort;
1497                        }
1498                        case LSParserFilter.FILTER_REJECT:{
1499                            Node JavaDoc parent = fCurrentNode.getParentNode ();
1500                            parent.removeChild (fCurrentNode);
1501                            fCurrentNode = parent;
1502                            return;
1503
1504                        }
1505                        case LSParserFilter.FILTER_SKIP: {
1506                            // make sure we don't loose chars if next event is characters()
1507
fFirstChunk = true;
1508                            removeEntityRef = true;
1509                            break;
1510                        }
1511
1512                        default: {
1513                            fCurrentNode = fCurrentNode.getParentNode ();
1514                        }
1515                    }
1516                } else {
1517                    fCurrentNode = fCurrentNode.getParentNode ();
1518                }
1519            }
1520
1521            if (!fCreateEntityRefNodes || removeEntityRef) {
1522                // move entity reference children to the list of
1523
// siblings of its parent and remove entity reference
1524
NodeList JavaDoc children = fCurrentNode.getChildNodes ();
1525                Node JavaDoc parent = fCurrentNode.getParentNode ();
1526                int length = children.getLength ();
1527                if (length > 0) {
1528
1529                    // get previous sibling of the entity reference
1530
Node JavaDoc node = fCurrentNode.getPreviousSibling ();
1531                    // normalize text nodes
1532
Node JavaDoc child = children.item (0);
1533                    if (node != null && node.getNodeType () == Node.TEXT_NODE &&
1534                    child.getNodeType () == Node.TEXT_NODE) {
1535                        ((Text JavaDoc)node).appendData (child.getNodeValue ());
1536                        fCurrentNode.removeChild (child);
1537
1538                    } else {
1539                        node = parent.insertBefore (child, fCurrentNode);
1540                        handleBaseURI (node);
1541                    }
1542
1543                    for (int i=1;i <length;i++) {
1544                        node = parent.insertBefore (children.item (0), fCurrentNode);
1545                        handleBaseURI (node);
1546                    }
1547                } // length > 0
1548
parent.removeChild (fCurrentNode);
1549                fCurrentNode = parent;
1550            }
1551        }
1552        else {
1553
1554            if (fDocumentTypeIndex != -1) {
1555                // find corresponding Entity decl
1556
int node = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
1557                while (node != -1) {
1558                    short nodeType = fDeferredDocumentImpl.getNodeType (node, false);
1559                    if (nodeType == Node.ENTITY_NODE) {
1560                        String JavaDoc nodeName =
1561                        fDeferredDocumentImpl.getNodeName (node, false);
1562                        if (nodeName.equals (name)) {
1563                            fDeferredEntityDecl = node;
1564                            break;
1565                        }
1566                    }
1567                    node = fDeferredDocumentImpl.getRealPrevSibling (node, false);
1568                }
1569            }
1570
1571            if (fDeferredEntityDecl != -1 &&
1572            fDeferredDocumentImpl.getLastChild (fDeferredEntityDecl, false) == -1) {
1573                // entity definition exists and it does not have any children
1574
int prevIndex = -1;
1575                int childIndex = fDeferredDocumentImpl.getLastChild (fCurrentNodeIndex, false);
1576                while (childIndex != -1) {
1577                    int cloneIndex = fDeferredDocumentImpl.cloneNode (childIndex, true);
1578                    fDeferredDocumentImpl.insertBefore (fDeferredEntityDecl, cloneIndex, prevIndex);
1579                    prevIndex = cloneIndex;
1580                    childIndex = fDeferredDocumentImpl.getRealPrevSibling (childIndex, false);
1581                }
1582            }
1583            if (fCreateEntityRefNodes) {
1584                fCurrentNodeIndex =
1585                fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex,
1586                false);
1587            } else { //!fCreateEntityRefNodes
1588
// move children of entity ref before the entity ref.
1589
// remove entity ref.
1590

1591                // holds a child of entity ref
1592
int childIndex = fDeferredDocumentImpl.getLastChild (fCurrentNodeIndex, false);
1593                int parentIndex =
1594                fDeferredDocumentImpl.getParentNode (fCurrentNodeIndex,
1595                false);
1596
1597                int prevIndex = fCurrentNodeIndex;
1598                int lastChild = childIndex;
1599                int sibling = -1;
1600                while (childIndex != -1) {
1601                    handleBaseURI (childIndex);
1602                    sibling = fDeferredDocumentImpl.getRealPrevSibling (childIndex, false);
1603                    fDeferredDocumentImpl.insertBefore (parentIndex, childIndex, prevIndex);
1604                    prevIndex = childIndex;
1605                    childIndex = sibling;
1606                }
1607                if(lastChild != -1)
1608                    fDeferredDocumentImpl.setAsLastChild (parentIndex, lastChild);
1609                else{
1610                    sibling = fDeferredDocumentImpl.getRealPrevSibling (prevIndex, false);
1611                    fDeferredDocumentImpl.setAsLastChild (parentIndex, sibling);
1612                }
1613                fCurrentNodeIndex = parentIndex;
1614            }
1615            fDeferredEntityDecl = -1;
1616        }
1617
1618
1619    } // endGeneralEntity(String, Augmentations)
1620

1621
1622    /**
1623     * Record baseURI information for the Element (by adding xml:base attribute)
1624     * or for the ProcessingInstruction (by setting a baseURI field)
1625     * Non deferred DOM.
1626     *
1627     * @param node
1628     */

1629    protected final void handleBaseURI (Node JavaDoc node){
1630        if (fDocumentImpl != null) {
1631            // REVISIT: remove dependency on our implementation when
1632
// DOM L3 becomes REC
1633

1634            String JavaDoc baseURI = null;
1635            short nodeType = node.getNodeType ();
1636
1637            if (nodeType == Node.ELEMENT_NODE) {
1638                // if an element already has xml:base attribute
1639
// do nothing
1640
if (fNamespaceAware) {
1641                    if (((Element JavaDoc)node).getAttributeNodeNS ("http://www.w3.org/XML/1998/namespace","base")!=null) {
1642                        return;
1643                    }
1644                } else if (((Element JavaDoc)node).getAttributeNode ("xml:base") != null) {
1645                    return;
1646                }
1647                // retrive the baseURI from the entity reference
1648
baseURI = ((EntityReferenceImpl)fCurrentNode).getBaseURI ();
1649                if (baseURI !=null && !baseURI.equals (fDocumentImpl.getDocumentURI ())) {
1650                    if (fNamespaceAware) {
1651                        ((Element JavaDoc)node).setAttributeNS ("http://www.w3.org/XML/1998/namespace","base", baseURI);
1652                    } else {
1653                        ((Element JavaDoc)node).setAttribute ("xml:base", baseURI);
1654                    }
1655                }
1656            }
1657            else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
1658
1659                baseURI = ((EntityReferenceImpl)fCurrentNode).getBaseURI ();
1660                if (baseURI !=null && fErrorHandler != null) {
1661                    DOMErrorImpl error = new DOMErrorImpl ();
1662                    error.fType = "pi-base-uri-not-preserved";
1663                    error.fRelatedData = baseURI;
1664                    error.fSeverity = DOMError.SEVERITY_WARNING;
1665                    fErrorHandler.getErrorHandler ().handleError (error);
1666                }
1667            }
1668        }
1669    }
1670
1671    /**
1672     *
1673     * Record baseURI information for the Element (by adding xml:base attribute)
1674     * or for the ProcessingInstruction (by setting a baseURI field)
1675     * Deferred DOM.
1676     *
1677     * @param node
1678     */

1679    protected final void handleBaseURI (int node){
1680        short nodeType = fDeferredDocumentImpl.getNodeType (node, false);
1681
1682        if (nodeType == Node.ELEMENT_NODE) {
1683            String JavaDoc baseURI = fDeferredDocumentImpl.getNodeValueString (fCurrentNodeIndex, false);
1684            if (baseURI == null) {
1685                baseURI = fDeferredDocumentImpl.getDeferredEntityBaseURI (fDeferredEntityDecl);
1686            }
1687            if (baseURI !=null && !baseURI.equals (fDeferredDocumentImpl.getDocumentURI ())) {
1688                fDeferredDocumentImpl.setDeferredAttribute (node,
1689                "xml:base",
1690                "http://www.w3.org/XML/1998/namespace",
1691                baseURI,
1692                true);
1693            }
1694        }
1695        else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
1696
1697
1698            // retrieve baseURI from the entity reference
1699
String JavaDoc baseURI = fDeferredDocumentImpl.getNodeValueString (fCurrentNodeIndex, false);
1700
1701            if (baseURI == null) {
1702                // try baseURI of the entity declaration
1703
baseURI = fDeferredDocumentImpl.getDeferredEntityBaseURI (fDeferredEntityDecl);
1704            }
1705
1706            if (baseURI != null && fErrorHandler != null) {
1707                DOMErrorImpl error = new DOMErrorImpl ();
1708                error.fType = "pi-base-uri-not-preserved";
1709                error.fRelatedData = baseURI;
1710                error.fSeverity = DOMError.SEVERITY_WARNING;
1711                fErrorHandler.getErrorHandler ().handleError (error);
1712            }
1713        }
1714    }
1715
1716
1717    //
1718
// XMLDTDHandler methods
1719
//
1720

1721    /**
1722     * The start of the DTD.
1723     *
1724     * @param locator The document locator, or null if the document
1725     * location cannot be reported during the parsing of
1726     * the document DTD. However, it is <em>strongly</em>
1727     * recommended that a locator be supplied that can
1728     * at least report the base system identifier of the
1729     * DTD.
1730     * @param augs Additional information that may include infoset
1731     * augmentations.
1732     *
1733     * @throws XNIException Thrown by handler to signal an error.
1734     */

1735    public void startDTD (XMLLocator locator, Augmentations augs) throws XNIException {
1736        if (DEBUG_EVENTS) {
1737            System.out.println ("==>startDTD");
1738            if (DEBUG_BASEURI) {
1739                System.out.println (" expandedSystemId: "+locator.getExpandedSystemId ());
1740                System.out.println (" baseURI:"+ locator.getBaseSystemId ());
1741            }
1742        }
1743
1744        fInDTD = true;
1745        if (locator != null) {
1746            fBaseURIStack.push (locator.getBaseSystemId ());
1747        }
1748        if (fDeferNodeExpansion || fDocumentImpl != null) {
1749            fInternalSubset = new StringBuffer JavaDoc (1024);
1750        }
1751    } // startDTD(XMLLocator)
1752

1753
1754    /**
1755     * The end of the DTD.
1756     *
1757     * @param augs Additional information that may include infoset
1758     * augmentations.
1759     *
1760     * @throws XNIException Thrown by handler to signal an error.
1761     */

1762    public void endDTD (Augmentations augs) throws XNIException {
1763        if (DEBUG_EVENTS) {
1764            System.out.println ("==>endDTD()");
1765        }
1766        fInDTD = false;
1767        if (!fBaseURIStack.isEmpty ()) {
1768            fBaseURIStack.pop ();
1769        }
1770        String JavaDoc internalSubset = fInternalSubset != null && fInternalSubset.length () > 0
1771        ? fInternalSubset.toString () : null;
1772        if (fDeferNodeExpansion) {
1773            if (internalSubset != null) {
1774                fDeferredDocumentImpl.setInternalSubset (fDocumentTypeIndex, internalSubset);
1775            }
1776        }
1777        else if (fDocumentImpl != null) {
1778            if (internalSubset != null) {
1779                ((DocumentTypeImpl)fDocumentType).setInternalSubset (internalSubset);
1780            }
1781        }
1782    } // endDTD()
1783

1784    /**
1785     * The start of a conditional section.
1786     *
1787     * @param type The type of the conditional section. This value will
1788     * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
1789     * @param augs Additional information that may include infoset
1790     * augmentations.
1791     *
1792     * @throws XNIException Thrown by handler to signal an error.
1793     *
1794     * @see #CONDITIONAL_INCLUDE
1795     * @see #CONDITIONAL_IGNORE
1796     */

1797    public void startConditional (short type, Augmentations augs) throws XNIException {
1798    } // startConditional(short)
1799

1800    /**
1801     * The end of a conditional section.
1802     *
1803     * @param augs Additional information that may include infoset
1804     * augmentations.
1805     *
1806     * @throws XNIException Thrown by handler to signal an error.
1807     */

1808    public void endConditional (Augmentations augs) throws XNIException {
1809    } // endConditional()
1810

1811
1812    /**
1813     * The start of the DTD external subset.
1814     *
1815     * @param augs Additional information that may include infoset
1816     * augmentations.
1817     *
1818     * @throws XNIException Thrown by handler to signal an error.
1819     */

1820    public void startExternalSubset (XMLResourceIdentifier identifier,
1821    Augmentations augs) throws XNIException {
1822        if (DEBUG_EVENTS) {
1823            System.out.println ("==>startExternalSubset");
1824            if (DEBUG_BASEURI) {
1825                System.out.println (" expandedSystemId: "+identifier.getExpandedSystemId ());
1826                System.out.println (" baseURI:"+ identifier.getBaseSystemId ());
1827            }
1828        }
1829        fBaseURIStack.push (identifier.getBaseSystemId ());
1830        fInDTDExternalSubset = true;
1831    } // startExternalSubset(Augmentations)
1832

1833    /**
1834     * The end of the DTD external subset.
1835     *
1836     * @param augs Additional information that may include infoset
1837     * augmentations.
1838     *
1839     * @throws XNIException Thrown by handler to signal an error.
1840     */

1841    public void endExternalSubset (Augmentations augs) throws XNIException {
1842        fInDTDExternalSubset = false;
1843        fBaseURIStack.pop ();
1844    } // endExternalSubset(Augmentations)
1845

1846    /**
1847     * An internal entity declaration.
1848     *
1849     * @param name The name of the entity. Parameter entity names start with
1850     * '%', whereas the name of a general entity is just the
1851     * entity name.
1852     * @param text The value of the entity.
1853     * @param nonNormalizedText The non-normalized value of the entity. This
1854     * value contains the same sequence of characters that was in
1855     * the internal entity declaration, without any entity
1856     * references expanded.
1857     * @param augs Additional information that may include infoset
1858     * augmentations.
1859     *
1860     * @throws XNIException Thrown by handler to signal an error.
1861     */

1862    public void internalEntityDecl (String JavaDoc name, XMLString text,
1863    XMLString nonNormalizedText,
1864    Augmentations augs) throws XNIException {
1865
1866        if (DEBUG_EVENTS) {
1867            System.out.println ("==>internalEntityDecl: "+name);
1868            if (DEBUG_BASEURI) {
1869                System.out.println (" baseURI:"+ (String JavaDoc)fBaseURIStack.peek ());
1870            }
1871        }
1872        // internal subset string
1873
if (fInternalSubset != null && !fInDTDExternalSubset) {
1874            fInternalSubset.append ("<!ENTITY ");
1875            if (name.startsWith ("%")) {
1876                fInternalSubset.append ("% ");
1877                fInternalSubset.append (name.substring (1));
1878            }
1879            else {
1880                fInternalSubset.append (name);
1881            }
1882            fInternalSubset.append (' ');
1883            String JavaDoc value = nonNormalizedText.toString ();
1884            boolean singleQuote = value.indexOf ('\'') == -1;
1885            fInternalSubset.append (singleQuote ? '\'' : '"');
1886            fInternalSubset.append (value);
1887            fInternalSubset.append (singleQuote ? '\'' : '"');
1888            fInternalSubset.append (">\n");
1889        }
1890
1891        // NOTE: We only know how to create these nodes for the Xerces
1892
// DOM implementation because DOM Level 2 does not specify
1893
// that functionality. -Ac
1894

1895        // create full node
1896
// don't add parameter entities!
1897
if(name.startsWith ("%"))
1898            return;
1899        if (fDocumentType != null) {
1900            NamedNodeMap JavaDoc entities = fDocumentType.getEntities ();
1901            EntityImpl entity = (EntityImpl)entities.getNamedItem (name);
1902            if (entity == null) {
1903                entity = (EntityImpl)fDocumentImpl.createEntity (name);
1904                entity.setBaseURI ((String JavaDoc)fBaseURIStack.peek ());
1905                entities.setNamedItem (entity);
1906            }
1907        }
1908
1909        // create deferred node
1910
if (fDocumentTypeIndex != -1) {
1911            boolean found = false;
1912            int node = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
1913            while (node != -1) {
1914                short nodeType = fDeferredDocumentImpl.getNodeType (node, false);
1915                if (nodeType == Node.ENTITY_NODE) {
1916                    String JavaDoc nodeName = fDeferredDocumentImpl.getNodeName (node, false);
1917                    if (nodeName.equals (name)) {
1918                        found = true;
1919                        break;
1920                    }
1921                }
1922                node = fDeferredDocumentImpl.getRealPrevSibling (node, false);
1923            }
1924            if (!found) {
1925                int entityIndex =
1926                fDeferredDocumentImpl.createDeferredEntity (name, null, null, null, (String JavaDoc)fBaseURIStack.peek ());
1927                fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, entityIndex);
1928            }
1929        }
1930
1931    } // internalEntityDecl(String,XMLString,XMLString)
1932

1933    /**
1934     * An external entity declaration.
1935     *
1936     * @param name The name of the entity. Parameter entity names start
1937     * with '%', whereas the name of a general entity is just
1938     * the entity name.
1939     * @param identifier An object containing all location information
1940     * pertinent to this notation.
1941     * @param augs Additional information that may include infoset
1942     * augmentations.
1943     *
1944     * @throws XNIException Thrown by handler to signal an error.
1945     */

1946    public void externalEntityDecl (String JavaDoc name, XMLResourceIdentifier identifier,
1947    Augmentations augs) throws XNIException {
1948
1949
1950        if (DEBUG_EVENTS) {
1951            System.out.println ("==>externalEntityDecl: "+name);
1952            if (DEBUG_BASEURI) {
1953                System.out.println (" expandedSystemId:"+ identifier.getExpandedSystemId ());
1954                System.out.println (" baseURI:"+ identifier.getBaseSystemId ());
1955            }
1956        }
1957        // internal subset string
1958
String JavaDoc publicId = identifier.getPublicId ();
1959        String JavaDoc literalSystemId = identifier.getLiteralSystemId ();
1960        if (fInternalSubset != null && !fInDTDExternalSubset) {
1961            fInternalSubset.append ("<!ENTITY ");
1962            if (name.startsWith ("%")) {
1963                fInternalSubset.append ("% ");
1964                fInternalSubset.append (name.substring (1));
1965            }
1966            else {
1967                fInternalSubset.append (name);
1968            }
1969            fInternalSubset.append (' ');
1970            if (publicId != null) {
1971                fInternalSubset.append ("PUBLIC '");
1972                fInternalSubset.append (publicId);
1973                fInternalSubset.append ("' '");
1974            }
1975            else {
1976                fInternalSubset.append ("SYSTEM '");
1977            }
1978            fInternalSubset.append (literalSystemId);
1979            fInternalSubset.append ("'>\n");
1980        }
1981
1982        // NOTE: We only know how to create these nodes for the Xerces
1983
// DOM implementation because DOM Level 2 does not specify
1984
// that functionality. -Ac
1985

1986        // create full node
1987
// don't add parameter entities!
1988
if(name.startsWith ("%"))
1989            return;
1990        if (fDocumentType != null) {
1991            NamedNodeMap JavaDoc entities = fDocumentType.getEntities ();
1992            EntityImpl entity = (EntityImpl)entities.getNamedItem (name);
1993            if (entity == null) {
1994                entity = (EntityImpl)fDocumentImpl.createEntity (name);
1995                entity.setPublicId (publicId);
1996                entity.setSystemId (literalSystemId);
1997                entity.setBaseURI (identifier.getBaseSystemId ());
1998                entities.setNamedItem (entity);
1999            }
2000        }
2001
2002        // create deferred node
2003
if (fDocumentTypeIndex != -1) {
2004            boolean found = false;
2005            int nodeIndex = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
2006            while (nodeIndex != -1) {
2007                short nodeType = fDeferredDocumentImpl.getNodeType (nodeIndex, false);
2008                if (nodeType == Node.ENTITY_NODE) {
2009                    String JavaDoc nodeName = fDeferredDocumentImpl.getNodeName (nodeIndex, false);
2010                    if (nodeName.equals (name)) {
2011                        found = true;
2012                        break;
2013                    }
2014                }
2015                nodeIndex = fDeferredDocumentImpl.getRealPrevSibling (nodeIndex, false);
2016            }
2017            if (!found) {
2018                int entityIndex = fDeferredDocumentImpl.createDeferredEntity (
2019                name, publicId, literalSystemId, null, identifier.getBaseSystemId ());
2020                fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, entityIndex);
2021            }
2022        }
2023
2024    } // externalEntityDecl(String,XMLResourceIdentifier, Augmentations)
2025

2026
2027    /**
2028     * This method notifies of the start of a parameter entity. The parameter
2029     * entity name start with a '%' character.
2030     *
2031     * @param name The name of the parameter entity.
2032     * @param identifier The resource identifier.
2033     * @param encoding The auto-detected IANA encoding name of the entity
2034     * stream. This value will be null in those situations
2035     * where the entity encoding is not auto-detected (e.g.
2036     * internal parameter entities).
2037     * @param augs Additional information that may include infoset
2038     * augmentations.
2039     *
2040     * @throws XNIException Thrown by handler to signal an error.
2041     */

2042    public void startParameterEntity (String JavaDoc name,
2043    XMLResourceIdentifier identifier,
2044    String JavaDoc encoding,
2045    Augmentations augs) throws XNIException {
2046        if (DEBUG_EVENTS) {
2047            System.out.println ("==>startParameterEntity: "+name);
2048            if (DEBUG_BASEURI) {
2049                System.out.println (" expandedSystemId: "+identifier.getExpandedSystemId ());
2050                System.out.println (" baseURI:"+ identifier.getBaseSystemId ());
2051            }
2052        }
2053        fBaseURIStack.push (identifier.getExpandedSystemId ());
2054    }
2055
2056
2057    /**
2058     * This method notifies the end of a parameter entity. Parameter entity
2059     * names begin with a '%' character.
2060     *
2061     * @param name The name of the parameter entity.
2062     * @param augs Additional information that may include infoset
2063     * augmentations.
2064     *
2065     * @throws XNIException Thrown by handler to signal an error.
2066     */

2067    public void endParameterEntity (String JavaDoc name, Augmentations augs) throws XNIException {
2068
2069        if (DEBUG_EVENTS) {
2070            System.out.println ("==>endParameterEntity: "+name);
2071        }
2072        fBaseURIStack.pop ();
2073    }
2074
2075    /**
2076     * An unparsed entity declaration.
2077     *
2078     * @param name The name of the entity.
2079     * @param identifier An object containing all location information
2080     * pertinent to this entity.
2081     * @param notation The name of the notation.
2082     * @param augs Additional information that may include infoset
2083     * augmentations.
2084     *
2085     * @throws XNIException Thrown by handler to signal an error.
2086     */

2087    public void unparsedEntityDecl (String JavaDoc name, XMLResourceIdentifier identifier,
2088    String JavaDoc notation, Augmentations augs)
2089    throws XNIException {
2090
2091        if (DEBUG_EVENTS) {
2092            System.out.println ("==>unparsedEntityDecl: "+name);
2093            if (DEBUG_BASEURI) {
2094                System.out.println (" expandedSystemId:"+ identifier.getExpandedSystemId ());
2095                System.out.println (" baseURI:"+ identifier.getBaseSystemId ());
2096            }
2097        }
2098        // internal subset string
2099
String JavaDoc publicId = identifier.getPublicId ();
2100        String JavaDoc literalSystemId = identifier.getLiteralSystemId ();
2101        if (fInternalSubset != null && !fInDTDExternalSubset) {
2102            fInternalSubset.append ("<!ENTITY ");
2103            fInternalSubset.append (name);
2104            fInternalSubset.append (' ');
2105            if (publicId != null) {
2106                fInternalSubset.append ("PUBLIC '");
2107                fInternalSubset.append (publicId);
2108                if (literalSystemId != null) {
2109                    fInternalSubset.append ("' '");
2110                    fInternalSubset.append (literalSystemId);
2111                }
2112            }
2113            else {
2114                fInternalSubset.append ("SYSTEM '");
2115                fInternalSubset.append (literalSystemId);
2116            }
2117            fInternalSubset.append ("' NDATA ");
2118            fInternalSubset.append (notation);
2119            fInternalSubset.append (">\n");
2120        }
2121
2122        // NOTE: We only know how to create these nodes for the Xerces
2123
// DOM implementation because DOM Level 2 does not specify
2124
// that functionality. -Ac
2125

2126        // create full node
2127
if (fDocumentType != null) {
2128            NamedNodeMap JavaDoc entities = fDocumentType.getEntities ();
2129            EntityImpl entity = (EntityImpl)entities.getNamedItem (name);
2130            if (entity == null) {
2131                entity = (EntityImpl)fDocumentImpl.createEntity (name);
2132                entity.setPublicId (publicId);
2133                entity.setSystemId (literalSystemId);
2134                entity.setNotationName (notation);
2135                entity.setBaseURI (identifier.getBaseSystemId ());
2136                entities.setNamedItem (entity);
2137            }
2138        }
2139
2140        // create deferred node
2141
if (fDocumentTypeIndex != -1) {
2142            boolean found = false;
2143            int nodeIndex = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
2144            while (nodeIndex != -1) {
2145                short nodeType = fDeferredDocumentImpl.getNodeType (nodeIndex, false);
2146                if (nodeType == Node.ENTITY_NODE) {
2147                    String JavaDoc nodeName = fDeferredDocumentImpl.getNodeName (nodeIndex, false);
2148                    if (nodeName.equals (name)) {
2149                        found = true;
2150                        break;
2151                    }
2152                }
2153                nodeIndex = fDeferredDocumentImpl.getRealPrevSibling (nodeIndex, false);
2154            }
2155            if (!found) {
2156                int entityIndex = fDeferredDocumentImpl.createDeferredEntity (
2157                name, publicId, literalSystemId, notation, identifier.getBaseSystemId ());
2158                fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, entityIndex);
2159            }
2160        }
2161
2162    } // unparsedEntityDecl(String,XMLResourceIdentifier, String, Augmentations)
2163

2164    /**
2165     * A notation declaration
2166     *
2167     * @param name The name of the notation.
2168     * @param identifier An object containing all location information
2169     * pertinent to this notation.
2170     * @param augs Additional information that may include infoset
2171     * augmentations.
2172     *
2173     * @throws XNIException Thrown by handler to signal an error.
2174     */

2175    public void notationDecl (String JavaDoc name, XMLResourceIdentifier identifier,
2176    Augmentations augs) throws XNIException {
2177
2178        // internal subset string
2179
String JavaDoc publicId = identifier.getPublicId ();
2180        String JavaDoc literalSystemId = identifier.getLiteralSystemId ();
2181        if (fInternalSubset != null && !fInDTDExternalSubset) {
2182            fInternalSubset.append ("<!NOTATION ");
2183            fInternalSubset.append (name);
2184            if (publicId != null) {
2185                fInternalSubset.append (" PUBLIC '");
2186                fInternalSubset.append (publicId);
2187                if (literalSystemId != null) {
2188                    fInternalSubset.append ("' '");
2189                    fInternalSubset.append (literalSystemId);
2190                }
2191            }
2192            else {
2193                fInternalSubset.append (" SYSTEM '");
2194                fInternalSubset.append (literalSystemId);
2195            }
2196            fInternalSubset.append ("'>\n");
2197        }
2198
2199        // NOTE: We only know how to create these nodes for the Xerces
2200
// DOM implementation because DOM Level 2 does not specify
2201
// that functionality. -Ac
2202

2203        // create full node
2204
if (fDocumentImpl !=null && fDocumentType != null) {
2205            NamedNodeMap JavaDoc notations = fDocumentType.getNotations ();
2206            if (notations.getNamedItem (name) == null) {
2207                NotationImpl notation = (NotationImpl)fDocumentImpl.createNotation (name);
2208                notation.setPublicId (publicId);
2209                notation.setSystemId (literalSystemId);
2210                notation.setBaseURI (identifier.getBaseSystemId ());
2211                notations.setNamedItem (notation);
2212            }
2213        }
2214
2215        // create deferred node
2216
if (fDocumentTypeIndex != -1) {
2217            boolean found = false;
2218            int nodeIndex = fDeferredDocumentImpl.getLastChild (fDocumentTypeIndex, false);
2219            while (nodeIndex != -1) {
2220                short nodeType = fDeferredDocumentImpl.getNodeType (nodeIndex, false);
2221                if (nodeType == Node.NOTATION_NODE) {
2222                    String JavaDoc nodeName = fDeferredDocumentImpl.getNodeName (nodeIndex, false);
2223                    if (nodeName.equals (name)) {
2224                        found = true;
2225                        break;
2226                    }
2227                }
2228                nodeIndex = fDeferredDocumentImpl.getPrevSibling (nodeIndex, false);
2229            }
2230            if (!found) {
2231                int notationIndex = fDeferredDocumentImpl.createDeferredNotation (
2232                name, publicId, literalSystemId, identifier.getBaseSystemId ());
2233                fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, notationIndex);
2234            }
2235        }
2236
2237    } // notationDecl(String,XMLResourceIdentifier, Augmentations)
2238

2239    /**
2240     * Characters within an IGNORE conditional section.
2241     *
2242     * @param text The ignored text.
2243     * @param augs Additional information that may include infoset
2244     * augmentations.
2245     *
2246     * @throws XNIException Thrown by handler to signal an error.
2247     */

2248    public void ignoredCharacters (XMLString text, Augmentations augs) throws XNIException {
2249    } // ignoredCharacters(XMLString, Augmentations)
2250

2251
2252    /**
2253     * An element declaration.
2254     *
2255     * @param name The name of the element.
2256     * @param contentModel The element content model.
2257     * @param augs Additional information that may include infoset
2258     * augmentations.
2259     *
2260     * @throws XNIException Thrown by handler to signal an error.
2261     */

2262    public void elementDecl (String JavaDoc name, String JavaDoc contentModel, Augmentations augs)
2263    throws XNIException {
2264
2265        // internal subset string
2266
if (fInternalSubset != null && !fInDTDExternalSubset) {
2267            fInternalSubset.append ("<!ELEMENT ");
2268            fInternalSubset.append (name);
2269            fInternalSubset.append (' ');
2270            fInternalSubset.append (contentModel);
2271            fInternalSubset.append (">\n");
2272        }
2273
2274    } // elementDecl(String,String)
2275

2276    /**
2277     * An attribute declaration.
2278     *
2279     * @param elementName The name of the element that this attribute
2280     * is associated with.
2281     * @param attributeName The name of the attribute.
2282     * @param type The attribute type. This value will be one of
2283     * the following: "CDATA", "ENTITY", "ENTITIES",
2284     * "ENUMERATION", "ID", "IDREF", "IDREFS",
2285     * "NMTOKEN", "NMTOKENS", or "NOTATION".
2286     * @param enumeration If the type has the value "ENUMERATION" or
2287     * "NOTATION", this array holds the allowed attribute
2288     * values; otherwise, this array is null.
2289     * @param defaultType The attribute default type. This value will be
2290     * one of the following: "#FIXED", "#IMPLIED",
2291     * "#REQUIRED", or null.
2292     * @param defaultValue The attribute default value, or null if no
2293     * default value is specified.
2294     * @param nonNormalizedDefaultValue The attribute default value with no normalization
2295     * performed, or null if no default value is specified.
2296     * @param augs Additional information that may include infoset
2297     * augmentations.
2298     *
2299     * @throws XNIException Thrown by handler to signal an error.
2300     */

2301    public void attributeDecl (String JavaDoc elementName, String JavaDoc attributeName,
2302    String JavaDoc type, String JavaDoc[] enumeration,
2303    String JavaDoc defaultType, XMLString defaultValue,
2304    XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
2305
2306        // internal subset string
2307
if (fInternalSubset != null && !fInDTDExternalSubset) {
2308            fInternalSubset.append ("<!ATTLIST ");
2309            fInternalSubset.append (elementName);
2310            fInternalSubset.append (' ');
2311            fInternalSubset.append (attributeName);
2312            fInternalSubset.append (' ');
2313            if (type.equals ("ENUMERATION")) {
2314                fInternalSubset.append ('(');
2315                for (int i = 0; i < enumeration.length; i++) {
2316                    if (i > 0) {
2317                        fInternalSubset.append ('|');
2318                    }
2319                    fInternalSubset.append (enumeration[i]);
2320                }
2321                fInternalSubset.append (')');
2322            }
2323            else {
2324                fInternalSubset.append (type);
2325            }
2326            if (defaultType != null) {
2327                fInternalSubset.append (' ');
2328                fInternalSubset.append (defaultType);
2329            }
2330            if (defaultValue != null) {
2331                fInternalSubset.append (" '");
2332                for (int i = 0; i < defaultValue.length; i++) {
2333                    char c = defaultValue.ch[defaultValue.offset + i];
2334                    if (c == '\'') {
2335                        fInternalSubset.append ("&apos;");
2336                    }
2337                    else {
2338                        fInternalSubset.append (c);
2339                    }
2340                }
2341                fInternalSubset.append ('\'');
2342            }
2343            fInternalSubset.append (">\n");
2344        }
2345        // REVISIT: This code applies to the support of domx/grammar-access
2346
// feature in Xerces 1
2347

2348        // deferred expansion
2349
if (fDeferredDocumentImpl != null) {
2350
2351            // get the default value
2352
if (defaultValue != null) {
2353
2354                // get element definition
2355
int elementDefIndex = fDeferredDocumentImpl.lookupElementDefinition (elementName);
2356
2357                // create element definition if not already there
2358
if (elementDefIndex == -1) {
2359                    elementDefIndex = fDeferredDocumentImpl.createDeferredElementDefinition (elementName);
2360                    fDeferredDocumentImpl.appendChild (fDocumentTypeIndex, elementDefIndex);
2361                }
2362                // add default attribute
2363
int attrIndex = fDeferredDocumentImpl.createDeferredAttribute (
2364                attributeName, defaultValue.toString (), false);
2365                if ("ID".equals (type)) {
2366                    fDeferredDocumentImpl.setIdAttribute (attrIndex);
2367                }
2368                // REVISIT: set ID type correctly
2369
fDeferredDocumentImpl.appendChild (elementDefIndex, attrIndex);
2370            }
2371
2372        } // if deferred
2373

2374        // full expansion
2375
else if (fDocumentImpl != null) {
2376
2377            // get the default value
2378
if (defaultValue != null) {
2379
2380                // get element definition node
2381
NamedNodeMap JavaDoc elements = ((DocumentTypeImpl)fDocumentType).getElements ();
2382                ElementDefinitionImpl elementDef = (ElementDefinitionImpl)elements.getNamedItem (elementName);
2383                if (elementDef == null) {
2384                    elementDef = fDocumentImpl.createElementDefinition (elementName);
2385                    ((DocumentTypeImpl)fDocumentType).getElements ().setNamedItem (elementDef);
2386                }
2387
2388                // REVISIT: Check for uniqueness of element name? -Ac
2389

2390                // create attribute and set properties
2391
boolean nsEnabled = fNamespaceAware;
2392                AttrImpl attr;
2393                if (nsEnabled) {
2394                    String JavaDoc namespaceURI = null;
2395                    // DOM Level 2 wants all namespace declaration attributes
2396
// to be bound to "http://www.w3.org/2000/xmlns/"
2397
// So as long as the XML parser doesn't do it, it needs to
2398
// done here.
2399
if (attributeName.startsWith ("xmlns:") ||
2400                    attributeName.equals ("xmlns")) {
2401                        namespaceURI = NamespaceContext.XMLNS_URI;
2402                    }
2403                    attr = (AttrImpl)fDocumentImpl.createAttributeNS (namespaceURI,
2404                    attributeName);
2405                }
2406                else {
2407                    attr = (AttrImpl)fDocumentImpl.createAttribute (attributeName);
2408                }
2409                attr.setValue (defaultValue.toString ());
2410                attr.setSpecified (false);
2411                attr.setIdAttribute ("ID".equals (type));
2412
2413                // add default attribute to element definition
2414
if (nsEnabled){
2415                    elementDef.getAttributes ().setNamedItemNS (attr);
2416                }
2417                else {
2418                    elementDef.getAttributes ().setNamedItem (attr);
2419                }
2420            }
2421
2422        } // if NOT defer-node-expansion
2423

2424    } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
2425

2426
2427    /**
2428     * The start of an attribute list.
2429     *
2430     * @param elementName The name of the element that this attribute
2431     * list is associated with.
2432     * @param augs Additional information that may include infoset
2433     * augmentations.
2434     *
2435     * @throws XNIException Thrown by handler to signal an error.
2436     */

2437    public void startAttlist (String JavaDoc elementName, Augmentations augs) throws XNIException {
2438    } // startAttlist(String)
2439

2440
2441    /**
2442     * The end of an attribute list.
2443     *
2444     * @param augs Additional information that may include infoset
2445     * augmentations.
2446     *
2447     * @throws XNIException Thrown by handler to signal an error.
2448     */

2449    public void endAttlist (Augmentations augs) throws XNIException {
2450    } // endAttlist()
2451

2452
2453    // method to create an element node.
2454
// subclasses can override this method to create element nodes in other ways.
2455
protected Element JavaDoc createElementNode (QName element) {
2456        Element JavaDoc el = null;
2457
2458        if (fNamespaceAware) {
2459            // if we are using xerces DOM implementation, call our
2460
// own constructor to reuse the strings we have here.
2461
if (fDocumentImpl != null) {
2462                el = fDocumentImpl.createElementNS (element.uri, element.rawname,
2463                element.localpart);
2464            }
2465            else {
2466                el = fDocument.createElementNS (element.uri, element.rawname);
2467            }
2468        }
2469        else {
2470            el = fDocument.createElement (element.rawname);
2471        }
2472
2473        return el;
2474    }
2475
2476    // method to create an attribute node.
2477
// subclasses can override this method to create attribute nodes in other ways.
2478
protected Attr JavaDoc createAttrNode (QName attrQName) {
2479        Attr JavaDoc attr = null;
2480
2481        if (fNamespaceAware) {
2482            if (fDocumentImpl != null) {
2483                // if we are using xerces DOM implementation, call our
2484
// own constructor to reuse the strings we have here.
2485
attr = fDocumentImpl.createAttributeNS (attrQName.uri,
2486                attrQName.rawname,
2487                attrQName.localpart);
2488            }
2489            else {
2490                attr = fDocument.createAttributeNS (attrQName.uri,
2491                attrQName.rawname);
2492            }
2493        }
2494        else {
2495            attr = fDocument.createAttribute (attrQName.rawname);
2496        }
2497
2498        return attr;
2499    }
2500
2501    /*
2502     * When the first characters() call is received, the data is stored in
2503     * a new Text node. If right after the first characters() we receive another chunk of data,
2504     * the data from the Text node, following the new characters are appended
2505     * to the fStringBuffer and the text node data is set to empty.
2506     *
2507     * This function is called when the state is changed and the
2508     * data must be appended to the current node.
2509     *
2510     * Note: if DOMFilter is set, you must make sure that if Node is skipped,
2511     * or removed fFistChunk must be set to true, otherwise some data can be lost.
2512     *
2513     */

2514    protected void setCharacterData (boolean sawChars){
2515
2516        // handle character data
2517
fFirstChunk = sawChars;
2518
2519
2520        // if we have data in the buffer we must have created
2521
// a text node already.
2522

2523        Node JavaDoc child = fCurrentNode.getLastChild ();
2524        if (child != null) {
2525            if (fStringBuffer.length () > 0) {
2526                // REVISIT: should this check be performed?
2527
if (child.getNodeType () == Node.TEXT_NODE) {
2528                    if (fDocumentImpl != null) {
2529                        ((TextImpl)child).replaceData (fStringBuffer.toString ());
2530                    }
2531                    else {
2532                        ((Text JavaDoc)child).setData (fStringBuffer.toString ());
2533                    }
2534                }
2535                // reset string buffer
2536
fStringBuffer.setLength (0);
2537            }
2538
2539            if (fDOMFilter !=null && !fInEntityRef) {
2540                if ( (child.getNodeType () == Node.TEXT_NODE ) &&
2541                ((fDOMFilter.getWhatToShow () & NodeFilter.SHOW_TEXT)!= 0) ) {
2542                    short code = fDOMFilter.acceptNode (child);
2543                    switch (code) {
2544                        case LSParserFilter.FILTER_INTERRUPT:{
2545                            throw abort;
2546                        }
2547                        case LSParserFilter.FILTER_REJECT:{
2548                            // fall through to SKIP since Comment has no children.
2549
}
2550                        case LSParserFilter.FILTER_SKIP: {
2551                            fCurrentNode.removeChild (child);
2552                            return;
2553                        }
2554                        default: {
2555                            // accept node -- do nothing
2556
}
2557                    }
2558                }
2559            } // end-if fDOMFilter !=null
2560

2561        } // end-if child !=null
2562
}
2563
2564
2565    /**
2566     * @see org.w3c.dom.ls.LSParser#abort()
2567     */

2568    public void abort () {
2569        throw abort;
2570    }
2571
2572
2573} // class AbstractDOMParser
2574
Popular Tags