KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > impl > dtd > XMLDTDProcessor


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999-2002 The Apache Software Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package com.sun.org.apache.xerces.internal.impl.dtd;
59
60 import java.util.Enumeration JavaDoc;
61 import java.util.Hashtable JavaDoc;
62 import java.util.Locale JavaDoc;
63 import java.util.StringTokenizer JavaDoc;
64 import java.util.Vector JavaDoc;
65
66 import com.sun.org.apache.xerces.internal.impl.Constants;
67 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
68 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
69 import com.sun.org.apache.xerces.internal.util.SymbolTable;
70 import com.sun.org.apache.xerces.internal.util.XMLChar;
71 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
72 import com.sun.org.apache.xerces.internal.xni.Augmentations;
73 import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
74 import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
75 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
76 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
77 import com.sun.org.apache.xerces.internal.xni.XMLString;
78 import com.sun.org.apache.xerces.internal.xni.XNIException;
79 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
80 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
81 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
82 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
83 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
84 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
85 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelFilter;
86 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource;
87 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDFilter;
88 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource;
89
90 /**
91  * The DTD processor. The processor implements a DTD
92  * filter: receiving DTD events from the DTD scanner; validating
93  * the content and structure; building a grammar, if applicable;
94  * and notifying the DTDHandler of the information resulting from the
95  * process.
96  * <p>
97  * This component requires the following features and properties from the
98  * component manager that uses it:
99  * <ul>
100  * <li>http://xml.org/sax/features/namespaces</li>
101  * <li>http://apache.org/xml/properties/internal/symbol-table</li>
102  * <li>http://apache.org/xml/properties/internal/error-reporter</li>
103  * <li>http://apache.org/xml/properties/internal/grammar-pool</li>
104  * <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
105  * </ul>
106  *
107  * @author Neil Graham, IBM
108  *
109  * @version $Id: XMLDTDProcessor.java,v 1.11 2003/11/10 00:59:46 mrglavas Exp $
110  */

111 public class XMLDTDProcessor
112         implements XMLComponent, XMLDTDFilter, XMLDTDContentModelFilter {
113
114     //
115
// Constants
116
//
117

118     /** Top level scope (-1). */
119     private static final int TOP_LEVEL_SCOPE = -1;
120
121     // feature identifiers
122

123     /** Feature identifier: validation. */
124     protected static final String JavaDoc VALIDATION =
125         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
126
127     /** Feature identifier: notify character references. */
128     protected static final String JavaDoc NOTIFY_CHAR_REFS =
129         Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_CHAR_REFS_FEATURE;
130
131     /** Feature identifier: warn on duplicate attdef */
132     protected static final String JavaDoc WARN_ON_DUPLICATE_ATTDEF =
133         Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
134         
135     protected static final String JavaDoc PARSER_SETTINGS =
136             Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
137
138     // property identifiers
139

140     /** Property identifier: symbol table. */
141     protected static final String JavaDoc SYMBOL_TABLE =
142         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
143
144     /** Property identifier: error reporter. */
145     protected static final String JavaDoc ERROR_REPORTER =
146         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
147
148     /** Property identifier: grammar pool. */
149     protected static final String JavaDoc GRAMMAR_POOL =
150         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
151
152     /** Property identifier: validator . */
153     protected static final String JavaDoc DTD_VALIDATOR =
154         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
155
156     // recognized features and properties
157

158     /** Recognized features. */
159     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
160         VALIDATION,
161         WARN_ON_DUPLICATE_ATTDEF,
162         NOTIFY_CHAR_REFS,
163     };
164
165     /** Feature defaults. */
166     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = {
167         null,
168         Boolean.FALSE,
169         null,
170     };
171
172     /** Recognized properties. */
173     private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
174         SYMBOL_TABLE,
175         ERROR_REPORTER,
176         GRAMMAR_POOL,
177         DTD_VALIDATOR,
178     };
179
180     /** Property defaults. */
181     private static final Object JavaDoc[] PROPERTY_DEFAULTS = {
182         null,
183         null,
184         null,
185         null,
186     };
187
188     // debugging
189

190     //
191
// Data
192
//
193

194     // features
195

196     /** Validation. */
197     protected boolean fValidation;
198
199     /** Validation against only DTD */
200     protected boolean fDTDValidation;
201
202     /** warn on duplicate attribute definition, this feature works only when validation is true */
203     protected boolean fWarnDuplicateAttdef;
204         
205     // properties
206

207     /** Symbol table. */
208     protected SymbolTable fSymbolTable;
209
210     /** Error reporter. */
211     protected XMLErrorReporter fErrorReporter;
212
213     /** Grammar bucket. */
214     protected DTDGrammarBucket fGrammarBucket;
215
216     // the validator to which we look for our grammar bucket (the
217
// validator needs to hold the bucket so that it can initialize
218
// the grammar with details like whether it's for a standalone document...
219
protected XMLDTDValidator fValidator;
220
221     // the grammar pool we'll try to add the grammar to:
222
protected XMLGrammarPool fGrammarPool;
223
224     // what's our Locale?
225
protected Locale JavaDoc fLocale;
226
227     // handlers
228

229     /** DTD handler. */
230     protected XMLDTDHandler fDTDHandler;
231
232     /** DTD source. */
233     protected XMLDTDSource fDTDSource;
234
235     /** DTD content model handler. */
236     protected XMLDTDContentModelHandler fDTDContentModelHandler;
237
238     /** DTD content model source. */
239     protected XMLDTDContentModelSource fDTDContentModelSource;
240
241     // grammars
242

243     /** DTD Grammar. */
244     protected DTDGrammar fDTDGrammar;
245
246     // state
247

248     /** Perform validation. */
249     private boolean fPerformValidation;
250
251     /** True if in an ignore conditional section of the DTD. */
252     protected boolean fInDTDIgnore;
253
254     // information regarding the current element
255

256     // validation states
257

258     /** Mixed. */
259     private boolean fMixed;
260
261     // temporary variables
262

263     /** Temporary entity declaration. */
264     private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
265
266     /** Notation declaration hash. */
267     private Hashtable JavaDoc fNDataDeclNotations = new Hashtable JavaDoc();
268
269     /** DTD element declaration name. */
270     private String JavaDoc fDTDElementDeclName = null;
271
272     /** Mixed element type "hash". */
273     private Vector JavaDoc fMixedElementTypes = new Vector JavaDoc();
274
275     /** Element declarations in DTD. */
276     private Vector JavaDoc fDTDElementDecls = new Vector JavaDoc();
277
278     // to check for duplicate ID or ANNOTATION attribute declare in
279
// ATTLIST, and misc VCs
280

281     /** ID attribute names. */
282     private Hashtable JavaDoc fTableOfIDAttributeNames;
283
284     /** NOTATION attribute names. */
285     private Hashtable JavaDoc fTableOfNOTATIONAttributeNames;
286
287     /** NOTATION enumeration values. */
288     private Hashtable JavaDoc fNotationEnumVals;
289
290     //
291
// Constructors
292
//
293

294     /** Default constructor. */
295     public XMLDTDProcessor() {
296
297         // initialize data
298

299     } // <init>()
300

301     //
302
// XMLComponent methods
303
//
304

305     /*
306      * Resets the component. The component can query the component manager
307      * about any features and properties that affect the operation of the
308      * component.
309      *
310      * @param componentManager The component manager.
311      *
312      * @throws SAXException Thrown by component on finitialization error.
313      * For example, if a feature or property is
314      * required for the operation of the component, the
315      * component manager may throw a
316      * SAXNotRecognizedException or a
317      * SAXNotSupportedException.
318      */

319     public void reset(XMLComponentManager componentManager) throws XMLConfigurationException {
320        
321         boolean parser_settings;
322         try {
323             parser_settings = componentManager.getFeature(PARSER_SETTINGS);
324         } catch (XMLConfigurationException e) {
325             parser_settings = true;
326         }
327
328         if (!parser_settings) {
329             // parser settings have not been changed
330
reset();
331             return;
332         }
333
334         // sax features
335
try {
336             fValidation = componentManager.getFeature(VALIDATION);
337         } catch (XMLConfigurationException e) {
338             fValidation = false;
339         }
340         try {
341             fDTDValidation =
342                 !(componentManager
343                     .getFeature(
344                         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE));
345         } catch (XMLConfigurationException e) {
346             // must be in a schema-less configuration!
347
fDTDValidation = true;
348         }
349
350         // Xerces features
351

352         try {
353             fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF);
354         } catch (XMLConfigurationException e) {
355             fWarnDuplicateAttdef = false;
356         }
357
358         // get needed components
359
fErrorReporter =
360             (XMLErrorReporter) componentManager.getProperty(
361                 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY);
362         fSymbolTable =
363             (SymbolTable) componentManager.getProperty(
364                 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY);
365         try {
366             fGrammarPool = (XMLGrammarPool) componentManager.getProperty(GRAMMAR_POOL);
367         } catch (XMLConfigurationException e) {
368             fGrammarPool = null;
369         }
370         try {
371             fValidator = (XMLDTDValidator) componentManager.getProperty(DTD_VALIDATOR);
372         } catch (XMLConfigurationException e) {
373             fValidator = null;
374         } catch (ClassCastException JavaDoc e) {
375             fValidator = null;
376         }
377         // we get our grammarBucket from the validator...
378
if (fValidator != null) {
379             fGrammarBucket = fValidator.getGrammarBucket();
380         } else {
381             fGrammarBucket = null;
382         }
383         reset();
384
385     } // reset(XMLComponentManager)
386

387     protected void reset() {
388         // clear grammars
389
fDTDGrammar = null;
390         // initialize state
391
fInDTDIgnore = false;
392
393         fNDataDeclNotations.clear();
394
395         // datatype validators
396
if (fValidation) {
397
398             if (fNotationEnumVals == null) {
399                 fNotationEnumVals = new Hashtable JavaDoc();
400             }
401             fNotationEnumVals.clear();
402
403             fTableOfIDAttributeNames = new Hashtable JavaDoc();
404             fTableOfNOTATIONAttributeNames = new Hashtable JavaDoc();
405         }
406
407     }
408     /**
409      * Returns a list of feature identifiers that are recognized by
410      * this component. This method may return null if no features
411      * are recognized by this component.
412      */

413     public String JavaDoc[] getRecognizedFeatures() {
414         return (String JavaDoc[])(RECOGNIZED_FEATURES.clone());
415     } // getRecognizedFeatures():String[]
416

417     /**
418      * Sets the state of a feature. This method is called by the component
419      * manager any time after reset when a feature changes state.
420      * <p>
421      * <strong>Note:</strong> Components should silently ignore features
422      * that do not affect the operation of the component.
423      *
424      * @param featureId The feature identifier.
425      * @param state The state of the feature.
426      *
427      * @throws SAXNotRecognizedException The component should not throw
428      * this exception.
429      * @throws SAXNotSupportedException The component should not throw
430      * this exception.
431      */

432     public void setFeature(String JavaDoc featureId, boolean state)
433             throws XMLConfigurationException {
434     } // setFeature(String,boolean)
435

436     /**
437      * Returns a list of property identifiers that are recognized by
438      * this component. This method may return null if no properties
439      * are recognized by this component.
440      */

441     public String JavaDoc[] getRecognizedProperties() {
442         return (String JavaDoc[])(RECOGNIZED_PROPERTIES.clone());
443     } // getRecognizedProperties():String[]
444

445     /**
446      * Sets the value of a property. This method is called by the component
447      * manager any time after reset when a property changes value.
448      * <p>
449      * <strong>Note:</strong> Components should silently ignore properties
450      * that do not affect the operation of the component.
451      *
452      * @param propertyId The property identifier.
453      * @param value The value of the property.
454      *
455      * @throws SAXNotRecognizedException The component should not throw
456      * this exception.
457      * @throws SAXNotSupportedException The component should not throw
458      * this exception.
459      */

460     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
461             throws XMLConfigurationException {
462     } // setProperty(String,Object)
463

464     /**
465      * Returns the default state for a feature, or null if this
466      * component does not want to report a default value for this
467      * feature.
468      *
469      * @param featureId The feature identifier.
470      *
471      * @since Xerces 2.2.0
472      */

473     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
474         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
475             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
476                 return FEATURE_DEFAULTS[i];
477             }
478         }
479         return null;
480     } // getFeatureDefault(String):Boolean
481

482     /**
483      * Returns the default state for a property, or null if this
484      * component does not want to report a default value for this
485      * property.
486      *
487      * @param propertyId The property identifier.
488      *
489      * @since Xerces 2.2.0
490      */

491     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
492         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
493             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
494                 return PROPERTY_DEFAULTS[i];
495             }
496         }
497         return null;
498     } // getPropertyDefault(String):Object
499

500     //
501
// XMLDTDSource methods
502
//
503

504     /**
505      * Sets the DTD handler.
506      *
507      * @param dtdHandler The DTD handler.
508      */

509     public void setDTDHandler(XMLDTDHandler dtdHandler) {
510         fDTDHandler = dtdHandler;
511     } // setDTDHandler(XMLDTDHandler)
512

513     /**
514      * Returns the DTD handler.
515      *
516      * @return The DTD handler.
517      */

518     public XMLDTDHandler getDTDHandler() {
519         return fDTDHandler;
520     } // getDTDHandler(): XMLDTDHandler
521

522     //
523
// XMLDTDContentModelSource methods
524
//
525

526     /**
527      * Sets the DTD content model handler.
528      *
529      * @param dtdContentModelHandler The DTD content model handler.
530      */

531     public void setDTDContentModelHandler(XMLDTDContentModelHandler dtdContentModelHandler) {
532         fDTDContentModelHandler = dtdContentModelHandler;
533     } // setDTDContentModelHandler(XMLDTDContentModelHandler)
534

535     /**
536      * Gets the DTD content model handler.
537      *
538      * @return dtdContentModelHandler The DTD content model handler.
539      */

540     public XMLDTDContentModelHandler getDTDContentModelHandler() {
541         return fDTDContentModelHandler;
542     } // getDTDContentModelHandler(): XMLDTDContentModelHandler
543

544     //
545
// XMLDTDContentModelHandler and XMLDTDHandler methods
546
//
547

548     /**
549      * The start of the DTD external subset.
550      *
551      * @param augs Additional information that may include infoset
552      * augmentations.
553      *
554      * @throws XNIException Thrown by handler to signal an error.
555      */

556     public void startExternalSubset(XMLResourceIdentifier identifier,
557                                     Augmentations augs) throws XNIException {
558         if(fDTDGrammar != null)
559             fDTDGrammar.startExternalSubset(identifier, augs);
560         if(fDTDHandler != null){
561             fDTDHandler.startExternalSubset(identifier, augs);
562         }
563     }
564
565     /**
566      * The end of the DTD external subset.
567      *
568      * @param augs Additional information that may include infoset
569      * augmentations.
570      *
571      * @throws XNIException Thrown by handler to signal an error.
572      */

573     public void endExternalSubset(Augmentations augs) throws XNIException {
574         if(fDTDGrammar != null)
575             fDTDGrammar.endExternalSubset(augs);
576         if(fDTDHandler != null){
577             fDTDHandler.endExternalSubset(augs);
578         }
579     }
580
581     /**
582      * Check standalone entity reference.
583      * Made static to make common between the validator and loader.
584      *
585      * @param name
586      *@param grammar grammar to which entity belongs
587      * @param tempEntityDecl empty entity declaration to put results in
588      * @param errorReporter error reporter to send errors to
589      *
590      * @throws XNIException Thrown by application to signal an error.
591      */

592     protected static void checkStandaloneEntityRef(String JavaDoc name, DTDGrammar grammar,
593                     XMLEntityDecl tempEntityDecl, XMLErrorReporter errorReporter) throws XNIException {
594         // check VC: Standalone Document Declartion, entities references appear in the document.
595
int entIndex = grammar.getEntityDeclIndex(name);
596         if (entIndex > -1) {
597             grammar.getEntityDecl(entIndex, tempEntityDecl);
598             if (tempEntityDecl.inExternal) {
599                 errorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
600                                             "MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
601                                             new Object JavaDoc[]{name}, XMLErrorReporter.SEVERITY_ERROR);
602             }
603         }
604     }
605
606     /**
607      * A comment.
608      *
609      * @param text The text in the comment.
610      * @param augs Additional information that may include infoset augmentations
611      *
612      * @throws XNIException Thrown by application to signal an error.
613      */

614     public void comment(XMLString text, Augmentations augs) throws XNIException {
615
616         // call handlers
617
if(fDTDGrammar != null)
618             fDTDGrammar.comment(text, augs);
619         if (fDTDHandler != null) {
620             fDTDHandler.comment(text, augs);
621         }
622
623     } // comment(XMLString)
624

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

643     public void processingInstruction(String JavaDoc target, XMLString data, Augmentations augs)
644     throws XNIException {
645
646         // call handlers
647
if(fDTDGrammar != null)
648             fDTDGrammar.processingInstruction(target, data, augs);
649         if (fDTDHandler != null) {
650             fDTDHandler.processingInstruction(target, data, augs);
651         }
652     } // processingInstruction(String,XMLString)
653

654     //
655
// XMLDTDHandler methods
656
//
657

658     /**
659      * The start of the DTD.
660      *
661      * @param locator The document locator, or null if the document
662      * location cannot be reported during the parsing of
663      * the document DTD. However, it is <em>strongly</em>
664      * recommended that a locator be supplied that can
665      * at least report the base system identifier of the
666      * DTD.
667      * @param augs Additional information that may include infoset
668      * augmentations.
669      *
670      * @throws XNIException Thrown by handler to signal an error.
671      */

672     public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
673
674
675         // initialize state
676
fNDataDeclNotations.clear();
677         fDTDElementDecls.removeAllElements();
678
679         // the grammar bucket's DTDGrammar will now be the
680
// one we want, whether we're constructing it or not.
681
// if we're not constructing it, then we should not have a reference
682
// to it!
683
if( !fGrammarBucket.getActiveGrammar().isImmutable()) {
684             fDTDGrammar = fGrammarBucket.getActiveGrammar();
685         }
686
687         // call handlers
688
if(fDTDGrammar != null )
689             fDTDGrammar.startDTD(locator, augs);
690         if (fDTDHandler != null) {
691             fDTDHandler.startDTD(locator, augs);
692         }
693
694     } // startDTD(XMLLocator)
695

696     /**
697      * Characters within an IGNORE conditional section.
698      *
699      * @param text The ignored text.
700      * @param augs Additional information that may include infoset
701      * augmentations.
702      *
703      * @throws XNIException Thrown by handler to signal an error.
704      */

705     public void ignoredCharacters(XMLString text, Augmentations augs) throws XNIException {
706
707         // ignored characters in DTD
708
if(fDTDGrammar != null )
709             fDTDGrammar.ignoredCharacters(text, augs);
710         if (fDTDHandler != null) {
711             fDTDHandler.ignoredCharacters(text, augs);
712         }
713     }
714
715     /**
716      * Notifies of the presence of a TextDecl line in an entity. If present,
717      * this method will be called immediately following the startParameterEntity call.
718      * <p>
719      * <strong>Note:</strong> This method is only called for external
720      * parameter entities referenced in the DTD.
721      *
722      * @param version The XML version, or null if not specified.
723      * @param encoding The IANA encoding name of the entity.
724      * @param augs Additional information that may include infoset
725      * augmentations.
726      *
727      * @throws XNIException Thrown by handler to signal an error.
728      */

729     public void textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs) throws XNIException {
730
731         // call handlers
732
if(fDTDGrammar != null )
733             fDTDGrammar.textDecl(version, encoding, augs);
734         if (fDTDHandler != null) {
735             fDTDHandler.textDecl(version, encoding, augs);
736         }
737     }
738
739     /**
740      * This method notifies of the start of a parameter entity. The parameter
741      * entity name start with a '%' character.
742      *
743      * @param name The name of the parameter entity.
744      * @param identifier The resource identifier.
745      * @param encoding The auto-detected IANA encoding name of the entity
746      * stream. This value will be null in those situations
747      * where the entity encoding is not auto-detected (e.g.
748      * internal parameter entities).
749      * @param augs Additional information that may include infoset
750      * augmentations.
751      *
752      * @throws XNIException Thrown by handler to signal an error.
753      */

754     public void startParameterEntity(String JavaDoc name,
755                                      XMLResourceIdentifier identifier,
756                                      String JavaDoc encoding,
757                                      Augmentations augs) throws XNIException {
758
759         if (fPerformValidation && fDTDGrammar != null &&
760                 fGrammarBucket.getStandalone()) {
761             checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter);
762         }
763         // call handlers
764
if(fDTDGrammar != null )
765             fDTDGrammar.startParameterEntity(name, identifier, encoding, augs);
766         if (fDTDHandler != null) {
767             fDTDHandler.startParameterEntity(name, identifier, encoding, augs);
768         }
769     }
770
771     /**
772      * This method notifies the end of a parameter entity. Parameter entity
773      * names begin with a '%' character.
774      *
775      * @param name The name of the parameter entity.
776      * @param augs Additional information that may include infoset
777      * augmentations.
778      *
779      * @throws XNIException Thrown by handler to signal an error.
780      */

781     public void endParameterEntity(String JavaDoc name, Augmentations augs) throws XNIException {
782
783         // call handlers
784
if(fDTDGrammar != null )
785             fDTDGrammar.endParameterEntity(name, augs);
786         if (fDTDHandler != null) {
787             fDTDHandler.endParameterEntity(name, augs);
788         }
789     }
790
791     /**
792      * An element declaration.
793      *
794      * @param name The name of the element.
795      * @param contentModel The element content model.
796      * @param augs Additional information that may include infoset
797      * augmentations.
798      *
799      * @throws XNIException Thrown by handler to signal an error.
800      */

801     public void elementDecl(String JavaDoc name, String JavaDoc contentModel, Augmentations augs)
802     throws XNIException {
803
804         //check VC: Unique Element Declaration
805
if (fValidation) {
806             if (fDTDElementDecls.contains(name)) {
807                 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
808                                            "MSG_ELEMENT_ALREADY_DECLARED",
809                                            new Object JavaDoc[]{ name},
810                                            XMLErrorReporter.SEVERITY_ERROR);
811             }
812             else {
813                 fDTDElementDecls.addElement(name);
814             }
815         }
816
817         // call handlers
818
if(fDTDGrammar != null )
819             fDTDGrammar.elementDecl(name, contentModel, augs);
820         if (fDTDHandler != null) {
821             fDTDHandler.elementDecl(name, contentModel, augs);
822         }
823
824     } // elementDecl(String,String)
825

826     /**
827      * The start of an attribute list.
828      *
829      * @param elementName The name of the element that this attribute
830      * list is associated with.
831      * @param augs Additional information that may include infoset
832      * augmentations.
833      *
834      * @throws XNIException Thrown by handler to signal an error.
835      */

836     public void startAttlist(String JavaDoc elementName, Augmentations augs)
837         throws XNIException {
838
839         // call handlers
840
if(fDTDGrammar != null )
841             fDTDGrammar.startAttlist(elementName, augs);
842         if (fDTDHandler != null) {
843             fDTDHandler.startAttlist(elementName, augs);
844         }
845
846     } // startAttlist(String)
847

848     /**
849      * An attribute declaration.
850      *
851      * @param elementName The name of the element that this attribute
852      * is associated with.
853      * @param attributeName The name of the attribute.
854      * @param type The attribute type. This value will be one of
855      * the following: "CDATA", "ENTITY", "ENTITIES",
856      * "ENUMERATION", "ID", "IDREF", "IDREFS",
857      * "NMTOKEN", "NMTOKENS", or "NOTATION".
858      * @param enumeration If the type has the value "ENUMERATION" or
859      * "NOTATION", this array holds the allowed attribute
860      * values; otherwise, this array is null.
861      * @param defaultType The attribute default type. This value will be
862      * one of the following: "#FIXED", "#IMPLIED",
863      * "#REQUIRED", or null.
864      * @param defaultValue The attribute default value, or null if no
865      * default value is specified.
866      * @param nonNormalizedDefaultValue The attribute default value with no normalization
867      * performed, or null if no default value is specified.
868      * @param augs Additional information that may include infoset
869      * augmentations.
870      *
871      * @throws XNIException Thrown by handler to signal an error.
872      */

873     public void attributeDecl(String JavaDoc elementName, String JavaDoc attributeName,
874                               String JavaDoc type, String JavaDoc[] enumeration,
875                               String JavaDoc defaultType, XMLString defaultValue,
876                               XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
877
878         if (type != XMLSymbols.fCDATASymbol && defaultValue != null) {
879             normalizeDefaultAttrValue(defaultValue);
880         }
881
882         if (fValidation) {
883         
884                 boolean duplicateAttributeDef = false ;
885                                         
886                 //Get Grammar index to grammar array
887
DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar:fGrammarBucket.getActiveGrammar());
888                 int elementIndex = grammar.getElementDeclIndex( elementName);
889                 if (grammar.getAttributeDeclIndex(elementIndex, attributeName) != -1) {
890                     //more than one attribute definition is provided for the same attribute of a given element type.
891
duplicateAttributeDef = true ;
892
893                     //this feature works only when validation is true.
894
if(fWarnDuplicateAttdef){
895                         fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
896                                                  "MSG_DUPLICATE_ATTRIBUTE_DEFINITION",
897                                                  new Object JavaDoc[]{ elementName, attributeName },
898                                                  XMLErrorReporter.SEVERITY_WARNING );
899                     }
900                 }
901
902
903             //
904
// a) VC: One ID per Element Type, If duplicate ID attribute
905
// b) VC: ID attribute Default. if there is a declareared attribute
906
// default for ID it should be of type #IMPLIED or #REQUIRED
907
if (type == XMLSymbols.fIDSymbol) {
908                 if (defaultValue != null && defaultValue.length != 0) {
909                     if (defaultType == null ||
910                         !(defaultType == XMLSymbols.fIMPLIEDSymbol ||
911                           defaultType == XMLSymbols.fREQUIREDSymbol)) {
912                         fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
913                                                    "IDDefaultTypeInvalid",
914                                                    new Object JavaDoc[]{ attributeName},
915                                                    XMLErrorReporter.SEVERITY_ERROR);
916                     }
917                 }
918
919                 if (!fTableOfIDAttributeNames.containsKey(elementName)) {
920                     fTableOfIDAttributeNames.put(elementName, attributeName);
921                 }
922                 else {
923                         //we should not report an error, when there is duplicate attribute definition for given element type
924
//according to XML 1.0 spec, When more than one definition is provided for the same attribute of a given
925
//element type, the first declaration is binding and later declaration are *ignored*. So processor should
926
//ignore the second declarations, however an application would be warned of the duplicate attribute defintion
927
// if http://apache.org/xml/features/validation/warn-on-duplicate-attdef feature is set to true,
928
// one typical case where this could be a problem, when any XML file
929
// provide the ID type information through internal subset so that it is available to the parser which read
930
//only internal subset. Now that attribute declaration(ID Type) can again be part of external parsed entity
931
//referenced. At that time if parser doesn't make this distinction it will throw an error for VC One ID per
932
//Element Type, which (second defintion) actually should be ignored. Application behavior may differ on the
933
//basis of error or warning thrown. - nb.
934

935                         if(!duplicateAttributeDef){
936                                 String JavaDoc previousIDAttributeName = (String JavaDoc)fTableOfIDAttributeNames.get( elementName );//rule a)
937
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
938                                                "MSG_MORE_THAN_ONE_ID_ATTRIBUTE",
939                                                new Object JavaDoc[]{ elementName, previousIDAttributeName, attributeName},
940                                                XMLErrorReporter.SEVERITY_ERROR);
941                         }
942                 }
943             }
944
945             //
946
// VC: One Notation Per Element Type, should check if there is a
947
// duplicate NOTATION attribute
948

949             if (type == XMLSymbols.fNOTATIONSymbol) {
950                 // VC: Notation Attributes: all notation names in the
951
// (attribute) declaration must be declared.
952
for (int i=0; i<enumeration.length; i++) {
953                     fNotationEnumVals.put(enumeration[i], attributeName);
954                 }
955
956                 if (fTableOfNOTATIONAttributeNames.containsKey( elementName ) == false) {
957                     fTableOfNOTATIONAttributeNames.put( elementName, attributeName);
958                 }
959                 else {
960                         //we should not report an error, when there is duplicate attribute definition for given element type
961
//according to XML 1.0 spec, When more than one definition is provided for the same attribute of a given
962
//element type, the first declaration is binding and later declaration are *ignored*. So processor should
963
//ignore the second declarations, however an application would be warned of the duplicate attribute defintion
964
// if http://apache.org/xml/features/validation/warn-on-duplicate-attdef feature is set to true, Application behavior may differ on the basis of error or
965
//warning thrown. - nb.
966

967                         if(!duplicateAttributeDef){
968                 
969                                 String JavaDoc previousNOTATIONAttributeName = (String JavaDoc) fTableOfNOTATIONAttributeNames.get( elementName );
970                                 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
971                                                "MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE",
972                                                new Object JavaDoc[]{ elementName, previousNOTATIONAttributeName, attributeName},
973                                                XMLErrorReporter.SEVERITY_ERROR);
974                          }
975                 }
976             }
977             
978             // VC: No Duplicate Tokens
979
// XML 1.0 SE Errata - E2
980
if (type == XMLSymbols.fENUMERATIONSymbol || type == XMLSymbols.fNOTATIONSymbol) {
981                 outer:
982                     for (int i = 0; i < enumeration.length; ++i) {
983                         for (int j = i + 1; j < enumeration.length; ++j) {
984                             if (enumeration[i].equals(enumeration[j])) {
985                                 // Only report the first uniqueness violation. There could be others,
986
// but additional overhead would be incurred tracking unique tokens
987
// that have already been encountered. -- mrglavas
988
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
989                                                type == XMLSymbols.fENUMERATIONSymbol
990                                                    ? "MSG_DISTINCT_TOKENS_IN_ENUMERATION"
991                                                    : "MSG_DISTINCT_NOTATION_IN_ENUMERATION",
992                                                new Object JavaDoc[]{ elementName, enumeration[i], attributeName },
993                                                XMLErrorReporter.SEVERITY_ERROR);
994                                 break outer;
995                             }
996                         }
997                     }
998             }
999
1000            // VC: Attribute Default Legal
1001
boolean ok = true;
1002            if (defaultValue != null &&
1003                (defaultType == null ||
1004                 (defaultType != null && defaultType == XMLSymbols.fFIXEDSymbol))) {
1005
1006                String JavaDoc value = defaultValue.toString();
1007                if (type == XMLSymbols.fNMTOKENSSymbol ||
1008                    type == XMLSymbols.fENTITIESSymbol ||
1009                    type == XMLSymbols.fIDREFSSymbol) {
1010
1011                    StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(value," ");
1012                    if (tokenizer.hasMoreTokens()) {
1013                        while (true) {
1014                            String JavaDoc nmtoken = tokenizer.nextToken();
1015                            if (type == XMLSymbols.fNMTOKENSSymbol) {
1016                                if (!isValidNmtoken(nmtoken)) {
1017                                    ok = false;
1018                                    break;
1019                                }
1020                            }
1021                            else if (type == XMLSymbols.fENTITIESSymbol ||
1022                                     type == XMLSymbols.fIDREFSSymbol) {
1023                                if (!isValidName(nmtoken)) {
1024                                    ok = false;
1025                                    break;
1026                                }
1027                            }
1028                            if (!tokenizer.hasMoreTokens()) {
1029                                break;
1030                            }
1031                        }
1032                    }
1033
1034                }
1035                else {
1036                    if (type == XMLSymbols.fENTITYSymbol ||
1037                        type == XMLSymbols.fIDSymbol ||
1038                        type == XMLSymbols.fIDREFSymbol ||
1039                        type == XMLSymbols.fNOTATIONSymbol) {
1040
1041                        if (!isValidName(value)) {
1042                            ok = false;
1043                        }
1044
1045                    }
1046                    else if (type == XMLSymbols.fNMTOKENSymbol ||
1047                             type == XMLSymbols.fENUMERATIONSymbol) {
1048
1049                        if (!isValidNmtoken(value)) {
1050                            ok = false;
1051                        }
1052                    }
1053
1054                    if (type == XMLSymbols.fNOTATIONSymbol ||
1055                        type == XMLSymbols.fENUMERATIONSymbol) {
1056                        ok = false;
1057                        for (int i=0; i<enumeration.length; i++) {
1058                            if (defaultValue.equals(enumeration[i])) {
1059                                ok = true;
1060                            }
1061                        }
1062                    }
1063
1064                }
1065                if (!ok) {
1066                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1067                                               "MSG_ATT_DEFAULT_INVALID",
1068                                               new Object JavaDoc[]{attributeName, value},
1069                                               XMLErrorReporter.SEVERITY_ERROR);
1070                }
1071            }
1072        }
1073
1074        // call handlers
1075
if(fDTDGrammar != null)
1076            fDTDGrammar.attributeDecl(elementName, attributeName,
1077                                  type, enumeration,
1078                                  defaultType, defaultValue, nonNormalizedDefaultValue, augs);
1079        if (fDTDHandler != null) {
1080            fDTDHandler.attributeDecl(elementName, attributeName,
1081                                      type, enumeration,
1082                                      defaultType, defaultValue, nonNormalizedDefaultValue, augs);
1083        }
1084
1085    } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
1086

1087    /**
1088     * The end of an attribute list.
1089     *
1090     * @param augs Additional information that may include infoset
1091     * augmentations.
1092     *
1093     * @throws XNIException Thrown by handler to signal an error.
1094     */

1095    public void endAttlist(Augmentations augs) throws XNIException {
1096
1097        // call handlers
1098
if(fDTDGrammar != null)
1099            fDTDGrammar.endAttlist(augs);
1100        if (fDTDHandler != null) {
1101            fDTDHandler.endAttlist(augs);
1102        }
1103
1104    } // endAttlist()
1105

1106    /**
1107     * An internal entity declaration.
1108     *
1109     * @param name The name of the entity. Parameter entity names start with
1110     * '%', whereas the name of a general entity is just the
1111     * entity name.
1112     * @param text The value of the entity.
1113     * @param nonNormalizedText The non-normalized value of the entity. This
1114     * value contains the same sequence of characters that was in
1115     * the internal entity declaration, without any entity
1116     * references expanded.
1117     * @param augs Additional information that may include infoset
1118     * augmentations.
1119     *
1120     * @throws XNIException Thrown by handler to signal an error.
1121     */

1122    public void internalEntityDecl(String JavaDoc name, XMLString text,
1123                                   XMLString nonNormalizedText,
1124                                   Augmentations augs) throws XNIException {
1125
1126        DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar());
1127        int index = grammar.getEntityDeclIndex(name) ;
1128
1129        //If the same entity is declared more than once, the first declaration
1130
//encountered is binding, SAX requires only effective(first) declaration
1131
//to be reported to the application
1132

1133        //REVISIT: Does it make sense to pass duplicate Entity information across
1134
//the pipeline -- nb?
1135

1136        //its a new entity and hasn't been declared.
1137
if(index == -1){
1138            //store internal entity declaration in grammar
1139
if(fDTDGrammar != null)
1140                fDTDGrammar.internalEntityDecl(name, text, nonNormalizedText, augs);
1141            // call handlers
1142
if (fDTDHandler != null) {
1143                fDTDHandler.internalEntityDecl(name, text, nonNormalizedText, augs);
1144            }
1145        }
1146
1147    } // internalEntityDecl(String,XMLString,XMLString)
1148

1149
1150    /**
1151     * An external entity declaration.
1152     *
1153     * @param name The name of the entity. Parameter entity names start
1154     * with '%', whereas the name of a general entity is just
1155     * the entity name.
1156     * @param identifier An object containing all location information
1157     * pertinent to this external entity.
1158     * @param augs Additional information that may include infoset
1159     * augmentations.
1160     *
1161     * @throws XNIException Thrown by handler to signal an error.
1162     */

1163    public void externalEntityDecl(String JavaDoc name, XMLResourceIdentifier identifier,
1164                                   Augmentations augs) throws XNIException {
1165
1166        DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar());
1167        int index = grammar.getEntityDeclIndex(name) ;
1168
1169        //If the same entity is declared more than once, the first declaration
1170
//encountered is binding, SAX requires only effective(first) declaration
1171
//to be reported to the application
1172

1173        //REVISIT: Does it make sense to pass duplicate entity information across
1174
//the pipeline -- nb?
1175

1176        //its a new entity and hasn't been declared.
1177
if(index == -1){
1178            //store external entity declaration in grammar
1179
if(fDTDGrammar != null)
1180                fDTDGrammar.externalEntityDecl(name, identifier, augs);
1181            // call handlers
1182
if (fDTDHandler != null) {
1183                fDTDHandler.externalEntityDecl(name, identifier, augs);
1184            }
1185        }
1186
1187    } // externalEntityDecl(String,XMLResourceIdentifier, Augmentations)
1188

1189    /**
1190     * An unparsed entity declaration.
1191     *
1192     * @param name The name of the entity.
1193     * @param identifier An object containing all location information
1194     * pertinent to this entity.
1195     * @param notation The name of the notation.
1196     * @param augs Additional information that may include infoset
1197     * augmentations.
1198     *
1199     * @throws XNIException Thrown by handler to signal an error.
1200     */

1201    public void unparsedEntityDecl(String JavaDoc name, XMLResourceIdentifier identifier,
1202                                   String JavaDoc notation,
1203                                   Augmentations augs) throws XNIException {
1204
1205        // VC: Notation declared, in the production of NDataDecl
1206
if (fValidation) {
1207            fNDataDeclNotations.put(name, notation);
1208        }
1209
1210        // call handlers
1211
if(fDTDGrammar != null)
1212            fDTDGrammar.unparsedEntityDecl(name, identifier, notation, augs);
1213        if (fDTDHandler != null) {
1214            fDTDHandler.unparsedEntityDecl(name, identifier, notation, augs);
1215        }
1216
1217    } // unparsedEntityDecl(String,XMLResourceIdentifier,String,Augmentations)
1218

1219    /**
1220     * A notation declaration
1221     *
1222     * @param name The name of the notation.
1223     * @param identifier An object containing all location information
1224     * pertinent to this notation.
1225     * @param augs Additional information that may include infoset
1226     * augmentations.
1227     *
1228     * @throws XNIException Thrown by handler to signal an error.
1229     */

1230    public void notationDecl(String JavaDoc name, XMLResourceIdentifier identifier,
1231                             Augmentations augs) throws XNIException {
1232
1233        // VC: Unique Notation Name
1234
if (fValidation) {
1235            DTDGrammar grammar = (fDTDGrammar != null ? fDTDGrammar : fGrammarBucket.getActiveGrammar());
1236            if (grammar.getNotationDeclIndex(name) != -1) {
1237                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1238                                           "UniqueNotationName",
1239                                           new Object JavaDoc[]{name},
1240                                           XMLErrorReporter.SEVERITY_ERROR);
1241            }
1242        }
1243        
1244        // call handlers
1245
if(fDTDGrammar != null)
1246            fDTDGrammar.notationDecl(name, identifier, augs);
1247        if (fDTDHandler != null) {
1248            fDTDHandler.notationDecl(name, identifier, augs);
1249        }
1250
1251    } // notationDecl(String,XMLResourceIdentifier, Augmentations)
1252

1253    /**
1254     * The start of a conditional section.
1255     *
1256     * @param type The type of the conditional section. This value will
1257     * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
1258     * @param augs Additional information that may include infoset
1259     * augmentations.
1260     *
1261     * @throws XNIException Thrown by handler to signal an error.
1262     *
1263     * @see #CONDITIONAL_INCLUDE
1264     * @see #CONDITIONAL_IGNORE
1265     */

1266    public void startConditional(short type, Augmentations augs) throws XNIException {
1267
1268        // set state
1269
fInDTDIgnore = type == XMLDTDHandler.CONDITIONAL_IGNORE;
1270
1271        // call handlers
1272
if(fDTDGrammar != null)
1273            fDTDGrammar.startConditional(type, augs);
1274        if (fDTDHandler != null) {
1275            fDTDHandler.startConditional(type, augs);
1276        }
1277
1278    } // startConditional(short)
1279

1280    /**
1281     * The end of a conditional section.
1282     *
1283     * @param augs Additional information that may include infoset
1284     * augmentations.
1285     *
1286     * @throws XNIException Thrown by handler to signal an error.
1287     */

1288    public void endConditional(Augmentations augs) throws XNIException {
1289
1290        // set state
1291
fInDTDIgnore = false;
1292
1293        // call handlers
1294
if(fDTDGrammar != null)
1295            fDTDGrammar.endConditional(augs);
1296        if (fDTDHandler != null) {
1297            fDTDHandler.endConditional(augs);
1298        }
1299
1300    } // endConditional()
1301

1302    /**
1303     * The end of the DTD.
1304     *
1305     * @param augs Additional information that may include infoset
1306     * augmentations.
1307     *
1308     * @throws XNIException Thrown by handler to signal an error.
1309     */

1310    public void endDTD(Augmentations augs) throws XNIException {
1311
1312
1313        // save grammar
1314
if(fDTDGrammar != null) {
1315            fDTDGrammar.endDTD(augs);
1316            if(fGrammarPool != null)
1317                fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_DTD, new Grammar[] {fDTDGrammar});
1318        }
1319        // check VC: Notation declared, in the production of NDataDecl
1320
if (fValidation) {
1321            DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar());
1322
1323            // VC : Notation Declared. for external entity declaration [Production 76].
1324
Enumeration JavaDoc entities = fNDataDeclNotations.keys();
1325            while (entities.hasMoreElements()) {
1326                String JavaDoc entity = (String JavaDoc) entities.nextElement();
1327                String JavaDoc notation = (String JavaDoc) fNDataDeclNotations.get(entity);
1328                if (grammar.getNotationDeclIndex(notation) == -1) {
1329                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1330                                               "MSG_NOTATION_NOT_DECLARED_FOR_UNPARSED_ENTITYDECL",
1331                                               new Object JavaDoc[]{entity, notation},
1332                                               XMLErrorReporter.SEVERITY_ERROR);
1333                }
1334            }
1335
1336            // VC: Notation Attributes:
1337
// all notation names in the (attribute) declaration must be declared.
1338
Enumeration JavaDoc notationVals = fNotationEnumVals.keys();
1339            while (notationVals.hasMoreElements()) {
1340                String JavaDoc notation = (String JavaDoc) notationVals.nextElement();
1341                String JavaDoc attributeName = (String JavaDoc) fNotationEnumVals.get(notation);
1342                if (grammar.getNotationDeclIndex(notation) == -1) {
1343                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1344                                               "MSG_NOTATION_NOT_DECLARED_FOR_NOTATIONTYPE_ATTRIBUTE",
1345                                               new Object JavaDoc[]{attributeName, notation},
1346                                               XMLErrorReporter.SEVERITY_ERROR);
1347                }
1348            }
1349            
1350            // VC: No Notation on Empty Element
1351
// An attribute of type NOTATION must not be declared on an element declared EMPTY.
1352
Enumeration JavaDoc elementsWithNotations = fTableOfNOTATIONAttributeNames.keys();
1353            while (elementsWithNotations.hasMoreElements()) {
1354                String JavaDoc elementName = (String JavaDoc) elementsWithNotations.nextElement();
1355                int elementIndex = grammar.getElementDeclIndex(elementName);
1356                if (grammar.getContentSpecType(elementIndex) == XMLElementDecl.TYPE_EMPTY) {
1357                    String JavaDoc attributeName = (String JavaDoc) fTableOfNOTATIONAttributeNames.get(elementName);
1358                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1359                                               "NoNotationOnEmptyElement",
1360                                               new Object JavaDoc[]{elementName, attributeName},
1361                                               XMLErrorReporter.SEVERITY_ERROR);
1362                }
1363            }
1364
1365            fTableOfIDAttributeNames = null;//should be safe to release these references
1366
fTableOfNOTATIONAttributeNames = null;
1367        }
1368
1369        // call handlers
1370
if (fDTDHandler != null) {
1371            fDTDHandler.endDTD(augs);
1372        }
1373
1374    } // endDTD()
1375

1376    // sets the XMLDTDSource of this handler
1377
public void setDTDSource(XMLDTDSource source ) {
1378        fDTDSource = source;
1379    } // setDTDSource(XMLDTDSource)
1380

1381    // returns the XMLDTDSource of this handler
1382
public XMLDTDSource getDTDSource() {
1383        return fDTDSource;
1384    } // getDTDSource(): XMLDTDSource
1385

1386    //
1387
// XMLDTDContentModelHandler methods
1388
//
1389

1390    // sets the XMLContentModelDTDSource of this handler
1391
public void setDTDContentModelSource(XMLDTDContentModelSource source ) {
1392        fDTDContentModelSource = source;
1393    } // setDTDContentModelSource(XMLDTDContentModelSource)
1394

1395    // returns the XMLDTDSource of this handler
1396
public XMLDTDContentModelSource getDTDContentModelSource() {
1397        return fDTDContentModelSource;
1398    } // getDTDContentModelSource(): XMLDTDContentModelSource
1399

1400
1401    /**
1402     * The start of a content model. Depending on the type of the content
1403     * model, specific methods may be called between the call to the
1404     * startContentModel method and the call to the endContentModel method.
1405     *
1406     * @param elementName The name of the element.
1407     * @param augs Additional information that may include infoset
1408     * augmentations.
1409     *
1410     * @throws XNIException Thrown by handler to signal an error.
1411     */

1412    public void startContentModel(String JavaDoc elementName, Augmentations augs)
1413        throws XNIException {
1414
1415        if (fValidation) {
1416            fDTDElementDeclName = elementName;
1417            fMixedElementTypes.removeAllElements();
1418        }
1419
1420        // call handlers
1421
if(fDTDGrammar != null)
1422            fDTDGrammar.startContentModel(elementName, augs);
1423        if (fDTDContentModelHandler != null) {
1424            fDTDContentModelHandler.startContentModel(elementName, augs);
1425        }
1426
1427    } // startContentModel(String)
1428

1429    /**
1430     * A content model of ANY.
1431     *
1432     * @param augs Additional information that may include infoset
1433     * augmentations.
1434     *
1435     * @throws XNIException Thrown by handler to signal an error.
1436     *
1437     * @see #empty
1438     * @see #startGroup
1439     */

1440    public void any(Augmentations augs) throws XNIException {
1441        if(fDTDGrammar != null)
1442            fDTDGrammar.any(augs);
1443        if (fDTDContentModelHandler != null) {
1444            fDTDContentModelHandler.any(augs);
1445        }
1446    } // any()
1447

1448    /**
1449     * A content model of EMPTY.
1450     *
1451     * @param augs Additional information that may include infoset
1452     * augmentations.
1453     *
1454     * @throws XNIException Thrown by handler to signal an error.
1455     *
1456     * @see #any
1457     * @see #startGroup
1458     */

1459    public void empty(Augmentations augs) throws XNIException {
1460        if(fDTDGrammar != null)
1461            fDTDGrammar.empty(augs);
1462        if (fDTDContentModelHandler != null) {
1463            fDTDContentModelHandler.empty(augs);
1464        }
1465    } // empty()
1466

1467    /**
1468     * A start of either a mixed or children content model. A mixed
1469     * content model will immediately be followed by a call to the
1470     * <code>pcdata()</code> method. A children content model will
1471     * contain additional groups and/or elements.
1472     *
1473     * @param augs Additional information that may include infoset
1474     * augmentations.
1475     *
1476     * @throws XNIException Thrown by handler to signal an error.
1477     *
1478     * @see #any
1479     * @see #empty
1480     */

1481    public void startGroup(Augmentations augs) throws XNIException {
1482
1483        fMixed = false;
1484        // call handlers
1485
if(fDTDGrammar != null)
1486            fDTDGrammar.startGroup(augs);
1487        if (fDTDContentModelHandler != null) {
1488            fDTDContentModelHandler.startGroup(augs);
1489        }
1490
1491    } // startGroup()
1492

1493    /**
1494     * The appearance of "#PCDATA" within a group signifying a
1495     * mixed content model. This method will be the first called
1496     * following the content model's <code>startGroup()</code>.
1497     *
1498     * @param augs Additional information that may include infoset
1499     * augmentations.
1500     *
1501     * @throws XNIException Thrown by handler to signal an error.
1502     *
1503     * @see #startGroup
1504     */

1505    public void pcdata(Augmentations augs) {
1506        fMixed = true;
1507        if(fDTDGrammar != null)
1508            fDTDGrammar.pcdata(augs);
1509        if (fDTDContentModelHandler != null) {
1510            fDTDContentModelHandler.pcdata(augs);
1511        }
1512    } // pcdata()
1513

1514    /**
1515     * A referenced element in a mixed or children content model.
1516     *
1517     * @param elementName The name of the referenced element.
1518     * @param augs Additional information that may include infoset
1519     * augmentations.
1520     *
1521     * @throws XNIException Thrown by handler to signal an error.
1522     */

1523    public void element(String JavaDoc elementName, Augmentations augs) throws XNIException {
1524
1525        // check VC: No duplicate Types, in a single mixed-content declaration
1526
if (fMixed && fValidation) {
1527            if (fMixedElementTypes.contains(elementName)) {
1528                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1529                                           "DuplicateTypeInMixedContent",
1530                                           new Object JavaDoc[]{fDTDElementDeclName, elementName},
1531                                           XMLErrorReporter.SEVERITY_ERROR);
1532            }
1533            else {
1534                fMixedElementTypes.addElement(elementName);
1535            }
1536        }
1537
1538        // call handlers
1539
if(fDTDGrammar != null)
1540            fDTDGrammar.element(elementName, augs);
1541        if (fDTDContentModelHandler != null) {
1542            fDTDContentModelHandler.element(elementName, augs);
1543        }
1544
1545    } // childrenElement(String)
1546

1547    /**
1548     * The separator between choices or sequences of a mixed or children
1549     * content model.
1550     *
1551     * @param separator The type of children separator.
1552     * @param augs Additional information that may include infoset
1553     * augmentations.
1554     *
1555     * @throws XNIException Thrown by handler to signal an error.
1556     *
1557     * @see #SEPARATOR_CHOICE
1558     * @see #SEPARATOR_SEQUENCE
1559     */

1560    public void separator(short separator, Augmentations augs)
1561        throws XNIException {
1562
1563        // call handlers
1564
if(fDTDGrammar != null)
1565            fDTDGrammar.separator(separator, augs);
1566        if (fDTDContentModelHandler != null) {
1567            fDTDContentModelHandler.separator(separator, augs);
1568        }
1569
1570    } // separator(short)
1571

1572    /**
1573     * The occurrence count for a child in a children content model or
1574     * for the mixed content model group.
1575     *
1576     * @param occurrence The occurrence count for the last element
1577     * or group.
1578     * @param augs Additional information that may include infoset
1579     * augmentations.
1580     *
1581     * @throws XNIException Thrown by handler to signal an error.
1582     *
1583     * @see #OCCURS_ZERO_OR_ONE
1584     * @see #OCCURS_ZERO_OR_MORE
1585     * @see #OCCURS_ONE_OR_MORE
1586     */

1587    public void occurrence(short occurrence, Augmentations augs)
1588        throws XNIException {
1589
1590        // call handlers
1591
if(fDTDGrammar != null)
1592            fDTDGrammar.occurrence(occurrence, augs);
1593        if (fDTDContentModelHandler != null) {
1594            fDTDContentModelHandler.occurrence(occurrence, augs);
1595        }
1596
1597    } // occurrence(short)
1598

1599    /**
1600     * The end of a group for mixed or children content models.
1601     *
1602     * @param augs Additional information that may include infoset
1603     * augmentations.
1604     *
1605     * @throws XNIException Thrown by handler to signal an error.
1606     */

1607    public void endGroup(Augmentations augs) throws XNIException {
1608
1609        // call handlers
1610
if(fDTDGrammar != null)
1611            fDTDGrammar.endGroup(augs);
1612        if (fDTDContentModelHandler != null) {
1613            fDTDContentModelHandler.endGroup(augs);
1614        }
1615
1616    } // endGroup()
1617

1618    /**
1619     * The end of a content model.
1620     *
1621     * @param augs Additional information that may include infoset
1622     * augmentations.
1623     *
1624     * @throws XNIException Thrown by handler to signal an error.
1625     */

1626    public void endContentModel(Augmentations augs) throws XNIException {
1627
1628        // call handlers
1629
if(fDTDGrammar != null)
1630            fDTDGrammar.endContentModel(augs);
1631        if (fDTDContentModelHandler != null) {
1632            fDTDContentModelHandler.endContentModel(augs);
1633        }
1634
1635    } // endContentModel()
1636

1637    //
1638
// Private methods
1639
//
1640

1641    /**
1642     * Normalize the attribute value of a non CDATA default attribute
1643     * collapsing sequences of space characters (x20)
1644     *
1645     * @param value The value to normalize
1646     * @return Whether the value was changed or not.
1647     */

1648    private boolean normalizeDefaultAttrValue(XMLString value) {
1649
1650        int oldLength = value.length;
1651
1652        boolean skipSpace = true; // skip leading spaces
1653
int current = value.offset;
1654        int end = value.offset + value.length;
1655        for (int i = value.offset; i < end; i++) {
1656            if (value.ch[i] == ' ') {
1657                if (!skipSpace) {
1658                    // take the first whitespace as a space and skip the others
1659
value.ch[current++] = ' ';
1660                    skipSpace = true;
1661                }
1662                else {
1663                    // just skip it.
1664
}
1665            }
1666            else {
1667                // simply shift non space chars if needed
1668
if (current != i) {
1669                    value.ch[current] = value.ch[i];
1670                }
1671                current++;
1672                skipSpace = false;
1673            }
1674        }
1675        if (current != end) {
1676            if (skipSpace) {
1677                // if we finished on a space trim it
1678
current--;
1679            }
1680            // set the new value length
1681
value.length = current - value.offset;
1682            return true;
1683        }
1684        return false;
1685    }
1686
1687    
1688    protected boolean isValidNmtoken(String JavaDoc nmtoken) {
1689        return XMLChar.isValidNmtoken(nmtoken);
1690    } // isValidNmtoken(String): boolean
1691

1692    protected boolean isValidName(String JavaDoc name) {
1693        return XMLChar.isValidName(name);
1694    } // isValidName(String): boolean
1695
} // class XMLDTDProcessor
1696
Popular Tags