KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > dtd > XMLDTDProcessor


1 /*
2  * Copyright 1999-2002,2004,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.impl.dtd;
18
19 import java.util.Enumeration JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Locale JavaDoc;
22 import java.util.StringTokenizer JavaDoc;
23 import java.util.Vector JavaDoc;
24
25 import org.apache.xerces.impl.Constants;
26 import org.apache.xerces.impl.XMLErrorReporter;
27 import org.apache.xerces.impl.msg.XMLMessageFormatter;
28 import org.apache.xerces.util.SymbolTable;
29 import org.apache.xerces.util.XMLChar;
30 import org.apache.xerces.util.XMLSymbols;
31 import org.apache.xerces.xni.Augmentations;
32 import org.apache.xerces.xni.XMLDTDContentModelHandler;
33 import org.apache.xerces.xni.XMLDTDHandler;
34 import org.apache.xerces.xni.XMLLocator;
35 import org.apache.xerces.xni.XMLResourceIdentifier;
36 import org.apache.xerces.xni.XMLString;
37 import org.apache.xerces.xni.XNIException;
38 import org.apache.xerces.xni.grammars.Grammar;
39 import org.apache.xerces.xni.grammars.XMLGrammarDescription;
40 import org.apache.xerces.xni.grammars.XMLGrammarPool;
41 import org.apache.xerces.xni.parser.XMLComponent;
42 import org.apache.xerces.xni.parser.XMLComponentManager;
43 import org.apache.xerces.xni.parser.XMLConfigurationException;
44 import org.apache.xerces.xni.parser.XMLDTDContentModelFilter;
45 import org.apache.xerces.xni.parser.XMLDTDContentModelSource;
46 import org.apache.xerces.xni.parser.XMLDTDFilter;
47 import org.apache.xerces.xni.parser.XMLDTDSource;
48
49 /**
50  * The DTD processor. The processor implements a DTD
51  * filter: receiving DTD events from the DTD scanner; validating
52  * the content and structure; building a grammar, if applicable;
53  * and notifying the DTDHandler of the information resulting from the
54  * process.
55  * <p>
56  * This component requires the following features and properties from the
57  * component manager that uses it:
58  * <ul>
59  * <li>http://xml.org/sax/features/namespaces</li>
60  * <li>http://apache.org/xml/properties/internal/symbol-table</li>
61  * <li>http://apache.org/xml/properties/internal/error-reporter</li>
62  * <li>http://apache.org/xml/properties/internal/grammar-pool</li>
63  * <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
64  * </ul>
65  *
66  * @xerces.internal
67  *
68  * @author Neil Graham, IBM
69  *
70  * @version $Id: XMLDTDProcessor.java,v 1.15 2005/03/07 23:28:41 mrglavas Exp $
71  */

72 public class XMLDTDProcessor
73         implements XMLComponent, XMLDTDFilter, XMLDTDContentModelFilter {
74
75     //
76
// Constants
77
//
78

79     /** Top level scope (-1). */
80     private static final int TOP_LEVEL_SCOPE = -1;
81
82     // feature identifiers
83

84     /** Feature identifier: validation. */
85     protected static final String JavaDoc VALIDATION =
86         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
87
88     /** Feature identifier: notify character references. */
89     protected static final String JavaDoc NOTIFY_CHAR_REFS =
90         Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_CHAR_REFS_FEATURE;
91
92     /** Feature identifier: warn on duplicate attdef */
93     protected static final String JavaDoc WARN_ON_DUPLICATE_ATTDEF =
94         Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
95         
96     protected static final String JavaDoc PARSER_SETTINGS =
97             Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
98
99     // property identifiers
100

101     /** Property identifier: symbol table. */
102     protected static final String JavaDoc SYMBOL_TABLE =
103         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
104
105     /** Property identifier: error reporter. */
106     protected static final String JavaDoc ERROR_REPORTER =
107         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
108
109     /** Property identifier: grammar pool. */
110     protected static final String JavaDoc GRAMMAR_POOL =
111         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
112
113     /** Property identifier: validator . */
114     protected static final String JavaDoc DTD_VALIDATOR =
115         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
116
117     // recognized features and properties
118

119     /** Recognized features. */
120     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
121         VALIDATION,
122         WARN_ON_DUPLICATE_ATTDEF,
123         NOTIFY_CHAR_REFS,
124     };
125
126     /** Feature defaults. */
127     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = {
128         null,
129         Boolean.FALSE,
130         null,
131     };
132
133     /** Recognized properties. */
134     private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
135         SYMBOL_TABLE,
136         ERROR_REPORTER,
137         GRAMMAR_POOL,
138         DTD_VALIDATOR,
139     };
140
141     /** Property defaults. */
142     private static final Object JavaDoc[] PROPERTY_DEFAULTS = {
143         null,
144         null,
145         null,
146         null,
147     };
148
149     // debugging
150

151     //
152
// Data
153
//
154

155     // features
156

157     /** Validation. */
158     protected boolean fValidation;
159
160     /** Validation against only DTD */
161     protected boolean fDTDValidation;
162
163     /** warn on duplicate attribute definition, this feature works only when validation is true */
164     protected boolean fWarnDuplicateAttdef;
165         
166     // properties
167

168     /** Symbol table. */
169     protected SymbolTable fSymbolTable;
170
171     /** Error reporter. */
172     protected XMLErrorReporter fErrorReporter;
173
174     /** Grammar bucket. */
175     protected DTDGrammarBucket fGrammarBucket;
176
177     // the validator to which we look for our grammar bucket (the
178
// validator needs to hold the bucket so that it can initialize
179
// the grammar with details like whether it's for a standalone document...
180
protected XMLDTDValidator fValidator;
181
182     // the grammar pool we'll try to add the grammar to:
183
protected XMLGrammarPool fGrammarPool;
184
185     // what's our Locale?
186
protected Locale JavaDoc fLocale;
187
188     // handlers
189

190     /** DTD handler. */
191     protected XMLDTDHandler fDTDHandler;
192
193     /** DTD source. */
194     protected XMLDTDSource fDTDSource;
195
196     /** DTD content model handler. */
197     protected XMLDTDContentModelHandler fDTDContentModelHandler;
198
199     /** DTD content model source. */
200     protected XMLDTDContentModelSource fDTDContentModelSource;
201
202     // grammars
203

204     /** DTD Grammar. */
205     protected DTDGrammar fDTDGrammar;
206
207     // state
208

209     /** Perform validation. */
210     private boolean fPerformValidation;
211
212     /** True if in an ignore conditional section of the DTD. */
213     protected boolean fInDTDIgnore;
214
215     // information regarding the current element
216

217     // validation states
218

219     /** Mixed. */
220     private boolean fMixed;
221
222     // temporary variables
223

224     /** Temporary entity declaration. */
225     private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
226
227     /** Notation declaration hash. */
228     private Hashtable JavaDoc fNDataDeclNotations = new Hashtable JavaDoc();
229
230     /** DTD element declaration name. */
231     private String JavaDoc fDTDElementDeclName = null;
232
233     /** Mixed element type "hash". */
234     private Vector JavaDoc fMixedElementTypes = new Vector JavaDoc();
235
236     /** Element declarations in DTD. */
237     private Vector JavaDoc fDTDElementDecls = new Vector JavaDoc();
238
239     // to check for duplicate ID or ANNOTATION attribute declare in
240
// ATTLIST, and misc VCs
241

242     /** ID attribute names. */
243     private Hashtable JavaDoc fTableOfIDAttributeNames;
244
245     /** NOTATION attribute names. */
246     private Hashtable JavaDoc fTableOfNOTATIONAttributeNames;
247
248     /** NOTATION enumeration values. */
249     private Hashtable JavaDoc fNotationEnumVals;
250
251     //
252
// Constructors
253
//
254

255     /** Default constructor. */
256     public XMLDTDProcessor() {
257
258         // initialize data
259

260     } // <init>()
261

262     //
263
// XMLComponent methods
264
//
265

266     /*
267      * Resets the component. The component can query the component manager
268      * about any features and properties that affect the operation of the
269      * component.
270      *
271      * @param componentManager The component manager.
272      *
273      * @throws SAXException Thrown by component on finitialization error.
274      * For example, if a feature or property is
275      * required for the operation of the component, the
276      * component manager may throw a
277      * SAXNotRecognizedException or a
278      * SAXNotSupportedException.
279      */

280     public void reset(XMLComponentManager componentManager) throws XMLConfigurationException {
281        
282         boolean parser_settings;
283         try {
284             parser_settings = componentManager.getFeature(PARSER_SETTINGS);
285         } catch (XMLConfigurationException e) {
286             parser_settings = true;
287         }
288
289         if (!parser_settings) {
290             // parser settings have not been changed
291
reset();
292             return;
293         }
294
295         // sax features
296
try {
297             fValidation = componentManager.getFeature(VALIDATION);
298         } catch (XMLConfigurationException e) {
299             fValidation = false;
300         }
301         try {
302             fDTDValidation =
303                 !(componentManager
304                     .getFeature(
305                         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE));
306         } catch (XMLConfigurationException e) {
307             // must be in a schema-less configuration!
308
fDTDValidation = true;
309         }
310
311         // Xerces features
312

313         try {
314             fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF);
315         } catch (XMLConfigurationException e) {
316             fWarnDuplicateAttdef = false;
317         }
318
319         // get needed components
320
fErrorReporter =
321             (XMLErrorReporter) componentManager.getProperty(
322                 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY);
323         fSymbolTable =
324             (SymbolTable) componentManager.getProperty(
325                 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY);
326         try {
327             fGrammarPool = (XMLGrammarPool) componentManager.getProperty(GRAMMAR_POOL);
328         } catch (XMLConfigurationException e) {
329             fGrammarPool = null;
330         }
331         try {
332             fValidator = (XMLDTDValidator) componentManager.getProperty(DTD_VALIDATOR);
333         } catch (XMLConfigurationException e) {
334             fValidator = null;
335         } catch (ClassCastException JavaDoc e) {
336             fValidator = null;
337         }
338         // we get our grammarBucket from the validator...
339
if (fValidator != null) {
340             fGrammarBucket = fValidator.getGrammarBucket();
341         } else {
342             fGrammarBucket = null;
343         }
344         reset();
345
346     } // reset(XMLComponentManager)
347

348     protected void reset() {
349         // clear grammars
350
fDTDGrammar = null;
351         // initialize state
352
fInDTDIgnore = false;
353
354         fNDataDeclNotations.clear();
355
356         // datatype validators
357
if (fValidation) {
358
359             if (fNotationEnumVals == null) {
360                 fNotationEnumVals = new Hashtable JavaDoc();
361             }
362             fNotationEnumVals.clear();
363
364             fTableOfIDAttributeNames = new Hashtable JavaDoc();
365             fTableOfNOTATIONAttributeNames = new Hashtable JavaDoc();
366         }
367
368     }
369     /**
370      * Returns a list of feature identifiers that are recognized by
371      * this component. This method may return null if no features
372      * are recognized by this component.
373      */

374     public String JavaDoc[] getRecognizedFeatures() {
375         return (String JavaDoc[])(RECOGNIZED_FEATURES.clone());
376     } // getRecognizedFeatures():String[]
377

378     /**
379      * Sets the state of a feature. This method is called by the component
380      * manager any time after reset when a feature changes state.
381      * <p>
382      * <strong>Note:</strong> Components should silently ignore features
383      * that do not affect the operation of the component.
384      *
385      * @param featureId The feature identifier.
386      * @param state The state of the feature.
387      *
388      * @throws SAXNotRecognizedException The component should not throw
389      * this exception.
390      * @throws SAXNotSupportedException The component should not throw
391      * this exception.
392      */

393     public void setFeature(String JavaDoc featureId, boolean state)
394             throws XMLConfigurationException {
395     } // setFeature(String,boolean)
396

397     /**
398      * Returns a list of property identifiers that are recognized by
399      * this component. This method may return null if no properties
400      * are recognized by this component.
401      */

402     public String JavaDoc[] getRecognizedProperties() {
403         return (String JavaDoc[])(RECOGNIZED_PROPERTIES.clone());
404     } // getRecognizedProperties():String[]
405

406     /**
407      * Sets the value of a property. This method is called by the component
408      * manager any time after reset when a property changes value.
409      * <p>
410      * <strong>Note:</strong> Components should silently ignore properties
411      * that do not affect the operation of the component.
412      *
413      * @param propertyId The property identifier.
414      * @param value The value of the property.
415      *
416      * @throws SAXNotRecognizedException The component should not throw
417      * this exception.
418      * @throws SAXNotSupportedException The component should not throw
419      * this exception.
420      */

421     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
422             throws XMLConfigurationException {
423     } // setProperty(String,Object)
424

425     /**
426      * Returns the default state for a feature, or null if this
427      * component does not want to report a default value for this
428      * feature.
429      *
430      * @param featureId The feature identifier.
431      *
432      * @since Xerces 2.2.0
433      */

434     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
435         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
436             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
437                 return FEATURE_DEFAULTS[i];
438             }
439         }
440         return null;
441     } // getFeatureDefault(String):Boolean
442

443     /**
444      * Returns the default state for a property, or null if this
445      * component does not want to report a default value for this
446      * property.
447      *
448      * @param propertyId The property identifier.
449      *
450      * @since Xerces 2.2.0
451      */

452     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
453         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
454             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
455                 return PROPERTY_DEFAULTS[i];
456             }
457         }
458         return null;
459     } // getPropertyDefault(String):Object
460

461     //
462
// XMLDTDSource methods
463
//
464

465     /**
466      * Sets the DTD handler.
467      *
468      * @param dtdHandler The DTD handler.
469      */

470     public void setDTDHandler(XMLDTDHandler dtdHandler) {
471         fDTDHandler = dtdHandler;
472     } // setDTDHandler(XMLDTDHandler)
473

474     /**
475      * Returns the DTD handler.
476      *
477      * @return The DTD handler.
478      */

479     public XMLDTDHandler getDTDHandler() {
480         return fDTDHandler;
481     } // getDTDHandler(): XMLDTDHandler
482

483     //
484
// XMLDTDContentModelSource methods
485
//
486

487     /**
488      * Sets the DTD content model handler.
489      *
490      * @param dtdContentModelHandler The DTD content model handler.
491      */

492     public void setDTDContentModelHandler(XMLDTDContentModelHandler dtdContentModelHandler) {
493         fDTDContentModelHandler = dtdContentModelHandler;
494     } // setDTDContentModelHandler(XMLDTDContentModelHandler)
495

496     /**
497      * Gets the DTD content model handler.
498      *
499      * @return dtdContentModelHandler The DTD content model handler.
500      */

501     public XMLDTDContentModelHandler getDTDContentModelHandler() {
502         return fDTDContentModelHandler;
503     } // getDTDContentModelHandler(): XMLDTDContentModelHandler
504

505     //
506
// XMLDTDContentModelHandler and XMLDTDHandler methods
507
//
508

509     /**
510      * The start of the DTD external subset.
511      *
512      * @param augs Additional information that may include infoset
513      * augmentations.
514      *
515      * @throws XNIException Thrown by handler to signal an error.
516      */

517     public void startExternalSubset(XMLResourceIdentifier identifier,
518                                     Augmentations augs) throws XNIException {
519         if(fDTDGrammar != null)
520             fDTDGrammar.startExternalSubset(identifier, augs);
521         if(fDTDHandler != null){
522             fDTDHandler.startExternalSubset(identifier, augs);
523         }
524     }
525
526     /**
527      * The end of the DTD external subset.
528      *
529      * @param augs Additional information that may include infoset
530      * augmentations.
531      *
532      * @throws XNIException Thrown by handler to signal an error.
533      */

534     public void endExternalSubset(Augmentations augs) throws XNIException {
535         if(fDTDGrammar != null)
536             fDTDGrammar.endExternalSubset(augs);
537         if(fDTDHandler != null){
538             fDTDHandler.endExternalSubset(augs);
539         }
540     }
541
542     /**
543      * Check standalone entity reference.
544      * Made static to make common between the validator and loader.
545      *
546      * @param name
547      *@param grammar grammar to which entity belongs
548      * @param tempEntityDecl empty entity declaration to put results in
549      * @param errorReporter error reporter to send errors to
550      *
551      * @throws XNIException Thrown by application to signal an error.
552      */

553     protected static void checkStandaloneEntityRef(String JavaDoc name, DTDGrammar grammar,
554                     XMLEntityDecl tempEntityDecl, XMLErrorReporter errorReporter) throws XNIException {
555         // check VC: Standalone Document Declartion, entities references appear in the document.
556
int entIndex = grammar.getEntityDeclIndex(name);
557         if (entIndex > -1) {
558             grammar.getEntityDecl(entIndex, tempEntityDecl);
559             if (tempEntityDecl.inExternal) {
560                 errorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
561                                             "MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
562                                             new Object JavaDoc[]{name}, XMLErrorReporter.SEVERITY_ERROR);
563             }
564         }
565     }
566
567     /**
568      * A comment.
569      *
570      * @param text The text in the comment.
571      * @param augs Additional information that may include infoset augmentations
572      *
573      * @throws XNIException Thrown by application to signal an error.
574      */

575     public void comment(XMLString text, Augmentations augs) throws XNIException {
576
577         // call handlers
578
if(fDTDGrammar != null)
579             fDTDGrammar.comment(text, augs);
580         if (fDTDHandler != null) {
581             fDTDHandler.comment(text, augs);
582         }
583
584     } // comment(XMLString)
585

586
587     /**
588      * A processing instruction. Processing instructions consist of a
589      * target name and, optionally, text data. The data is only meaningful
590      * to the application.
591      * <p>
592      * Typically, a processing instruction's data will contain a series
593      * of pseudo-attributes. These pseudo-attributes follow the form of
594      * element attributes but are <strong>not</strong> parsed or presented
595      * to the application as anything other than text. The application is
596      * responsible for parsing the data.
597      *
598      * @param target The target.
599      * @param data The data or null if none specified.
600      * @param augs Additional information that may include infoset augmentations
601      *
602      * @throws XNIException Thrown by handler to signal an error.
603      */

604     public void processingInstruction(String JavaDoc target, XMLString data, Augmentations augs)
605     throws XNIException {
606
607         // call handlers
608
if(fDTDGrammar != null)
609             fDTDGrammar.processingInstruction(target, data, augs);
610         if (fDTDHandler != null) {
611             fDTDHandler.processingInstruction(target, data, augs);
612         }
613     } // processingInstruction(String,XMLString)
614

615     //
616
// XMLDTDHandler methods
617
//
618

619     /**
620      * The start of the DTD.
621      *
622      * @param locator The document locator, or null if the document
623      * location cannot be reported during the parsing of
624      * the document DTD. However, it is <em>strongly</em>
625      * recommended that a locator be supplied that can
626      * at least report the base system identifier of the
627      * DTD.
628      * @param augs Additional information that may include infoset
629      * augmentations.
630      *
631      * @throws XNIException Thrown by handler to signal an error.
632      */

633     public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
634
635
636         // initialize state
637
fNDataDeclNotations.clear();
638         fDTDElementDecls.removeAllElements();
639
640         // the grammar bucket's DTDGrammar will now be the
641
// one we want, whether we're constructing it or not.
642
// if we're not constructing it, then we should not have a reference
643
// to it!
644
if( !fGrammarBucket.getActiveGrammar().isImmutable()) {
645             fDTDGrammar = fGrammarBucket.getActiveGrammar();
646         }
647
648         // call handlers
649
if(fDTDGrammar != null )
650             fDTDGrammar.startDTD(locator, augs);
651         if (fDTDHandler != null) {
652             fDTDHandler.startDTD(locator, augs);
653         }
654
655     } // startDTD(XMLLocator)
656

657     /**
658      * Characters within an IGNORE conditional section.
659      *
660      * @param text The ignored text.
661      * @param augs Additional information that may include infoset
662      * augmentations.
663      *
664      * @throws XNIException Thrown by handler to signal an error.
665      */

666     public void ignoredCharacters(XMLString text, Augmentations augs) throws XNIException {
667
668         // ignored characters in DTD
669
if(fDTDGrammar != null )
670             fDTDGrammar.ignoredCharacters(text, augs);
671         if (fDTDHandler != null) {
672             fDTDHandler.ignoredCharacters(text, augs);
673         }
674     }
675
676     /**
677      * Notifies of the presence of a TextDecl line in an entity. If present,
678      * this method will be called immediately following the startParameterEntity call.
679      * <p>
680      * <strong>Note:</strong> This method is only called for external
681      * parameter entities referenced in the DTD.
682      *
683      * @param version The XML version, or null if not specified.
684      * @param encoding The IANA encoding name of the entity.
685      * @param augs Additional information that may include infoset
686      * augmentations.
687      *
688      * @throws XNIException Thrown by handler to signal an error.
689      */

690     public void textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs) throws XNIException {
691
692         // call handlers
693
if(fDTDGrammar != null )
694             fDTDGrammar.textDecl(version, encoding, augs);
695         if (fDTDHandler != null) {
696             fDTDHandler.textDecl(version, encoding, augs);
697         }
698     }
699
700     /**
701      * This method notifies of the start of a parameter entity. The parameter
702      * entity name start with a '%' character.
703      *
704      * @param name The name of the parameter entity.
705      * @param identifier The resource identifier.
706      * @param encoding The auto-detected IANA encoding name of the entity
707      * stream. This value will be null in those situations
708      * where the entity encoding is not auto-detected (e.g.
709      * internal parameter entities).
710      * @param augs Additional information that may include infoset
711      * augmentations.
712      *
713      * @throws XNIException Thrown by handler to signal an error.
714      */

715     public void startParameterEntity(String JavaDoc name,
716                                      XMLResourceIdentifier identifier,
717                                      String JavaDoc encoding,
718                                      Augmentations augs) throws XNIException {
719
720         if (fPerformValidation && fDTDGrammar != null &&
721                 fGrammarBucket.getStandalone()) {
722             checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter);
723         }
724         // call handlers
725
if(fDTDGrammar != null )
726             fDTDGrammar.startParameterEntity(name, identifier, encoding, augs);
727         if (fDTDHandler != null) {
728             fDTDHandler.startParameterEntity(name, identifier, encoding, augs);
729         }
730     }
731
732     /**
733      * This method notifies the end of a parameter entity. Parameter entity
734      * names begin with a '%' character.
735      *
736      * @param name The name of the parameter entity.
737      * @param augs Additional information that may include infoset
738      * augmentations.
739      *
740      * @throws XNIException Thrown by handler to signal an error.
741      */

742     public void endParameterEntity(String JavaDoc name, Augmentations augs) throws XNIException {
743
744         // call handlers
745
if(fDTDGrammar != null )
746             fDTDGrammar.endParameterEntity(name, augs);
747         if (fDTDHandler != null) {
748             fDTDHandler.endParameterEntity(name, augs);
749         }
750     }
751
752     /**
753      * An element declaration.
754      *
755      * @param name The name of the element.
756      * @param contentModel The element content model.
757      * @param augs Additional information that may include infoset
758      * augmentations.
759      *
760      * @throws XNIException Thrown by handler to signal an error.
761      */

762     public void elementDecl(String JavaDoc name, String JavaDoc contentModel, Augmentations augs)
763     throws XNIException {
764
765         //check VC: Unique Element Declaration
766
if (fValidation) {
767             if (fDTDElementDecls.contains(name)) {
768                 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
769                                            "MSG_ELEMENT_ALREADY_DECLARED",
770                                            new Object JavaDoc[]{ name},
771                                            XMLErrorReporter.SEVERITY_ERROR);
772             }
773             else {
774                 fDTDElementDecls.addElement(name);
775             }
776         }
777
778         // call handlers
779
if(fDTDGrammar != null )
780             fDTDGrammar.elementDecl(name, contentModel, augs);
781         if (fDTDHandler != null) {
782             fDTDHandler.elementDecl(name, contentModel, augs);
783         }
784
785     } // elementDecl(String,String)
786

787     /**
788      * The start of an attribute list.
789      *
790      * @param elementName The name of the element that this attribute
791      * list is associated with.
792      * @param augs Additional information that may include infoset
793      * augmentations.
794      *
795      * @throws XNIException Thrown by handler to signal an error.
796      */

797     public void startAttlist(String JavaDoc elementName, Augmentations augs)
798         throws XNIException {
799
800         // call handlers
801
if(fDTDGrammar != null )
802             fDTDGrammar.startAttlist(elementName, augs);
803         if (fDTDHandler != null) {
804             fDTDHandler.startAttlist(elementName, augs);
805         }
806
807     } // startAttlist(String)
808

809     /**
810      * An attribute declaration.
811      *
812      * @param elementName The name of the element that this attribute
813      * is associated with.
814      * @param attributeName The name of the attribute.
815      * @param type The attribute type. This value will be one of
816      * the following: "CDATA", "ENTITY", "ENTITIES",
817      * "ENUMERATION", "ID", "IDREF", "IDREFS",
818      * "NMTOKEN", "NMTOKENS", or "NOTATION".
819      * @param enumeration If the type has the value "ENUMERATION" or
820      * "NOTATION", this array holds the allowed attribute
821      * values; otherwise, this array is null.
822      * @param defaultType The attribute default type. This value will be
823      * one of the following: "#FIXED", "#IMPLIED",
824      * "#REQUIRED", or null.
825      * @param defaultValue The attribute default value, or null if no
826      * default value is specified.
827      * @param nonNormalizedDefaultValue The attribute default value with no normalization
828      * performed, or null if no default value is specified.
829      * @param augs Additional information that may include infoset
830      * augmentations.
831      *
832      * @throws XNIException Thrown by handler to signal an error.
833      */

834     public void attributeDecl(String JavaDoc elementName, String JavaDoc attributeName,
835                               String JavaDoc type, String JavaDoc[] enumeration,
836                               String JavaDoc defaultType, XMLString defaultValue,
837                               XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
838
839         if (type != XMLSymbols.fCDATASymbol && defaultValue != null) {
840             normalizeDefaultAttrValue(defaultValue);
841         }
842
843         if (fValidation) {
844         
845                 boolean duplicateAttributeDef = false ;
846                                         
847                 //Get Grammar index to grammar array
848
DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar:fGrammarBucket.getActiveGrammar());
849                 int elementIndex = grammar.getElementDeclIndex( elementName);
850                 if (grammar.getAttributeDeclIndex(elementIndex, attributeName) != -1) {
851                     //more than one attribute definition is provided for the same attribute of a given element type.
852
duplicateAttributeDef = true ;
853
854                     //this feature works only when validation is true.
855
if(fWarnDuplicateAttdef){
856                         fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
857                                                  "MSG_DUPLICATE_ATTRIBUTE_DEFINITION",
858                                                  new Object JavaDoc[]{ elementName, attributeName },
859                                                  XMLErrorReporter.SEVERITY_WARNING );
860                     }
861                 }
862
863
864             //
865
// a) VC: One ID per Element Type, If duplicate ID attribute
866
// b) VC: ID attribute Default. if there is a declareared attribute
867
// default for ID it should be of type #IMPLIED or #REQUIRED
868
if (type == XMLSymbols.fIDSymbol) {
869                 if (defaultValue != null && defaultValue.length != 0) {
870                     if (defaultType == null ||
871                         !(defaultType == XMLSymbols.fIMPLIEDSymbol ||
872                           defaultType == XMLSymbols.fREQUIREDSymbol)) {
873                         fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
874                                                    "IDDefaultTypeInvalid",
875                                                    new Object JavaDoc[]{ attributeName},
876                                                    XMLErrorReporter.SEVERITY_ERROR);
877                     }
878                 }
879
880                 if (!fTableOfIDAttributeNames.containsKey(elementName)) {
881                     fTableOfIDAttributeNames.put(elementName, attributeName);
882                 }
883                 else {
884                         //we should not report an error, when there is duplicate attribute definition for given element type
885
//according to XML 1.0 spec, When more than one definition is provided for the same attribute of a given
886
//element type, the first declaration is binding and later declaration are *ignored*. So processor should
887
//ignore the second declarations, however an application would be warned of the duplicate attribute defintion
888
// if http://apache.org/xml/features/validation/warn-on-duplicate-attdef feature is set to true,
889
// one typical case where this could be a problem, when any XML file
890
// provide the ID type information through internal subset so that it is available to the parser which read
891
//only internal subset. Now that attribute declaration(ID Type) can again be part of external parsed entity
892
//referenced. At that time if parser doesn't make this distinction it will throw an error for VC One ID per
893
//Element Type, which (second defintion) actually should be ignored. Application behavior may differ on the
894
//basis of error or warning thrown. - nb.
895

896                         if(!duplicateAttributeDef){
897                                 String JavaDoc previousIDAttributeName = (String JavaDoc)fTableOfIDAttributeNames.get( elementName );//rule a)
898
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
899                                                "MSG_MORE_THAN_ONE_ID_ATTRIBUTE",
900                                                new Object JavaDoc[]{ elementName, previousIDAttributeName, attributeName},
901                                                XMLErrorReporter.SEVERITY_ERROR);
902                         }
903                 }
904             }
905
906             //
907
// VC: One Notation Per Element Type, should check if there is a
908
// duplicate NOTATION attribute
909

910             if (type == XMLSymbols.fNOTATIONSymbol) {
911                 // VC: Notation Attributes: all notation names in the
912
// (attribute) declaration must be declared.
913
for (int i=0; i<enumeration.length; i++) {
914                     fNotationEnumVals.put(enumeration[i], attributeName);
915                 }
916
917                 if (fTableOfNOTATIONAttributeNames.containsKey( elementName ) == false) {
918                     fTableOfNOTATIONAttributeNames.put( elementName, attributeName);
919                 }
920                 else {
921                         //we should not report an error, when there is duplicate attribute definition for given element type
922
//according to XML 1.0 spec, When more than one definition is provided for the same attribute of a given
923
//element type, the first declaration is binding and later declaration are *ignored*. So processor should
924
//ignore the second declarations, however an application would be warned of the duplicate attribute defintion
925
// 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
926
//warning thrown. - nb.
927

928                         if(!duplicateAttributeDef){
929                 
930                                 String JavaDoc previousNOTATIONAttributeName = (String JavaDoc) fTableOfNOTATIONAttributeNames.get( elementName );
931                                 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
932                                                "MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE",
933                                                new Object JavaDoc[]{ elementName, previousNOTATIONAttributeName, attributeName},
934                                                XMLErrorReporter.SEVERITY_ERROR);
935                          }
936                 }
937             }
938             
939             // VC: No Duplicate Tokens
940
// XML 1.0 SE Errata - E2
941
if (type == XMLSymbols.fENUMERATIONSymbol || type == XMLSymbols.fNOTATIONSymbol) {
942                 outer:
943                     for (int i = 0; i < enumeration.length; ++i) {
944                         for (int j = i + 1; j < enumeration.length; ++j) {
945                             if (enumeration[i].equals(enumeration[j])) {
946                                 // Only report the first uniqueness violation. There could be others,
947
// but additional overhead would be incurred tracking unique tokens
948
// that have already been encountered. -- mrglavas
949
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
950                                                type == XMLSymbols.fENUMERATIONSymbol
951                                                    ? "MSG_DISTINCT_TOKENS_IN_ENUMERATION"
952                                                    : "MSG_DISTINCT_NOTATION_IN_ENUMERATION",
953                                                new Object JavaDoc[]{ elementName, enumeration[i], attributeName },
954                                                XMLErrorReporter.SEVERITY_ERROR);
955                                 break outer;
956                             }
957                         }
958                     }
959             }
960
961             // VC: Attribute Default Legal
962
boolean ok = true;
963             if (defaultValue != null &&
964                 (defaultType == null ||
965                  (defaultType != null && defaultType == XMLSymbols.fFIXEDSymbol))) {
966
967                 String JavaDoc value = defaultValue.toString();
968                 if (type == XMLSymbols.fNMTOKENSSymbol ||
969                     type == XMLSymbols.fENTITIESSymbol ||
970                     type == XMLSymbols.fIDREFSSymbol) {
971
972                     StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(value," ");
973                     if (tokenizer.hasMoreTokens()) {
974                         while (true) {
975                             String JavaDoc nmtoken = tokenizer.nextToken();
976                             if (type == XMLSymbols.fNMTOKENSSymbol) {
977                                 if (!isValidNmtoken(nmtoken)) {
978                                     ok = false;
979                                     break;
980                                 }
981                             }
982                             else if (type == XMLSymbols.fENTITIESSymbol ||
983                                      type == XMLSymbols.fIDREFSSymbol) {
984                                 if (!isValidName(nmtoken)) {
985                                     ok = false;
986                                     break;
987                                 }
988                             }
989                             if (!tokenizer.hasMoreTokens()) {
990                                 break;
991                             }
992                         }
993                     }
994
995                 }
996                 else {
997                     if (type == XMLSymbols.fENTITYSymbol ||
998                         type == XMLSymbols.fIDSymbol ||
999                         type == XMLSymbols.fIDREFSymbol ||
1000                        type == XMLSymbols.fNOTATIONSymbol) {
1001
1002                        if (!isValidName(value)) {
1003                            ok = false;
1004                        }
1005
1006                    }
1007                    else if (type == XMLSymbols.fNMTOKENSymbol ||
1008                             type == XMLSymbols.fENUMERATIONSymbol) {
1009
1010                        if (!isValidNmtoken(value)) {
1011                            ok = false;
1012                        }
1013                    }
1014
1015                    if (type == XMLSymbols.fNOTATIONSymbol ||
1016                        type == XMLSymbols.fENUMERATIONSymbol) {
1017                        ok = false;
1018                        for (int i=0; i<enumeration.length; i++) {
1019                            if (defaultValue.equals(enumeration[i])) {
1020                                ok = true;
1021                            }
1022                        }
1023                    }
1024
1025                }
1026                if (!ok) {
1027                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1028                                               "MSG_ATT_DEFAULT_INVALID",
1029                                               new Object JavaDoc[]{attributeName, value},
1030                                               XMLErrorReporter.SEVERITY_ERROR);
1031                }
1032            }
1033        }
1034
1035        // call handlers
1036
if(fDTDGrammar != null)
1037            fDTDGrammar.attributeDecl(elementName, attributeName,
1038                                  type, enumeration,
1039                                  defaultType, defaultValue, nonNormalizedDefaultValue, augs);
1040        if (fDTDHandler != null) {
1041            fDTDHandler.attributeDecl(elementName, attributeName,
1042                                      type, enumeration,
1043                                      defaultType, defaultValue, nonNormalizedDefaultValue, augs);
1044        }
1045
1046    } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
1047

1048    /**
1049     * The end of an attribute list.
1050     *
1051     * @param augs Additional information that may include infoset
1052     * augmentations.
1053     *
1054     * @throws XNIException Thrown by handler to signal an error.
1055     */

1056    public void endAttlist(Augmentations augs) throws XNIException {
1057
1058        // call handlers
1059
if(fDTDGrammar != null)
1060            fDTDGrammar.endAttlist(augs);
1061        if (fDTDHandler != null) {
1062            fDTDHandler.endAttlist(augs);
1063        }
1064
1065    } // endAttlist()
1066

1067    /**
1068     * An internal entity declaration.
1069     *
1070     * @param name The name of the entity. Parameter entity names start with
1071     * '%', whereas the name of a general entity is just the
1072     * entity name.
1073     * @param text The value of the entity.
1074     * @param nonNormalizedText The non-normalized value of the entity. This
1075     * value contains the same sequence of characters that was in
1076     * the internal entity declaration, without any entity
1077     * references expanded.
1078     * @param augs Additional information that may include infoset
1079     * augmentations.
1080     *
1081     * @throws XNIException Thrown by handler to signal an error.
1082     */

1083    public void internalEntityDecl(String JavaDoc name, XMLString text,
1084                                   XMLString nonNormalizedText,
1085                                   Augmentations augs) throws XNIException {
1086
1087        DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar());
1088        int index = grammar.getEntityDeclIndex(name) ;
1089
1090        //If the same entity is declared more than once, the first declaration
1091
//encountered is binding, SAX requires only effective(first) declaration
1092
//to be reported to the application
1093

1094        //REVISIT: Does it make sense to pass duplicate Entity information across
1095
//the pipeline -- nb?
1096

1097        //its a new entity and hasn't been declared.
1098
if(index == -1){
1099            //store internal entity declaration in grammar
1100
if(fDTDGrammar != null)
1101                fDTDGrammar.internalEntityDecl(name, text, nonNormalizedText, augs);
1102            // call handlers
1103
if (fDTDHandler != null) {
1104                fDTDHandler.internalEntityDecl(name, text, nonNormalizedText, augs);
1105            }
1106        }
1107
1108    } // internalEntityDecl(String,XMLString,XMLString)
1109

1110
1111    /**
1112     * An external entity declaration.
1113     *
1114     * @param name The name of the entity. Parameter entity names start
1115     * with '%', whereas the name of a general entity is just
1116     * the entity name.
1117     * @param identifier An object containing all location information
1118     * pertinent to this external entity.
1119     * @param augs Additional information that may include infoset
1120     * augmentations.
1121     *
1122     * @throws XNIException Thrown by handler to signal an error.
1123     */

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

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

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

1150    /**
1151     * An unparsed entity declaration.
1152     *
1153     * @param name The name of the entity.
1154     * @param identifier An object containing all location information
1155     * pertinent to this entity.
1156     * @param notation The name of the notation.
1157     * @param augs Additional information that may include infoset
1158     * augmentations.
1159     *
1160     * @throws XNIException Thrown by handler to signal an error.
1161     */

1162    public void unparsedEntityDecl(String JavaDoc name, XMLResourceIdentifier identifier,
1163                                   String JavaDoc notation,
1164                                   Augmentations augs) throws XNIException {
1165
1166        // VC: Notation declared, in the production of NDataDecl
1167
if (fValidation) {
1168            fNDataDeclNotations.put(name, notation);
1169        }
1170
1171        // call handlers
1172
if(fDTDGrammar != null)
1173            fDTDGrammar.unparsedEntityDecl(name, identifier, notation, augs);
1174        if (fDTDHandler != null) {
1175            fDTDHandler.unparsedEntityDecl(name, identifier, notation, augs);
1176        }
1177
1178    } // unparsedEntityDecl(String,XMLResourceIdentifier,String,Augmentations)
1179

1180    /**
1181     * A notation declaration
1182     *
1183     * @param name The name of the notation.
1184     * @param identifier An object containing all location information
1185     * pertinent to this notation.
1186     * @param augs Additional information that may include infoset
1187     * augmentations.
1188     *
1189     * @throws XNIException Thrown by handler to signal an error.
1190     */

1191    public void notationDecl(String JavaDoc name, XMLResourceIdentifier identifier,
1192                             Augmentations augs) throws XNIException {
1193
1194        // VC: Unique Notation Name
1195
if (fValidation) {
1196            DTDGrammar grammar = (fDTDGrammar != null ? fDTDGrammar : fGrammarBucket.getActiveGrammar());
1197            if (grammar.getNotationDeclIndex(name) != -1) {
1198                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1199                                           "UniqueNotationName",
1200                                           new Object JavaDoc[]{name},
1201                                           XMLErrorReporter.SEVERITY_ERROR);
1202            }
1203        }
1204        
1205        // call handlers
1206
if(fDTDGrammar != null)
1207            fDTDGrammar.notationDecl(name, identifier, augs);
1208        if (fDTDHandler != null) {
1209            fDTDHandler.notationDecl(name, identifier, augs);
1210        }
1211
1212    } // notationDecl(String,XMLResourceIdentifier, Augmentations)
1213

1214    /**
1215     * The start of a conditional section.
1216     *
1217     * @param type The type of the conditional section. This value will
1218     * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
1219     * @param augs Additional information that may include infoset
1220     * augmentations.
1221     *
1222     * @throws XNIException Thrown by handler to signal an error.
1223     *
1224     * @see #CONDITIONAL_INCLUDE
1225     * @see #CONDITIONAL_IGNORE
1226     */

1227    public void startConditional(short type, Augmentations augs) throws XNIException {
1228
1229        // set state
1230
fInDTDIgnore = type == XMLDTDHandler.CONDITIONAL_IGNORE;
1231
1232        // call handlers
1233
if(fDTDGrammar != null)
1234            fDTDGrammar.startConditional(type, augs);
1235        if (fDTDHandler != null) {
1236            fDTDHandler.startConditional(type, augs);
1237        }
1238
1239    } // startConditional(short)
1240

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

1249    public void endConditional(Augmentations augs) throws XNIException {
1250
1251        // set state
1252
fInDTDIgnore = false;
1253
1254        // call handlers
1255
if(fDTDGrammar != null)
1256            fDTDGrammar.endConditional(augs);
1257        if (fDTDHandler != null) {
1258            fDTDHandler.endConditional(augs);
1259        }
1260
1261    } // endConditional()
1262

1263    /**
1264     * The end of the DTD.
1265     *
1266     * @param augs Additional information that may include infoset
1267     * augmentations.
1268     *
1269     * @throws XNIException Thrown by handler to signal an error.
1270     */

1271    public void endDTD(Augmentations augs) throws XNIException {
1272
1273
1274        // save grammar
1275
if(fDTDGrammar != null) {
1276            fDTDGrammar.endDTD(augs);
1277            if(fGrammarPool != null)
1278                fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_DTD, new Grammar[] {fDTDGrammar});
1279        }
1280        // check VC: Notation declared, in the production of NDataDecl
1281
if (fValidation) {
1282            DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar());
1283
1284            // VC : Notation Declared. for external entity declaration [Production 76].
1285
Enumeration JavaDoc entities = fNDataDeclNotations.keys();
1286            while (entities.hasMoreElements()) {
1287                String JavaDoc entity = (String JavaDoc) entities.nextElement();
1288                String JavaDoc notation = (String JavaDoc) fNDataDeclNotations.get(entity);
1289                if (grammar.getNotationDeclIndex(notation) == -1) {
1290                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1291                                               "MSG_NOTATION_NOT_DECLARED_FOR_UNPARSED_ENTITYDECL",
1292                                               new Object JavaDoc[]{entity, notation},
1293                                               XMLErrorReporter.SEVERITY_ERROR);
1294                }
1295            }
1296
1297            // VC: Notation Attributes:
1298
// all notation names in the (attribute) declaration must be declared.
1299
Enumeration JavaDoc notationVals = fNotationEnumVals.keys();
1300            while (notationVals.hasMoreElements()) {
1301                String JavaDoc notation = (String JavaDoc) notationVals.nextElement();
1302                String JavaDoc attributeName = (String JavaDoc) fNotationEnumVals.get(notation);
1303                if (grammar.getNotationDeclIndex(notation) == -1) {
1304                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1305                                               "MSG_NOTATION_NOT_DECLARED_FOR_NOTATIONTYPE_ATTRIBUTE",
1306                                               new Object JavaDoc[]{attributeName, notation},
1307                                               XMLErrorReporter.SEVERITY_ERROR);
1308                }
1309            }
1310            
1311            // VC: No Notation on Empty Element
1312
// An attribute of type NOTATION must not be declared on an element declared EMPTY.
1313
Enumeration JavaDoc elementsWithNotations = fTableOfNOTATIONAttributeNames.keys();
1314            while (elementsWithNotations.hasMoreElements()) {
1315                String JavaDoc elementName = (String JavaDoc) elementsWithNotations.nextElement();
1316                int elementIndex = grammar.getElementDeclIndex(elementName);
1317                if (grammar.getContentSpecType(elementIndex) == XMLElementDecl.TYPE_EMPTY) {
1318                    String JavaDoc attributeName = (String JavaDoc) fTableOfNOTATIONAttributeNames.get(elementName);
1319                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1320                                               "NoNotationOnEmptyElement",
1321                                               new Object JavaDoc[]{elementName, attributeName},
1322                                               XMLErrorReporter.SEVERITY_ERROR);
1323                }
1324            }
1325
1326            fTableOfIDAttributeNames = null;//should be safe to release these references
1327
fTableOfNOTATIONAttributeNames = null;
1328        }
1329
1330        // call handlers
1331
if (fDTDHandler != null) {
1332            fDTDHandler.endDTD(augs);
1333        }
1334
1335    } // endDTD()
1336

1337    // sets the XMLDTDSource of this handler
1338
public void setDTDSource(XMLDTDSource source ) {
1339        fDTDSource = source;
1340    } // setDTDSource(XMLDTDSource)
1341

1342    // returns the XMLDTDSource of this handler
1343
public XMLDTDSource getDTDSource() {
1344        return fDTDSource;
1345    } // getDTDSource(): XMLDTDSource
1346

1347    //
1348
// XMLDTDContentModelHandler methods
1349
//
1350

1351    // sets the XMLContentModelDTDSource of this handler
1352
public void setDTDContentModelSource(XMLDTDContentModelSource source ) {
1353        fDTDContentModelSource = source;
1354    } // setDTDContentModelSource(XMLDTDContentModelSource)
1355

1356    // returns the XMLDTDSource of this handler
1357
public XMLDTDContentModelSource getDTDContentModelSource() {
1358        return fDTDContentModelSource;
1359    } // getDTDContentModelSource(): XMLDTDContentModelSource
1360

1361
1362    /**
1363     * The start of a content model. Depending on the type of the content
1364     * model, specific methods may be called between the call to the
1365     * startContentModel method and the call to the endContentModel method.
1366     *
1367     * @param elementName The name of the element.
1368     * @param augs Additional information that may include infoset
1369     * augmentations.
1370     *
1371     * @throws XNIException Thrown by handler to signal an error.
1372     */

1373    public void startContentModel(String JavaDoc elementName, Augmentations augs)
1374        throws XNIException {
1375
1376        if (fValidation) {
1377            fDTDElementDeclName = elementName;
1378            fMixedElementTypes.removeAllElements();
1379        }
1380
1381        // call handlers
1382
if(fDTDGrammar != null)
1383            fDTDGrammar.startContentModel(elementName, augs);
1384        if (fDTDContentModelHandler != null) {
1385            fDTDContentModelHandler.startContentModel(elementName, augs);
1386        }
1387
1388    } // startContentModel(String)
1389

1390    /**
1391     * A content model of ANY.
1392     *
1393     * @param augs Additional information that may include infoset
1394     * augmentations.
1395     *
1396     * @throws XNIException Thrown by handler to signal an error.
1397     *
1398     * @see #empty
1399     * @see #startGroup
1400     */

1401    public void any(Augmentations augs) throws XNIException {
1402        if(fDTDGrammar != null)
1403            fDTDGrammar.any(augs);
1404        if (fDTDContentModelHandler != null) {
1405            fDTDContentModelHandler.any(augs);
1406        }
1407    } // any()
1408

1409    /**
1410     * A content model of EMPTY.
1411     *
1412     * @param augs Additional information that may include infoset
1413     * augmentations.
1414     *
1415     * @throws XNIException Thrown by handler to signal an error.
1416     *
1417     * @see #any
1418     * @see #startGroup
1419     */

1420    public void empty(Augmentations augs) throws XNIException {
1421        if(fDTDGrammar != null)
1422            fDTDGrammar.empty(augs);
1423        if (fDTDContentModelHandler != null) {
1424            fDTDContentModelHandler.empty(augs);
1425        }
1426    } // empty()
1427

1428    /**
1429     * A start of either a mixed or children content model. A mixed
1430     * content model will immediately be followed by a call to the
1431     * <code>pcdata()</code> method. A children content model will
1432     * contain additional groups and/or elements.
1433     *
1434     * @param augs Additional information that may include infoset
1435     * augmentations.
1436     *
1437     * @throws XNIException Thrown by handler to signal an error.
1438     *
1439     * @see #any
1440     * @see #empty
1441     */

1442    public void startGroup(Augmentations augs) throws XNIException {
1443
1444        fMixed = false;
1445        // call handlers
1446
if(fDTDGrammar != null)
1447            fDTDGrammar.startGroup(augs);
1448        if (fDTDContentModelHandler != null) {
1449            fDTDContentModelHandler.startGroup(augs);
1450        }
1451
1452    } // startGroup()
1453

1454    /**
1455     * The appearance of "#PCDATA" within a group signifying a
1456     * mixed content model. This method will be the first called
1457     * following the content model's <code>startGroup()</code>.
1458     *
1459     * @param augs Additional information that may include infoset
1460     * augmentations.
1461     *
1462     * @throws XNIException Thrown by handler to signal an error.
1463     *
1464     * @see #startGroup
1465     */

1466    public void pcdata(Augmentations augs) {
1467        fMixed = true;
1468        if(fDTDGrammar != null)
1469            fDTDGrammar.pcdata(augs);
1470        if (fDTDContentModelHandler != null) {
1471            fDTDContentModelHandler.pcdata(augs);
1472        }
1473    } // pcdata()
1474

1475    /**
1476     * A referenced element in a mixed or children content model.
1477     *
1478     * @param elementName The name of the referenced element.
1479     * @param augs Additional information that may include infoset
1480     * augmentations.
1481     *
1482     * @throws XNIException Thrown by handler to signal an error.
1483     */

1484    public void element(String JavaDoc elementName, Augmentations augs) throws XNIException {
1485
1486        // check VC: No duplicate Types, in a single mixed-content declaration
1487
if (fMixed && fValidation) {
1488            if (fMixedElementTypes.contains(elementName)) {
1489                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1490                                           "DuplicateTypeInMixedContent",
1491                                           new Object JavaDoc[]{fDTDElementDeclName, elementName},
1492                                           XMLErrorReporter.SEVERITY_ERROR);
1493            }
1494            else {
1495                fMixedElementTypes.addElement(elementName);
1496            }
1497        }
1498
1499        // call handlers
1500
if(fDTDGrammar != null)
1501            fDTDGrammar.element(elementName, augs);
1502        if (fDTDContentModelHandler != null) {
1503            fDTDContentModelHandler.element(elementName, augs);
1504        }
1505
1506    } // childrenElement(String)
1507

1508    /**
1509     * The separator between choices or sequences of a mixed or children
1510     * content model.
1511     *
1512     * @param separator The type of children separator.
1513     * @param augs Additional information that may include infoset
1514     * augmentations.
1515     *
1516     * @throws XNIException Thrown by handler to signal an error.
1517     *
1518     * @see #SEPARATOR_CHOICE
1519     * @see #SEPARATOR_SEQUENCE
1520     */

1521    public void separator(short separator, Augmentations augs)
1522        throws XNIException {
1523
1524        // call handlers
1525
if(fDTDGrammar != null)
1526            fDTDGrammar.separator(separator, augs);
1527        if (fDTDContentModelHandler != null) {
1528            fDTDContentModelHandler.separator(separator, augs);
1529        }
1530
1531    } // separator(short)
1532

1533    /**
1534     * The occurrence count for a child in a children content model or
1535     * for the mixed content model group.
1536     *
1537     * @param occurrence The occurrence count for the last element
1538     * or group.
1539     * @param augs Additional information that may include infoset
1540     * augmentations.
1541     *
1542     * @throws XNIException Thrown by handler to signal an error.
1543     *
1544     * @see #OCCURS_ZERO_OR_ONE
1545     * @see #OCCURS_ZERO_OR_MORE
1546     * @see #OCCURS_ONE_OR_MORE
1547     */

1548    public void occurrence(short occurrence, Augmentations augs)
1549        throws XNIException {
1550
1551        // call handlers
1552
if(fDTDGrammar != null)
1553            fDTDGrammar.occurrence(occurrence, augs);
1554        if (fDTDContentModelHandler != null) {
1555            fDTDContentModelHandler.occurrence(occurrence, augs);
1556        }
1557
1558    } // occurrence(short)
1559

1560    /**
1561     * The end of a group for mixed or children content models.
1562     *
1563     * @param augs Additional information that may include infoset
1564     * augmentations.
1565     *
1566     * @throws XNIException Thrown by handler to signal an error.
1567     */

1568    public void endGroup(Augmentations augs) throws XNIException {
1569
1570        // call handlers
1571
if(fDTDGrammar != null)
1572            fDTDGrammar.endGroup(augs);
1573        if (fDTDContentModelHandler != null) {
1574            fDTDContentModelHandler.endGroup(augs);
1575        }
1576
1577    } // endGroup()
1578

1579    /**
1580     * The end of a content model.
1581     *
1582     * @param augs Additional information that may include infoset
1583     * augmentations.
1584     *
1585     * @throws XNIException Thrown by handler to signal an error.
1586     */

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

1598    //
1599
// Private methods
1600
//
1601

1602    /**
1603     * Normalize the attribute value of a non CDATA default attribute
1604     * collapsing sequences of space characters (x20)
1605     *
1606     * @param value The value to normalize
1607     * @return Whether the value was changed or not.
1608     */

1609    private boolean normalizeDefaultAttrValue(XMLString value) {
1610
1611        boolean skipSpace = true; // skip leading spaces
1612
int current = value.offset;
1613        int end = value.offset + value.length;
1614        for (int i = value.offset; i < end; i++) {
1615            if (value.ch[i] == ' ') {
1616                if (!skipSpace) {
1617                    // take the first whitespace as a space and skip the others
1618
value.ch[current++] = ' ';
1619                    skipSpace = true;
1620                }
1621                else {
1622                    // just skip it.
1623
}
1624            }
1625            else {
1626                // simply shift non space chars if needed
1627
if (current != i) {
1628                    value.ch[current] = value.ch[i];
1629                }
1630                current++;
1631                skipSpace = false;
1632            }
1633        }
1634        if (current != end) {
1635            if (skipSpace) {
1636                // if we finished on a space trim it
1637
current--;
1638            }
1639            // set the new value length
1640
value.length = current - value.offset;
1641            return true;
1642        }
1643        return false;
1644    }
1645
1646    
1647    protected boolean isValidNmtoken(String JavaDoc nmtoken) {
1648        return XMLChar.isValidNmtoken(nmtoken);
1649    } // isValidNmtoken(String): boolean
1650

1651    protected boolean isValidName(String JavaDoc name) {
1652        return XMLChar.isValidName(name);
1653    } // isValidName(String): boolean
1654
} // class XMLDTDProcessor
1655
Popular Tags