KickJava   Java API By Example, From Geeks To Geeks.

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


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

57
58 package com.sun.org.apache.xerces.internal.impl.dtd;
59
60 import com.sun.org.apache.xerces.internal.impl.Constants;
61 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
62 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
63 import com.sun.org.apache.xerces.internal.impl.dtd.models.ContentModelValidator;
64 import com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory;
65 import com.sun.org.apache.xerces.internal.impl.dv.DatatypeValidator;
66 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
67 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
68 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
69 import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
70 import com.sun.org.apache.xerces.internal.util.SymbolTable;
71 import com.sun.org.apache.xerces.internal.util.XMLChar;
72 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
73 import com.sun.org.apache.xerces.internal.xni.Augmentations;
74 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
75 import com.sun.org.apache.xerces.internal.xni.QName;
76 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
77 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
78 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
79 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
80 import com.sun.org.apache.xerces.internal.xni.XMLString;
81 import com.sun.org.apache.xerces.internal.xni.XNIException;
82 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
83 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
84 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
85 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
86 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
87 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
88 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentFilter;
89 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
90
91 /**
92  * The DTD validator. The validator implements a document
93  * filter: receiving document events from the scanner; validating
94  * the content and structure; augmenting the InfoSet, if applicable;
95  * and notifying the parser of the information resulting from the
96  * validation process.
97  * <p> Formerly, this component also handled DTD events and grammar construction.
98  * To facilitate the development of a meaningful DTD grammar caching/preparsing
99  * framework, this functionality has been moved into the XMLDTDLoader
100  * class. Therefore, this class no longer implements the DTDFilter
101  * or DTDContentModelFilter interfaces.
102  * <p>
103  * This component requires the following features and properties from the
104  * component manager that uses it:
105  * <ul>
106  * <li>http://xml.org/sax/features/namespaces</li>
107  * <li>http://xml.org/sax/features/validation</li>
108  * <li>http://apache.org/xml/features/validation/dynamic</li>
109  * <li>http://apache.org/xml/properties/internal/symbol-table</li>
110  * <li>http://apache.org/xml/properties/internal/error-reporter</li>
111  * <li>http://apache.org/xml/properties/internal/grammar-pool</li>
112  * <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
113  * </ul>
114  *
115  * @author Eric Ye, IBM
116  * @author Andy Clark, IBM
117  * @author Jeffrey Rodriguez IBM
118  * @author Neil Graham, IBM
119  *
120  * @version $Id: XMLDTDValidator.java,v 1.59 2004/04/25 05:05:49 mrglavas Exp $
121  */

122 public class XMLDTDValidator
123         implements XMLComponent, XMLDocumentFilter, XMLDTDValidatorFilter {
124
125     //
126
// Constants
127
//
128

129     /** Symbol: "&lt;&lt;datatypes>>". */
130
131     /** Top level scope (-1). */
132     private static final int TOP_LEVEL_SCOPE = -1;
133
134     // feature identifiers
135

136     /** Feature identifier: namespaces. */
137     protected static final String JavaDoc NAMESPACES =
138     Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
139
140     /** Feature identifier: validation. */
141     protected static final String JavaDoc VALIDATION =
142     Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
143
144     /** Feature identifier: dynamic validation. */
145     protected static final String JavaDoc DYNAMIC_VALIDATION =
146     Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
147
148     /** Feature identifier: warn on duplicate attdef */
149     protected static final String JavaDoc WARN_ON_DUPLICATE_ATTDEF =
150     Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
151     
152     protected static final String JavaDoc PARSER_SETTINGS =
153         Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
154
155
156
157     // property identifiers
158

159     /** Property identifier: symbol table. */
160     protected static final String JavaDoc SYMBOL_TABLE =
161         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
162
163     /** Property identifier: error reporter. */
164     protected static final String JavaDoc ERROR_REPORTER =
165         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
166
167     /** Property identifier: grammar pool. */
168     protected static final String JavaDoc GRAMMAR_POOL =
169         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
170
171     /** Property identifier: datatype validator factory. */
172     protected static final String JavaDoc DATATYPE_VALIDATOR_FACTORY =
173         Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
174
175     // property identifier: ValidationManager
176
protected static final String JavaDoc VALIDATION_MANAGER =
177         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
178
179     // recognized features and properties
180

181     /** Recognized features. */
182     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
183         NAMESPACES,
184         VALIDATION,
185         DYNAMIC_VALIDATION
186     };
187
188     /** Feature defaults. */
189     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = {
190         null,
191         null,
192         Boolean.FALSE,
193     };
194
195     /** Recognized properties. */
196     private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
197         SYMBOL_TABLE,
198         ERROR_REPORTER,
199         GRAMMAR_POOL,
200         DATATYPE_VALIDATOR_FACTORY,
201         VALIDATION_MANAGER
202     };
203
204     /** Property defaults. */
205     private static final Object JavaDoc[] PROPERTY_DEFAULTS = {
206         null,
207         null,
208         null,
209         null,
210         null,
211     };
212
213     // debugging
214

215     /** Compile to true to debug attributes. */
216     private static final boolean DEBUG_ATTRIBUTES = false;
217
218     /** Compile to true to debug element children. */
219     private static final boolean DEBUG_ELEMENT_CHILDREN = false;
220
221     //
222
// Data
223
//
224

225     // updated during reset
226
protected ValidationManager fValidationManager = null;
227     
228     // validation state
229
protected ValidationState fValidationState = new ValidationState();
230
231     // features
232

233     /** Namespaces. */
234     protected boolean fNamespaces;
235
236     /** Validation. */
237     protected boolean fValidation;
238
239     /** Validation against only DTD */
240     protected boolean fDTDValidation;
241
242     /**
243      * Dynamic validation. This state of this feature is only useful when
244      * the validation feature is set to <code>true</code>.
245      */

246     protected boolean fDynamicValidation;
247
248     /** warn on duplicate attribute definition, this feature works only when validation is true */
249     protected boolean fWarnDuplicateAttdef;
250         
251     // properties
252

253     /** Symbol table. */
254     protected SymbolTable fSymbolTable;
255
256     /** Error reporter. */
257     protected XMLErrorReporter fErrorReporter;
258
259     // the grammar pool
260
protected XMLGrammarPool fGrammarPool;
261
262     /** Grammar bucket. */
263     protected DTDGrammarBucket fGrammarBucket;
264
265     /* location of the document as passed in from startDocument call */
266     protected XMLLocator fDocLocation;
267
268     /** Namespace support. */
269     protected NamespaceContext fNamespaceContext = null;
270
271     /** Datatype validator factory. */
272     protected DTDDVFactory fDatatypeValidatorFactory;
273
274     // handlers
275

276     /** Document handler. */
277     protected XMLDocumentHandler fDocumentHandler;
278
279     protected XMLDocumentSource fDocumentSource;
280     // grammars
281

282     /** DTD Grammar. */
283     protected DTDGrammar fDTDGrammar;
284
285     // state
286

287     /** True if seen DOCTYPE declaration. */
288     protected boolean fSeenDoctypeDecl = false;
289
290     /** Perform validation. */
291     private boolean fPerformValidation;
292     
293     /** Schema type: None, DTD, Schema */
294     private String JavaDoc fSchemaType;
295
296     // information regarding the current element
297

298     /** Current element name. */
299     private final QName fCurrentElement = new QName();
300
301     /** Current element index. */
302     private int fCurrentElementIndex = -1;
303
304     /** Current content spec type. */
305     private int fCurrentContentSpecType = -1;
306
307     /** The root element name. */
308     private final QName fRootElement = new QName();
309
310     private boolean fInCDATASection = false;
311     // element stack
312

313     /** Element index stack. */
314     private int[] fElementIndexStack = new int[8];
315
316     /** Content spec type stack. */
317     private int[] fContentSpecTypeStack = new int[8];
318
319     /** Element name stack. */
320     private QName[] fElementQNamePartsStack = new QName[8];
321
322     // children list and offset stack
323

324     /**
325      * Element children. This data structure is a growing stack that
326      * holds the children of elements from the root to the current
327      * element depth. This structure never gets "deeper" than the
328      * deepest element. Space is re-used once each element is closed.
329      * <p>
330      * <strong>Note:</strong> This is much more efficient use of memory
331      * than creating new arrays for each element depth.
332      * <p>
333      * <strong>Note:</strong> The use of this data structure is for
334      * validation "on the way out". If the validation model changes to
335      * "on the way in", then this data structure is not needed.
336      */

337     private QName[] fElementChildren = new QName[32];
338
339     /** Element children count. */
340     private int fElementChildrenLength = 0;
341
342     /**
343      * Element children offset stack. This stack refers to offsets
344      * into the <code>fElementChildren</code> array.
345      * @see #fElementChildren
346      */

347     private int[] fElementChildrenOffsetStack = new int[32];
348
349     /** Element depth. */
350     private int fElementDepth = -1;
351
352     // validation states
353

354     /** True if seen the root element. */
355     private boolean fSeenRootElement = false;
356
357     /** True if inside of element content. */
358     private boolean fInElementContent = false;
359
360     // temporary variables
361

362     /** Temporary element declaration. */
363     private XMLElementDecl fTempElementDecl = new XMLElementDecl();
364
365     /** Temporary atribute declaration. */
366     private XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();
367
368     /** Temporary entity declaration. */
369     private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
370
371     /** Temporary qualified name. */
372     private QName fTempQName = new QName();
373
374     /** Temporary string buffers. */
375     private StringBuffer JavaDoc fBuffer = new StringBuffer JavaDoc();
376
377     // symbols: general
378

379     // attribute validators
380

381     /** Datatype validator: ID. */
382     protected DatatypeValidator fValID;
383
384     /** Datatype validator: IDREF. */
385     protected DatatypeValidator fValIDRef;
386
387     /** Datatype validator: IDREFS. */
388     protected DatatypeValidator fValIDRefs;
389
390     /** Datatype validator: ENTITY. */
391     protected DatatypeValidator fValENTITY;
392
393     /** Datatype validator: ENTITIES. */
394     protected DatatypeValidator fValENTITIES;
395
396     /** Datatype validator: NMTOKEN. */
397     protected DatatypeValidator fValNMTOKEN;
398
399     /** Datatype validator: NMTOKENS. */
400     protected DatatypeValidator fValNMTOKENS;
401
402     /** Datatype validator: NOTATION. */
403     protected DatatypeValidator fValNOTATION;
404
405     // to check for duplicate ID or ANNOTATION attribute declare in
406
// ATTLIST, and misc VCs
407

408     //
409
// Constructors
410
//
411

412     /** Default constructor. */
413     public XMLDTDValidator() {
414
415         // initialize data
416
for (int i = 0; i < fElementQNamePartsStack.length; i++) {
417             fElementQNamePartsStack[i] = new QName();
418         }
419         fGrammarBucket = new DTDGrammarBucket();
420
421     } // <init>()
422

423     DTDGrammarBucket getGrammarBucket() {
424         return fGrammarBucket;
425     } // getGrammarBucket(): DTDGrammarBucket
426

427     //
428
// XMLComponent methods
429
//
430

431     /*
432      * Resets the component. The component can query the component manager
433      * about any features and properties that affect the operation of the
434      * component.
435      *
436      * @param componentManager The component manager.
437      *
438      * @throws SAXException Thrown by component on finitialization error.
439      * For example, if a feature or property is
440      * required for the operation of the component, the
441      * component manager may throw a
442      * SAXNotRecognizedException or a
443      * SAXNotSupportedException.
444      */

445     public void reset(XMLComponentManager componentManager)
446     throws XMLConfigurationException {
447
448         // clear grammars
449
fDTDGrammar = null;
450         fSeenDoctypeDecl = false;
451         fInCDATASection = false;
452         // initialize state
453
fSeenRootElement = false;
454         fInElementContent = false;
455         fCurrentElementIndex = -1;
456         fCurrentContentSpecType = -1;
457
458         fRootElement.clear();
459
460         fValidationState.resetIDTables();
461         
462         fGrammarBucket.clear();
463         fElementDepth = -1;
464         fElementChildrenLength = 0;
465         
466         boolean parser_settings;
467         try {
468             parser_settings = componentManager.getFeature(PARSER_SETTINGS);
469         }
470         catch (XMLConfigurationException e){
471             parser_settings = true;
472         }
473         
474         if (!parser_settings){
475             // parser settings have not been changed
476
fValidationManager.addValidationState(fValidationState);
477             return;
478         }
479
480         // sax features
481
try {
482             fNamespaces = componentManager.getFeature(NAMESPACES);
483         }
484         catch (XMLConfigurationException e) {
485             fNamespaces = true;
486         }
487         try {
488             fValidation = componentManager.getFeature(VALIDATION);
489         }
490         catch (XMLConfigurationException e) {
491             fValidation = false;
492         }
493         try {
494             fDTDValidation = !(componentManager.getFeature(Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE));
495         }
496         catch (XMLConfigurationException e) {
497             // must be in a schema-less configuration!
498
fDTDValidation = true;
499         }
500
501         // Xerces features
502
try {
503             fDynamicValidation = componentManager.getFeature(DYNAMIC_VALIDATION);
504         }
505         catch (XMLConfigurationException e) {
506             fDynamicValidation = false;
507         }
508         
509         try {
510             fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF);
511         }
512         catch (XMLConfigurationException e) {
513             fWarnDuplicateAttdef = false;
514         }
515         
516         try {
517             fSchemaType = (String JavaDoc)componentManager.getProperty (Constants.JAXP_PROPERTY_PREFIX
518             + Constants.SCHEMA_LANGUAGE);
519         }
520         catch (XMLConfigurationException e){
521             fSchemaType = null;
522         }
523
524         fValidationManager= (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
525         fValidationManager.addValidationState(fValidationState);
526         fValidationState.setUsingNamespaces(fNamespaces);
527         
528         // get needed components
529
fErrorReporter = (XMLErrorReporter)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.ERROR_REPORTER_PROPERTY);
530         fSymbolTable = (SymbolTable)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.SYMBOL_TABLE_PROPERTY);
531         try {
532             fGrammarPool= (XMLGrammarPool)componentManager.getProperty(GRAMMAR_POOL);
533         } catch (XMLConfigurationException e) {
534             fGrammarPool = null;
535         }
536
537         fDatatypeValidatorFactory = (DTDDVFactory)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY);
538         init();
539
540     } // reset(XMLComponentManager)
541

542     /**
543      * Returns a list of feature identifiers that are recognized by
544      * this component. This method may return null if no features
545      * are recognized by this component.
546      */

547     public String JavaDoc[] getRecognizedFeatures() {
548         return (String JavaDoc[])(RECOGNIZED_FEATURES.clone());
549     } // getRecognizedFeatures():String[]
550

551     /**
552      * Sets the state of a feature. This method is called by the component
553      * manager any time after reset when a feature changes state.
554      * <p>
555      * <strong>Note:</strong> Components should silently ignore features
556      * that do not affect the operation of the component.
557      *
558      * @param featureId The feature identifier.
559      * @param state The state of the feature.
560      *
561      * @throws SAXNotRecognizedException The component should not throw
562      * this exception.
563      * @throws SAXNotSupportedException The component should not throw
564      * this exception.
565      */

566     public void setFeature(String JavaDoc featureId, boolean state)
567     throws XMLConfigurationException {
568     } // setFeature(String,boolean)
569

570     /**
571      * Returns a list of property identifiers that are recognized by
572      * this component. This method may return null if no properties
573      * are recognized by this component.
574      */

575     public String JavaDoc[] getRecognizedProperties() {
576         return (String JavaDoc[])(RECOGNIZED_PROPERTIES.clone());
577     } // getRecognizedProperties():String[]
578

579     /**
580      * Sets the value of a property. This method is called by the component
581      * manager any time after reset when a property changes value.
582      * <p>
583      * <strong>Note:</strong> Components should silently ignore properties
584      * that do not affect the operation of the component.
585      *
586      * @param propertyId The property identifier.
587      * @param value The value of the property.
588      *
589      * @throws SAXNotRecognizedException The component should not throw
590      * this exception.
591      * @throws SAXNotSupportedException The component should not throw
592      * this exception.
593      */

594     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
595     throws XMLConfigurationException {
596     } // setProperty(String,Object)
597

598     /**
599      * Returns the default state for a feature, or null if this
600      * component does not want to report a default value for this
601      * feature.
602      *
603      * @param featureId The feature identifier.
604      *
605      * @since Xerces 2.2.0
606      */

607     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
608         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
609             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
610                 return FEATURE_DEFAULTS[i];
611             }
612         }
613         return null;
614     } // getFeatureDefault(String):Boolean
615

616     /**
617      * Returns the default state for a property, or null if this
618      * component does not want to report a default value for this
619      * property.
620      *
621      * @param propertyId The property identifier.
622      *
623      * @since Xerces 2.2.0
624      */

625     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
626         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
627             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
628                 return PROPERTY_DEFAULTS[i];
629             }
630         }
631         return null;
632     } // getPropertyDefault(String):Object
633

634     //
635
// XMLDocumentSource methods
636
//
637

638     /** Sets the document handler to receive information about the document. */
639     public void setDocumentHandler(XMLDocumentHandler documentHandler) {
640         fDocumentHandler = documentHandler;
641     } // setDocumentHandler(XMLDocumentHandler)
642

643     /** Returns the document handler */
644     public XMLDocumentHandler getDocumentHandler() {
645         return fDocumentHandler;
646     } // getDocumentHandler(): XMLDocumentHandler
647

648
649     //
650
// XMLDocumentHandler methods
651
//
652

653     /** Sets the document source */
654     public void setDocumentSource(XMLDocumentSource source){
655         fDocumentSource = source;
656     } // setDocumentSource
657

658     /** Returns the document source */
659     public XMLDocumentSource getDocumentSource (){
660         return fDocumentSource;
661     } // getDocumentSource
662

663     /**
664      * The start of the document.
665      *
666      * @param locator The system identifier of the entity if the entity
667      * is external, null otherwise.
668      * @param encoding The auto-detected IANA encoding name of the entity
669      * stream. This value will be null in those situations
670      * where the entity encoding is not auto-detected (e.g.
671      * internal entities or a document entity that is
672      * parsed from a java.io.Reader).
673      * @param namespaceContext
674      * The namespace context in effect at the
675      * start of this document.
676      * This object represents the current context.
677      * Implementors of this class are responsible
678      * for copying the namespace bindings from the
679      * the current context (and its parent contexts)
680      * if that information is important.
681      * @param augs Additional information that may include infoset augmentations
682      *
683      * @throws XNIException Thrown by handler to signal an error.
684      */

685     public void startDocument(XMLLocator locator, String JavaDoc encoding,
686                               NamespaceContext namespaceContext, Augmentations augs)
687     throws XNIException {
688
689         // call handlers
690
// get initial grammars
691
if(fGrammarPool != null) {
692             Grammar [] grammars = fGrammarPool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_DTD);
693             for(int i = 0; i<grammars.length; i++) {
694                 fGrammarBucket.putGrammar((DTDGrammar)grammars[i]);
695             }
696         }
697         fDocLocation = locator;
698         fNamespaceContext = namespaceContext;
699    
700         if (fDocumentHandler != null) {
701             fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
702         }
703
704     } // startDocument(XMLLocator,String)
705

706     /**
707      * Notifies of the presence of an XMLDecl line in the document. If
708      * present, this method will be called immediately following the
709      * startDocument call.
710      *
711      * @param version The XML version.
712      * @param encoding The IANA encoding name of the document, or null if
713      * not specified.
714      * @param standalone The standalone value, or null if not specified.
715      * @param augs Additional information that may include infoset augmentations
716      *
717      * @throws XNIException Thrown by handler to signal an error.
718      */

719     public void xmlDecl(String JavaDoc version, String JavaDoc encoding, String JavaDoc standalone, Augmentations augs)
720     throws XNIException {
721
722         // save standalone state
723
fGrammarBucket.setStandalone(standalone != null && standalone.equals("yes"));
724
725         // call handlers
726
if (fDocumentHandler != null) {
727             fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
728         }
729
730     } // xmlDecl(String,String,String)
731

732     /**
733      * Notifies of the presence of the DOCTYPE line in the document.
734      *
735      * @param rootElement The name of the root element.
736      * @param publicId The public identifier if an external DTD or null
737      * if the external DTD is specified using SYSTEM.
738      * @param systemId The system identifier if an external DTD, null
739      * otherwise.
740      * @param augs Additional information that may include infoset augmentations
741      *
742      * @throws XNIException Thrown by handler to signal an error.
743      */

744     public void doctypeDecl(String JavaDoc rootElement, String JavaDoc publicId, String JavaDoc systemId,
745                             Augmentations augs)
746     throws XNIException {
747
748         // save root element state
749
fSeenDoctypeDecl = true;
750         fRootElement.setValues(null, rootElement, rootElement, null);
751         // find or create grammar:
752
String JavaDoc eid = null;
753         try {
754             eid = XMLEntityManager.expandSystemId(systemId, fDocLocation.getExpandedSystemId(), false);
755         } catch (java.io.IOException JavaDoc e) {
756         }
757         XMLDTDDescription grammarDesc = new XMLDTDDescription(publicId, systemId, fDocLocation.getExpandedSystemId(), eid, rootElement);
758         fDTDGrammar = fGrammarBucket.getGrammar(grammarDesc);
759         if(fDTDGrammar == null) {
760             // give grammar pool a chance...
761
if(fGrammarPool != null) {
762                 fDTDGrammar = (DTDGrammar)fGrammarPool.retrieveGrammar(grammarDesc);
763             }
764         }
765         if(fDTDGrammar == null) {
766             // we'll have to create it...
767
fDTDGrammar = new DTDGrammar(fSymbolTable, grammarDesc);
768         } else {
769             // we've found a cached one;so let's make sure not to read
770
// any external subset!
771
fValidationManager.setCachedDTD(true);
772         }
773         fGrammarBucket.setActiveGrammar(fDTDGrammar);
774
775         // call handlers
776
if (fDocumentHandler != null) {
777             fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
778         }
779
780     } // doctypeDecl(String,String,String, Augmentations)
781

782
783     /**
784      * The start of an element.
785      *
786      * @param element The name of the element.
787      * @param attributes The element attributes.
788      * @param augs Additional information that may include infoset augmentations
789      *
790      * @throws XNIException Thrown by handler to signal an error.
791      */

792     public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
793     throws XNIException {
794
795         handleStartElement(element, attributes, augs);
796         // call handlers
797
if (fDocumentHandler != null) {
798             fDocumentHandler.startElement(element, attributes, augs);
799
800         }
801
802     } // startElement(QName,XMLAttributes)
803

804     /**
805      * An empty element.
806      *
807      * @param element The name of the element.
808      * @param attributes The element attributes.
809      * @param augs Additional information that may include infoset augmentations
810      *
811      * @throws XNIException Thrown by handler to signal an error.
812      */

813     public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
814     throws XNIException {
815
816         boolean removed = handleStartElement(element, attributes, augs);
817
818         if (fDocumentHandler !=null) {
819             fDocumentHandler.emptyElement(element, attributes, augs);
820         }
821         if (!removed) {
822             handleEndElement(element, augs, true);
823         }
824         
825
826     } // emptyElement(QName,XMLAttributes)
827

828     /**
829      * Character content.
830      *
831      * @param text The content.
832      *
833      * @param augs Additional information that may include infoset augmentations
834      *
835      * @throws XNIException Thrown by handler to signal an error.
836      */

837     public void characters(XMLString text, Augmentations augs) throws XNIException {
838
839         boolean callNextCharacters = true;
840
841         // REVISIT: [Q] Is there a more efficient way of doing this?
842
// Perhaps if the scanner told us so we don't have to
843
// look at the characters again. -Ac
844
boolean allWhiteSpace = true;
845         for (int i=text.offset; i< text.offset+text.length; i++) {
846             if (!isSpace(text.ch[i])) {
847                 allWhiteSpace = false;
848                 break;
849             }
850         }
851         // call the ignoreableWhiteSpace callback
852
// never call ignorableWhitespace if we are in cdata section
853
if (fInElementContent && allWhiteSpace && !fInCDATASection) {
854             if (fDocumentHandler != null) {
855                 fDocumentHandler.ignorableWhitespace(text, augs);
856                 callNextCharacters = false;
857             }
858         }
859
860         // validate
861
if (fPerformValidation) {
862             if (fInElementContent) {
863                 if (fGrammarBucket.getStandalone() &&
864                     fDTDGrammar.getElementDeclIsExternal(fCurrentElementIndex)) {
865                     if (allWhiteSpace) {
866                         fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
867                                                     "MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE",
868                                                     null, XMLErrorReporter.SEVERITY_ERROR);
869                     }
870                 }
871                 if (!allWhiteSpace) {
872                     charDataInContent();
873                 }
874                 
875                 // For E15.2
876
if (augs != null && augs.getItem(Constants.CHAR_REF_PROBABLE_WS) == Boolean.TRUE) {
877                     fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
878                                                "MSG_CONTENT_INVALID_SPECIFIED",
879                                                new Object JavaDoc[]{ fCurrentElement.rawname,
880                                                    fDTDGrammar.getContentSpecAsString(fElementDepth),
881                                                    "character reference"},
882                                                XMLErrorReporter.SEVERITY_ERROR);
883                 }
884             }
885
886             if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
887                 charDataInContent();
888             }
889         }
890
891         // call handlers
892
if (callNextCharacters && fDocumentHandler != null) {
893             fDocumentHandler.characters(text, augs);
894         }
895
896     } // characters(XMLString)
897

898
899
900     /**
901      * Ignorable whitespace. For this method to be called, the document
902      * source must have some way of determining that the text containing
903      * only whitespace characters should be considered ignorable. For
904      * example, the validator can determine if a length of whitespace
905      * characters in the document are ignorable based on the element
906      * content model.
907      *
908      * @param text The ignorable whitespace.
909      * @param augs Additional information that may include infoset augmentations
910      *
911      * @throws XNIException Thrown by handler to signal an error.
912      */

913     public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
914
915         // call handlers
916
if (fDocumentHandler != null) {
917             fDocumentHandler.ignorableWhitespace(text, augs);
918         }
919
920     } // ignorableWhitespace(XMLString)
921

922     /**
923      * The end of an element.
924      *
925      * @param element The name of the element.
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 endElement(QName element, Augmentations augs) throws XNIException {
931
932         handleEndElement(element, augs, false);
933
934     } // endElement(QName)
935

936     /**
937      * The start of a CDATA section.
938      * @param augs Additional information that may include infoset augmentations
939      *
940      * @throws XNIException Thrown by handler to signal an error.
941      */

942     public void startCDATA(Augmentations augs) throws XNIException {
943
944         if (fPerformValidation && fInElementContent) {
945             charDataInContent();
946         }
947         fInCDATASection = true;
948         // call handlers
949
if (fDocumentHandler != null) {
950             fDocumentHandler.startCDATA(augs);
951         }
952
953     } // startCDATA()
954

955     /**
956      * The end of a CDATA section.
957      * @param augs Additional information that may include infoset augmentations
958      *
959      * @throws XNIException Thrown by handler to signal an error.
960      */

961     public void endCDATA(Augmentations augs) throws XNIException {
962
963         fInCDATASection = false;
964         // call handlers
965
if (fDocumentHandler != null) {
966             fDocumentHandler.endCDATA(augs);
967         }
968
969     } // endCDATA()
970

971     /**
972      * The end of the document.
973      * @param augs Additional information that may include infoset augmentations
974      *
975      * @throws XNIException Thrown by handler to signal an error.
976      */

977     public void endDocument(Augmentations augs) throws XNIException {
978
979         // call handlers
980
if (fDocumentHandler != null) {
981             fDocumentHandler.endDocument(augs);
982         }
983
984     } // endDocument()
985

986     /**
987      * A comment.
988      *
989      * @param text The text in the comment.
990      * @param augs Additional information that may include infoset augmentations
991      *
992      * @throws XNIException Thrown by application to signal an error.
993      */

994     public void comment(XMLString text, Augmentations augs) throws XNIException {
995         // fixes E15.1
996
if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
997             fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
998             if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
999                     fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1000                                               "MSG_CONTENT_INVALID_SPECIFIED",
1001                                               new Object JavaDoc[]{ fCurrentElement.rawname,
1002                                                             "EMPTY",
1003                                                             "comment"},
1004                                               XMLErrorReporter.SEVERITY_ERROR);
1005            }
1006        }
1007        // call handlers
1008
if (fDocumentHandler != null) {
1009            fDocumentHandler.comment(text, augs);
1010        }
1011
1012    } // comment(XMLString)
1013

1014
1015    /**
1016     * A processing instruction. Processing instructions consist of a
1017     * target name and, optionally, text data. The data is only meaningful
1018     * to the application.
1019     * <p>
1020     * Typically, a processing instruction's data will contain a series
1021     * of pseudo-attributes. These pseudo-attributes follow the form of
1022     * element attributes but are <strong>not</strong> parsed or presented
1023     * to the application as anything other than text. The application is
1024     * responsible for parsing the data.
1025     *
1026     * @param target The target.
1027     * @param data The data or null if none specified.
1028     * @param augs Additional information that may include infoset augmentations
1029     *
1030     * @throws XNIException Thrown by handler to signal an error.
1031     */

1032    public void processingInstruction(String JavaDoc target, XMLString data, Augmentations augs)
1033    throws XNIException {
1034
1035        // fixes E15.1
1036
if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
1037            fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
1038            if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
1039                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1040                                               "MSG_CONTENT_INVALID_SPECIFIED",
1041                                               new Object JavaDoc[]{ fCurrentElement.rawname,
1042                                                             "EMPTY",
1043                                                             "processing instruction"},
1044                                               XMLErrorReporter.SEVERITY_ERROR);
1045            }
1046        }
1047        // call handlers
1048
if (fDocumentHandler != null) {
1049            fDocumentHandler.processingInstruction(target, data, augs);
1050        }
1051    } // processingInstruction(String,XMLString)
1052

1053    /**
1054     * This method notifies the start of a general entity.
1055     * <p>
1056     * <strong>Note:</strong> This method is not called for entity references
1057     * appearing as part of attribute values.
1058     *
1059     * @param name The name of the general entity.
1060     * @param identifier The resource identifier.
1061     * @param encoding The auto-detected IANA encoding name of the entity
1062     * stream. This value will be null in those situations
1063     * where the entity encoding is not auto-detected (e.g.
1064     * internal entities or a document entity that is
1065     * parsed from a java.io.Reader).
1066     * @param augs Additional information that may include infoset augmentations
1067     *
1068     * @exception XNIException Thrown by handler to signal an error.
1069     */

1070    public void startGeneralEntity(String JavaDoc name,
1071                                   XMLResourceIdentifier identifier,
1072                                   String JavaDoc encoding,
1073                                   Augmentations augs) throws XNIException {
1074        if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
1075            fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
1076            // fixes E15.1
1077
if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
1078                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1079                                           "MSG_CONTENT_INVALID_SPECIFIED",
1080                                           new Object JavaDoc[]{ fCurrentElement.rawname,
1081                                                         "EMPTY", "ENTITY"},
1082                                           XMLErrorReporter.SEVERITY_ERROR);
1083            }
1084            if (fGrammarBucket.getStandalone()) {
1085                XMLDTDLoader.checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter);
1086            }
1087        }
1088        if (fDocumentHandler != null) {
1089            fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
1090        }
1091    }
1092
1093    /**
1094     * This method notifies the end of a general entity.
1095     * <p>
1096     * <strong>Note:</strong> This method is not called for entity references
1097     * appearing as part of attribute values.
1098     *
1099     * @param name The name of the entity.
1100     * @param augs Additional information that may include infoset augmentations
1101     *
1102     * @exception XNIException
1103     * Thrown by handler to signal an error.
1104     */

1105    public void endGeneralEntity(String JavaDoc name, Augmentations augs) throws XNIException {
1106        // call handlers
1107
if (fDocumentHandler != null) {
1108            fDocumentHandler.endGeneralEntity(name, augs);
1109        }
1110    } // endEntity(String)
1111

1112    /**
1113     * Notifies of the presence of a TextDecl line in an entity. If present,
1114     * this method will be called immediately following the startParameterEntity call.
1115     * <p>
1116     * <strong>Note:</strong> This method is only called for external
1117     * parameter entities referenced in the DTD.
1118     *
1119     * @param version The XML version, or null if not specified.
1120     * @param encoding The IANA encoding name of the entity.
1121     * @param augs Additional information that may include infoset
1122     * augmentations.
1123     *
1124     * @throws XNIException Thrown by handler to signal an error.
1125     */

1126    public void textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs) throws XNIException {
1127
1128        // call handlers
1129
if (fDocumentHandler != null) {
1130            fDocumentHandler.textDecl(version, encoding, augs);
1131        }
1132    }
1133
1134
1135    public final boolean hasGrammar(){
1136        
1137        return (fDTDGrammar != null);
1138    }
1139    
1140    public final boolean validate(){
1141        // Do validation if all of the following are true:
1142
// 1. The JAXP Schema Language property is not XML Schema
1143
// REVISIT: since only DTD and Schema are supported at this time,
1144
// such checking is sufficient. but if more schema types
1145
// are introduced in the future, we'll need to change it
1146
// to something like
1147
// (fSchemaType == null || fSchemaType == NS_XML_DTD)
1148
// 2. One of the following is true (validation features)
1149
// 2.1 Dynamic validation is off, and validation is on
1150
// 2.2 Dynamic validation is on, and DOCTYPE was seen
1151
// 3 Xerces schema validation feature is off, or DOCTYPE was seen.
1152
return (fSchemaType != Constants.NS_XMLSCHEMA) &&
1153               (!fDynamicValidation && fValidation ||
1154                fDynamicValidation && fSeenDoctypeDecl) &&
1155               (fDTDValidation || fSeenDoctypeDecl);
1156    }
1157    
1158            //REVISIT:we can convert into functions.. adding default attribute values.. and one validating.
1159

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

1314            // fTempAttDecl should have the right value set now, so
1315
// the following is not needed
1316
// fGrammar.getAttributeDecl(attDefIndex,fTempAttDecl);
1317

1318            String JavaDoc type = getAttributeTypeName(fTempAttDecl);
1319            attributes.setType(i, type);
1320            attributes.getAugmentations(i).putItem(Constants.ATTRIBUTE_DECLARED, Boolean.TRUE);
1321
1322            boolean changedByNormalization = false;
1323            String JavaDoc oldValue = attributes.getValue(i);
1324            String JavaDoc attrValue = oldValue;
1325            if (attributes.isSpecified(i) && type != XMLSymbols.fCDATASymbol) {
1326                changedByNormalization = normalizeAttrValue(attributes, i);
1327                attrValue = attributes.getValue(i);
1328                if (fPerformValidation && fGrammarBucket.getStandalone()
1329                    && changedByNormalization
1330                    && fDTDGrammar.getAttributeDeclIsExternal(position)
1331                   ) {
1332                    // check VC: Standalone Document Declaration
1333
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1334                                               "MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE",
1335                                               new Object JavaDoc[]{attrRawName, oldValue, attrValue},
1336                                               XMLErrorReporter.SEVERITY_ERROR);
1337                }
1338            }
1339            if (!fPerformValidation) {
1340                continue;
1341            }
1342            if (fTempAttDecl.simpleType.defaultType ==
1343                XMLSimpleType.DEFAULT_TYPE_FIXED) {
1344                String JavaDoc defaultValue = fTempAttDecl.simpleType.defaultValue;
1345
1346                if (!attrValue.equals(defaultValue)) {
1347                    Object JavaDoc[] args = {elementName.localpart,
1348                        attrRawName,
1349                        attrValue,
1350                        defaultValue};
1351                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1352                                               "MSG_FIXED_ATTVALUE_INVALID",
1353                                               args, XMLErrorReporter.SEVERITY_ERROR);
1354                }
1355            }
1356
1357            if (fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENTITY ||
1358                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENUMERATION ||
1359                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ID ||
1360                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_IDREF ||
1361                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NMTOKEN ||
1362                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NOTATION
1363               ) {
1364                validateDTDattribute(elementName, attrValue, fTempAttDecl);
1365            }
1366        } // for all attributes
1367

1368    } // addDTDDefaultAttrsAndValidate(int,XMLAttrList)
1369

1370    /** Checks entities in attribute values for standalone VC. */
1371    protected String JavaDoc getExternalEntityRefInAttrValue(String JavaDoc nonNormalizedValue) {
1372        int valLength = nonNormalizedValue.length();
1373        int ampIndex = nonNormalizedValue.indexOf('&');
1374        while (ampIndex != -1) {
1375            if (ampIndex + 1 < valLength &&
1376                nonNormalizedValue.charAt(ampIndex+1) != '#') {
1377                int semicolonIndex = nonNormalizedValue.indexOf(';', ampIndex+1);
1378                String JavaDoc entityName = nonNormalizedValue.substring(ampIndex+1, semicolonIndex);
1379                entityName = fSymbolTable.addSymbol(entityName);
1380                int entIndex = fDTDGrammar.getEntityDeclIndex(entityName);
1381                if (entIndex > -1) {
1382                    fDTDGrammar.getEntityDecl(entIndex, fEntityDecl);
1383                    if (fEntityDecl.inExternal ||
1384                        (entityName = getExternalEntityRefInAttrValue(fEntityDecl.value)) != null) {
1385                        return entityName;
1386                    }
1387                }
1388            }
1389            ampIndex = nonNormalizedValue.indexOf('&', ampIndex+1);
1390        }
1391        return null;
1392    } // isExternalEntityRefInAttrValue(String):String
1393

1394    /**
1395     * Validate attributes in DTD fashion.
1396     */

1397    protected void validateDTDattribute(QName element, String JavaDoc attValue,
1398                                      XMLAttributeDecl attributeDecl)
1399    throws XNIException {
1400
1401        switch (attributeDecl.simpleType.type) {
1402        case XMLSimpleType.TYPE_ENTITY: {
1403                // NOTE: Save this information because invalidStandaloneAttDef
1404
boolean isAlistAttribute = attributeDecl.simpleType.list;
1405
1406                try {
1407                    if (isAlistAttribute) {
1408                        fValENTITIES.validate(attValue, fValidationState);
1409                    }
1410                    else {
1411                        fValENTITY.validate(attValue, fValidationState);
1412                    }
1413                }
1414                catch (InvalidDatatypeValueException ex) {
1415                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1416                                               ex.getKey(),
1417                                               ex.getArgs(),
1418                                               XMLErrorReporter.SEVERITY_ERROR );
1419
1420                }
1421                break;
1422            }
1423
1424        case XMLSimpleType.TYPE_NOTATION:
1425        case XMLSimpleType.TYPE_ENUMERATION: {
1426                boolean found = false;
1427                String JavaDoc [] enumVals = attributeDecl.simpleType.enumeration;
1428                if (enumVals == null) {
1429                    found = false;
1430                }
1431                else
1432                    for (int i = 0; i < enumVals.length; i++) {
1433                        if (attValue == enumVals[i] || attValue.equals(enumVals[i])) {
1434                            found = true;
1435                            break;
1436                        }
1437                    }
1438
1439                if (!found) {
1440                    StringBuffer JavaDoc enumValueString = new StringBuffer JavaDoc();
1441                    if (enumVals != null)
1442                        for (int i = 0; i < enumVals.length; i++) {
1443                            enumValueString.append(enumVals[i]+" ");
1444                        }
1445                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1446                                               "MSG_ATTRIBUTE_VALUE_NOT_IN_LIST",
1447                                               new Object JavaDoc[]{attributeDecl.name.rawname, attValue, enumValueString},
1448                                               XMLErrorReporter.SEVERITY_ERROR);
1449                }
1450                break;
1451            }
1452
1453        case XMLSimpleType.TYPE_ID: {
1454                try {
1455                    fValID.validate(attValue, fValidationState);
1456                }
1457                catch (InvalidDatatypeValueException ex) {
1458                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1459                                               ex.getKey(),
1460                                               ex.getArgs(),
1461                                               XMLErrorReporter.SEVERITY_ERROR );
1462                }
1463                break;
1464            }
1465
1466        case XMLSimpleType.TYPE_IDREF: {
1467                boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
1468

1469                try {
1470                    if (isAlistAttribute) {
1471                        fValIDRefs.validate(attValue, fValidationState);
1472                    }
1473                    else {
1474                        fValIDRef.validate(attValue, fValidationState);
1475                    }
1476                }
1477                catch (InvalidDatatypeValueException ex) {
1478                    if (isAlistAttribute) {
1479                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1480                                                   "IDREFSInvalid",
1481                                                   new Object JavaDoc[]{attValue},
1482                                                   XMLErrorReporter.SEVERITY_ERROR );
1483                    }
1484                    else {
1485                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1486                                                   ex.getKey(),
1487                                                   ex.getArgs(),
1488                                                   XMLErrorReporter.SEVERITY_ERROR );
1489                    }
1490
1491                }
1492                break;
1493            }
1494
1495        case XMLSimpleType.TYPE_NMTOKEN: {
1496                boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
1497
//changes fTempAttDef
1498
try {
1499                    if (isAlistAttribute) {
1500                        fValNMTOKENS.validate(attValue, fValidationState);
1501                    }
1502                    else {
1503                        fValNMTOKEN.validate(attValue, fValidationState);
1504                    }
1505                }
1506                catch (InvalidDatatypeValueException ex) {
1507                    if (isAlistAttribute) {
1508                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1509                                                   "NMTOKENSInvalid",
1510                                                   new Object JavaDoc[] { attValue},
1511                                                   XMLErrorReporter.SEVERITY_ERROR);
1512                    }
1513                    else {
1514                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1515                                                   "NMTOKENInvalid",
1516                                                   new Object JavaDoc[] { attValue},
1517                                                   XMLErrorReporter.SEVERITY_ERROR);
1518                    }
1519                }
1520                break;
1521            }
1522
1523        } // switch
1524

1525    } // validateDTDattribute(QName,String,XMLAttributeDecl)
1526

1527
1528    /** Returns true if invalid standalone attribute definition. */
1529    protected boolean invalidStandaloneAttDef(QName element, QName attribute) {
1530        // REVISIT: This obviously needs to be fixed! -Ac
1531
boolean state = true;
1532        /*
1533       if (fStandaloneReader == -1) {
1534          return false;
1535       }
1536       // we are normalizing a default att value... this ok?
1537       if (element.rawname == -1) {
1538          return false;
1539       }
1540       return getAttDefIsExternal(element, attribute);
1541       */

1542        return state;
1543    }
1544
1545
1546    //
1547
// Private methods
1548
//
1549

1550
1551    /**
1552     * Normalize the attribute value of a non CDATA attributes collapsing
1553     * sequences of space characters (x20)
1554     *
1555     * @param attributes The list of attributes
1556     * @param index The index of the attribute to normalize
1557     */

1558    private boolean normalizeAttrValue(XMLAttributes attributes, int index) {
1559        // vars
1560
boolean leadingSpace = true;
1561        boolean spaceStart = false;
1562        boolean readingNonSpace = false;
1563        int count = 0;
1564        int eaten = 0;
1565        String JavaDoc attrValue = attributes.getValue(index);
1566        char[] attValue = new char[attrValue.length()];
1567
1568        fBuffer.setLength(0);
1569        attrValue.getChars(0, attrValue.length(), attValue, 0);
1570        for (int i = 0; i < attValue.length; i++) {
1571
1572            if (attValue[i] == ' ') {
1573
1574                // now the tricky part
1575
if (readingNonSpace) {
1576                    spaceStart = true;
1577                    readingNonSpace = false;
1578                }
1579
1580                if (spaceStart && !leadingSpace) {
1581                    spaceStart = false;
1582                    fBuffer.append(attValue[i]);
1583                    count++;
1584                }
1585                else {
1586                    if (leadingSpace || !spaceStart) {
1587                        eaten ++;
1588                        /*** BUG #3512 ***
1589                        int entityCount = attributes.getEntityCount(index);
1590                        for (int j = 0; j < entityCount; j++) {
1591                            int offset = attributes.getEntityOffset(index, j);
1592                            int length = attributes.getEntityLength(index, j);
1593                            if (offset <= i-eaten+1) {
1594                                if (offset+length >= i-eaten+1) {
1595                                    if (length > 0)
1596                                        length--;
1597                                }
1598                            }
1599                            else {
1600                                if (offset > 0)
1601                                    offset--;
1602                            }
1603                            attributes.setEntityOffset(index, j, offset);
1604                            attributes.setEntityLength(index, j, length);
1605                        }
1606                        /***/

1607                    }
1608                }
1609
1610            }
1611            else {
1612                readingNonSpace = true;
1613                spaceStart = false;
1614                leadingSpace = false;
1615                fBuffer.append(attValue[i]);
1616                count++;
1617            }
1618        }
1619
1620        // check if the last appended character is a space.
1621
if (count > 0 && fBuffer.charAt(count-1) == ' ') {
1622            fBuffer.setLength(count-1);
1623            /*** BUG #3512 ***
1624            int entityCount = attributes.getEntityCount(index);
1625            for (int j=0; j < entityCount; j++) {
1626                int offset = attributes.getEntityOffset(index, j);
1627                int length = attributes.getEntityLength(index, j);
1628                if (offset < count-1) {
1629                    if (offset+length == count) {
1630                        length--;
1631                    }
1632                }
1633                else {
1634                    offset--;
1635                }
1636                attributes.setEntityOffset(index, j, offset);
1637                attributes.setEntityLength(index, j, length);
1638            }
1639            /***/

1640        }
1641        String JavaDoc newValue = fBuffer.toString();
1642        attributes.setValue(index, newValue);
1643        return ! attrValue.equals(newValue);
1644    }
1645
1646    /** Root element specified. */
1647    private final void rootElementSpecified(QName rootElement) throws XNIException {
1648        if (fPerformValidation) {
1649            String JavaDoc root1 = fRootElement.rawname;
1650            String JavaDoc root2 = rootElement.rawname;
1651            if (root1 == null || !root1.equals(root2)) {
1652                fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
1653                                            "RootElementTypeMustMatchDoctypedecl",
1654                                            new Object JavaDoc[]{root1, root2},
1655                                            XMLErrorReporter.SEVERITY_ERROR);
1656            }
1657        }
1658    } // rootElementSpecified(QName)
1659

1660    /**
1661     * Check that the content of an element is valid.
1662     * <p>
1663     * This is the method of primary concern to the validator. This method is called
1664     * upon the scanner reaching the end tag of an element. At that time, the
1665     * element's children must be structurally validated, so it calls this method.
1666     * The index of the element being checked (in the decl pool), is provided as
1667     * well as an array of element name indexes of the children. The validator must
1668     * confirm that this element can have these children in this order.
1669     * <p>
1670     * This can also be called to do 'what if' testing of content models just to see
1671     * if they would be valid.
1672     * <p>
1673     * Note that the element index is an index into the element decl pool, whereas
1674     * the children indexes are name indexes, i.e. into the string pool.
1675     * <p>
1676     * A value of -1 in the children array indicates a PCDATA node. All other
1677     * indexes will be positive and represent child elements. The count can be
1678     * zero, since some elements have the EMPTY content model and that must be
1679     * confirmed.
1680     *
1681     * @param elementIndex The index within the <code>ElementDeclPool</code> of this
1682     * element.
1683     * @param childCount The number of entries in the <code>children</code> array.
1684     * @param children The children of this element.
1685     *
1686     * @return The value -1 if fully valid, else the 0 based index of the child
1687     * that first failed. If the value returned is equal to the number
1688     * of children, then additional content is required to reach a valid
1689     * ending state.
1690     *
1691     * @exception Exception Thrown on error.
1692     */

1693    private int checkContent(int elementIndex,
1694                             QName[] children,
1695                             int childOffset,
1696                             int childCount) throws XNIException {
1697
1698        fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
1699
1700        // Get the element name index from the element
1701
final String JavaDoc elementType = fCurrentElement.rawname;
1702
1703        // Get out the content spec for this element
1704
final int contentType = fCurrentContentSpecType;
1705
1706
1707        //
1708
// Deal with the possible types of content. We try to optimized here
1709
// by dealing specially with content models that don't require the
1710
// full DFA treatment.
1711
//
1712
if (contentType == XMLElementDecl.TYPE_EMPTY) {
1713            //
1714
// If the child count is greater than zero, then this is
1715
// an error right off the bat at index 0.
1716
//
1717
if (childCount != 0) {
1718                return 0;
1719            }
1720        }
1721        else if (contentType == XMLElementDecl.TYPE_ANY) {
1722            //
1723
// This one is open game so we don't pass any judgement on it
1724
// at all. Its assumed to fine since it can hold anything.
1725
//
1726
}
1727        else if (contentType == XMLElementDecl.TYPE_MIXED ||
1728                 contentType == XMLElementDecl.TYPE_CHILDREN) {
1729            // Get the content model for this element, faulting it in if needed
1730
ContentModelValidator cmElem = null;
1731            cmElem = fTempElementDecl.contentModelValidator;
1732            int result = cmElem.validate(children, childOffset, childCount);
1733            return result;
1734        }
1735        else if (contentType == -1) {
1736            //REVISIT
1737
/****
1738            reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
1739                                      XMLMessages.VC_ELEMENT_VALID,
1740                                      elementType);
1741            /****/

1742        }
1743        else if (contentType == XMLElementDecl.TYPE_SIMPLE) {
1744
1745            //REVISIT
1746
// this should never be reached in the case of DTD validation.
1747

1748        }
1749        else {
1750            //REVISIT
1751
/****
1752            fErrorReporter.reportError(fErrorReporter.getLocator(),
1753                                       ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
1754                                       ImplementationMessages.VAL_CST,
1755                                       0,
1756                                       null,
1757                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
1758            /****/

1759        }
1760
1761        // We succeeded
1762
return -1;
1763
1764    } // checkContent(int,int,QName[]):int
1765

1766    /** Returns the content spec type for an element index. */
1767    private int getContentSpecType(int elementIndex) {
1768
1769        int contentSpecType = -1;
1770        if (elementIndex > -1) {
1771            if (fDTDGrammar.getElementDecl(elementIndex,fTempElementDecl)) {
1772                contentSpecType = fTempElementDecl.type;
1773            }
1774        }
1775        return contentSpecType;
1776    }
1777
1778    /** Character data in content. */
1779    private void charDataInContent() {
1780
1781        if (DEBUG_ELEMENT_CHILDREN) {
1782            System.out.println("charDataInContent()");
1783        }
1784        if (fElementChildren.length <= fElementChildrenLength) {
1785            QName[] newarray = new QName[fElementChildren.length * 2];
1786            System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
1787            fElementChildren = newarray;
1788        }
1789        QName qname = fElementChildren[fElementChildrenLength];
1790        if (qname == null) {
1791            for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
1792                fElementChildren[i] = new QName();
1793            }
1794            qname = fElementChildren[fElementChildrenLength];
1795        }
1796        qname.clear();
1797        fElementChildrenLength++;
1798
1799    } // charDataInCount()
1800

1801    /** convert attribute type from ints to strings */
1802    private String JavaDoc getAttributeTypeName(XMLAttributeDecl attrDecl) {
1803
1804        switch (attrDecl.simpleType.type) {
1805        case XMLSimpleType.TYPE_ENTITY: {
1806                return attrDecl.simpleType.list ? XMLSymbols.fENTITIESSymbol : XMLSymbols.fENTITYSymbol;
1807            }
1808        case XMLSimpleType.TYPE_ENUMERATION: {
1809                StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1810                buffer.append('(');
1811                for (int i=0; i<attrDecl.simpleType.enumeration.length ; i++) {
1812                    if (i > 0) {
1813                        buffer.append("|");
1814                    }
1815                    buffer.append(attrDecl.simpleType.enumeration[i]);
1816                }
1817                buffer.append(')');
1818                return fSymbolTable.addSymbol(buffer.toString());
1819            }
1820        case XMLSimpleType.TYPE_ID: {
1821                return XMLSymbols.fIDSymbol;
1822            }
1823        case XMLSimpleType.TYPE_IDREF: {
1824                return attrDecl.simpleType.list ? XMLSymbols.fIDREFSSymbol : XMLSymbols.fIDREFSymbol;
1825            }
1826        case XMLSimpleType.TYPE_NMTOKEN: {
1827                return attrDecl.simpleType.list ? XMLSymbols.fNMTOKENSSymbol : XMLSymbols.fNMTOKENSymbol;
1828            }
1829        case XMLSimpleType.TYPE_NOTATION: {
1830                return XMLSymbols.fNOTATIONSymbol;
1831            }
1832        }
1833        return XMLSymbols.fCDATASymbol;
1834
1835    } // getAttributeTypeName(XMLAttributeDecl):String
1836

1837    /** initialization */
1838    protected void init() {
1839
1840        // datatype validators
1841
if (fValidation || fDynamicValidation) {
1842            try {
1843                //REVISIT: datatypeRegistry + initialization of datatype
1844
// why do we cast to ListDatatypeValidator?
1845
fValID = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDSymbol);
1846                fValIDRef = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSymbol);
1847                fValIDRefs = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSSymbol);
1848                fValENTITY = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITYSymbol);
1849                fValENTITIES = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITIESSymbol);
1850                fValNMTOKEN = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSymbol);
1851                fValNMTOKENS = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSSymbol);
1852                fValNOTATION = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNOTATIONSymbol);
1853
1854            }
1855            catch (Exception JavaDoc e) {
1856                // should never happen
1857
e.printStackTrace(System.err);
1858            }
1859
1860        }
1861
1862    } // init()
1863

1864    /** ensure element stack capacity */
1865    private void ensureStackCapacity ( int newElementDepth) {
1866        if (newElementDepth == fElementQNamePartsStack.length) {
1867            int[] newStack = new int[newElementDepth * 2];
1868
1869            QName[] newStackOfQueue = new QName[newElementDepth * 2];
1870            System.arraycopy(this.fElementQNamePartsStack, 0, newStackOfQueue, 0, newElementDepth );
1871            fElementQNamePartsStack = newStackOfQueue;
1872
1873            QName qname = fElementQNamePartsStack[newElementDepth];
1874            if (qname == null) {
1875                for (int i = newElementDepth; i < fElementQNamePartsStack.length; i++) {
1876                    fElementQNamePartsStack[i] = new QName();
1877                }
1878            }
1879
1880            newStack = new int[newElementDepth * 2];
1881            System.arraycopy(fElementIndexStack, 0, newStack, 0, newElementDepth);
1882            fElementIndexStack = newStack;
1883
1884            newStack = new int[newElementDepth * 2];
1885            System.arraycopy(fContentSpecTypeStack, 0, newStack, 0, newElementDepth);
1886            fContentSpecTypeStack = newStack;
1887
1888        }
1889    } // ensureStackCapacity
1890

1891    
1892    //
1893
// Protected methods
1894
//
1895

1896    /** Handle element
1897     * @return true if validator is removed from the pipeline
1898     */

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

2017    protected void startNamespaceScope(QName element, XMLAttributes attributes, Augmentations augs){
2018    }
2019
2020    /** Handle end element. */
2021    protected void handleEndElement(QName element, Augmentations augs, boolean isEmpty)
2022    throws XNIException {
2023
2024        // decrease element depth
2025
fElementDepth--;
2026
2027        // validate
2028
if (fPerformValidation) {
2029            int elementIndex = fCurrentElementIndex;
2030            if (elementIndex != -1 && fCurrentContentSpecType != -1) {
2031                QName children[] = fElementChildren;
2032                int childrenOffset = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
2033                int childrenLength = fElementChildrenLength - childrenOffset;
2034                int result = checkContent(elementIndex,
2035                                          children, childrenOffset, childrenLength);
2036
2037                if (result != -1) {
2038                    fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
2039                    if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
2040                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
2041                                                   "MSG_CONTENT_INVALID",
2042                                                   new Object JavaDoc[]{ element.rawname, "EMPTY"},
2043                                                   XMLErrorReporter.SEVERITY_ERROR);
2044                    }
2045                    else {
2046                        String JavaDoc messageKey = result != childrenLength ?
2047                                            "MSG_CONTENT_INVALID" : "MSG_CONTENT_INCOMPLETE";
2048                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
2049                                                   messageKey,
2050                                                   new Object JavaDoc[]{ element.rawname,
2051                                                       fDTDGrammar.getContentSpecAsString(elementIndex)},
2052                                                   XMLErrorReporter.SEVERITY_ERROR);
2053                    }
2054                }
2055            }
2056            fElementChildrenLength = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
2057        }
2058        
2059        endNamespaceScope(fCurrentElement, augs, isEmpty);
2060        
2061        // now pop this element off the top of the element stack
2062
if (fElementDepth < -1) {
2063            throw new RuntimeException JavaDoc("FWK008 Element stack underflow");
2064        }
2065        if (fElementDepth < 0) {
2066            fCurrentElement.clear();
2067            fCurrentElementIndex = -1;
2068            fCurrentContentSpecType = -1;
2069            fInElementContent = false;
2070
2071            // TO DO : fix this
2072
//
2073
// Check after document is fully parsed
2074
// (1) check that there was an element with a matching id for every
2075
// IDREF and IDREFS attr (V_IDREF0)
2076
//
2077
if (fPerformValidation) {
2078                String JavaDoc value = fValidationState.checkIDRefID();
2079                if (value != null) {
2080                    fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
2081                                                "MSG_ELEMENT_WITH_ID_REQUIRED",
2082                                                new Object JavaDoc[]{value},
2083                                                XMLErrorReporter.SEVERITY_ERROR );
2084                }
2085            }
2086            return;
2087        }
2088
2089        // If Namespace enable then localName != rawName
2090
fCurrentElement.setValues(fElementQNamePartsStack[fElementDepth]);
2091
2092        fCurrentElementIndex = fElementIndexStack[fElementDepth];
2093        fCurrentContentSpecType = fContentSpecTypeStack[fElementDepth];
2094        fInElementContent = (fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN);
2095
2096    } // handleEndElement(QName,boolean)
2097

2098    protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty){
2099
2100        // call handlers
2101
if (fDocumentHandler != null && !isEmpty) {
2102            // NOTE: The binding of the element doesn't actually happen
2103
// yet because the namespace binder does that. However,
2104
// if it does it before this point, then the endPrefix-
2105
// Mapping calls get made too soon! As long as the
2106
// rawnames match, we know it'll have a good binding,
2107
// so we can just use the current element. -Ac
2108
fDocumentHandler.endElement(fCurrentElement, augs);
2109        }
2110    }
2111
2112    // returns whether a character is space according to the
2113
// version of XML this validator supports.
2114
protected boolean isSpace(int c) {
2115        return XMLChar.isSpace(c);
2116    } // isSpace(int): boolean
2117

2118} // class XMLDTDValidator
2119
Popular Tags