KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * Copyright 1999-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 org.apache.xerces.impl.Constants;
20 import org.apache.xerces.impl.RevalidationHandler;
21 import org.apache.xerces.impl.XMLEntityManager;
22 import org.apache.xerces.impl.XMLErrorReporter;
23 import org.apache.xerces.impl.dtd.models.ContentModelValidator;
24 import org.apache.xerces.impl.dv.DTDDVFactory;
25 import org.apache.xerces.impl.dv.DatatypeValidator;
26 import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
27 import org.apache.xerces.impl.msg.XMLMessageFormatter;
28 import org.apache.xerces.impl.validation.ValidationManager;
29 import org.apache.xerces.impl.validation.ValidationState;
30 import org.apache.xerces.util.SymbolTable;
31 import org.apache.xerces.util.XMLChar;
32 import org.apache.xerces.util.XMLSymbols;
33 import org.apache.xerces.xni.Augmentations;
34 import org.apache.xerces.xni.NamespaceContext;
35 import org.apache.xerces.xni.QName;
36 import org.apache.xerces.xni.XMLAttributes;
37 import org.apache.xerces.xni.XMLDocumentHandler;
38 import org.apache.xerces.xni.XMLLocator;
39 import org.apache.xerces.xni.XMLResourceIdentifier;
40 import org.apache.xerces.xni.XMLString;
41 import org.apache.xerces.xni.XNIException;
42 import org.apache.xerces.xni.grammars.Grammar;
43 import org.apache.xerces.xni.grammars.XMLGrammarDescription;
44 import org.apache.xerces.xni.grammars.XMLGrammarPool;
45 import org.apache.xerces.xni.parser.XMLComponent;
46 import org.apache.xerces.xni.parser.XMLComponentManager;
47 import org.apache.xerces.xni.parser.XMLConfigurationException;
48 import org.apache.xerces.xni.parser.XMLDocumentFilter;
49 import org.apache.xerces.xni.parser.XMLDocumentSource;
50
51 /**
52  * The DTD validator. The validator implements a document
53  * filter: receiving document events from the scanner; validating
54  * the content and structure; augmenting the InfoSet, if applicable;
55  * and notifying the parser of the information resulting from the
56  * validation process.
57  * <p> Formerly, this component also handled DTD events and grammar construction.
58  * To facilitate the development of a meaningful DTD grammar caching/preparsing
59  * framework, this functionality has been moved into the XMLDTDLoader
60  * class. Therefore, this class no longer implements the DTDFilter
61  * or DTDContentModelFilter interfaces.
62  * <p>
63  * This component requires the following features and properties from the
64  * component manager that uses it:
65  * <ul>
66  * <li>http://xml.org/sax/features/namespaces</li>
67  * <li>http://xml.org/sax/features/validation</li>
68  * <li>http://apache.org/xml/features/validation/dynamic</li>
69  * <li>http://apache.org/xml/properties/internal/symbol-table</li>
70  * <li>http://apache.org/xml/properties/internal/error-reporter</li>
71  * <li>http://apache.org/xml/properties/internal/grammar-pool</li>
72  * <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
73  * </ul>
74  *
75  * @xerces.internal
76  *
77  * @author Eric Ye, IBM
78  * @author Andy Clark, IBM
79  * @author Jeffrey Rodriguez IBM
80  * @author Neil Graham, IBM
81  *
82  * @version $Id: XMLDTDValidator.java,v 1.62 2005/05/10 15:36:42 ankitp Exp $
83  */

84 public class XMLDTDValidator
85         implements XMLComponent, XMLDocumentFilter, XMLDTDValidatorFilter, RevalidationHandler {
86
87     //
88
// Constants
89
//
90

91     /** Symbol: "&lt;&lt;datatypes>>". */
92
93     /** Top level scope (-1). */
94     private static final int TOP_LEVEL_SCOPE = -1;
95
96     // feature identifiers
97

98     /** Feature identifier: namespaces. */
99     protected static final String JavaDoc NAMESPACES =
100     Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
101
102     /** Feature identifier: validation. */
103     protected static final String JavaDoc VALIDATION =
104     Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
105
106     /** Feature identifier: dynamic validation. */
107     protected static final String JavaDoc DYNAMIC_VALIDATION =
108     Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
109
110     /** Feature identifier: warn on duplicate attdef */
111     protected static final String JavaDoc WARN_ON_DUPLICATE_ATTDEF =
112     Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
113     
114     protected static final String JavaDoc PARSER_SETTINGS =
115         Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
116
117
118
119     // property identifiers
120

121     /** Property identifier: symbol table. */
122     protected static final String JavaDoc SYMBOL_TABLE =
123         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
124
125     /** Property identifier: error reporter. */
126     protected static final String JavaDoc ERROR_REPORTER =
127         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
128
129     /** Property identifier: grammar pool. */
130     protected static final String JavaDoc GRAMMAR_POOL =
131         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
132
133     /** Property identifier: datatype validator factory. */
134     protected static final String JavaDoc DATATYPE_VALIDATOR_FACTORY =
135         Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
136
137     // property identifier: ValidationManager
138
protected static final String JavaDoc VALIDATION_MANAGER =
139         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
140
141     // recognized features and properties
142

143     /** Recognized features. */
144     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
145         NAMESPACES,
146         VALIDATION,
147         DYNAMIC_VALIDATION
148     };
149
150     /** Feature defaults. */
151     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = {
152         null,
153         null,
154         Boolean.FALSE,
155     };
156
157     /** Recognized properties. */
158     private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
159         SYMBOL_TABLE,
160         ERROR_REPORTER,
161         GRAMMAR_POOL,
162         DATATYPE_VALIDATOR_FACTORY,
163         VALIDATION_MANAGER
164     };
165
166     /** Property defaults. */
167     private static final Object JavaDoc[] PROPERTY_DEFAULTS = {
168         null,
169         null,
170         null,
171         null,
172         null,
173     };
174
175     // debugging
176

177     /** Compile to true to debug attributes. */
178     private static final boolean DEBUG_ATTRIBUTES = false;
179
180     /** Compile to true to debug element children. */
181     private static final boolean DEBUG_ELEMENT_CHILDREN = false;
182
183     //
184
// Data
185
//
186

187     // updated during reset
188
protected ValidationManager fValidationManager = null;
189     
190     // validation state
191
protected ValidationState fValidationState = new ValidationState();
192
193     // features
194

195     /** Namespaces. */
196     protected boolean fNamespaces;
197
198     /** Validation. */
199     protected boolean fValidation;
200
201     /** Validation against only DTD */
202     protected boolean fDTDValidation;
203
204     /**
205      * Dynamic validation. This state of this feature is only useful when
206      * the validation feature is set to <code>true</code>.
207      */

208     protected boolean fDynamicValidation;
209
210     /** warn on duplicate attribute definition, this feature works only when validation is true */
211     protected boolean fWarnDuplicateAttdef;
212         
213     // properties
214

215     /** Symbol table. */
216     protected SymbolTable fSymbolTable;
217
218     /** Error reporter. */
219     protected XMLErrorReporter fErrorReporter;
220
221     // the grammar pool
222
protected XMLGrammarPool fGrammarPool;
223
224     /** Grammar bucket. */
225     protected DTDGrammarBucket fGrammarBucket;
226
227     /* location of the document as passed in from startDocument call */
228     protected XMLLocator fDocLocation;
229
230     /** Namespace support. */
231     protected NamespaceContext fNamespaceContext = null;
232
233     /** Datatype validator factory. */
234     protected DTDDVFactory fDatatypeValidatorFactory;
235
236     // handlers
237

238     /** Document handler. */
239     protected XMLDocumentHandler fDocumentHandler;
240
241     protected XMLDocumentSource fDocumentSource;
242     // grammars
243

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

249     /** True if seen DOCTYPE declaration. */
250     protected boolean fSeenDoctypeDecl = false;
251
252     /** Perform validation. */
253     private boolean fPerformValidation;
254     
255     /** Schema type: None, DTD, Schema */
256     private String JavaDoc fSchemaType;
257
258     // information regarding the current element
259

260     /** Current element name. */
261     private final QName fCurrentElement = new QName();
262
263     /** Current element index. */
264     private int fCurrentElementIndex = -1;
265
266     /** Current content spec type. */
267     private int fCurrentContentSpecType = -1;
268
269     /** The root element name. */
270     private final QName fRootElement = new QName();
271
272     private boolean fInCDATASection = false;
273     // element stack
274

275     /** Element index stack. */
276     private int[] fElementIndexStack = new int[8];
277
278     /** Content spec type stack. */
279     private int[] fContentSpecTypeStack = new int[8];
280
281     /** Element name stack. */
282     private QName[] fElementQNamePartsStack = new QName[8];
283
284     // children list and offset stack
285

286     /**
287      * Element children. This data structure is a growing stack that
288      * holds the children of elements from the root to the current
289      * element depth. This structure never gets "deeper" than the
290      * deepest element. Space is re-used once each element is closed.
291      * <p>
292      * <strong>Note:</strong> This is much more efficient use of memory
293      * than creating new arrays for each element depth.
294      * <p>
295      * <strong>Note:</strong> The use of this data structure is for
296      * validation "on the way out". If the validation model changes to
297      * "on the way in", then this data structure is not needed.
298      */

299     private QName[] fElementChildren = new QName[32];
300
301     /** Element children count. */
302     private int fElementChildrenLength = 0;
303
304     /**
305      * Element children offset stack. This stack refers to offsets
306      * into the <code>fElementChildren</code> array.
307      * @see #fElementChildren
308      */

309     private int[] fElementChildrenOffsetStack = new int[32];
310
311     /** Element depth. */
312     private int fElementDepth = -1;
313
314     // validation states
315

316     /** True if seen the root element. */
317     private boolean fSeenRootElement = false;
318
319     /** True if inside of element content. */
320     private boolean fInElementContent = false;
321
322     // temporary variables
323

324     /** Temporary element declaration. */
325     private XMLElementDecl fTempElementDecl = new XMLElementDecl();
326
327     /** Temporary atribute declaration. */
328     private XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();
329
330     /** Temporary entity declaration. */
331     private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
332
333     /** Temporary qualified name. */
334     private QName fTempQName = new QName();
335
336     /** Temporary string buffers. */
337     private StringBuffer JavaDoc fBuffer = new StringBuffer JavaDoc();
338
339     // symbols: general
340

341     // attribute validators
342

343     /** Datatype validator: ID. */
344     protected DatatypeValidator fValID;
345
346     /** Datatype validator: IDREF. */
347     protected DatatypeValidator fValIDRef;
348
349     /** Datatype validator: IDREFS. */
350     protected DatatypeValidator fValIDRefs;
351
352     /** Datatype validator: ENTITY. */
353     protected DatatypeValidator fValENTITY;
354
355     /** Datatype validator: ENTITIES. */
356     protected DatatypeValidator fValENTITIES;
357
358     /** Datatype validator: NMTOKEN. */
359     protected DatatypeValidator fValNMTOKEN;
360
361     /** Datatype validator: NMTOKENS. */
362     protected DatatypeValidator fValNMTOKENS;
363
364     /** Datatype validator: NOTATION. */
365     protected DatatypeValidator fValNOTATION;
366
367     // to check for duplicate ID or ANNOTATION attribute declare in
368
// ATTLIST, and misc VCs
369

370     //
371
// Constructors
372
//
373

374     /** Default constructor. */
375     public XMLDTDValidator() {
376
377         // initialize data
378
for (int i = 0; i < fElementQNamePartsStack.length; i++) {
379             fElementQNamePartsStack[i] = new QName();
380         }
381         fGrammarBucket = new DTDGrammarBucket();
382
383     } // <init>()
384

385     DTDGrammarBucket getGrammarBucket() {
386         return fGrammarBucket;
387     } // getGrammarBucket(): DTDGrammarBucket
388

389     //
390
// XMLComponent methods
391
//
392

393     /*
394      * Resets the component. The component can query the component manager
395      * about any features and properties that affect the operation of the
396      * component.
397      *
398      * @param componentManager The component manager.
399      *
400      * @throws SAXException Thrown by component on finitialization error.
401      * For example, if a feature or property is
402      * required for the operation of the component, the
403      * component manager may throw a
404      * SAXNotRecognizedException or a
405      * SAXNotSupportedException.
406      */

407     public void reset(XMLComponentManager componentManager)
408     throws XMLConfigurationException {
409
410         // clear grammars
411
fDTDGrammar = null;
412         fSeenDoctypeDecl = false;
413         fInCDATASection = false;
414         // initialize state
415
fSeenRootElement = false;
416         fInElementContent = false;
417         fCurrentElementIndex = -1;
418         fCurrentContentSpecType = -1;
419
420         fRootElement.clear();
421
422         fValidationState.resetIDTables();
423         
424         fGrammarBucket.clear();
425         fElementDepth = -1;
426         fElementChildrenLength = 0;
427         
428         boolean parser_settings;
429         try {
430             parser_settings = componentManager.getFeature(PARSER_SETTINGS);
431         }
432         catch (XMLConfigurationException e){
433             parser_settings = true;
434         }
435         
436         if (!parser_settings){
437             // parser settings have not been changed
438
fValidationManager.addValidationState(fValidationState);
439             return;
440         }
441
442         // sax features
443
try {
444             fNamespaces = componentManager.getFeature(NAMESPACES);
445         }
446         catch (XMLConfigurationException e) {
447             fNamespaces = true;
448         }
449         try {
450             fValidation = componentManager.getFeature(VALIDATION);
451         }
452         catch (XMLConfigurationException e) {
453             fValidation = false;
454         }
455         try {
456             fDTDValidation = !(componentManager.getFeature(Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE));
457         }
458         catch (XMLConfigurationException e) {
459             // must be in a schema-less configuration!
460
fDTDValidation = true;
461         }
462
463         // Xerces features
464
try {
465             fDynamicValidation = componentManager.getFeature(DYNAMIC_VALIDATION);
466         }
467         catch (XMLConfigurationException e) {
468             fDynamicValidation = false;
469         }
470         
471         try {
472             fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF);
473         }
474         catch (XMLConfigurationException e) {
475             fWarnDuplicateAttdef = false;
476         }
477         
478         try {
479             fSchemaType = (String JavaDoc)componentManager.getProperty (Constants.JAXP_PROPERTY_PREFIX
480             + Constants.SCHEMA_LANGUAGE);
481         }
482         catch (XMLConfigurationException e){
483             fSchemaType = null;
484         }
485
486         fValidationManager= (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
487         fValidationManager.addValidationState(fValidationState);
488         fValidationState.setUsingNamespaces(fNamespaces);
489         
490         // get needed components
491
fErrorReporter = (XMLErrorReporter)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.ERROR_REPORTER_PROPERTY);
492         fSymbolTable = (SymbolTable)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.SYMBOL_TABLE_PROPERTY);
493         try {
494             fGrammarPool= (XMLGrammarPool)componentManager.getProperty(GRAMMAR_POOL);
495         } catch (XMLConfigurationException e) {
496             fGrammarPool = null;
497         }
498
499         fDatatypeValidatorFactory = (DTDDVFactory)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY);
500         init();
501
502     } // reset(XMLComponentManager)
503

504     /**
505      * Returns a list of feature identifiers that are recognized by
506      * this component. This method may return null if no features
507      * are recognized by this component.
508      */

509     public String JavaDoc[] getRecognizedFeatures() {
510         return (String JavaDoc[])(RECOGNIZED_FEATURES.clone());
511     } // getRecognizedFeatures():String[]
512

513     /**
514      * Sets the state of a feature. This method is called by the component
515      * manager any time after reset when a feature changes state.
516      * <p>
517      * <strong>Note:</strong> Components should silently ignore features
518      * that do not affect the operation of the component.
519      *
520      * @param featureId The feature identifier.
521      * @param state The state of the feature.
522      *
523      * @throws SAXNotRecognizedException The component should not throw
524      * this exception.
525      * @throws SAXNotSupportedException The component should not throw
526      * this exception.
527      */

528     public void setFeature(String JavaDoc featureId, boolean state)
529     throws XMLConfigurationException {
530     } // setFeature(String,boolean)
531

532     /**
533      * Returns a list of property identifiers that are recognized by
534      * this component. This method may return null if no properties
535      * are recognized by this component.
536      */

537     public String JavaDoc[] getRecognizedProperties() {
538         return (String JavaDoc[])(RECOGNIZED_PROPERTIES.clone());
539     } // getRecognizedProperties():String[]
540

541     /**
542      * Sets the value of a property. This method is called by the component
543      * manager any time after reset when a property changes value.
544      * <p>
545      * <strong>Note:</strong> Components should silently ignore properties
546      * that do not affect the operation of the component.
547      *
548      * @param propertyId The property identifier.
549      * @param value The value of the property.
550      *
551      * @throws SAXNotRecognizedException The component should not throw
552      * this exception.
553      * @throws SAXNotSupportedException The component should not throw
554      * this exception.
555      */

556     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
557     throws XMLConfigurationException {
558     } // setProperty(String,Object)
559

560     /**
561      * Returns the default state for a feature, or null if this
562      * component does not want to report a default value for this
563      * feature.
564      *
565      * @param featureId The feature identifier.
566      *
567      * @since Xerces 2.2.0
568      */

569     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
570         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
571             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
572                 return FEATURE_DEFAULTS[i];
573             }
574         }
575         return null;
576     } // getFeatureDefault(String):Boolean
577

578     /**
579      * Returns the default state for a property, or null if this
580      * component does not want to report a default value for this
581      * property.
582      *
583      * @param propertyId The property identifier.
584      *
585      * @since Xerces 2.2.0
586      */

587     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
588         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
589             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
590                 return PROPERTY_DEFAULTS[i];
591             }
592         }
593         return null;
594     } // getPropertyDefault(String):Object
595

596     //
597
// XMLDocumentSource methods
598
//
599

600     /** Sets the document handler to receive information about the document. */
601     public void setDocumentHandler(XMLDocumentHandler documentHandler) {
602         fDocumentHandler = documentHandler;
603     } // setDocumentHandler(XMLDocumentHandler)
604

605     /** Returns the document handler */
606     public XMLDocumentHandler getDocumentHandler() {
607         return fDocumentHandler;
608     } // getDocumentHandler(): XMLDocumentHandler
609

610
611     //
612
// XMLDocumentHandler methods
613
//
614

615     /** Sets the document source */
616     public void setDocumentSource(XMLDocumentSource source){
617         fDocumentSource = source;
618     } // setDocumentSource
619

620     /** Returns the document source */
621     public XMLDocumentSource getDocumentSource (){
622         return fDocumentSource;
623     } // getDocumentSource
624

625     /**
626      * The start of the document.
627      *
628      * @param locator The system identifier of the entity if the entity
629      * is external, null otherwise.
630      * @param encoding The auto-detected IANA encoding name of the entity
631      * stream. This value will be null in those situations
632      * where the entity encoding is not auto-detected (e.g.
633      * internal entities or a document entity that is
634      * parsed from a java.io.Reader).
635      * @param namespaceContext
636      * The namespace context in effect at the
637      * start of this document.
638      * This object represents the current context.
639      * Implementors of this class are responsible
640      * for copying the namespace bindings from the
641      * the current context (and its parent contexts)
642      * if that information is important.
643      * @param augs Additional information that may include infoset augmentations
644      *
645      * @throws XNIException Thrown by handler to signal an error.
646      */

647     public void startDocument(XMLLocator locator, String JavaDoc encoding,
648                               NamespaceContext namespaceContext, Augmentations augs)
649     throws XNIException {
650
651         // call handlers
652
// get initial grammars
653
if(fGrammarPool != null) {
654             Grammar [] grammars = fGrammarPool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_DTD);
655             for(int i = 0; i<grammars.length; i++) {
656                 fGrammarBucket.putGrammar((DTDGrammar)grammars[i]);
657             }
658         }
659         fDocLocation = locator;
660         fNamespaceContext = namespaceContext;
661    
662         if (fDocumentHandler != null) {
663             fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
664         }
665
666     } // startDocument(XMLLocator,String)
667

668     /**
669      * Notifies of the presence of an XMLDecl line in the document. If
670      * present, this method will be called immediately following the
671      * startDocument call.
672      *
673      * @param version The XML version.
674      * @param encoding The IANA encoding name of the document, or null if
675      * not specified.
676      * @param standalone The standalone value, or null if not specified.
677      * @param augs Additional information that may include infoset augmentations
678      *
679      * @throws XNIException Thrown by handler to signal an error.
680      */

681     public void xmlDecl(String JavaDoc version, String JavaDoc encoding, String JavaDoc standalone, Augmentations augs)
682     throws XNIException {
683
684         // save standalone state
685
fGrammarBucket.setStandalone(standalone != null && standalone.equals("yes"));
686
687         // call handlers
688
if (fDocumentHandler != null) {
689             fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
690         }
691
692     } // xmlDecl(String,String,String)
693

694     /**
695      * Notifies of the presence of the DOCTYPE line in the document.
696      *
697      * @param rootElement The name of the root element.
698      * @param publicId The public identifier if an external DTD or null
699      * if the external DTD is specified using SYSTEM.
700      * @param systemId The system identifier if an external DTD, null
701      * otherwise.
702      * @param augs Additional information that may include infoset augmentations
703      *
704      * @throws XNIException Thrown by handler to signal an error.
705      */

706     public void doctypeDecl(String JavaDoc rootElement, String JavaDoc publicId, String JavaDoc systemId,
707                             Augmentations augs)
708     throws XNIException {
709
710         // save root element state
711
fSeenDoctypeDecl = true;
712         fRootElement.setValues(null, rootElement, rootElement, null);
713         // find or create grammar:
714
String JavaDoc eid = null;
715         try {
716             eid = XMLEntityManager.expandSystemId(systemId, fDocLocation.getExpandedSystemId(), false);
717         } catch (java.io.IOException JavaDoc e) {
718         }
719         XMLDTDDescription grammarDesc = new XMLDTDDescription(publicId, systemId, fDocLocation.getExpandedSystemId(), eid, rootElement);
720         fDTDGrammar = fGrammarBucket.getGrammar(grammarDesc);
721         if(fDTDGrammar == null) {
722             // give grammar pool a chance...
723
//
724
// Do not bother checking the pool if no public or system identifier was provided.
725
// Since so many different DTDs have roots in common, using only a root name as the
726
// key may cause an unexpected grammar to be retrieved from the grammar pool. This scenario
727
// would occur when an ExternalSubsetResolver has been queried and the
728
// XMLInputSource returned contains an input stream but no external identifier.
729
// This can never happen when the instance document specified a DOCTYPE. -- mrglavas
730
if (fGrammarPool != null && (systemId != null || publicId != null)) {
731                 fDTDGrammar = (DTDGrammar)fGrammarPool.retrieveGrammar(grammarDesc);
732             }
733         }
734         if(fDTDGrammar == null) {
735             // we'll have to create it...
736
fDTDGrammar = new DTDGrammar(fSymbolTable, grammarDesc);
737         } else {
738             // we've found a cached one;so let's make sure not to read
739
// any external subset!
740
fValidationManager.setCachedDTD(true);
741         }
742         fGrammarBucket.setActiveGrammar(fDTDGrammar);
743
744         // call handlers
745
if (fDocumentHandler != null) {
746             fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
747         }
748
749     } // doctypeDecl(String,String,String, Augmentations)
750

751
752     /**
753      * The start of an element.
754      *
755      * @param element The name of the element.
756      * @param attributes The element attributes.
757      * @param augs Additional information that may include infoset augmentations
758      *
759      * @throws XNIException Thrown by handler to signal an error.
760      */

761     public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
762     throws XNIException {
763
764         handleStartElement(element, attributes, augs);
765         // call handlers
766
if (fDocumentHandler != null) {
767             fDocumentHandler.startElement(element, attributes, augs);
768
769         }
770
771     } // startElement(QName,XMLAttributes)
772

773     /**
774      * An empty element.
775      *
776      * @param element The name of the element.
777      * @param attributes The element attributes.
778      * @param augs Additional information that may include infoset augmentations
779      *
780      * @throws XNIException Thrown by handler to signal an error.
781      */

782     public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
783     throws XNIException {
784
785         boolean removed = handleStartElement(element, attributes, augs);
786
787         if (fDocumentHandler !=null) {
788             fDocumentHandler.emptyElement(element, attributes, augs);
789         }
790         if (!removed) {
791             handleEndElement(element, augs, true);
792         }
793         
794
795     } // emptyElement(QName,XMLAttributes)
796

797     /**
798      * Character content.
799      *
800      * @param text The content.
801      *
802      * @param augs Additional information that may include infoset augmentations
803      *
804      * @throws XNIException Thrown by handler to signal an error.
805      */

806     public void characters(XMLString text, Augmentations augs) throws XNIException {
807
808         boolean callNextCharacters = true;
809
810         // REVISIT: [Q] Is there a more efficient way of doing this?
811
// Perhaps if the scanner told us so we don't have to
812
// look at the characters again. -Ac
813
boolean allWhiteSpace = true;
814         for (int i=text.offset; i< text.offset+text.length; i++) {
815             if (!isSpace(text.ch[i])) {
816                 allWhiteSpace = false;
817                 break;
818             }
819         }
820         // call the ignoreableWhiteSpace callback
821
// never call ignorableWhitespace if we are in cdata section
822
if (fInElementContent && allWhiteSpace && !fInCDATASection) {
823             if (fDocumentHandler != null) {
824                 fDocumentHandler.ignorableWhitespace(text, augs);
825                 callNextCharacters = false;
826             }
827         }
828
829         // validate
830
if (fPerformValidation) {
831             if (fInElementContent) {
832                 if (fGrammarBucket.getStandalone() &&
833                     fDTDGrammar.getElementDeclIsExternal(fCurrentElementIndex)) {
834                     if (allWhiteSpace) {
835                         fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
836                                                     "MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE",
837                                                     null, XMLErrorReporter.SEVERITY_ERROR);
838                     }
839                 }
840                 if (!allWhiteSpace) {
841                     charDataInContent();
842                 }
843                 
844                 // For E15.2
845
if (augs != null && augs.getItem(Constants.CHAR_REF_PROBABLE_WS) == Boolean.TRUE) {
846                     fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
847                                                "MSG_CONTENT_INVALID_SPECIFIED",
848                                                new Object JavaDoc[]{ fCurrentElement.rawname,
849                                                    fDTDGrammar.getContentSpecAsString(fElementDepth),
850                                                    "character reference"},
851                                                XMLErrorReporter.SEVERITY_ERROR);
852                 }
853             }
854
855             if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
856                 charDataInContent();
857             }
858         }
859
860         // call handlers
861
if (callNextCharacters && fDocumentHandler != null) {
862             fDocumentHandler.characters(text, augs);
863         }
864
865     } // characters(XMLString)
866

867
868
869     /**
870      * Ignorable whitespace. For this method to be called, the document
871      * source must have some way of determining that the text containing
872      * only whitespace characters should be considered ignorable. For
873      * example, the validator can determine if a length of whitespace
874      * characters in the document are ignorable based on the element
875      * content model.
876      *
877      * @param text The ignorable whitespace.
878      * @param augs Additional information that may include infoset augmentations
879      *
880      * @throws XNIException Thrown by handler to signal an error.
881      */

882     public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
883
884         // call handlers
885
if (fDocumentHandler != null) {
886             fDocumentHandler.ignorableWhitespace(text, augs);
887         }
888
889     } // ignorableWhitespace(XMLString)
890

891     /**
892      * The end of an element.
893      *
894      * @param element The name of the element.
895      * @param augs Additional information that may include infoset augmentations
896      *
897      * @throws XNIException Thrown by handler to signal an error.
898      */

899     public void endElement(QName element, Augmentations augs) throws XNIException {
900
901         handleEndElement(element, augs, false);
902
903     } // endElement(QName)
904

905     /**
906      * The start of a CDATA section.
907      * @param augs Additional information that may include infoset augmentations
908      *
909      * @throws XNIException Thrown by handler to signal an error.
910      */

911     public void startCDATA(Augmentations augs) throws XNIException {
912
913         if (fPerformValidation && fInElementContent) {
914             charDataInContent();
915         }
916         fInCDATASection = true;
917         // call handlers
918
if (fDocumentHandler != null) {
919             fDocumentHandler.startCDATA(augs);
920         }
921
922     } // startCDATA()
923

924     /**
925      * The end of a CDATA section.
926      * @param augs Additional information that may include infoset augmentations
927      *
928      * @throws XNIException Thrown by handler to signal an error.
929      */

930     public void endCDATA(Augmentations augs) throws XNIException {
931
932         fInCDATASection = false;
933         // call handlers
934
if (fDocumentHandler != null) {
935             fDocumentHandler.endCDATA(augs);
936         }
937
938     } // endCDATA()
939

940     /**
941      * The end of the document.
942      * @param augs Additional information that may include infoset augmentations
943      *
944      * @throws XNIException Thrown by handler to signal an error.
945      */

946     public void endDocument(Augmentations augs) throws XNIException {
947
948         // call handlers
949
if (fDocumentHandler != null) {
950             fDocumentHandler.endDocument(augs);
951         }
952
953     } // endDocument()
954

955     /**
956      * A comment.
957      *
958      * @param text The text in the comment.
959      * @param augs Additional information that may include infoset augmentations
960      *
961      * @throws XNIException Thrown by application to signal an error.
962      */

963     public void comment(XMLString text, Augmentations augs) throws XNIException {
964         // fixes E15.1
965
if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
966             fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
967             if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
968                     fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
969                                                "MSG_CONTENT_INVALID_SPECIFIED",
970                                                new Object JavaDoc[]{ fCurrentElement.rawname,
971                                                              "EMPTY",
972                                                              "comment"},
973                                                XMLErrorReporter.SEVERITY_ERROR);
974             }
975         }
976         // call handlers
977
if (fDocumentHandler != null) {
978             fDocumentHandler.comment(text, augs);
979         }
980
981     } // comment(XMLString)
982

983
984     /**
985      * A processing instruction. Processing instructions consist of a
986      * target name and, optionally, text data. The data is only meaningful
987      * to the application.
988      * <p>
989      * Typically, a processing instruction's data will contain a series
990      * of pseudo-attributes. These pseudo-attributes follow the form of
991      * element attributes but are <strong>not</strong> parsed or presented
992      * to the application as anything other than text. The application is
993      * responsible for parsing the data.
994      *
995      * @param target The target.
996      * @param data The data or null if none specified.
997      * @param augs Additional information that may include infoset augmentations
998      *
999      * @throws XNIException Thrown by handler to signal an error.
1000     */

1001    public void processingInstruction(String JavaDoc target, XMLString data, Augmentations augs)
1002    throws XNIException {
1003
1004        // fixes E15.1
1005
if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
1006            fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
1007            if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
1008                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1009                                               "MSG_CONTENT_INVALID_SPECIFIED",
1010                                               new Object JavaDoc[]{ fCurrentElement.rawname,
1011                                                             "EMPTY",
1012                                                             "processing instruction"},
1013                                               XMLErrorReporter.SEVERITY_ERROR);
1014            }
1015        }
1016        // call handlers
1017
if (fDocumentHandler != null) {
1018            fDocumentHandler.processingInstruction(target, data, augs);
1019        }
1020    } // processingInstruction(String,XMLString)
1021

1022    /**
1023     * This method notifies the start of a general entity.
1024     * <p>
1025     * <strong>Note:</strong> This method is not called for entity references
1026     * appearing as part of attribute values.
1027     *
1028     * @param name The name of the general entity.
1029     * @param identifier The resource identifier.
1030     * @param encoding The auto-detected IANA encoding name of the entity
1031     * stream. This value will be null in those situations
1032     * where the entity encoding is not auto-detected (e.g.
1033     * internal entities or a document entity that is
1034     * parsed from a java.io.Reader).
1035     * @param augs Additional information that may include infoset augmentations
1036     *
1037     * @exception XNIException Thrown by handler to signal an error.
1038     */

1039    public void startGeneralEntity(String JavaDoc name,
1040                                   XMLResourceIdentifier identifier,
1041                                   String JavaDoc encoding,
1042                                   Augmentations augs) throws XNIException {
1043        if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
1044            fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
1045            // fixes E15.1
1046
if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
1047                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1048                                           "MSG_CONTENT_INVALID_SPECIFIED",
1049                                           new Object JavaDoc[]{ fCurrentElement.rawname,
1050                                                         "EMPTY", "ENTITY"},
1051                                           XMLErrorReporter.SEVERITY_ERROR);
1052            }
1053            if (fGrammarBucket.getStandalone()) {
1054                XMLDTDLoader.checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter);
1055            }
1056        }
1057        if (fDocumentHandler != null) {
1058            fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
1059        }
1060    }
1061
1062    /**
1063     * This method notifies the end of a general entity.
1064     * <p>
1065     * <strong>Note:</strong> This method is not called for entity references
1066     * appearing as part of attribute values.
1067     *
1068     * @param name The name of the entity.
1069     * @param augs Additional information that may include infoset augmentations
1070     *
1071     * @exception XNIException
1072     * Thrown by handler to signal an error.
1073     */

1074    public void endGeneralEntity(String JavaDoc name, Augmentations augs) throws XNIException {
1075        // call handlers
1076
if (fDocumentHandler != null) {
1077            fDocumentHandler.endGeneralEntity(name, augs);
1078        }
1079    } // endEntity(String)
1080

1081    /**
1082     * Notifies of the presence of a TextDecl line in an entity. If present,
1083     * this method will be called immediately following the startParameterEntity call.
1084     * <p>
1085     * <strong>Note:</strong> This method is only called for external
1086     * parameter entities referenced in the DTD.
1087     *
1088     * @param version The XML version, or null if not specified.
1089     * @param encoding The IANA encoding name of the entity.
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 textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs) throws XNIException {
1096
1097        // call handlers
1098
if (fDocumentHandler != null) {
1099            fDocumentHandler.textDecl(version, encoding, augs);
1100        }
1101    }
1102
1103
1104    public final boolean hasGrammar(){
1105        
1106        return (fDTDGrammar != null);
1107    }
1108    
1109    public final boolean validate(){
1110        // Do validation if all of the following are true:
1111
// 1. The JAXP Schema Language property is not XML Schema
1112
// REVISIT: since only DTD and Schema are supported at this time,
1113
// such checking is sufficient. but if more schema types
1114
// are introduced in the future, we'll need to change it
1115
// to something like
1116
// (fSchemaType == null || fSchemaType == NS_XML_DTD)
1117
// 2. One of the following is true (validation features)
1118
// 2.1 Dynamic validation is off, and validation is on
1119
// 2.2 Dynamic validation is on, and DOCTYPE was seen
1120
// 3 Xerces schema validation feature is off, or DOCTYPE was seen.
1121
return (fSchemaType != Constants.NS_XMLSCHEMA) &&
1122               (!fDynamicValidation && fValidation ||
1123                fDynamicValidation && fSeenDoctypeDecl) &&
1124               (fDTDValidation || fSeenDoctypeDecl);
1125    }
1126    
1127            //REVISIT:we can convert into functions.. adding default attribute values.. and one validating.
1128

1129    /** Add default attributes and validate. */
1130    protected void addDTDDefaultAttrsAndValidate(QName elementName, int elementIndex,
1131                                               XMLAttributes attributes)
1132    throws XNIException {
1133
1134        // is there anything to do?
1135
if (elementIndex == -1 || fDTDGrammar == null) {
1136            return;
1137        }
1138
1139        //
1140
// Check after all specified attrs are scanned
1141
// (1) report error for REQUIRED attrs that are missing (V_TAGc)
1142
// (2) add default attrs (FIXED and NOT_FIXED)
1143
//
1144
int attlistIndex = fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
1145
1146        while (attlistIndex != -1) {
1147
1148            fDTDGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);
1149
1150            if (DEBUG_ATTRIBUTES) {
1151                if (fTempAttDecl != null) {
1152                    XMLElementDecl elementDecl = new XMLElementDecl();
1153                    fDTDGrammar.getElementDecl(elementIndex, elementDecl);
1154                    System.out.println("element: "+(elementDecl.name.localpart));
1155                    System.out.println("attlistIndex " + attlistIndex + "\n"+
1156                                       "attName : '"+(fTempAttDecl.name.localpart) + "'\n"
1157                                       + "attType : "+fTempAttDecl.simpleType.type + "\n"
1158                                       + "attDefaultType : "+fTempAttDecl.simpleType.defaultType + "\n"
1159                                       + "attDefaultValue : '"+fTempAttDecl.simpleType.defaultValue + "'\n"
1160                                       + attributes.getLength() +"\n"
1161                                      );
1162                }
1163            }
1164            String JavaDoc attPrefix = fTempAttDecl.name.prefix;
1165            String JavaDoc attLocalpart = fTempAttDecl.name.localpart;
1166            String JavaDoc attRawName = fTempAttDecl.name.rawname;
1167            String JavaDoc attType = getAttributeTypeName(fTempAttDecl);
1168            int attDefaultType =fTempAttDecl.simpleType.defaultType;
1169            String JavaDoc attValue = null;
1170                            
1171            if (fTempAttDecl.simpleType.defaultValue != null) {
1172                attValue = fTempAttDecl.simpleType.defaultValue;
1173            }
1174            
1175            boolean specified = false;
1176            boolean required = attDefaultType == XMLSimpleType.DEFAULT_TYPE_REQUIRED;
1177            boolean cdata = attType == XMLSymbols.fCDATASymbol;
1178
1179            if (!cdata || required || attValue != null) {
1180                int attrCount = attributes.getLength();
1181                for (int i = 0; i < attrCount; i++) {
1182                    if (attributes.getQName(i) == attRawName) {
1183                        specified = true;
1184                        break;
1185                    }
1186                }
1187            }
1188
1189            if (!specified) {
1190                if (required) {
1191                    if (fPerformValidation) {
1192                        Object JavaDoc[] args = {elementName.localpart, attRawName};
1193                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1194                                                   "MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED", args,
1195                                                   XMLErrorReporter.SEVERITY_ERROR);
1196                    }
1197                }
1198                else if (attValue != null) {
1199                    if (fPerformValidation && fGrammarBucket.getStandalone()) {
1200                        if (fDTDGrammar.getAttributeDeclIsExternal(attlistIndex)) {
1201
1202                            Object JavaDoc[] args = { elementName.localpart, attRawName};
1203                            fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1204                                                       "MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED", args,
1205                                                       XMLErrorReporter.SEVERITY_ERROR);
1206                        }
1207                    }
1208
1209                    // add namespace information
1210
if (fNamespaces) {
1211                        int index = attRawName.indexOf(':');
1212                        if (index != -1) {
1213                            attPrefix = attRawName.substring(0, index);
1214                            attPrefix = fSymbolTable.addSymbol(attPrefix);
1215                            attLocalpart = attRawName.substring(index + 1);
1216                            attLocalpart = fSymbolTable.addSymbol(attLocalpart);
1217                        }
1218                    }
1219
1220                    // add attribute
1221
fTempQName.setValues(attPrefix, attLocalpart, attRawName, fTempAttDecl.name.uri);
1222                    int newAttr = attributes.addAttribute(fTempQName, attType, attValue);
1223                }
1224            }
1225            // get next att decl in the Grammar for this element
1226
attlistIndex = fDTDGrammar.getNextAttributeDeclIndex(attlistIndex);
1227        }
1228
1229        // now iterate through the expanded attributes for
1230
// 1. if every attribute seen is declared in the DTD
1231
// 2. check if the VC: default_fixed holds
1232
// 3. validate every attribute.
1233
int attrCount = attributes.getLength();
1234        for (int i = 0; i < attrCount; i++) {
1235            String JavaDoc attrRawName = attributes.getQName(i);
1236            boolean declared = false;
1237            if (fPerformValidation) {
1238                if (fGrammarBucket.getStandalone()) {
1239                    // check VC: Standalone Document Declaration, entities
1240
// references appear in the document.
1241
// REVISIT: this can be combined to a single check in
1242
// startEntity if we add one more argument in
1243
// startEnity, inAttrValue
1244
String JavaDoc nonNormalizedValue = attributes.getNonNormalizedValue(i);
1245                    if (nonNormalizedValue != null) {
1246                        String JavaDoc entityName = getExternalEntityRefInAttrValue(nonNormalizedValue);
1247                        if (entityName != null) {
1248                            fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1249                                                       "MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
1250                                                       new Object JavaDoc[]{entityName},
1251                                                       XMLErrorReporter.SEVERITY_ERROR);
1252                        }
1253                    }
1254                }
1255            }
1256            int attDefIndex = -1;
1257            int position =
1258            fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
1259            while (position != -1) {
1260                fDTDGrammar.getAttributeDecl(position, fTempAttDecl);
1261                if (fTempAttDecl.name.rawname == attrRawName) {
1262                    // found the match att decl,
1263
attDefIndex = position;
1264                    declared = true;
1265                    break;
1266                }
1267                position = fDTDGrammar.getNextAttributeDeclIndex(position);
1268            }
1269            if (!declared) {
1270                if (fPerformValidation) {
1271                    // REVISIT - cache the elem/attr tuple so that we only
1272
// give this error once for each unique occurrence
1273
Object JavaDoc[] args = { elementName.rawname, attrRawName};
1274
1275                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1276                                               "MSG_ATTRIBUTE_NOT_DECLARED",
1277                                               args,XMLErrorReporter.SEVERITY_ERROR);
1278                }
1279                continue;
1280            }
1281            // attribute is declared
1282

1283            // fTempAttDecl should have the right value set now, so
1284
// the following is not needed
1285
// fGrammar.getAttributeDecl(attDefIndex,fTempAttDecl);
1286

1287            String JavaDoc type = getAttributeTypeName(fTempAttDecl);
1288            attributes.setType(i, type);
1289            attributes.getAugmentations(i).putItem(Constants.ATTRIBUTE_DECLARED, Boolean.TRUE);
1290
1291            boolean changedByNormalization = false;
1292            String JavaDoc oldValue = attributes.getValue(i);
1293            String JavaDoc attrValue = oldValue;
1294            if (attributes.isSpecified(i) && type != XMLSymbols.fCDATASymbol) {
1295                changedByNormalization = normalizeAttrValue(attributes, i);
1296                attrValue = attributes.getValue(i);
1297                if (fPerformValidation && fGrammarBucket.getStandalone()
1298                    && changedByNormalization
1299                    && fDTDGrammar.getAttributeDeclIsExternal(position)
1300                   ) {
1301                    // check VC: Standalone Document Declaration
1302
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1303                                               "MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE",
1304                                               new Object JavaDoc[]{attrRawName, oldValue, attrValue},
1305                                               XMLErrorReporter.SEVERITY_ERROR);
1306                }
1307            }
1308            if (!fPerformValidation) {
1309                continue;
1310            }
1311            if (fTempAttDecl.simpleType.defaultType ==
1312                XMLSimpleType.DEFAULT_TYPE_FIXED) {
1313                String JavaDoc defaultValue = fTempAttDecl.simpleType.defaultValue;
1314
1315                if (!attrValue.equals(defaultValue)) {
1316                    Object JavaDoc[] args = {elementName.localpart,
1317                        attrRawName,
1318                        attrValue,
1319                        defaultValue};
1320                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1321                                               "MSG_FIXED_ATTVALUE_INVALID",
1322                                               args, XMLErrorReporter.SEVERITY_ERROR);
1323                }
1324            }
1325
1326            if (fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENTITY ||
1327                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENUMERATION ||
1328                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ID ||
1329                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_IDREF ||
1330                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NMTOKEN ||
1331                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NOTATION
1332               ) {
1333                validateDTDattribute(elementName, attrValue, fTempAttDecl);
1334            }
1335        } // for all attributes
1336

1337    } // addDTDDefaultAttrsAndValidate(int,XMLAttrList)
1338

1339    /** Checks entities in attribute values for standalone VC. */
1340    protected String JavaDoc getExternalEntityRefInAttrValue(String JavaDoc nonNormalizedValue) {
1341        int valLength = nonNormalizedValue.length();
1342        int ampIndex = nonNormalizedValue.indexOf('&');
1343        while (ampIndex != -1) {
1344            if (ampIndex + 1 < valLength &&
1345                nonNormalizedValue.charAt(ampIndex+1) != '#') {
1346                int semicolonIndex = nonNormalizedValue.indexOf(';', ampIndex+1);
1347                String JavaDoc entityName = nonNormalizedValue.substring(ampIndex+1, semicolonIndex);
1348                entityName = fSymbolTable.addSymbol(entityName);
1349                int entIndex = fDTDGrammar.getEntityDeclIndex(entityName);
1350                if (entIndex > -1) {
1351                    fDTDGrammar.getEntityDecl(entIndex, fEntityDecl);
1352                    if (fEntityDecl.inExternal ||
1353                        (entityName = getExternalEntityRefInAttrValue(fEntityDecl.value)) != null) {
1354                        return entityName;
1355                    }
1356                }
1357            }
1358            ampIndex = nonNormalizedValue.indexOf('&', ampIndex+1);
1359        }
1360        return null;
1361    } // isExternalEntityRefInAttrValue(String):String
1362

1363    /**
1364     * Validate attributes in DTD fashion.
1365     */

1366    protected void validateDTDattribute(QName element, String JavaDoc attValue,
1367                                      XMLAttributeDecl attributeDecl)
1368    throws XNIException {
1369
1370        switch (attributeDecl.simpleType.type) {
1371        case XMLSimpleType.TYPE_ENTITY: {
1372                // NOTE: Save this information because invalidStandaloneAttDef
1373
boolean isAlistAttribute = attributeDecl.simpleType.list;
1374
1375                try {
1376                    if (isAlistAttribute) {
1377                        fValENTITIES.validate(attValue, fValidationState);
1378                    }
1379                    else {
1380                        fValENTITY.validate(attValue, fValidationState);
1381                    }
1382                }
1383                catch (InvalidDatatypeValueException ex) {
1384                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1385                                               ex.getKey(),
1386                                               ex.getArgs(),
1387                                               XMLErrorReporter.SEVERITY_ERROR );
1388
1389                }
1390                break;
1391            }
1392
1393        case XMLSimpleType.TYPE_NOTATION:
1394        case XMLSimpleType.TYPE_ENUMERATION: {
1395                boolean found = false;
1396                String JavaDoc [] enumVals = attributeDecl.simpleType.enumeration;
1397                if (enumVals == null) {
1398                    found = false;
1399                }
1400                else
1401                    for (int i = 0; i < enumVals.length; i++) {
1402                        if (attValue == enumVals[i] || attValue.equals(enumVals[i])) {
1403                            found = true;
1404                            break;
1405                        }
1406                    }
1407
1408                if (!found) {
1409                    StringBuffer JavaDoc enumValueString = new StringBuffer JavaDoc();
1410                    if (enumVals != null)
1411                        for (int i = 0; i < enumVals.length; i++) {
1412                            enumValueString.append(enumVals[i]+" ");
1413                        }
1414                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1415                                               "MSG_ATTRIBUTE_VALUE_NOT_IN_LIST",
1416                                               new Object JavaDoc[]{attributeDecl.name.rawname, attValue, enumValueString},
1417                                               XMLErrorReporter.SEVERITY_ERROR);
1418                }
1419                break;
1420            }
1421
1422        case XMLSimpleType.TYPE_ID: {
1423                try {
1424                    fValID.validate(attValue, fValidationState);
1425                }
1426                catch (InvalidDatatypeValueException ex) {
1427                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1428                                               ex.getKey(),
1429                                               ex.getArgs(),
1430                                               XMLErrorReporter.SEVERITY_ERROR );
1431                }
1432                break;
1433            }
1434
1435        case XMLSimpleType.TYPE_IDREF: {
1436                boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
1437

1438                try {
1439                    if (isAlistAttribute) {
1440                        fValIDRefs.validate(attValue, fValidationState);
1441                    }
1442                    else {
1443                        fValIDRef.validate(attValue, fValidationState);
1444                    }
1445                }
1446                catch (InvalidDatatypeValueException ex) {
1447                    if (isAlistAttribute) {
1448                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1449                                                   "IDREFSInvalid",
1450                                                   new Object JavaDoc[]{attValue},
1451                                                   XMLErrorReporter.SEVERITY_ERROR );
1452                    }
1453                    else {
1454                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1455                                                   ex.getKey(),
1456                                                   ex.getArgs(),
1457                                                   XMLErrorReporter.SEVERITY_ERROR );
1458                    }
1459
1460                }
1461                break;
1462            }
1463
1464        case XMLSimpleType.TYPE_NMTOKEN: {
1465                boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
1466
//changes fTempAttDef
1467
try {
1468                    if (isAlistAttribute) {
1469                        fValNMTOKENS.validate(attValue, fValidationState);
1470                    }
1471                    else {
1472                        fValNMTOKEN.validate(attValue, fValidationState);
1473                    }
1474                }
1475                catch (InvalidDatatypeValueException ex) {
1476                    if (isAlistAttribute) {
1477                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1478                                                   "NMTOKENSInvalid",
1479                                                   new Object JavaDoc[] { attValue},
1480                                                   XMLErrorReporter.SEVERITY_ERROR);
1481                    }
1482                    else {
1483                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1484                                                   "NMTOKENInvalid",
1485                                                   new Object JavaDoc[] { attValue},
1486                                                   XMLErrorReporter.SEVERITY_ERROR);
1487                    }
1488                }
1489                break;
1490            }
1491
1492        } // switch
1493

1494    } // validateDTDattribute(QName,String,XMLAttributeDecl)
1495

1496
1497    /** Returns true if invalid standalone attribute definition. */
1498    protected boolean invalidStandaloneAttDef(QName element, QName attribute) {
1499        // REVISIT: This obviously needs to be fixed! -Ac
1500
boolean state = true;
1501        /*
1502       if (fStandaloneReader == -1) {
1503          return false;
1504       }
1505       // we are normalizing a default att value... this ok?
1506       if (element.rawname == -1) {
1507          return false;
1508       }
1509       return getAttDefIsExternal(element, attribute);
1510       */

1511        return state;
1512    }
1513
1514
1515    //
1516
// Private methods
1517
//
1518

1519
1520    /**
1521     * Normalize the attribute value of a non CDATA attributes collapsing
1522     * sequences of space characters (x20)
1523     *
1524     * @param attributes The list of attributes
1525     * @param index The index of the attribute to normalize
1526     */

1527    private boolean normalizeAttrValue(XMLAttributes attributes, int index) {
1528        // vars
1529
boolean leadingSpace = true;
1530        boolean spaceStart = false;
1531        boolean readingNonSpace = false;
1532        int count = 0;
1533        int eaten = 0;
1534        String JavaDoc attrValue = attributes.getValue(index);
1535        char[] attValue = new char[attrValue.length()];
1536
1537        fBuffer.setLength(0);
1538        attrValue.getChars(0, attrValue.length(), attValue, 0);
1539        for (int i = 0; i < attValue.length; i++) {
1540
1541            if (attValue[i] == ' ') {
1542
1543                // now the tricky part
1544
if (readingNonSpace) {
1545                    spaceStart = true;
1546                    readingNonSpace = false;
1547                }
1548
1549                if (spaceStart && !leadingSpace) {
1550                    spaceStart = false;
1551                    fBuffer.append(attValue[i]);
1552                    count++;
1553                }
1554                else {
1555                    if (leadingSpace || !spaceStart) {
1556                        eaten ++;
1557                        /*** BUG #3512 ***
1558                        int entityCount = attributes.getEntityCount(index);
1559                        for (int j = 0; j < entityCount; j++) {
1560                            int offset = attributes.getEntityOffset(index, j);
1561                            int length = attributes.getEntityLength(index, j);
1562                            if (offset <= i-eaten+1) {
1563                                if (offset+length >= i-eaten+1) {
1564                                    if (length > 0)
1565                                        length--;
1566                                }
1567                            }
1568                            else {
1569                                if (offset > 0)
1570                                    offset--;
1571                            }
1572                            attributes.setEntityOffset(index, j, offset);
1573                            attributes.setEntityLength(index, j, length);
1574                        }
1575                        /***/

1576                    }
1577                }
1578
1579            }
1580            else {
1581                readingNonSpace = true;
1582                spaceStart = false;
1583                leadingSpace = false;
1584                fBuffer.append(attValue[i]);
1585                count++;
1586            }
1587        }
1588
1589        // check if the last appended character is a space.
1590
if (count > 0 && fBuffer.charAt(count-1) == ' ') {
1591            fBuffer.setLength(count-1);
1592            /*** BUG #3512 ***
1593            int entityCount = attributes.getEntityCount(index);
1594            for (int j=0; j < entityCount; j++) {
1595                int offset = attributes.getEntityOffset(index, j);
1596                int length = attributes.getEntityLength(index, j);
1597                if (offset < count-1) {
1598                    if (offset+length == count) {
1599                        length--;
1600                    }
1601                }
1602                else {
1603                    offset--;
1604                }
1605                attributes.setEntityOffset(index, j, offset);
1606                attributes.setEntityLength(index, j, length);
1607            }
1608            /***/

1609        }
1610        String JavaDoc newValue = fBuffer.toString();
1611        attributes.setValue(index, newValue);
1612        return ! attrValue.equals(newValue);
1613    }
1614
1615    /** Root element specified. */
1616    private final void rootElementSpecified(QName rootElement) throws XNIException {
1617        if (fPerformValidation) {
1618            String JavaDoc root1 = fRootElement.rawname;
1619            String JavaDoc root2 = rootElement.rawname;
1620            if (root1 == null || !root1.equals(root2)) {
1621                fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
1622                                            "RootElementTypeMustMatchDoctypedecl",
1623                                            new Object JavaDoc[]{root1, root2},
1624                                            XMLErrorReporter.SEVERITY_ERROR);
1625            }
1626        }
1627    } // rootElementSpecified(QName)
1628

1629    /**
1630     * Check that the content of an element is valid.
1631     * <p>
1632     * This is the method of primary concern to the validator. This method is called
1633     * upon the scanner reaching the end tag of an element. At that time, the
1634     * element's children must be structurally validated, so it calls this method.
1635     * The index of the element being checked (in the decl pool), is provided as
1636     * well as an array of element name indexes of the children. The validator must
1637     * confirm that this element can have these children in this order.
1638     * <p>
1639     * This can also be called to do 'what if' testing of content models just to see
1640     * if they would be valid.
1641     * <p>
1642     * Note that the element index is an index into the element decl pool, whereas
1643     * the children indexes are name indexes, i.e. into the string pool.
1644     * <p>
1645     * A value of -1 in the children array indicates a PCDATA node. All other
1646     * indexes will be positive and represent child elements. The count can be
1647     * zero, since some elements have the EMPTY content model and that must be
1648     * confirmed.
1649     *
1650     * @param elementIndex The index within the <code>ElementDeclPool</code> of this
1651     * element.
1652     * @param childCount The number of entries in the <code>children</code> array.
1653     * @param children The children of this element.
1654     *
1655     * @return The value -1 if fully valid, else the 0 based index of the child
1656     * that first failed. If the value returned is equal to the number
1657     * of children, then additional content is required to reach a valid
1658     * ending state.
1659     *
1660     * @exception Exception Thrown on error.
1661     */

1662    private int checkContent(int elementIndex,
1663                             QName[] children,
1664                             int childOffset,
1665                             int childCount) throws XNIException {
1666
1667        fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
1668
1669        // Get the element name index from the element
1670
final String JavaDoc elementType = fCurrentElement.rawname;
1671
1672        // Get out the content spec for this element
1673
final int contentType = fCurrentContentSpecType;
1674
1675
1676        //
1677
// Deal with the possible types of content. We try to optimized here
1678
// by dealing specially with content models that don't require the
1679
// full DFA treatment.
1680
//
1681
if (contentType == XMLElementDecl.TYPE_EMPTY) {
1682            //
1683
// If the child count is greater than zero, then this is
1684
// an error right off the bat at index 0.
1685
//
1686
if (childCount != 0) {
1687                return 0;
1688            }
1689        }
1690        else if (contentType == XMLElementDecl.TYPE_ANY) {
1691            //
1692
// This one is open game so we don't pass any judgement on it
1693
// at all. Its assumed to fine since it can hold anything.
1694
//
1695
}
1696        else if (contentType == XMLElementDecl.TYPE_MIXED ||
1697                 contentType == XMLElementDecl.TYPE_CHILDREN) {
1698            // Get the content model for this element, faulting it in if needed
1699
ContentModelValidator cmElem = null;
1700            cmElem = fTempElementDecl.contentModelValidator;
1701            int result = cmElem.validate(children, childOffset, childCount);
1702            return result;
1703        }
1704        else if (contentType == -1) {
1705            //REVISIT
1706
/****
1707            reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
1708                                      XMLMessages.VC_ELEMENT_VALID,
1709                                      elementType);
1710            /****/

1711        }
1712        else if (contentType == XMLElementDecl.TYPE_SIMPLE) {
1713
1714            //REVISIT
1715
// this should never be reached in the case of DTD validation.
1716

1717        }
1718        else {
1719            //REVISIT
1720
/****
1721            fErrorReporter.reportError(fErrorReporter.getLocator(),
1722                                       ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
1723                                       ImplementationMessages.VAL_CST,
1724                                       0,
1725                                       null,
1726                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
1727            /****/

1728        }
1729
1730        // We succeeded
1731
return -1;
1732
1733    } // checkContent(int,int,QName[]):int
1734

1735    /** Returns the content spec type for an element index. */
1736    private int getContentSpecType(int elementIndex) {
1737
1738        int contentSpecType = -1;
1739        if (elementIndex > -1) {
1740            if (fDTDGrammar.getElementDecl(elementIndex,fTempElementDecl)) {
1741                contentSpecType = fTempElementDecl.type;
1742            }
1743        }
1744        return contentSpecType;
1745    }
1746
1747    /** Character data in content. */
1748    private void charDataInContent() {
1749
1750        if (DEBUG_ELEMENT_CHILDREN) {
1751            System.out.println("charDataInContent()");
1752        }
1753        if (fElementChildren.length <= fElementChildrenLength) {
1754            QName[] newarray = new QName[fElementChildren.length * 2];
1755            System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
1756            fElementChildren = newarray;
1757        }
1758        QName qname = fElementChildren[fElementChildrenLength];
1759        if (qname == null) {
1760            for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
1761                fElementChildren[i] = new QName();
1762            }
1763            qname = fElementChildren[fElementChildrenLength];
1764        }
1765        qname.clear();
1766        fElementChildrenLength++;
1767
1768    } // charDataInCount()
1769

1770    /** convert attribute type from ints to strings */
1771    private String JavaDoc getAttributeTypeName(XMLAttributeDecl attrDecl) {
1772
1773        switch (attrDecl.simpleType.type) {
1774        case XMLSimpleType.TYPE_ENTITY: {
1775                return attrDecl.simpleType.list ? XMLSymbols.fENTITIESSymbol : XMLSymbols.fENTITYSymbol;
1776            }
1777        case XMLSimpleType.TYPE_ENUMERATION: {
1778                StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1779                buffer.append('(');
1780                for (int i=0; i<attrDecl.simpleType.enumeration.length ; i++) {
1781                    if (i > 0) {
1782                        buffer.append("|");
1783                    }
1784                    buffer.append(attrDecl.simpleType.enumeration[i]);
1785                }
1786                buffer.append(')');
1787                return fSymbolTable.addSymbol(buffer.toString());
1788            }
1789        case XMLSimpleType.TYPE_ID: {
1790                return XMLSymbols.fIDSymbol;
1791            }
1792        case XMLSimpleType.TYPE_IDREF: {
1793                return attrDecl.simpleType.list ? XMLSymbols.fIDREFSSymbol : XMLSymbols.fIDREFSymbol;
1794            }
1795        case XMLSimpleType.TYPE_NMTOKEN: {
1796                return attrDecl.simpleType.list ? XMLSymbols.fNMTOKENSSymbol : XMLSymbols.fNMTOKENSymbol;
1797            }
1798        case XMLSimpleType.TYPE_NOTATION: {
1799                return XMLSymbols.fNOTATIONSymbol;
1800            }
1801        }
1802        return XMLSymbols.fCDATASymbol;
1803
1804    } // getAttributeTypeName(XMLAttributeDecl):String
1805

1806    /** initialization */
1807    protected void init() {
1808
1809        // datatype validators
1810
if (fValidation || fDynamicValidation) {
1811            try {
1812                //REVISIT: datatypeRegistry + initialization of datatype
1813
// why do we cast to ListDatatypeValidator?
1814
fValID = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDSymbol);
1815                fValIDRef = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSymbol);
1816                fValIDRefs = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSSymbol);
1817                fValENTITY = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITYSymbol);
1818                fValENTITIES = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITIESSymbol);
1819                fValNMTOKEN = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSymbol);
1820                fValNMTOKENS = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSSymbol);
1821                fValNOTATION = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNOTATIONSymbol);
1822
1823            }
1824            catch (Exception JavaDoc e) {
1825                // should never happen
1826
e.printStackTrace(System.err);
1827            }
1828
1829        }
1830
1831    } // init()
1832

1833    /** ensure element stack capacity */
1834    private void ensureStackCapacity ( int newElementDepth) {
1835        if (newElementDepth == fElementQNamePartsStack.length) {
1836            int[] newStack = new int[newElementDepth * 2];
1837
1838            QName[] newStackOfQueue = new QName[newElementDepth * 2];
1839            System.arraycopy(this.fElementQNamePartsStack, 0, newStackOfQueue, 0, newElementDepth );
1840            fElementQNamePartsStack = newStackOfQueue;
1841
1842            QName qname = fElementQNamePartsStack[newElementDepth];
1843            if (qname == null) {
1844                for (int i = newElementDepth; i < fElementQNamePartsStack.length; i++) {
1845                    fElementQNamePartsStack[i] = new QName();
1846                }
1847            }
1848
1849            newStack = new int[newElementDepth * 2];
1850            System.arraycopy(fElementIndexStack, 0, newStack, 0, newElementDepth);
1851            fElementIndexStack = newStack;
1852
1853            newStack = new int[newElementDepth * 2];
1854            System.arraycopy(fContentSpecTypeStack, 0, newStack, 0, newElementDepth);
1855            fContentSpecTypeStack = newStack;
1856
1857        }
1858    } // ensureStackCapacity
1859

1860    
1861    //
1862
// Protected methods
1863
//
1864

1865    /** Handle element
1866     * @return true if validator is removed from the pipeline
1867     */

1868    protected boolean handleStartElement(QName element, XMLAttributes attributes, Augmentations augs)
1869                        throws XNIException {
1870
1871
1872        // VC: Root Element Type
1873
// see if the root element's name matches the one in DoctypeDecl
1874
if (!fSeenRootElement) {
1875            // REVISIT: Here are current assumptions about validation features
1876
// given that XMLSchema validator is in the pipeline
1877
//
1878
// http://xml.org/sax/features/validation = true
1879
// http://apache.org/xml/features/validation/schema = true
1880
//
1881
// [1] XML instance document only has reference to a DTD
1882
// Outcome: report validation errors only against dtd.
1883
//
1884
// [2] XML instance document has only XML Schema grammars:
1885
// Outcome: report validation errors only against schemas (no errors produced from DTD validator)
1886
//
1887
// [3] XML instance document has DTD and XML schemas:
1888
// [a] if schema language is not set outcome - validation errors reported against both grammars: DTD and schemas.
1889
// [b] if schema language is set to XML Schema - do not report validation errors
1890
//
1891
// if dynamic validation is on
1892
// validate only against grammar we've found (depending on settings
1893
// for schema feature)
1894
//
1895
//
1896
fPerformValidation = validate();
1897            fSeenRootElement = true;
1898            fValidationManager.setEntityState(fDTDGrammar);
1899            fValidationManager.setGrammarFound(fSeenDoctypeDecl);
1900            rootElementSpecified(element);
1901        }
1902        if (fDTDGrammar == null) {
1903
1904            if (!fPerformValidation) {
1905                fCurrentElementIndex = -1;
1906                fCurrentContentSpecType = -1;
1907                fInElementContent = false;
1908            }
1909            if (fPerformValidation) {
1910                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1911                                           "MSG_GRAMMAR_NOT_FOUND",
1912                                           new Object JavaDoc[]{ element.rawname},
1913                                           XMLErrorReporter.SEVERITY_ERROR);
1914            }
1915            // modify pipeline
1916
if (fDocumentSource !=null ) {
1917                fDocumentSource.setDocumentHandler(fDocumentHandler);
1918                if (fDocumentHandler != null)
1919                    fDocumentHandler.setDocumentSource(fDocumentSource);
1920                return true;
1921            }
1922        }
1923        else {
1924            // resolve the element
1925
fCurrentElementIndex = fDTDGrammar.getElementDeclIndex(element);
1926            //changed here.. new function for getContentSpecType
1927
fCurrentContentSpecType = fDTDGrammar.getContentSpecType(fCurrentElementIndex);
1928            if (fCurrentContentSpecType == -1 && fPerformValidation) {
1929                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1930                                           "MSG_ELEMENT_NOT_DECLARED",
1931                                           new Object JavaDoc[]{ element.rawname},
1932                                           XMLErrorReporter.SEVERITY_ERROR);
1933            }
1934            
1935            // 0. insert default attributes
1936
// 1. normalize the attributes
1937
// 2. validate the attrivute list.
1938
// TO DO:
1939
//changed here.. also pass element name,
1940
addDTDDefaultAttrsAndValidate(element, fCurrentElementIndex, attributes);
1941        }
1942
1943        // set element content state
1944
fInElementContent = fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN;
1945
1946        // increment the element depth, add this element's
1947
// QName to its enclosing element 's children list
1948
fElementDepth++;
1949        if (fPerformValidation) {
1950            // push current length onto stack
1951
if (fElementChildrenOffsetStack.length <= fElementDepth) {
1952                int newarray[] = new int[fElementChildrenOffsetStack.length * 2];
1953                System.arraycopy(fElementChildrenOffsetStack, 0, newarray, 0, fElementChildrenOffsetStack.length);
1954                fElementChildrenOffsetStack = newarray;
1955            }
1956            fElementChildrenOffsetStack[fElementDepth] = fElementChildrenLength;
1957
1958            // add this element to children
1959
if (fElementChildren.length <= fElementChildrenLength) {
1960                QName[] newarray = new QName[fElementChildrenLength * 2];
1961                System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
1962                fElementChildren = newarray;
1963            }
1964            QName qname = fElementChildren[fElementChildrenLength];
1965            if (qname == null) {
1966                for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
1967                    fElementChildren[i] = new QName();
1968                }
1969                qname = fElementChildren[fElementChildrenLength];
1970            }
1971            qname.setValues(element);
1972            fElementChildrenLength++;
1973        }
1974
1975        // save current element information
1976
fCurrentElement.setValues(element);
1977        ensureStackCapacity(fElementDepth);
1978        fElementQNamePartsStack[fElementDepth].setValues(fCurrentElement);
1979        fElementIndexStack[fElementDepth] = fCurrentElementIndex;
1980        fContentSpecTypeStack[fElementDepth] = fCurrentContentSpecType;
1981        startNamespaceScope(element, attributes, augs);
1982        return false;
1983
1984    } // handleStartElement(QName,XMLAttributes)
1985

1986    protected void startNamespaceScope(QName element, XMLAttributes attributes, Augmentations augs){
1987    }
1988
1989    /** Handle end element. */
1990    protected void handleEndElement(QName element, Augmentations augs, boolean isEmpty)
1991    throws XNIException {
1992
1993        // decrease element depth
1994
fElementDepth--;
1995
1996        // validate
1997
if (fPerformValidation) {
1998            int elementIndex = fCurrentElementIndex;
1999            if (elementIndex != -1 && fCurrentContentSpecType != -1) {
2000                QName children[] = fElementChildren;
2001                int childrenOffset = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
2002                int childrenLength = fElementChildrenLength - childrenOffset;
2003                int result = checkContent(elementIndex,
2004                                          children, childrenOffset, childrenLength);
2005
2006                if (result != -1) {
2007                    fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
2008                    if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
2009                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
2010                                                   "MSG_CONTENT_INVALID",
2011                                                   new Object JavaDoc[]{ element.rawname, "EMPTY"},
2012                                                   XMLErrorReporter.SEVERITY_ERROR);
2013                    }
2014                    else {
2015                        String JavaDoc messageKey = result != childrenLength ?
2016                                            "MSG_CONTENT_INVALID" : "MSG_CONTENT_INCOMPLETE";
2017                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
2018                                                   messageKey,
2019                                                   new Object JavaDoc[]{ element.rawname,
2020                                                       fDTDGrammar.getContentSpecAsString(elementIndex)},
2021                                                   XMLErrorReporter.SEVERITY_ERROR);
2022                    }
2023                }
2024            }
2025            fElementChildrenLength = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
2026        }
2027        
2028        endNamespaceScope(fCurrentElement, augs, isEmpty);
2029        
2030        // now pop this element off the top of the element stack
2031
if (fElementDepth < -1) {
2032            throw new RuntimeException JavaDoc("FWK008 Element stack underflow");
2033        }
2034        if (fElementDepth < 0) {
2035            fCurrentElement.clear();
2036            fCurrentElementIndex = -1;
2037            fCurrentContentSpecType = -1;
2038            fInElementContent = false;
2039
2040            // TO DO : fix this
2041
//
2042
// Check after document is fully parsed
2043
// (1) check that there was an element with a matching id for every
2044
// IDREF and IDREFS attr (V_IDREF0)
2045
//
2046
if (fPerformValidation) {
2047                String JavaDoc value = fValidationState.checkIDRefID();
2048                if (value != null) {
2049                    fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
2050                                                "MSG_ELEMENT_WITH_ID_REQUIRED",
2051                                                new Object JavaDoc[]{value},
2052                                                XMLErrorReporter.SEVERITY_ERROR );
2053                }
2054            }
2055            return;
2056        }
2057
2058        // If Namespace enable then localName != rawName
2059
fCurrentElement.setValues(fElementQNamePartsStack[fElementDepth]);
2060
2061        fCurrentElementIndex = fElementIndexStack[fElementDepth];
2062        fCurrentContentSpecType = fContentSpecTypeStack[fElementDepth];
2063        fInElementContent = (fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN);
2064
2065    } // handleEndElement(QName,boolean)
2066

2067    protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty){
2068
2069        // call handlers
2070
if (fDocumentHandler != null && !isEmpty) {
2071            // NOTE: The binding of the element doesn't actually happen
2072
// yet because the namespace binder does that. However,
2073
// if it does it before this point, then the endPrefix-
2074
// Mapping calls get made too soon! As long as the
2075
// rawnames match, we know it'll have a good binding,
2076
// so we can just use the current element. -Ac
2077
fDocumentHandler.endElement(fCurrentElement, augs);
2078        }
2079    }
2080
2081    // returns whether a character is space according to the
2082
// version of XML this validator supports.
2083
protected boolean isSpace(int c) {
2084        return XMLChar.isSpace(c);
2085    } // isSpace(int): boolean
2086

2087    public boolean characterData(String JavaDoc data, Augmentations augs) {
2088        characters(new XMLString(data.toCharArray(), 0, data.length()), augs);
2089        return true;
2090    }
2091
2092} // class XMLDTDValidator
2093
Popular Tags