KickJava   Java API By Example, From Geeks To Geeks.

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


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

57
58 package com.sun.org.apache.xerces.internal.impl.dtd;
59
60 import java.util.Hashtable JavaDoc;
61 import java.util.Vector JavaDoc;
62
63 import com.sun.org.apache.xerces.internal.impl.dtd.models.CMAny;
64 import com.sun.org.apache.xerces.internal.impl.dtd.models.CMBinOp;
65 import com.sun.org.apache.xerces.internal.impl.dtd.models.CMLeaf;
66 import com.sun.org.apache.xerces.internal.impl.dtd.models.CMNode;
67 import com.sun.org.apache.xerces.internal.impl.dtd.models.CMUniOp;
68 import com.sun.org.apache.xerces.internal.impl.dtd.models.ContentModelValidator;
69 import com.sun.org.apache.xerces.internal.impl.dtd.models.DFAContentModel;
70 import com.sun.org.apache.xerces.internal.impl.dtd.models.MixedContentModel;
71 import com.sun.org.apache.xerces.internal.impl.dtd.models.SimpleContentModel;
72 import com.sun.org.apache.xerces.internal.impl.dv.DatatypeValidator;
73 import com.sun.org.apache.xerces.internal.impl.validation.EntityState;
74 import com.sun.org.apache.xerces.internal.util.SymbolTable;
75 import com.sun.org.apache.xerces.internal.xni.Augmentations;
76 import com.sun.org.apache.xerces.internal.xni.QName;
77 import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
78 import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
79 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
80 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
81 import com.sun.org.apache.xerces.internal.xni.XMLString;
82 import com.sun.org.apache.xerces.internal.xni.XNIException;
83 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
84 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
85 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource;
86 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource;
87
88 /**
89  * A DTD grammar. This class implements the XNI handler interfaces
90  * for DTD information so that it can build the approprate validation
91  * structures automatically from the callbacks.
92  *
93  * @author Eric Ye, IBM
94  * @author Jeffrey Rodriguez, IBM
95  * @author Andy Clark, IBM
96  * @author Neil Graham, IBM
97  *
98  * @version $Id: DTDGrammar.java,v 1.28 2004/03/28 04:06:46 mrglavas Exp $
99  */

100 public class DTDGrammar
101     implements XMLDTDHandler, XMLDTDContentModelHandler, EntityState, Grammar {
102
103     //
104
// Constants
105
//
106

107     /** Top level scope (-1). */
108     public static final int TOP_LEVEL_SCOPE = -1;
109
110     // private
111

112     /** Chunk shift (8). */
113     private static final int CHUNK_SHIFT = 8; // 2^8 = 256
114

115     /** Chunk size (1 << CHUNK_SHIFT). */
116     private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
117
118     /** Chunk mask (CHUNK_SIZE - 1). */
119     private static final int CHUNK_MASK = CHUNK_SIZE - 1;
120
121     /** Initial chunk count (1 << (10 - CHUNK_SHIFT)). */
122     private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k
123

124     /** List flag (0x80). */
125     private static final short LIST_FLAG = 0x80;
126
127     /** List mask (~LIST_FLAG). */
128     private static final short LIST_MASK = ~LIST_FLAG;
129
130     // debugging
131

132     /** Debug DTDGrammar. */
133     private static final boolean DEBUG = false;
134
135     //
136
// Data
137
//
138

139     protected XMLDTDSource fDTDSource = null;
140     protected XMLDTDContentModelSource fDTDContentModelSource = null;
141
142     /** Current element index. */
143     protected int fCurrentElementIndex;
144
145     /** Current attribute index. */
146     protected int fCurrentAttributeIndex;
147
148     /** fReadingExternalDTD */
149     protected boolean fReadingExternalDTD = false;
150
151     /** Symbol table. */
152     private SymbolTable fSymbolTable;
153
154     // The XMLDTDDescription with which this Grammar is associated
155
protected XMLDTDDescription fGrammarDescription = null;
156
157     // element declarations
158

159     /** Number of element declarations. */
160     private int fElementDeclCount = 0;
161
162     /** Element declaration name. */
163     private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
164
165     /**
166      * Element declaration type.
167      * @see XMLElementDecl
168      */

169     private short fElementDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
170
171     /**
172      * Element declaration content spec index. This index value is used
173      * to refer to the content spec information tables.
174      */

175     private int fElementDeclContentSpecIndex[][] = new int[INITIAL_CHUNK_COUNT][];
176
177     /**
178      * Element declaration content model validator. This validator is
179      * constructed from the content spec nodes.
180      */

181     private ContentModelValidator fElementDeclContentModelValidator[][] = new ContentModelValidator[INITIAL_CHUNK_COUNT][];
182
183     /** First attribute declaration of an element declaration. */
184     private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
185
186     /** Last attribute declaration of an element declaration. */
187     private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
188
189     // attribute declarations
190

191     /** Number of attribute declarations. */
192     private int fAttributeDeclCount = 0 ;
193
194     /** Attribute declaration name. */
195     private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
196
197     // is this grammar immutable? (fully constructed and not changeable)
198
private boolean fIsImmutable = false;
199
200     /**
201      * Attribute declaration type.
202      * @see XMLAttributeDecl
203      */

204     private short fAttributeDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
205
206     /** Attribute declaration enumeration values. */
207     private String JavaDoc[] fAttributeDeclEnumeration[][] = new String JavaDoc[INITIAL_CHUNK_COUNT][][];
208     private short fAttributeDeclDefaultType[][] = new short[INITIAL_CHUNK_COUNT][];
209     private DatatypeValidator fAttributeDeclDatatypeValidator[][] = new DatatypeValidator[INITIAL_CHUNK_COUNT][];
210     private String JavaDoc fAttributeDeclDefaultValue[][] = new String JavaDoc[INITIAL_CHUNK_COUNT][];
211     private String JavaDoc fAttributeDeclNonNormalizedDefaultValue[][] = new String JavaDoc[INITIAL_CHUNK_COUNT][];
212     private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
213
214     // content specs
215

216     // here saves the content spec binary trees for element decls,
217
// each element with a content model will hold a pointer which is
218
// the index of the head node of the content spec tree.
219

220     private int fContentSpecCount = 0;
221     private short fContentSpecType[][] = new short[INITIAL_CHUNK_COUNT][];
222     private Object JavaDoc fContentSpecValue[][] = new Object JavaDoc[INITIAL_CHUNK_COUNT][];
223     private Object JavaDoc fContentSpecOtherValue[][] = new Object JavaDoc[INITIAL_CHUNK_COUNT][];
224
225     // entities
226

227     private int fEntityCount = 0;
228     private String JavaDoc fEntityName[][] = new String JavaDoc[INITIAL_CHUNK_COUNT][];
229     private String JavaDoc[][] fEntityValue = new String JavaDoc[INITIAL_CHUNK_COUNT][];
230     private String JavaDoc[][] fEntityPublicId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
231     private String JavaDoc[][] fEntitySystemId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
232     private String JavaDoc[][] fEntityBaseSystemId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
233     private String JavaDoc[][] fEntityNotation = new String JavaDoc[INITIAL_CHUNK_COUNT][];
234     private byte[][] fEntityIsPE = new byte[INITIAL_CHUNK_COUNT][];
235     private byte[][] fEntityInExternal = new byte[INITIAL_CHUNK_COUNT][];
236
237     // notations
238

239     private int fNotationCount = 0;
240     private String JavaDoc fNotationName[][] = new String JavaDoc[INITIAL_CHUNK_COUNT][];
241     private String JavaDoc[][] fNotationPublicId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
242     private String JavaDoc[][] fNotationSystemId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
243     private String JavaDoc[][] fNotationBaseSystemId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
244
245     // other information
246

247     /** Element index mapping table. */
248     private QNameHashtable fElementIndexMap = new QNameHashtable();
249
250     /** Entity index mapping table. */
251     private QNameHashtable fEntityIndexMap = new QNameHashtable();
252
253     /** Notation index mapping table. */
254     private QNameHashtable fNotationIndexMap = new QNameHashtable();
255
256     // temp variables
257

258     /** Mixed. */
259     private boolean fMixed;
260
261     /** Temporary qualified name. */
262     private QName fQName = new QName();
263     
264     /** Temporary qualified name. */
265     private QName fQName2 = new QName();
266
267     /** Temporary Attribute decl. */
268     protected XMLAttributeDecl fAttributeDecl = new XMLAttributeDecl();
269
270     // for buildSyntaxTree method
271

272     private int fLeafCount = 0;
273     private int fEpsilonIndex = -1;
274     
275     /** Element declaration. */
276     private XMLElementDecl fElementDecl = new XMLElementDecl();
277
278     /** Entity declaration. */
279     private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
280
281     /** Simple type. */
282     private XMLSimpleType fSimpleType = new XMLSimpleType();
283
284     /** Content spec node. */
285     private XMLContentSpec fContentSpec = new XMLContentSpec();
286
287     /** table of XMLElementDecl */
288     Hashtable JavaDoc fElementDeclTab = new Hashtable JavaDoc();
289
290     /** Children content model operation stack. */
291     private short[] fOpStack = null;
292
293     /** Children content model index stack. */
294     private int[] fNodeIndexStack = null;
295
296     /** Children content model previous node index stack. */
297     private int[] fPrevNodeIndexStack = null;
298
299     /** Stack depth */
300     private int fDepth = 0;
301
302     /** Entity stack. */
303     private boolean[] fPEntityStack = new boolean[4];
304     private int fPEDepth = 0;
305
306     // additional fields(columns) for the element Decl pool in the Grammar
307

308     /** flag if the elementDecl is External. */
309     private int fElementDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][];
310
311
312     // additional fields(columns) for the attribute Decl pool in the Grammar
313

314     /** flag if the AttributeDecl is External. */
315     private int fAttributeDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][];
316
317     // for mixedElement method
318

319     int valueIndex = -1;
320     int prevNodeIndex = -1;
321     int nodeIndex = -1;
322
323     //
324
// Constructors
325
//
326

327     /** Default constructor. */
328     public DTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) {
329         fSymbolTable = symbolTable;
330         fGrammarDescription = desc;
331     } // <init>(SymbolTable)
332

333     // Grammar methods
334

335     // return the XMLDTDDescription object with which this is associated
336
public XMLGrammarDescription getGrammarDescription() {
337         return fGrammarDescription;
338     } // getGrammarDescription(): XMLGrammarDescription
339

340     //
341
// Public methods
342
//
343

344     /**
345      * Returns true if the specified element declaration is external.
346      *
347      * @param elementDeclIndex The element declaration index.
348      */

349     public boolean getElementDeclIsExternal(int elementDeclIndex) {
350
351         if (elementDeclIndex < 0) {
352             return false;
353         }
354
355         int chunk = elementDeclIndex >> CHUNK_SHIFT;
356         int index = elementDeclIndex & CHUNK_MASK;
357         return (fElementDeclIsExternal[chunk][index] != 0);
358
359     } // getElementDeclIsExternal(int):boolean
360

361     /**
362      * Returns true if the specified attribute declaration is external.
363      *
364      * @param attributeDeclIndex Attribute declaration index.
365      */

366     public boolean getAttributeDeclIsExternal(int attributeDeclIndex) {
367
368         if (attributeDeclIndex < 0) {
369             return false;
370         }
371
372         int chunk = attributeDeclIndex >> CHUNK_SHIFT;
373         int index = attributeDeclIndex & CHUNK_MASK;
374         return (fAttributeDeclIsExternal[chunk][index] != 0);
375     }
376
377     public int getAttributeDeclIndex(int elementDeclIndex, String JavaDoc attributeDeclName) {
378         if (elementDeclIndex == -1) {
379             return -1;
380         }
381         int attDefIndex = getFirstAttributeDeclIndex(elementDeclIndex);
382         while (attDefIndex != -1) {
383             getAttributeDecl(attDefIndex, fAttributeDecl);
384
385             if (fAttributeDecl.name.rawname == attributeDeclName
386                 || attributeDeclName.equals(fAttributeDecl.name.rawname) ) {
387                 return attDefIndex;
388             }
389             attDefIndex = getNextAttributeDeclIndex(attDefIndex);
390         }
391         return -1;
392     } // getAttributeDeclIndex (int,QName)
393

394     //
395
// XMLDTDHandler methods
396
//
397

398     /**
399      * The start of the DTD.
400      *
401      * @param locator The document locator, or null if the document
402      * location cannot be reported during the parsing of
403      * the document DTD. However, it is <em>strongly</em>
404      * recommended that a locator be supplied that can
405      * at least report the base system identifier of the
406      * DTD.
407      *
408      * @param augs Additional information that may include infoset
409      * augmentations.
410      * @throws XNIException Thrown by handler to signal an error.
411      */

412     public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
413         //Initialize stack
414
fOpStack = null;
415         fNodeIndexStack = null;
416         fPrevNodeIndexStack = null;
417     } // startDTD(XMLLocator)
418

419     /**
420      * This method notifies of the start of an entity. The DTD has the
421      * pseudo-name of "[dtd]" and parameter entity names start with '%'.
422      * <p>
423      * <strong>Note:</strong> Since the DTD is an entity, the handler
424      * will be notified of the start of the DTD entity by calling the
425      * startParameterEntity method with the entity name "[dtd]" <em>before</em> calling
426      * the startDTD method.
427      *
428      * @param name The name of the parameter entity.
429      * @param identifier The resource identifier.
430      * @param encoding The auto-detected IANA encoding name of the entity
431      * stream. This value will be null in those situations
432      * where the entity encoding is not auto-detected (e.g.
433      * internal parameter entities).
434      * @param augs Additional information that may include infoset
435      * augmentations.
436      *
437      * @throws XNIException Thrown by handler to signal an error.
438      */

439     public void startParameterEntity(String JavaDoc name,
440                                      XMLResourceIdentifier identifier,
441                                      String JavaDoc encoding,
442                                      Augmentations augs) throws XNIException {
443
444         // keep track of this entity before fEntityDepth is increased
445
if (fPEDepth == fPEntityStack.length) {
446             boolean[] entityarray = new boolean[fPEntityStack.length * 2];
447             System.arraycopy(fPEntityStack, 0, entityarray, 0, fPEntityStack.length);
448             fPEntityStack = entityarray;
449         }
450         fPEntityStack[fPEDepth] = fReadingExternalDTD;
451         fPEDepth++;
452
453     } // startParameterEntity(String,XMLResourceIdentifier,String,Augmentations)
454

455     /**
456      * The start of the DTD external subset.
457      *
458      * @param augs Additional information that may include infoset
459      * augmentations.
460      *
461      * @throws XNIException Thrown by handler to signal an error.
462      */

463     public void startExternalSubset(XMLResourceIdentifier identifier,
464                                     Augmentations augs) throws XNIException {
465         fReadingExternalDTD = true;
466     } // startExternalSubset(Augmentations)
467

468     /**
469      * This method notifies the end of an entity. The DTD has the pseudo-name
470      * of "[dtd]" and parameter entity names start with '%'.
471      * <p>
472      * <strong>Note:</strong> Since the DTD is an entity, the handler
473      * will be notified of the end of the DTD entity by calling the
474      * endEntity method with the entity name "[dtd]" <em>after</em> calling
475      * the endDTD method.
476      *
477      * @param name The name of the entity.
478      * @param augs Additional information that may include infoset
479      * augmentations.
480      * @throws XNIException Thrown by handler to signal an error.
481      */

482     public void endParameterEntity(String JavaDoc name, Augmentations augs) throws XNIException {
483
484         fPEDepth--;
485         fReadingExternalDTD = fPEntityStack[fPEDepth];
486
487     } // endParameterEntity(String,Augmentations)
488

489     /**
490      * The end of the DTD external subset.
491      *
492      * @param augs Additional information that may include infoset
493      * augmentations.
494      *
495      * @throws XNIException Thrown by handler to signal an error.
496      */

497     public void endExternalSubset(Augmentations augs) throws XNIException {
498         fReadingExternalDTD = false;
499     } // endExternalSubset(Augmentations)
500

501     /**
502      * An element declaration.
503      *
504      * @param name The name of the element.
505      * @param contentModel The element content model.
506      * @param augs Additional information that may include infoset
507      * augmentations.
508      * @throws XNIException Thrown by handler to signal an error.
509      */

510     public void elementDecl(String JavaDoc name, String JavaDoc contentModel, Augmentations augs)
511         throws XNIException {
512
513         XMLElementDecl tmpElementDecl = (XMLElementDecl) fElementDeclTab.get(name) ;
514
515         // check if it is already defined
516
if ( tmpElementDecl != null ) {
517             if (tmpElementDecl.type == -1) {
518                 fCurrentElementIndex = getElementDeclIndex(name);
519             }
520             else {
521                 // duplicate element, ignored.
522
return;
523             }
524         }
525         else {
526             fCurrentElementIndex = createElementDecl();//create element decl
527
}
528
529         XMLElementDecl elementDecl = new XMLElementDecl();
530         
531         fQName.setValues(null, name, name, null);
532        
533         elementDecl.name.setValues(fQName);
534
535         elementDecl.contentModelValidator = null;
536         elementDecl.scope= -1;
537         if (contentModel.equals("EMPTY")) {
538             elementDecl.type = XMLElementDecl.TYPE_EMPTY;
539         }
540         else if (contentModel.equals("ANY")) {
541             elementDecl.type = XMLElementDecl.TYPE_ANY;
542         }
543         else if (contentModel.startsWith("(") ) {
544             if (contentModel.indexOf("#PCDATA") > 0 ) {
545                 elementDecl.type = XMLElementDecl.TYPE_MIXED;
546             }
547             else {
548                 elementDecl.type = XMLElementDecl.TYPE_CHILDREN;
549             }
550         }
551
552
553         //add(or set) this elementDecl to the local cache
554
this.fElementDeclTab.put(name, elementDecl );
555
556         fElementDecl = elementDecl;
557
558         if ((fDepth == 0 ||
559             (fDepth == 1 && elementDecl.type == XMLElementDecl.TYPE_MIXED)) &&
560             fNodeIndexStack != null) {
561             if (elementDecl.type == XMLElementDecl.TYPE_MIXED) {
562                 int pcdata = addUniqueLeafNode(null);
563                 if (fNodeIndexStack[0] == -1) {
564                     fNodeIndexStack[0] = pcdata;
565                 }
566                 else {
567                     fNodeIndexStack[0] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
568                                                             pcdata, fNodeIndexStack[0]);
569                 }
570             }
571             setContentSpecIndex(fCurrentElementIndex, fNodeIndexStack[fDepth]);
572         }
573
574         if ( DEBUG ) {
575             System.out.println( "name = " + fElementDecl.name.localpart );
576             System.out.println( "Type = " + fElementDecl.type );
577         }
578
579         setElementDecl(fCurrentElementIndex, fElementDecl );//set internal structure
580

581         int chunk = fCurrentElementIndex >> CHUNK_SHIFT;
582         int index = fCurrentElementIndex & CHUNK_MASK;
583         ensureElementDeclCapacity(chunk);
584         fElementDeclIsExternal[chunk][index] = fReadingExternalDTD? 1 : 0;
585
586     } // elementDecl(String,String)
587

588     /**
589      * An attribute declaration.
590      *
591      * @param elementName The name of the element that this attribute
592      * is associated with.
593      * @param attributeName The name of the attribute.
594      * @param type The attribute type. This value will be one of
595      * the following: "CDATA", "ENTITY", "ENTITIES",
596      * "ENUMERATION", "ID", "IDREF", "IDREFS",
597      * "NMTOKEN", "NMTOKENS", or "NOTATION".
598      * @param enumeration If the type has the value "ENUMERATION", this
599      * array holds the allowed attribute values;
600      * otherwise, this array is null.
601      * @param defaultType The attribute default type. This value will be
602      * one of the following: "#FIXED", "#IMPLIED",
603      * "#REQUIRED", or null.
604      * @param defaultValue The attribute default value, or null if no
605      * default value is specified.
606      * @param nonNormalizedDefaultValue The attribute default value with no normalization
607      * performed, or null if no default value is specified.
608      *
609      * @param augs Additional information that may include infoset
610      * augmentations.
611      * @throws XNIException Thrown by handler to signal an error.
612      */

613     public void attributeDecl(String JavaDoc elementName, String JavaDoc attributeName,
614                               String JavaDoc type, String JavaDoc[] enumeration,
615                               String JavaDoc defaultType, XMLString defaultValue,
616                               XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
617
618         if ( this.fElementDeclTab.containsKey( (String JavaDoc) elementName) ) {
619             //if ElementDecl has already being created in the Grammar then remove from table,
620
//this.fElementDeclTab.remove( (String) elementName );
621
}
622         // then it is forward reference to a element decl, create the elementDecl first.
623
else {
624             fCurrentElementIndex = createElementDecl();//create element decl
625

626             XMLElementDecl elementDecl = new XMLElementDecl();
627             elementDecl.name.setValues(null, elementName, elementName, null);
628
629             elementDecl.scope= -1;
630
631             //add(or set) this elementDecl to the local cache
632
this.fElementDeclTab.put(elementName, elementDecl );
633
634             //set internal structure
635
setElementDecl(fCurrentElementIndex, elementDecl );
636         }
637
638         //Get Grammar index to grammar array
639
int elementIndex = getElementDeclIndex(elementName);
640         
641         //return, when more than one definition is provided for the same attribute of given element type
642
//only the first declaration is binding and later declarations are ignored
643
if (getAttributeDeclIndex(elementIndex, attributeName) != -1) {
644             return;
645         }
646
647         fCurrentAttributeIndex = createAttributeDecl();// Create current Attribute Decl
648

649         fSimpleType.clear();
650         if ( defaultType != null ) {
651             if ( defaultType.equals( "#FIXED") ) {
652                 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_FIXED;
653             } else if ( defaultType.equals( "#IMPLIED") ) {
654                 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
655             } else if ( defaultType.equals( "#REQUIRED") ) {
656                 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_REQUIRED;
657             }
658         }
659         if ( DEBUG ) {
660             System.out.println("defaultvalue = " + defaultValue.toString() );
661         }
662         fSimpleType.defaultValue = defaultValue!=null ? defaultValue.toString() : null;
663         fSimpleType.nonNormalizedDefaultValue = nonNormalizedDefaultValue!=null ? nonNormalizedDefaultValue.toString() : null;
664         fSimpleType.enumeration = enumeration;
665
666         if (type.equals("CDATA")) {
667             fSimpleType.type = XMLSimpleType.TYPE_CDATA;
668         }
669         else if ( type.equals("ID") ) {
670             fSimpleType.type = XMLSimpleType.TYPE_ID;
671         }
672         else if ( type.startsWith("IDREF") ) {
673             fSimpleType.type = XMLSimpleType.TYPE_IDREF;
674             if (type.indexOf("S") > 0) {
675                 fSimpleType.list = true;
676             }
677         }
678         else if (type.equals("ENTITIES")) {
679             fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
680             fSimpleType.list = true;
681         }
682         else if (type.equals("ENTITY")) {
683             fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
684         }
685         else if (type.equals("NMTOKENS")) {
686             fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
687             fSimpleType.list = true;
688         }
689         else if (type.equals("NMTOKEN")) {
690             fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
691         }
692         else if (type.startsWith("NOTATION") ) {
693             fSimpleType.type = XMLSimpleType.TYPE_NOTATION;
694         }
695         else if (type.startsWith("ENUMERATION") ) {
696             fSimpleType.type = XMLSimpleType.TYPE_ENUMERATION;
697         }
698         else {
699             // REVISIT: Report error message. -Ac
700
System.err.println("!!! unknown attribute type "+type);
701         }
702         // REVISIT: The datatype should be stored with the attribute value
703
// and not special-cased in the XMLValidator. -Ac
704
//fSimpleType.datatypeValidator = fDatatypeValidatorFactory.createDatatypeValidator(type, null, facets, fSimpleType.list);
705

706         fQName.setValues(null, attributeName, attributeName, null);
707         fAttributeDecl.setValues( fQName, fSimpleType, false );
708
709         setAttributeDecl(elementIndex, fCurrentAttributeIndex, fAttributeDecl);
710
711         int chunk = fCurrentAttributeIndex >> CHUNK_SHIFT;
712         int index = fCurrentAttributeIndex & CHUNK_MASK;
713         ensureAttributeDeclCapacity(chunk);
714         fAttributeDeclIsExternal[chunk][index] = fReadingExternalDTD ? 1 : 0;
715
716     } // attributeDecl(String,String,String,String[],String,XMLString,XMLString, Augmentations)
717

718     /**
719      * An internal entity declaration.
720      *
721      * @param name The name of the entity. Parameter entity names start with
722      * '%', whereas the name of a general entity is just the
723      * entity name.
724      * @param text The value of the entity.
725      * @param nonNormalizedText The non-normalized value of the entity. This
726      * value contains the same sequence of characters that was in
727      * the internal entity declaration, without any entity
728      * references expanded.
729      * @param augs Additional information that may include infoset
730      * augmentations.
731      * @throws XNIException Thrown by handler to signal an error.
732      */

733     public void internalEntityDecl(String JavaDoc name, XMLString text,
734                                    XMLString nonNormalizedText,
735                                    Augmentations augs) throws XNIException {
736
737         int entityIndex = getEntityDeclIndex(name);
738         if( entityIndex == -1){
739             entityIndex = createEntityDecl();
740             boolean isPE = name.startsWith("%");
741             boolean inExternal = fReadingExternalDTD;
742             XMLEntityDecl entityDecl = new XMLEntityDecl();
743             entityDecl.setValues(name,null,null, null, null,
744                                  text.toString(), isPE, inExternal);
745
746             setEntityDecl(entityIndex, entityDecl);
747         }
748
749     } // internalEntityDecl(String,XMLString,XMLString)
750

751     /**
752      * An external entity declaration.
753      *
754      * @param name The name of the entity. Parameter entity names start
755      * with '%', whereas the name of a general entity is just
756      * the entity name.
757      * @param identifier An object containing all location information
758      * pertinent to this external entity declaration.
759      * @param augs Additional information that may include infoset
760      * augmentations.
761      * @throws XNIException Thrown by handler to signal an error.
762      */

763     public void externalEntityDecl(String JavaDoc name,
764                                    XMLResourceIdentifier identifier,
765                                    Augmentations augs) throws XNIException {
766
767         int entityIndex = getEntityDeclIndex(name);
768         if( entityIndex == -1){
769             entityIndex = createEntityDecl();
770             boolean isPE = name.startsWith("%");
771             boolean inExternal = fReadingExternalDTD;
772
773             XMLEntityDecl entityDecl = new XMLEntityDecl();
774             entityDecl.setValues(name, identifier.getPublicId(), identifier.getLiteralSystemId(),
775                                 identifier.getBaseSystemId(),
776                                 null, null, isPE, inExternal);
777
778             setEntityDecl(entityIndex, entityDecl);
779         }
780     } // externalEntityDecl(String, XMLResourceIdentifier, Augmentations)
781

782     /**
783      * An unparsed entity declaration.
784      *
785      * @param name The name of the entity.
786      * @param identifier An object containing all location information
787      * pertinent to this entity.
788      * @param notation The name of the notation.
789      * @param augs Additional information that may include infoset
790      * augmentations.
791      * @throws XNIException Thrown by handler to signal an error.
792      */

793     public void unparsedEntityDecl(String JavaDoc name, XMLResourceIdentifier identifier,
794                                    String JavaDoc notation,
795                                    Augmentations augs) throws XNIException {
796
797         XMLEntityDecl entityDecl = new XMLEntityDecl();
798         boolean isPE = name.startsWith("%");
799         boolean inExternal = fReadingExternalDTD;
800
801         entityDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(),
802                             identifier.getBaseSystemId(), notation,
803                             null, isPE, inExternal);
804         int entityIndex = getEntityDeclIndex(name);
805         if (entityIndex == -1) {
806             entityIndex = createEntityDecl();
807             setEntityDecl(entityIndex, entityDecl);
808         }
809
810     } // unparsedEntityDecl(String,StringXMLResourceIdentifier,Augmentations)
811

812     /**
813      * A notation declaration
814      *
815      * @param name The name of the notation.
816      * @param identifier An object containing all location information
817      * pertinent to this notation.
818      * @param augs Additional information that may include infoset
819      * augmentations.
820      * @throws XNIException Thrown by handler to signal an error.
821      */

822     public void notationDecl(String JavaDoc name, XMLResourceIdentifier identifier,
823                              Augmentations augs) throws XNIException {
824
825         XMLNotationDecl notationDecl = new XMLNotationDecl();
826         notationDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(),
827                 identifier.getBaseSystemId());
828         int notationIndex = getNotationDeclIndex(name);
829         if (notationIndex == -1) {
830             notationIndex = createNotationDecl();
831             setNotationDecl(notationIndex, notationDecl);
832         }
833
834     } // notationDecl(String,XMLResourceIdentifier,Augmentations)
835

836     /**
837      * The end of the DTD.
838      *
839      * @param augs Additional information that may include infoset
840      * augmentations.
841      * @throws XNIException Thrown by handler to signal an error.
842      */

843     public void endDTD(Augmentations augs) throws XNIException {
844         fIsImmutable = true;
845         // make sure our description contains useful stuff...
846
if(fGrammarDescription.getRootName() == null) {
847             // we don't know what the root is; so use possibleRoots...
848
int chunk, index = 0;
849             String JavaDoc currName = null;
850             Vector JavaDoc elements = new Vector JavaDoc();
851             for (int i=0; i < fElementDeclCount; i++) {
852                 chunk = i >> CHUNK_SHIFT;
853                 index = i & CHUNK_MASK;
854                 currName = fElementDeclName[chunk][index].rawname;
855                 elements.addElement(currName);
856             }
857             fGrammarDescription.setPossibleRoots(elements);
858         }
859     } // endDTD()
860

861     // sets the source of this handler
862
public void setDTDSource(XMLDTDSource source) {
863         fDTDSource = source;
864     } // setDTDSource(XMLDTDSource)
865

866     // returns the source of this handler
867
public XMLDTDSource getDTDSource() {
868         return fDTDSource;
869     } // getDTDSource(): XMLDTDSource
870

871     // no-op methods
872

873     /**
874      * Notifies of the presence of a TextDecl line in an entity. If present,
875      * this method will be called immediately following the startEntity call.
876      * <p>
877      * <strong>Note:</strong> This method is only called for external
878      * parameter entities referenced in the DTD.
879      *
880      * @param version The XML version, or null if not specified.
881      * @param encoding The IANA encoding name of the entity.
882      *
883      * @param augs Additional information that may include infoset
884      * augmentations.
885      * @throws XNIException Thrown by handler to signal an error.
886      */

887     public void textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs)
888         throws XNIException {}
889
890     /**
891      * A comment.
892      *
893      * @param text The text in the comment.
894      * @param augs Additional information that may include infoset
895      * augmentations.
896      * @throws XNIException Thrown by application to signal an error.
897      */

898     public void comment(XMLString text, Augmentations augs) throws XNIException {}
899
900     /**
901      * A processing instruction. Processing instructions consist of a
902      * target name and, optionally, text data. The data is only meaningful
903      * to the application.
904      * <p>
905      * Typically, a processing instruction's data will contain a series
906      * of pseudo-attributes. These pseudo-attributes follow the form of
907      * element attributes but are <strong>not</strong> parsed or presented
908      * to the application as anything other than text. The application is
909      * responsible for parsing the data.
910      *
911      * @param target The target.
912      * @param data The data or null if none specified.
913      * @param augs Additional information that may include infoset
914      * augmentations.
915      * @throws XNIException Thrown by handler to signal an error.
916      */

917     public void processingInstruction(String JavaDoc target, XMLString data,
918                                       Augmentations augs) throws XNIException {}
919
920     /**
921      * The start of an attribute list.
922      *
923      * @param elementName The name of the element that this attribute
924      * list is associated with.
925      * @param augs Additional information that may include infoset
926      * augmentations.
927      * @throws XNIException Thrown by handler to signal an error.
928      */

929     public void startAttlist(String JavaDoc elementName, Augmentations augs)
930         throws XNIException {}
931
932     /**
933      * The end of an attribute list.
934      * @param augs Additional information that may include infoset
935      * augmentations.
936      * @throws XNIException Thrown by handler to signal an error.
937      */

938     public void endAttlist(Augmentations augs) throws XNIException {}
939
940     /**
941      * The start of a conditional section.
942      *
943      * @param type The type of the conditional section. This value will
944      * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
945      * @param augs Additional information that may include infoset
946      * augmentations.
947      * @throws XNIException Thrown by handler to signal an error.
948      *
949      * @see XMLDTDHandler#CONDITIONAL_INCLUDE
950      * @see XMLDTDHandler#CONDITIONAL_IGNORE
951      */

952     public void startConditional(short type, Augmentations augs)
953         throws XNIException {}
954
955     /**
956      * Characters within an IGNORE conditional section.
957      *
958      * @param text The ignored text.
959      * @param augs Additional information that may include infoset
960      * augmentations.
961      */

962     public void ignoredCharacters(XMLString text, Augmentations augs)
963         throws XNIException {}
964
965     /**
966      * The end of a conditional section.
967      * @param augs Additional information that may include infoset
968      * augmentations.
969      * @throws XNIException Thrown by handler to signal an error.
970      */

971     public void endConditional(Augmentations augs) throws XNIException {}
972
973     //
974
// XMLDTDContentModelHandler methods
975
//
976

977     // set content model source
978
public void setDTDContentModelSource(XMLDTDContentModelSource source) {
979         fDTDContentModelSource = source;
980     }
981
982     // get content model source
983
public XMLDTDContentModelSource getDTDContentModelSource() {
984         return fDTDContentModelSource;
985     }
986
987     /**
988      * The start of a content model. Depending on the type of the content
989      * model, specific methods may be called between the call to the
990      * startContentModel method and the call to the endContentModel method.
991      *
992      * @param elementName The name of the element.
993      * @param augs Additional information that may include infoset
994      * augmentations.
995      * @throws XNIException Thrown by handler to signal an error.
996      */

997     public void startContentModel(String JavaDoc elementName, Augmentations augs)
998         throws XNIException {
999
1000        XMLElementDecl elementDecl = (XMLElementDecl) this.fElementDeclTab.get( elementName);
1001        if ( elementDecl != null ) {
1002            fElementDecl = elementDecl;
1003        }
1004        fDepth = 0;
1005        initializeContentModelStack();
1006
1007    } // startContentModel(String)
1008

1009    /**
1010     * A start of either a mixed or children content model. A mixed
1011     * content model will immediately be followed by a call to the
1012     * <code>pcdata()</code> method. A children content model will
1013     * contain additional groups and/or elements.
1014     *
1015     * @param augs Additional information that may include infoset
1016     * augmentations.
1017     * @throws XNIException Thrown by handler to signal an error.
1018     *
1019     * @see #any
1020     * @see #empty
1021     */

1022    public void startGroup(Augmentations augs) throws XNIException {
1023        fDepth++;
1024        initializeContentModelStack();
1025        fMixed = false;
1026    } // startGroup()
1027

1028    /**
1029     * The appearance of "#PCDATA" within a group signifying a
1030     * mixed content model. This method will be the first called
1031     * following the content model's <code>startGroup()</code>.
1032     *
1033     *@param augs Additional information that may include infoset
1034     * augmentations.
1035     *
1036     * @throws XNIException Thrown by handler to signal an error.
1037     *
1038     * @see #startGroup
1039     */

1040    public void pcdata(Augmentations augs) throws XNIException {
1041        fMixed = true;
1042    } // pcdata()
1043

1044    /**
1045     * A referenced element in a mixed or children content model.
1046     *
1047     * @param elementName The name of the referenced element.
1048     * @param augs Additional information that may include infoset
1049     * augmentations.
1050     *
1051     * @throws XNIException Thrown by handler to signal an error.
1052     */

1053    public void element(String JavaDoc elementName, Augmentations augs) throws XNIException {
1054        if (fMixed) {
1055            if (fNodeIndexStack[fDepth] == -1 ) {
1056                fNodeIndexStack[fDepth] = addUniqueLeafNode(elementName);
1057            }
1058            else {
1059                fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
1060                                                             fNodeIndexStack[fDepth],
1061                                                             addUniqueLeafNode(elementName));
1062            }
1063        }
1064        else {
1065            fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, elementName);
1066        }
1067    } // element(String)
1068

1069    /**
1070     * The separator between choices or sequences of a mixed or children
1071     * content model.
1072     *
1073     * @param separator The type of children separator.
1074     * @param augs Additional information that may include infoset
1075     * augmentations.
1076     * @throws XNIException Thrown by handler to signal an error.
1077     *
1078     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE
1079     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE
1080     */

1081    public void separator(short separator, Augmentations augs) throws XNIException {
1082
1083        if (!fMixed) {
1084            if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_SEQ && separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE ) {
1085                if (fPrevNodeIndexStack[fDepth] != -1) {
1086                    fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
1087                }
1088                fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth];
1089                fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
1090            } else if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_CHOICE && separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) {
1091                if (fPrevNodeIndexStack[fDepth] != -1) {
1092                    fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
1093                }
1094                fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth];
1095                fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
1096            }
1097        }
1098
1099    } // separator(short)
1100

1101    /**
1102     * The occurrence count for a child in a children content model or
1103     * for the mixed content model group.
1104     *
1105     * @param occurrence The occurrence count for the last element
1106     * or group.
1107     * @param augs Additional information that may include infoset
1108     * augmentations.
1109     * @throws XNIException Thrown by handler to signal an error.
1110     *
1111     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE
1112     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE
1113     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE
1114     */

1115    public void occurrence(short occurrence, Augmentations augs) throws XNIException {
1116
1117        if (!fMixed) {
1118            if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE ) {
1119                fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[fDepth], -1);
1120            } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE ) {
1121                fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[fDepth], -1 );
1122            } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) {
1123                fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[fDepth], -1 );
1124            }
1125        }
1126
1127    } // occurrence(short)
1128

1129    /**
1130     * The end of a group for mixed or children content models.
1131     *
1132     * @param augs Additional information that may include infoset
1133     * augmentations.
1134     * @throws XNIException Thrown by handler to signal an error.
1135     */

1136    public void endGroup(Augmentations augs) throws XNIException {
1137
1138        if (!fMixed) {
1139            if (fPrevNodeIndexStack[fDepth] != -1) {
1140                fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
1141            }
1142            int nodeIndex = fNodeIndexStack[fDepth--];
1143            fNodeIndexStack[fDepth] = nodeIndex;
1144        }
1145
1146    } // endGroup()
1147

1148    // no-op methods
1149

1150    /**
1151     * A content model of ANY.
1152     *
1153     * @param augs Additional information that may include infoset
1154     * augmentations.
1155     * @throws XNIException Thrown by handler to signal an error.
1156     *
1157     * @see #empty
1158     * @see #startGroup
1159     */

1160    public void any(Augmentations augs) throws XNIException {}
1161
1162    /**
1163     * A content model of EMPTY.
1164     *
1165     * @param augs Additional information that may include infoset
1166     * augmentations.
1167     * @throws XNIException Thrown by handler to signal an error.
1168     *
1169     * @see #any
1170     * @see #startGroup
1171     */

1172    public void empty(Augmentations augs) throws XNIException {}
1173
1174    /**
1175     * The end of a content model.
1176     * @param augs Additional information that may include infoset
1177     * augmentations.
1178     *
1179     * @throws XNIException Thrown by handler to signal an error.
1180     */

1181    public void endContentModel(Augmentations augs) throws XNIException {}
1182
1183    //
1184
// Grammar methods
1185
//
1186

1187    /** Returns true if this grammar is namespace aware. */
1188    public boolean isNamespaceAware() {
1189        return false;
1190    } // isNamespaceAware():boolean
1191

1192    /** Returns the symbol table. */
1193    public SymbolTable getSymbolTable() {
1194        return fSymbolTable;
1195    } // getSymbolTable():SymbolTable
1196

1197    /**
1198     * Returns the index of the first element declaration. This index
1199     * is then used to query more information about the element declaration.
1200     *
1201     * @see #getNextElementDeclIndex
1202     * @see #getElementDecl
1203     */

1204    public int getFirstElementDeclIndex() {
1205        return fElementDeclCount >= 0 ? 0 : -1;
1206    } // getFirstElementDeclIndex():int
1207

1208    /**
1209     * Returns the next index of the element declaration following the
1210     * specified element declaration.
1211     *
1212     * @param elementDeclIndex The element declaration index.
1213     */

1214    public int getNextElementDeclIndex(int elementDeclIndex) {
1215        return elementDeclIndex < fElementDeclCount - 1
1216             ? elementDeclIndex + 1 : -1;
1217    } // getNextElementDeclIndex(int):int
1218

1219    /**
1220     * getElementDeclIndex
1221     *
1222     * @param elementDeclName
1223     *
1224     * @return index of the elementDeclName in scope
1225     */

1226    public int getElementDeclIndex(String JavaDoc elementDeclName) {
1227        int mapping = fElementIndexMap.get(elementDeclName);
1228        //System.out.println("getElementDeclIndex("+elementDeclName+") -> "+mapping);
1229
return mapping;
1230    } // getElementDeclIndex(String):int
1231

1232    /** Returns the element decl index.
1233     * @param elementDeclQName qualilfied name of the element
1234     */

1235    public int getElementDeclIndex(QName elementDeclQName) {
1236        return getElementDeclIndex(elementDeclQName.rawname);
1237    } // getElementDeclIndex(QName):int
1238

1239        /** make separate function for getting contentSpecType of element.
1240      * we can avoid setting of the element values.
1241        */

1242
1243        public short getContentSpecType(int elementIndex){
1244        if (elementIndex < 0 || elementIndex >= fElementDeclCount) {
1245            return -1 ;
1246        }
1247
1248        int chunk = elementIndex >> CHUNK_SHIFT;
1249        int index = elementIndex & CHUNK_MASK;
1250            
1251        if(fElementDeclType[chunk][index] == -1){
1252            return -1 ;
1253                }
1254        else{
1255                       return (short) (fElementDeclType[chunk][index] & LIST_MASK);
1256                }
1257
1258        }//getContentSpecType
1259

1260    /**
1261     * getElementDecl
1262     *
1263     * @param elementDeclIndex
1264     * @param elementDecl The values of this structure are set by this call.
1265     *
1266     * @return True if find the element, False otherwise.
1267     */

1268    public boolean getElementDecl(int elementDeclIndex,
1269                                  XMLElementDecl elementDecl) {
1270
1271        if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1272            return false;
1273        }
1274
1275        int chunk = elementDeclIndex >> CHUNK_SHIFT;
1276        int index = elementDeclIndex & CHUNK_MASK;
1277
1278        elementDecl.name.setValues(fElementDeclName[chunk][index]);
1279
1280        if (fElementDeclType[chunk][index] == -1) {
1281            elementDecl.type = -1;
1282            elementDecl.simpleType.list = false;
1283        } else {
1284            elementDecl.type = (short) (fElementDeclType[chunk][index] & LIST_MASK);
1285            elementDecl.simpleType.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0;
1286        }
1287
1288        /* Validators are null until we add that code */
1289        if (elementDecl.type == XMLElementDecl.TYPE_CHILDREN || elementDecl.type == XMLElementDecl.TYPE_MIXED) {
1290            elementDecl.contentModelValidator = getElementContentModelValidator(elementDeclIndex);
1291        }
1292              
1293        elementDecl.simpleType.datatypeValidator = null;
1294        elementDecl.simpleType.defaultType = -1;
1295        elementDecl.simpleType.defaultValue = null;
1296
1297        return true;
1298
1299    } // getElementDecl(int,XMLElementDecl):boolean
1300

1301    // REVISIT: Make this getAttributeDeclCount/getAttributeDeclAt. -Ac
1302

1303    /**
1304     * getFirstAttributeDeclIndex
1305     *
1306     * @param elementDeclIndex
1307     *
1308     * @return index of the first attribute for element declaration elementDeclIndex
1309     */

1310    public int getFirstAttributeDeclIndex(int elementDeclIndex) {
1311        int chunk = elementDeclIndex >> CHUNK_SHIFT;
1312        int index = elementDeclIndex & CHUNK_MASK;
1313
1314        return fElementDeclFirstAttributeDeclIndex[chunk][index];
1315    } // getFirstAttributeDeclIndex
1316

1317    /**
1318     * getNextAttributeDeclIndex
1319     *
1320     * @param attributeDeclIndex
1321     *
1322     * @return index of the next attribute of the attribute at attributeDeclIndex
1323     */

1324    public int getNextAttributeDeclIndex(int attributeDeclIndex) {
1325        int chunk = attributeDeclIndex >> CHUNK_SHIFT;
1326        int index = attributeDeclIndex & CHUNK_MASK;
1327
1328        return fAttributeDeclNextAttributeDeclIndex[chunk][index];
1329    } // getNextAttributeDeclIndex
1330

1331    /**
1332     * getAttributeDecl
1333     *
1334     * @param attributeDeclIndex
1335     * @param attributeDecl The values of this structure are set by this call.
1336     *
1337     * @return true if getAttributeDecl was able to fill in the value of attributeDecl
1338     */

1339    public boolean getAttributeDecl(int attributeDeclIndex, XMLAttributeDecl attributeDecl) {
1340        if (attributeDeclIndex < 0 || attributeDeclIndex >= fAttributeDeclCount) {
1341            return false;
1342        }
1343        int chunk = attributeDeclIndex >> CHUNK_SHIFT;
1344        int index = attributeDeclIndex & CHUNK_MASK;
1345
1346        attributeDecl.name.setValues(fAttributeDeclName[chunk][index]);
1347
1348        short attributeType;
1349        boolean isList;
1350
1351        if (fAttributeDeclType[chunk][index] == -1) {
1352
1353            attributeType = -1;
1354            isList = false;
1355        } else {
1356            attributeType = (short) (fAttributeDeclType[chunk][index] & LIST_MASK);
1357            isList = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0;
1358        }
1359        attributeDecl.simpleType.setValues(attributeType,fAttributeDeclName[chunk][index].localpart,
1360                                           fAttributeDeclEnumeration[chunk][index],
1361                                           isList, fAttributeDeclDefaultType[chunk][index],
1362                                           fAttributeDeclDefaultValue[chunk][index],
1363                                           fAttributeDeclNonNormalizedDefaultValue[chunk][index],
1364                                           fAttributeDeclDatatypeValidator[chunk][index]);
1365        return true;
1366
1367    } // getAttributeDecl
1368

1369
1370    /**
1371     * Returns whether the given attribute is of type CDATA or not
1372     *
1373     * @param elName The element name.
1374     * @param atName The attribute name.
1375     *
1376     * @return true if the attribute is of type CDATA
1377     */

1378    public boolean isCDATAAttribute(QName elName, QName atName) {
1379        int elDeclIdx = getElementDeclIndex(elName);
1380        int atDeclIdx = getAttributeDeclIndex(elDeclIdx, atName.rawname);
1381        if (getAttributeDecl(elDeclIdx, fAttributeDecl)
1382            && fAttributeDecl.simpleType.type != XMLSimpleType.TYPE_CDATA){
1383            return false;
1384        }
1385        return true;
1386    }
1387
1388    /**
1389     * getEntityDeclIndex
1390     *
1391     * @param entityDeclName
1392     *
1393     * @return the index of the EntityDecl
1394     */

1395    public int getEntityDeclIndex(String JavaDoc entityDeclName) {
1396        if (entityDeclName == null) {
1397            return -1;
1398        }
1399
1400        return fEntityIndexMap.get(entityDeclName);
1401    } // getEntityDeclIndex
1402

1403    /**
1404     * getEntityDecl
1405     *
1406     * @param entityDeclIndex
1407     * @param entityDecl
1408     *
1409     * @return true if getEntityDecl was able to fill entityDecl with the contents of the entity
1410     * with index entityDeclIndex
1411     */

1412    public boolean getEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) {
1413        if (entityDeclIndex < 0 || entityDeclIndex >= fEntityCount) {
1414            return false;
1415        }
1416        int chunk = entityDeclIndex >> CHUNK_SHIFT;
1417        int index = entityDeclIndex & CHUNK_MASK;
1418
1419        entityDecl.setValues(fEntityName[chunk][index],
1420                             fEntityPublicId[chunk][index],
1421                             fEntitySystemId[chunk][index],
1422                             fEntityBaseSystemId[chunk][index],
1423                             fEntityNotation[chunk][index],
1424                             fEntityValue[chunk][index],
1425                             fEntityIsPE[chunk][index] == 0 ? false : true ,
1426                             fEntityInExternal[chunk][index] == 0 ? false : true );
1427
1428        return true;
1429    } // getEntityDecl
1430

1431    /**
1432     * getNotationDeclIndex
1433     *
1434     * @param notationDeclName
1435     *
1436     * @return the index if found a notation with the name, otherwise -1.
1437     */

1438    public int getNotationDeclIndex(String JavaDoc notationDeclName) {
1439        if (notationDeclName == null) {
1440            return -1;
1441        }
1442
1443        return fNotationIndexMap.get(notationDeclName);
1444    } // getNotationDeclIndex
1445

1446    /**
1447     * getNotationDecl
1448     *
1449     * @param notationDeclIndex
1450     * @param notationDecl
1451     *
1452     * @return return true of getNotationDecl can fill notationDecl with information about
1453     * the notation at notationDeclIndex.
1454     */

1455    public boolean getNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) {
1456        if (notationDeclIndex < 0 || notationDeclIndex >= fNotationCount) {
1457            return false;
1458        }
1459        int chunk = notationDeclIndex >> CHUNK_SHIFT;
1460        int index = notationDeclIndex & CHUNK_MASK;
1461
1462        notationDecl.setValues(fNotationName[chunk][index],
1463                               fNotationPublicId[chunk][index],
1464                               fNotationSystemId[chunk][index],
1465                               fNotationBaseSystemId[chunk][index]);
1466
1467        return true;
1468
1469    } // getNotationDecl
1470

1471    /**
1472     * getContentSpec
1473     *
1474     * @param contentSpecIndex
1475     * @param contentSpec
1476     *
1477     * @return true if find the requested contentSpec node, false otherwise
1478     */

1479    public boolean getContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) {
1480        if (contentSpecIndex < 0 || contentSpecIndex >= fContentSpecCount )
1481            return false;
1482
1483        int chunk = contentSpecIndex >> CHUNK_SHIFT;
1484        int index = contentSpecIndex & CHUNK_MASK;
1485
1486        contentSpec.type = fContentSpecType[chunk][index];
1487        contentSpec.value = fContentSpecValue[chunk][index];
1488        contentSpec.otherValue = fContentSpecOtherValue[chunk][index];
1489        return true;
1490    }
1491
1492    /**
1493     * getContentSpecAsString
1494     *
1495     * @param elementDeclIndex
1496     *
1497     * @return String
1498     */

1499    public String JavaDoc getContentSpecAsString(int elementDeclIndex){
1500
1501        if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1502            return null;
1503        }
1504
1505        int chunk = elementDeclIndex >> CHUNK_SHIFT;
1506        int index = elementDeclIndex & CHUNK_MASK;
1507
1508        int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
1509
1510        // lookup content spec node
1511
XMLContentSpec contentSpec = new XMLContentSpec();
1512
1513        if (getContentSpec(contentSpecIndex, contentSpec)) {
1514
1515            // build string
1516
StringBuffer JavaDoc str = new StringBuffer JavaDoc();
1517            int parentContentSpecType = contentSpec.type & 0x0f;
1518            int nextContentSpec;
1519            switch (parentContentSpecType) {
1520                case XMLContentSpec.CONTENTSPECNODE_LEAF: {
1521                    str.append('(');
1522                    if (contentSpec.value == null && contentSpec.otherValue == null) {
1523                        str.append("#PCDATA");
1524                    }
1525                    else {
1526                        str.append(contentSpec.value);
1527                    }
1528                    str.append(')');
1529                    break;
1530                }
1531                case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
1532                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
1533                    nextContentSpec = contentSpec.type;
1534
1535                    if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1536                        str.append('(');
1537                        str.append(contentSpec.value);
1538                        str.append(')');
1539                    } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
1540                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
1541                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
1542                        str.append('(' );
1543                        appendContentSpec(contentSpec, str,
1544                                          true, parentContentSpecType );
1545                        str.append(')');
1546                    } else {
1547                        appendContentSpec(contentSpec, str,
1548                                          true, parentContentSpecType );
1549                    }
1550                    str.append('?');
1551                    break;
1552                }
1553                case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
1554                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
1555                    nextContentSpec = contentSpec.type;
1556
1557                    if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1558                        str.append('(');
1559                        if (contentSpec.value == null && contentSpec.otherValue == null) {
1560                            str.append("#PCDATA");
1561                        }
1562                        else if (contentSpec.otherValue != null) {
1563                            str.append("##any:uri="+contentSpec.otherValue);
1564                        }
1565                        else if (contentSpec.value == null) {
1566                            str.append("##any");
1567                        }
1568                        else {
1569                            appendContentSpec(contentSpec, str,
1570                                              true, parentContentSpecType );
1571                        }
1572                        str.append(')');
1573                    } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
1574                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
1575                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
1576                        str.append('(' );
1577                        appendContentSpec(contentSpec, str,
1578                                          true, parentContentSpecType );
1579                        str.append(')');
1580                    } else {
1581                        appendContentSpec(contentSpec, str,
1582                                          true, parentContentSpecType );
1583                    }
1584                    str.append('*');
1585                    break;
1586                }
1587                case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
1588                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
1589                    nextContentSpec = contentSpec.type;
1590
1591                    if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1592                        str.append('(');
1593                        if (contentSpec.value == null && contentSpec.otherValue == null) {
1594                            str.append("#PCDATA");
1595                        }
1596                        else if (contentSpec.otherValue != null) {
1597                            str.append("##any:uri="+contentSpec.otherValue);
1598                        }
1599                        else if (contentSpec.value == null) {
1600                            str.append("##any");
1601                        }
1602                        else {
1603                            str.append(contentSpec.value);
1604                        }
1605                        str.append(')');
1606                    } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
1607                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
1608                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
1609                        str.append('(' );
1610                        appendContentSpec(contentSpec, str,
1611                                          true, parentContentSpecType );
1612                        str.append(')');
1613                    } else {
1614                        appendContentSpec(contentSpec, str,
1615                                          true, parentContentSpecType);
1616                    }
1617                    str.append('+');
1618                    break;
1619                }
1620                case XMLContentSpec.CONTENTSPECNODE_CHOICE:
1621                case XMLContentSpec.CONTENTSPECNODE_SEQ: {
1622                    appendContentSpec(contentSpec, str,
1623                                      true, parentContentSpecType );
1624                    break;
1625                }
1626                case XMLContentSpec.CONTENTSPECNODE_ANY: {
1627                    str.append("##any");
1628                    if (contentSpec.otherValue != null) {
1629                        str.append(":uri=");
1630                        str.append(contentSpec.otherValue);
1631                    }
1632                    break;
1633                }
1634                case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: {
1635                    str.append("##other:uri=");
1636                    str.append(contentSpec.otherValue);
1637                    break;
1638                }
1639                case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: {
1640                    str.append("##local");
1641                    break;
1642                }
1643                default: {
1644                    str.append("???");
1645                }
1646
1647            } // switch type
1648

1649            // return string
1650
return str.toString();
1651        }
1652
1653        // not found
1654
return null;
1655
1656    } // getContentSpecAsString(int):String
1657

1658    // debugging
1659

1660    public void printElements( ) {
1661        int elementDeclIndex = 0;
1662        XMLElementDecl elementDecl = new XMLElementDecl();
1663        while (getElementDecl(elementDeclIndex++, elementDecl)) {
1664
1665            System.out.println("element decl: "+elementDecl.name+
1666                               ", "+ elementDecl.name.rawname );
1667
1668            // ", "+ elementDecl.contentModelValidator.toString());
1669
}
1670    }
1671
1672    public void printAttributes(int elementDeclIndex) {
1673        int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex);
1674        System.out.print(elementDeclIndex);
1675        System.out.print(" [");
1676        while (attributeDeclIndex != -1) {
1677            System.out.print(' ');
1678            System.out.print(attributeDeclIndex);
1679            printAttribute(attributeDeclIndex);
1680            attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex);
1681            if (attributeDeclIndex != -1) {
1682                System.out.print(",");
1683            }
1684        }
1685        System.out.println(" ]");
1686    }
1687
1688    //
1689
// Protected methods
1690
//
1691

1692    /**
1693     * getElementContentModelValidator
1694     *
1695     * @param elementDeclIndex
1696     *
1697     * @return its ContentModelValidator if any.
1698     */

1699    protected ContentModelValidator getElementContentModelValidator(int elementDeclIndex) {
1700
1701        int chunk = elementDeclIndex >> CHUNK_SHIFT;
1702        int index = elementDeclIndex & CHUNK_MASK;
1703
1704        ContentModelValidator contentModel = fElementDeclContentModelValidator[chunk][index];
1705
1706        // If we have one, just return that. Otherwise, gotta create one
1707
if (contentModel != null) {
1708            return contentModel;
1709        }
1710
1711        int contentType = fElementDeclType[chunk][index];
1712        if (contentType == XMLElementDecl.TYPE_SIMPLE) {
1713            return null;
1714        }
1715
1716        // Get the type of content this element has
1717
int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
1718
1719        /***
1720        if ( contentSpecIndex == -1 )
1721            return null;
1722        /***/

1723
1724        XMLContentSpec contentSpec = new XMLContentSpec();
1725        getContentSpec( contentSpecIndex, contentSpec );
1726
1727        // And create the content model according to the spec type
1728
if ( contentType == XMLElementDecl.TYPE_MIXED ) {
1729            //
1730
// Just create a mixel content model object. This type of
1731
// content model is optimized for mixed content validation.
1732
//
1733
ChildrenList children = new ChildrenList();
1734            contentSpecTree(contentSpecIndex, contentSpec, children);
1735            contentModel = new MixedContentModel(children.qname,
1736                                                 children.type,
1737                                                 0, children.length,
1738                                                 false);
1739        } else if (contentType == XMLElementDecl.TYPE_CHILDREN) {
1740            // This method will create an optimal model for the complexity
1741
// of the element's defined model. If its simple, it will create
1742
// a SimpleContentModel object. If its a simple list, it will
1743
// create a SimpleListContentModel object. If its complex, it
1744
// will create a DFAContentModel object.
1745
//
1746
contentModel = createChildModel(contentSpecIndex);
1747        } else {
1748            throw new RuntimeException JavaDoc("Unknown content type for a element decl "
1749                                     + "in getElementContentModelValidator() in AbstractDTDGrammar class");
1750        }
1751
1752        // Add the new model to the content model for this element
1753
fElementDeclContentModelValidator[chunk][index] = contentModel;
1754
1755        return contentModel;
1756
1757    } // getElementContentModelValidator(int):ContentModelValidator
1758

1759   protected int createElementDecl() {
1760      int chunk = fElementDeclCount >> CHUNK_SHIFT;
1761      int index = fElementDeclCount & CHUNK_MASK;
1762      ensureElementDeclCapacity(chunk);
1763      fElementDeclName[chunk][index] = new QName();
1764      fElementDeclType[chunk][index] = -1;
1765      fElementDeclContentModelValidator[chunk][index] = null;
1766      fElementDeclFirstAttributeDeclIndex[chunk][index] = -1;
1767      fElementDeclLastAttributeDeclIndex[chunk][index] = -1;
1768      return fElementDeclCount++;
1769   }
1770
1771   protected void setElementDecl(int elementDeclIndex, XMLElementDecl elementDecl) {
1772      if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1773         return;
1774      }
1775      int chunk = elementDeclIndex >> CHUNK_SHIFT;
1776      int index = elementDeclIndex & CHUNK_MASK;
1777
1778      int scope = elementDecl.scope;
1779
1780
1781      fElementDeclName[chunk][index].setValues(elementDecl.name);
1782      fElementDeclType[chunk][index] = elementDecl.type;
1783
1784      fElementDeclContentModelValidator[chunk][index] = elementDecl.contentModelValidator;
1785         
1786
1787      if (elementDecl.simpleType.list == true ) {
1788         fElementDeclType[chunk][index] |= LIST_FLAG;
1789      }
1790
1791      fElementIndexMap.put(elementDecl.name.rawname, elementDeclIndex);
1792   }
1793
1794
1795
1796
1797   protected void putElementNameMapping(QName name, int scope,
1798                                        int elementDeclIndex) {
1799   }
1800
1801   protected void setFirstAttributeDeclIndex(int elementDeclIndex, int newFirstAttrIndex){
1802
1803      if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1804         return;
1805      }
1806
1807      int chunk = elementDeclIndex >> CHUNK_SHIFT;
1808      int index = elementDeclIndex & CHUNK_MASK;
1809
1810      fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex;
1811   }
1812   
1813   protected void setContentSpecIndex(int elementDeclIndex, int contentSpecIndex){
1814
1815      if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1816         return;
1817      }
1818
1819      int chunk = elementDeclIndex >> CHUNK_SHIFT;
1820      int index = elementDeclIndex & CHUNK_MASK;
1821
1822      fElementDeclContentSpecIndex[chunk][index] = contentSpecIndex;
1823   }
1824
1825
1826   protected int createAttributeDecl() {
1827      int chunk = fAttributeDeclCount >> CHUNK_SHIFT;
1828      int index = fAttributeDeclCount & CHUNK_MASK;
1829
1830      ensureAttributeDeclCapacity(chunk);
1831      fAttributeDeclName[chunk][index] = new QName();
1832      fAttributeDeclType[chunk][index] = -1;
1833      fAttributeDeclDatatypeValidator[chunk][index] = null;
1834      fAttributeDeclEnumeration[chunk][index] = null;
1835      fAttributeDeclDefaultType[chunk][index] = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
1836      fAttributeDeclDefaultValue[chunk][index] = null;
1837      fAttributeDeclNonNormalizedDefaultValue[chunk][index] = null;
1838      fAttributeDeclNextAttributeDeclIndex[chunk][index] = -1;
1839      return fAttributeDeclCount++;
1840   }
1841
1842
1843   protected void setAttributeDecl(int elementDeclIndex, int attributeDeclIndex,
1844                                   XMLAttributeDecl attributeDecl) {
1845      int attrChunk = attributeDeclIndex >> CHUNK_SHIFT;
1846      int attrIndex = attributeDeclIndex & CHUNK_MASK;
1847      fAttributeDeclName[attrChunk][attrIndex].setValues(attributeDecl.name);
1848      fAttributeDeclType[attrChunk][attrIndex] = attributeDecl.simpleType.type;
1849
1850      if (attributeDecl.simpleType.list) {
1851         fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG;
1852      }
1853      fAttributeDeclEnumeration[attrChunk][attrIndex] = attributeDecl.simpleType.enumeration;
1854      fAttributeDeclDefaultType[attrChunk][attrIndex] = attributeDecl.simpleType.defaultType;
1855      fAttributeDeclDatatypeValidator[attrChunk][attrIndex] = attributeDecl.simpleType.datatypeValidator;
1856
1857      fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.defaultValue;
1858      fAttributeDeclNonNormalizedDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.nonNormalizedDefaultValue;
1859
1860      int elemChunk = elementDeclIndex >> CHUNK_SHIFT;
1861      int elemIndex = elementDeclIndex & CHUNK_MASK;
1862      int index = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex];
1863      while (index != -1) {
1864         if (index == attributeDeclIndex) {
1865            break;
1866         }
1867         attrChunk = index >> CHUNK_SHIFT;
1868         attrIndex = index & CHUNK_MASK;
1869         index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex];
1870      }
1871      if (index == -1) {
1872         if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) {
1873            fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
1874         } else {
1875            index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex];
1876            attrChunk = index >> CHUNK_SHIFT;
1877            attrIndex = index & CHUNK_MASK;
1878            fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex;
1879         }
1880         fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
1881      }
1882   }
1883
1884   protected int createContentSpec() {
1885      int chunk = fContentSpecCount >> CHUNK_SHIFT;
1886      int index = fContentSpecCount & CHUNK_MASK;
1887
1888      ensureContentSpecCapacity(chunk);
1889      fContentSpecType[chunk][index] = -1;
1890      fContentSpecValue[chunk][index] = null;
1891      fContentSpecOtherValue[chunk][index] = null;
1892
1893      return fContentSpecCount++;
1894   }
1895
1896   protected void setContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) {
1897      int chunk = contentSpecIndex >> CHUNK_SHIFT;
1898      int index = contentSpecIndex & CHUNK_MASK;
1899
1900      fContentSpecType[chunk][index] = contentSpec.type;
1901      fContentSpecValue[chunk][index] = contentSpec.value;
1902      fContentSpecOtherValue[chunk][index] = contentSpec.otherValue;
1903   }
1904
1905
1906   protected int createEntityDecl() {
1907       int chunk = fEntityCount >> CHUNK_SHIFT;
1908       int index = fEntityCount & CHUNK_MASK;
1909
1910      ensureEntityDeclCapacity(chunk);
1911      fEntityIsPE[chunk][index] = 0;
1912      fEntityInExternal[chunk][index] = 0;
1913
1914      return fEntityCount++;
1915   }
1916
1917   protected void setEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) {
1918       int chunk = entityDeclIndex >> CHUNK_SHIFT;
1919       int index = entityDeclIndex & CHUNK_MASK;
1920
1921       fEntityName[chunk][index] = entityDecl.name;
1922       fEntityValue[chunk][index] = entityDecl.value;
1923       fEntityPublicId[chunk][index] = entityDecl.publicId;
1924       fEntitySystemId[chunk][index] = entityDecl.systemId;
1925       fEntityBaseSystemId[chunk][index] = entityDecl.baseSystemId;
1926       fEntityNotation[chunk][index] = entityDecl.notation;
1927       fEntityIsPE[chunk][index] = entityDecl.isPE ? (byte)1 : (byte)0;
1928       fEntityInExternal[chunk][index] = entityDecl.inExternal ? (byte)1 : (byte)0;
1929
1930       fEntityIndexMap.put(entityDecl.name, entityDeclIndex);
1931   }
1932   
1933
1934   protected int createNotationDecl() {
1935       int chunk = fNotationCount >> CHUNK_SHIFT;
1936       int index = fNotationCount & CHUNK_MASK;
1937
1938       ensureNotationDeclCapacity(chunk);
1939
1940       return fNotationCount++;
1941   }
1942
1943   protected void setNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) {
1944       int chunk = notationDeclIndex >> CHUNK_SHIFT;
1945       int index = notationDeclIndex & CHUNK_MASK;
1946
1947       fNotationName[chunk][index] = notationDecl.name;
1948       fNotationPublicId[chunk][index] = notationDecl.publicId;
1949       fNotationSystemId[chunk][index] = notationDecl.systemId;
1950       fNotationBaseSystemId[chunk][index] = notationDecl.baseSystemId;
1951
1952       fNotationIndexMap.put(notationDecl.name, notationDeclIndex);
1953   }
1954
1955    /**
1956     * Create an XMLContentSpec for a single non-leaf
1957     *
1958     * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
1959     * @param nodeValue handle to an XMLContentSpec
1960     * @return handle to the newly create XMLContentSpec
1961     */

1962    protected int addContentSpecNode(short nodeType, String JavaDoc nodeValue) {
1963
1964        // create content spec node
1965
int contentSpecIndex = createContentSpec();
1966
1967        // set content spec node values
1968
fContentSpec.setValues(nodeType, nodeValue, null);
1969        setContentSpec(contentSpecIndex, fContentSpec);
1970
1971        // return index
1972
return contentSpecIndex;
1973
1974    } // addContentSpecNode(short,String):int
1975

1976    /**
1977     * create an XMLContentSpec for a leaf
1978     *
1979     * @param elementName the name (Element) for the node
1980     * @return handle to the newly create XMLContentSpec
1981     */

1982    protected int addUniqueLeafNode(String JavaDoc elementName) {
1983
1984        // create content spec node
1985
int contentSpecIndex = createContentSpec();
1986
1987        // set content spec node values
1988
fContentSpec.setValues( XMLContentSpec.CONTENTSPECNODE_LEAF,
1989                                elementName, null);
1990        setContentSpec(contentSpecIndex, fContentSpec);
1991
1992        // return index
1993
return contentSpecIndex;
1994
1995    } // addUniqueLeafNode(String):int
1996

1997    /**
1998     * Create an XMLContentSpec for a two child leaf
1999     *
2000     * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
2001     * @param leftNodeIndex handle to an XMLContentSpec
2002     * @param rightNodeIndex handle to an XMLContentSpec
2003     * @return handle to the newly create XMLContentSpec
2004     */

2005    protected int addContentSpecNode(short nodeType,
2006                                     int leftNodeIndex, int rightNodeIndex) {
2007
2008        // create content spec node
2009
int contentSpecIndex = createContentSpec();
2010
2011        // set content spec node values
2012
int[] leftIntArray = new int[1];
2013        int[] rightIntArray = new int[1];
2014
2015        leftIntArray[0] = leftNodeIndex;
2016        rightIntArray[0] = rightNodeIndex;
2017        fContentSpec.setValues(nodeType, leftIntArray, rightIntArray);
2018        setContentSpec(contentSpecIndex, fContentSpec);
2019
2020        // return index
2021
return contentSpecIndex;
2022
2023    } // addContentSpecNode(short,int,int):int
2024

2025    /** Initialize content model stack. */
2026    protected void initializeContentModelStack() {
2027
2028        if (fOpStack == null) {
2029            fOpStack = new short[8];
2030            fNodeIndexStack = new int[8];
2031            fPrevNodeIndexStack = new int[8];
2032        } else if (fDepth == fOpStack.length) {
2033            short[] newStack = new short[fDepth * 2];
2034            System.arraycopy(fOpStack, 0, newStack, 0, fDepth);
2035            fOpStack = newStack;
2036            int[] newIntStack = new int[fDepth * 2];
2037            System.arraycopy(fNodeIndexStack, 0, newIntStack, 0, fDepth);
2038            fNodeIndexStack = newIntStack;
2039            newIntStack = new int[fDepth * 2];
2040            System.arraycopy(fPrevNodeIndexStack, 0, newIntStack, 0, fDepth);
2041            fPrevNodeIndexStack = newIntStack;
2042        }
2043        fOpStack[fDepth] = -1;
2044        fNodeIndexStack[fDepth] = -1;
2045        fPrevNodeIndexStack[fDepth] = -1;
2046
2047    } // initializeContentModelStack()
2048

2049    boolean isImmutable() {
2050        return fIsImmutable;
2051    }
2052
2053    //
2054
// Private methods
2055
//
2056

2057    private void appendContentSpec(XMLContentSpec contentSpec,
2058                                   StringBuffer JavaDoc str, boolean parens,
2059                                   int parentContentSpecType ) {
2060
2061        int thisContentSpec = contentSpec.type & 0x0f;
2062        switch (thisContentSpec) {
2063            case XMLContentSpec.CONTENTSPECNODE_LEAF: {
2064                if (contentSpec.value == null && contentSpec.otherValue == null) {
2065                    str.append("#PCDATA");
2066                }
2067                else if (contentSpec.value == null && contentSpec.otherValue != null) {
2068                    str.append("##any:uri="+contentSpec.otherValue);
2069                }
2070                else if (contentSpec.value == null) {
2071                    str.append("##any");
2072                }
2073                else {
2074                    str.append(contentSpec.value);
2075                }
2076                break;
2077            }
2078            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
2079                if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
2080                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2081                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
2082                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2083                    str.append('(');
2084                    appendContentSpec(contentSpec, str, true, thisContentSpec );
2085                    str.append(')');
2086                }
2087                else {
2088                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2089                    appendContentSpec( contentSpec, str, true, thisContentSpec );
2090                }
2091                str.append('?');
2092                break;
2093            }
2094            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
2095                if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
2096                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2097                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
2098                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2099                    str.append('(');
2100                    appendContentSpec(contentSpec, str, true, thisContentSpec);
2101                    str.append(')' );
2102                }
2103                else {
2104                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2105                    appendContentSpec(contentSpec, str, true, thisContentSpec);
2106                }
2107                str.append('*');
2108                break;
2109            }
2110            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
2111                if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
2112                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2113                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
2114
2115                    str.append('(');
2116                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2117                    appendContentSpec(contentSpec, str, true, thisContentSpec);
2118                    str.append(')' );
2119                }
2120                else {
2121                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2122                    appendContentSpec(contentSpec, str, true, thisContentSpec);
2123                }
2124                str.append('+');
2125                break;
2126            }
2127            case XMLContentSpec.CONTENTSPECNODE_CHOICE:
2128            case XMLContentSpec.CONTENTSPECNODE_SEQ: {
2129                if (parens) {
2130                    str.append('(');
2131                }
2132                int type = contentSpec.type;
2133                int otherValue = ((int[])contentSpec.otherValue)[0];
2134                getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2135                appendContentSpec(contentSpec, str, contentSpec.type != type, thisContentSpec);
2136                if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) {
2137                    str.append('|');
2138                }
2139                else {
2140                    str.append(',');
2141                }
2142                getContentSpec(otherValue, contentSpec);
2143                appendContentSpec(contentSpec, str, true, thisContentSpec);
2144                if (parens) {
2145                    str.append(')');
2146                }
2147                break;
2148            }
2149            case XMLContentSpec.CONTENTSPECNODE_ANY: {
2150                str.append("##any");
2151                if (contentSpec.otherValue != null) {
2152                    str.append(":uri=");
2153                    str.append(contentSpec.otherValue);
2154                }
2155                break;
2156            }
2157            case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: {
2158                str.append("##other:uri=");
2159                str.append(contentSpec.otherValue);
2160                break;
2161            }
2162            case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: {
2163                str.append("##local");
2164                break;
2165            }
2166            default: {
2167                str.append("???");
2168                break;
2169            }
2170
2171        } // switch type
2172

2173    } // appendContentSpec(XMLContentSpec.Provider,StringPool,XMLContentSpec,StringBuffer,boolean)
2174

2175    // debugging
2176

2177    private void printAttribute(int attributeDeclIndex) {
2178
2179        XMLAttributeDecl attributeDecl = new XMLAttributeDecl();
2180        if (getAttributeDecl(attributeDeclIndex, attributeDecl)) {
2181            System.out.print(" { ");
2182            System.out.print(attributeDecl.name.localpart);
2183            System.out.print(" }");
2184        }
2185
2186    } // printAttribute(int)
2187

2188    // content models
2189

2190    /**
2191     * When the element has a 'CHILDREN' model, this method is called to
2192     * create the content model object. It looks for some special case simple
2193     * models and creates SimpleContentModel objects for those. For the rest
2194     * it creates the standard DFA style model.
2195     */

2196    private ContentModelValidator createChildModel(int contentSpecIndex) {
2197        
2198        //
2199
// Get the content spec node for the element we are working on.
2200
// This will tell us what kind of node it is, which tells us what
2201
// kind of model we will try to create.
2202
//
2203
XMLContentSpec contentSpec = new XMLContentSpec();
2204        getContentSpec(contentSpecIndex, contentSpec);
2205
2206        if ((contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY ||
2207            (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER ||
2208            (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
2209            // let fall through to build a DFAContentModel
2210
}
2211
2212        else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2213            //
2214
// Check that the left value is not -1, since any content model
2215
// with PCDATA should be MIXED, so we should not have gotten here.
2216
//
2217
if (contentSpec.value == null && contentSpec.otherValue == null)
2218                throw new RuntimeException JavaDoc("ImplementationMessages.VAL_NPCD");
2219
2220            //
2221
// Its a single leaf, so its an 'a' type of content model, i.e.
2222
// just one instance of one element. That one is definitely a
2223
// simple content model.
2224
//
2225

2226            fQName.setValues(null, (String JavaDoc)contentSpec.value,
2227                              (String JavaDoc)contentSpec.value, (String JavaDoc)contentSpec.otherValue);
2228            return new SimpleContentModel(contentSpec.type, fQName, null);
2229        } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
2230                    || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
2231            //
2232
// Lets see if both of the children are leafs. If so, then it
2233
// it has to be a simple content model
2234
//
2235
XMLContentSpec contentSpecLeft = new XMLContentSpec();
2236            XMLContentSpec contentSpecRight = new XMLContentSpec();
2237
2238            getContentSpec( ((int[])contentSpec.value)[0], contentSpecLeft);
2239            getContentSpec( ((int[])contentSpec.otherValue)[0], contentSpecRight);
2240
2241            if ((contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
2242                 && (contentSpecRight.type == XMLContentSpec.CONTENTSPECNODE_LEAF)) {
2243                //
2244
// Its a simple choice or sequence, so we can do a simple
2245
// content model for it.
2246
//
2247
fQName.setValues(null, (String JavaDoc)contentSpecLeft.value,
2248                                  (String JavaDoc)contentSpecLeft.value, (String JavaDoc)contentSpecLeft.otherValue);
2249                fQName2.setValues(null, (String JavaDoc)contentSpecRight.value,
2250                                  (String JavaDoc)contentSpecRight.value, (String JavaDoc)contentSpecRight.otherValue);
2251                return new SimpleContentModel(contentSpec.type, fQName, fQName2);
2252            }
2253        } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE)
2254                    || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE)
2255                    || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE)) {
2256            //
2257
// Its a repetition, so see if its one child is a leaf. If so
2258
// its a repetition of a single element, so we can do a simple
2259
// content model for that.
2260
//
2261
XMLContentSpec contentSpecLeft = new XMLContentSpec();
2262            getContentSpec(((int[])contentSpec.value)[0], contentSpecLeft);
2263    
2264            if (contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2265                //
2266
// It is, so we can create a simple content model here that
2267
// will check for this repetition. We pass -1 for the unused
2268
// right node.
2269
//
2270
fQName.setValues(null, (String JavaDoc)contentSpecLeft.value,
2271                                  (String JavaDoc)contentSpecLeft.value, (String JavaDoc)contentSpecLeft.otherValue);
2272                return new SimpleContentModel(contentSpec.type, fQName, null);
2273            }
2274        } else {
2275            throw new RuntimeException JavaDoc("ImplementationMessages.VAL_CST");
2276        }
2277
2278        //
2279
// Its not a simple content model, so here we have to create a DFA
2280
// for this element. So we create a DFAContentModel object. He
2281
// encapsulates all of the work to create the DFA.
2282
//
2283

2284        fLeafCount = 0;
2285        //int leafCount = countLeaves(contentSpecIndex);
2286
fLeafCount = 0;
2287        CMNode cmn = buildSyntaxTree(contentSpecIndex, contentSpec);
2288
2289        // REVISIT: has to be fLeafCount because we convert x+ to x,x*, one more leaf
2290
return new DFAContentModel( cmn, fLeafCount, false);
2291
2292    } // createChildModel(int):ContentModelValidator
2293

2294    private final CMNode buildSyntaxTree(int startNode,
2295                                         XMLContentSpec contentSpec) {
2296
2297        // We will build a node at this level for the new tree
2298
CMNode nodeRet = null;
2299        getContentSpec(startNode, contentSpec);
2300        if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY) {
2301            //nodeRet = new CMAny(contentSpec.type, -1, fLeafCount++);
2302
nodeRet = new CMAny(contentSpec.type, (String JavaDoc)contentSpec.otherValue, fLeafCount++);
2303        }
2304        else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
2305            nodeRet = new CMAny(contentSpec.type, (String JavaDoc)contentSpec.otherValue, fLeafCount++);
2306        }
2307        else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
2308            nodeRet = new CMAny(contentSpec.type, null, fLeafCount++);
2309        }
2310        //
2311
// If this node is a leaf, then its an easy one. We just add it
2312
// to the tree.
2313
//
2314
else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2315            //
2316
// Create a new leaf node, and pass it the current leaf count,
2317
// which is its DFA state position. Bump the leaf count after
2318
// storing it. This makes the positions zero based since we
2319
// store first and then increment.
2320
//
2321
fQName.setValues(null, (String JavaDoc)contentSpec.value,
2322                              (String JavaDoc)contentSpec.value, (String JavaDoc)contentSpec.otherValue);
2323            nodeRet = new CMLeaf(fQName, fLeafCount++);
2324        }
2325        else {
2326            //
2327
// Its not a leaf, so we have to recurse its left and maybe right
2328
// nodes. Save both values before we recurse and trash the node.
2329
final int leftNode = ((int[])contentSpec.value)[0];
2330            final int rightNode = ((int[])contentSpec.otherValue)[0];
2331
2332            if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
2333                || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
2334                //
2335
// Recurse on both children, and return a binary op node
2336
// with the two created sub nodes as its children. The node
2337
// type is the same type as the source.
2338
//
2339

2340                nodeRet = new CMBinOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec)
2341                                       , buildSyntaxTree(rightNode, contentSpec));
2342            }
2343            else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) {
2344                nodeRet = new CMUniOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec));
2345            }
2346            else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
2347                  || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE
2348                  || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
2349                nodeRet = new CMUniOp(contentSpec.type, buildSyntaxTree(leftNode, contentSpec));
2350            }
2351            else {
2352                throw new RuntimeException JavaDoc("ImplementationMessages.VAL_CST");
2353            }
2354        }
2355        // And return our new node for this level
2356
return nodeRet;
2357    }
2358   
2359    /**
2360     * Build a vector of valid QNames from Content Spec
2361     * table.
2362     *
2363     * @param contentSpecIndex
2364     * Content Spec index
2365     * @param vectorQName
2366     * Array of QName
2367     * @exception RuntimeException
2368     */

2369    private void contentSpecTree(int contentSpecIndex,
2370                                 XMLContentSpec contentSpec,
2371                                 ChildrenList children) {
2372
2373        // Handle any and leaf nodes
2374
getContentSpec( contentSpecIndex, contentSpec);
2375        if ( contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF ||
2376            (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY ||
2377            (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL ||
2378            (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
2379
2380            // resize arrays, if needed
2381
if (children.length == children.qname.length) {
2382                QName[] newQName = new QName[children.length * 2];
2383                System.arraycopy(children.qname, 0, newQName, 0, children.length);
2384                children.qname = newQName;
2385                int[] newType = new int[children.length * 2];
2386                System.arraycopy(children.type, 0, newType, 0, children.length);
2387                children.type = newType;
2388            }
2389
2390            // save values and return length
2391
children.qname[children.length] = new QName(null, (String JavaDoc)contentSpec.value,
2392                                                     (String JavaDoc) contentSpec.value,
2393                                                     (String JavaDoc) contentSpec.otherValue);
2394            children.type[children.length] = contentSpec.type;
2395            children.length++;
2396            return;
2397        }
2398
2399        //
2400
// Its not a leaf, so we have to recurse its left and maybe right
2401
// nodes. Save both values before we recurse and trash the node.
2402
//
2403
final int leftNode = contentSpec.value != null
2404                           ? ((int[])(contentSpec.value))[0] : -1;
2405        int rightNode = -1 ;
2406        if (contentSpec.otherValue != null )
2407            rightNode = ((int[])(contentSpec.otherValue))[0];
2408        else
2409            return;
2410
2411        if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE ||
2412            contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
2413            contentSpecTree(leftNode, contentSpec, children);
2414            contentSpecTree(rightNode, contentSpec, children);
2415            return;
2416        }
2417
2418        if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ||
2419            contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2420            contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
2421            contentSpecTree(leftNode, contentSpec, children);
2422            return;
2423        }
2424
2425        // error
2426
throw new RuntimeException JavaDoc("Invalid content spec type seen in contentSpecTree() method of AbstractDTDGrammar class : "+contentSpec.type);
2427
2428    } // contentSpecTree(int,XMLContentSpec,ChildrenList)
2429

2430    // ensure capacity
2431

2432    private void ensureElementDeclCapacity(int chunk) {
2433        if (chunk >= fElementDeclName.length) {
2434            fElementDeclIsExternal = resize(fElementDeclIsExternal,
2435                                     fElementDeclIsExternal.length * 2);
2436
2437            fElementDeclName = resize(fElementDeclName, fElementDeclName.length * 2);
2438            fElementDeclType = resize(fElementDeclType, fElementDeclType.length * 2);
2439            fElementDeclContentModelValidator = resize(fElementDeclContentModelValidator, fElementDeclContentModelValidator.length * 2);
2440            fElementDeclContentSpecIndex = resize(fElementDeclContentSpecIndex,fElementDeclContentSpecIndex.length * 2);
2441            fElementDeclFirstAttributeDeclIndex = resize(fElementDeclFirstAttributeDeclIndex, fElementDeclFirstAttributeDeclIndex.length * 2);
2442            fElementDeclLastAttributeDeclIndex = resize(fElementDeclLastAttributeDeclIndex, fElementDeclLastAttributeDeclIndex.length * 2);
2443        }
2444        else if (fElementDeclName[chunk] != null) {
2445            return;
2446        }
2447
2448        fElementDeclIsExternal[chunk] = new int[CHUNK_SIZE];
2449        fElementDeclName[chunk] = new QName[CHUNK_SIZE];
2450        fElementDeclType[chunk] = new short[CHUNK_SIZE];
2451        fElementDeclContentModelValidator[chunk] = new ContentModelValidator[CHUNK_SIZE];
2452        fElementDeclContentSpecIndex[chunk] = new int[CHUNK_SIZE];
2453        fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2454        fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2455        return;
2456    }
2457
2458    private void ensureAttributeDeclCapacity(int chunk) {
2459
2460        if (chunk >= fAttributeDeclName.length) {
2461            fAttributeDeclIsExternal = resize(fAttributeDeclIsExternal,
2462                                       fAttributeDeclIsExternal.length * 2);
2463            fAttributeDeclName = resize(fAttributeDeclName, fAttributeDeclName.length * 2);
2464            fAttributeDeclType = resize(fAttributeDeclType, fAttributeDeclType.length * 2);
2465            fAttributeDeclEnumeration = resize(fAttributeDeclEnumeration, fAttributeDeclEnumeration.length * 2);
2466            fAttributeDeclDefaultType = resize(fAttributeDeclDefaultType, fAttributeDeclDefaultType.length * 2);
2467            fAttributeDeclDatatypeValidator = resize(fAttributeDeclDatatypeValidator, fAttributeDeclDatatypeValidator.length * 2);
2468            fAttributeDeclDefaultValue = resize(fAttributeDeclDefaultValue, fAttributeDeclDefaultValue.length * 2);
2469            fAttributeDeclNonNormalizedDefaultValue = resize(fAttributeDeclNonNormalizedDefaultValue, fAttributeDeclNonNormalizedDefaultValue.length * 2);
2470            fAttributeDeclNextAttributeDeclIndex = resize(fAttributeDeclNextAttributeDeclIndex, fAttributeDeclNextAttributeDeclIndex.length * 2);
2471        }
2472        else if (fAttributeDeclName[chunk] != null) {
2473            return;
2474        }
2475
2476        fAttributeDeclIsExternal[chunk] = new int[CHUNK_SIZE];
2477        fAttributeDeclName[chunk] = new QName[CHUNK_SIZE];
2478        fAttributeDeclType[chunk] = new short[CHUNK_SIZE];
2479        fAttributeDeclEnumeration[chunk] = new String JavaDoc[CHUNK_SIZE][];
2480        fAttributeDeclDefaultType[chunk] = new short[CHUNK_SIZE];
2481        fAttributeDeclDatatypeValidator[chunk] = new DatatypeValidator[CHUNK_SIZE];
2482        fAttributeDeclDefaultValue[chunk] = new String JavaDoc[CHUNK_SIZE];
2483        fAttributeDeclNonNormalizedDefaultValue[chunk] = new String JavaDoc[CHUNK_SIZE];
2484        fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2485        return;
2486    }
2487   
2488    private void ensureEntityDeclCapacity(int chunk) {
2489        if (chunk >= fEntityName.length) {
2490            fEntityName = resize(fEntityName, fEntityName.length * 2);
2491            fEntityValue = resize(fEntityValue, fEntityValue.length * 2);
2492            fEntityPublicId = resize(fEntityPublicId, fEntityPublicId.length * 2);
2493            fEntitySystemId = resize(fEntitySystemId, fEntitySystemId.length * 2);
2494            fEntityBaseSystemId = resize(fEntityBaseSystemId, fEntityBaseSystemId.length * 2);
2495            fEntityNotation = resize(fEntityNotation, fEntityNotation.length * 2);
2496            fEntityIsPE = resize(fEntityIsPE, fEntityIsPE.length * 2);
2497            fEntityInExternal = resize(fEntityInExternal, fEntityInExternal.length * 2);
2498        }
2499        else if (fEntityName[chunk] != null) {
2500            return;
2501        }
2502
2503        fEntityName[chunk] = new String JavaDoc[CHUNK_SIZE];
2504        fEntityValue[chunk] = new String JavaDoc[CHUNK_SIZE];
2505        fEntityPublicId[chunk] = new String JavaDoc[CHUNK_SIZE];
2506        fEntitySystemId[chunk] = new String JavaDoc[CHUNK_SIZE];
2507        fEntityBaseSystemId[chunk] = new String JavaDoc[CHUNK_SIZE];
2508        fEntityNotation[chunk] = new String JavaDoc[CHUNK_SIZE];
2509        fEntityIsPE[chunk] = new byte[CHUNK_SIZE];
2510        fEntityInExternal[chunk] = new byte[CHUNK_SIZE];
2511        return;
2512    }
2513      
2514    private void ensureNotationDeclCapacity(int chunk) {
2515        if (chunk >= fNotationName.length) {
2516            fNotationName = resize(fNotationName, fNotationName.length * 2);
2517            fNotationPublicId = resize(fNotationPublicId, fNotationPublicId.length * 2);
2518            fNotationSystemId = resize(fNotationSystemId, fNotationSystemId.length * 2);
2519            fNotationBaseSystemId = resize(fNotationBaseSystemId, fNotationBaseSystemId.length * 2);
2520        }
2521        else if (fNotationName[chunk] != null) {
2522            return;
2523        }
2524
2525        fNotationName[chunk] = new String JavaDoc[CHUNK_SIZE];
2526        fNotationPublicId[chunk] = new String JavaDoc[CHUNK_SIZE];
2527        fNotationSystemId[chunk] = new String JavaDoc[CHUNK_SIZE];
2528        fNotationBaseSystemId[chunk] = new String JavaDoc[CHUNK_SIZE];
2529        return;
2530    }
2531
2532    private void ensureContentSpecCapacity(int chunk) {
2533        if (chunk >= fContentSpecType.length) {
2534            fContentSpecType = resize(fContentSpecType, fContentSpecType.length * 2);
2535            fContentSpecValue = resize(fContentSpecValue, fContentSpecValue.length * 2);
2536            fContentSpecOtherValue = resize(fContentSpecOtherValue, fContentSpecOtherValue.length * 2);
2537        }
2538        else if (fContentSpecType[chunk] != null) {
2539            return;
2540        }
2541
2542        fContentSpecType[chunk] = new short[CHUNK_SIZE];
2543        fContentSpecValue[chunk] = new Object JavaDoc[CHUNK_SIZE];
2544        fContentSpecOtherValue[chunk] = new Object JavaDoc[CHUNK_SIZE];
2545        return;
2546    }
2547
2548    //
2549
// Private static methods
2550
//
2551

2552    // resize chunks
2553

2554    private static byte[][] resize(byte array[][], int newsize) {
2555        byte newarray[][] = new byte[newsize][];
2556        System.arraycopy(array, 0, newarray, 0, array.length);
2557        return newarray;
2558    }
2559   
2560    private static short[][] resize(short array[][], int newsize) {
2561        short newarray[][] = new short[newsize][];
2562        System.arraycopy(array, 0, newarray, 0, array.length);
2563        return newarray;
2564    }
2565
2566    private static int[][] resize(int array[][], int newsize) {
2567        int newarray[][] = new int[newsize][];
2568        System.arraycopy(array, 0, newarray, 0, array.length);
2569        return newarray;
2570    }
2571
2572    private static DatatypeValidator[][] resize(DatatypeValidator array[][], int newsize) {
2573        DatatypeValidator newarray[][] = new DatatypeValidator[newsize][];
2574        System.arraycopy(array, 0, newarray, 0, array.length);
2575        return newarray;
2576    }
2577
2578    private static ContentModelValidator[][] resize(ContentModelValidator array[][], int newsize) {
2579        ContentModelValidator newarray[][] = new ContentModelValidator[newsize][];
2580        System.arraycopy(array, 0, newarray, 0, array.length);
2581        return newarray;
2582    }
2583
2584    private static Object JavaDoc[][] resize(Object JavaDoc array[][], int newsize) {
2585        Object JavaDoc newarray[][] = new Object JavaDoc[newsize][];
2586        System.arraycopy(array, 0, newarray, 0, array.length);
2587        return newarray;
2588    }
2589
2590    private static QName[][] resize(QName array[][], int newsize) {
2591        QName newarray[][] = new QName[newsize][];
2592        System.arraycopy(array, 0, newarray, 0, array.length);
2593        return newarray;
2594    }
2595
2596    private static String JavaDoc[][] resize(String JavaDoc array[][], int newsize) {
2597        String JavaDoc newarray[][] = new String JavaDoc[newsize][];
2598        System.arraycopy(array, 0, newarray, 0, array.length);
2599        return newarray;
2600    }
2601
2602    private static String JavaDoc[][][] resize(String JavaDoc array[][][], int newsize) {
2603        String JavaDoc newarray[][][] = new String JavaDoc[newsize] [][];
2604        System.arraycopy(array, 0, newarray, 0, array.length);
2605        return newarray;
2606    }
2607
2608    //
2609
// Classes
2610
//
2611

2612    /**
2613     * Children list for <code>contentSpecTree</code> method.
2614     *
2615     * @author Eric Ye, IBM
2616     */

2617    private static class ChildrenList {
2618        
2619        //
2620
// Data
2621
//
2622

2623        /** Length. */
2624        public int length = 0;
2625
2626        // NOTE: The following set of data is mutually exclusive. It is
2627
// written this way because Java doesn't have a native
2628
// union data structure. -Ac
2629

2630        /** Left and right children names. */
2631        public QName[] qname = new QName[2];
2632
2633        /** Left and right children types. */
2634        public int[] type = new int[2];
2635
2636    } // class ChildrenList
2637

2638    //
2639
// Classes
2640
//
2641

2642    /**
2643     * A simple Hashtable implementation that takes a tuple (String, String)
2644     * as the key and a int as value.
2645     *
2646     * @author Eric Ye, IBM
2647     * @author Andy Clark, IBM
2648     */

2649    protected static final class QNameHashtable {
2650    
2651        //
2652
// Constants
2653
//
2654

2655        /** Initial bucket size (4). */
2656        private static final int INITIAL_BUCKET_SIZE = 4;
2657
2658        // NOTE: Changed previous hashtable size from 512 to 101 so
2659
// that we get a better distribution for hashing. -Ac
2660
/** Hashtable size (101). */
2661        private static final int HASHTABLE_SIZE = 101;
2662
2663        //
2664
// Data
2665
//
2666
private Object JavaDoc[][] fHashTable = new Object JavaDoc[HASHTABLE_SIZE][];
2667
2668        //
2669
// Public methods
2670
//
2671
/** Associates the given value with the specified key tuple. */
2672        public void put(String JavaDoc key, int value) {
2673
2674            int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE;
2675            Object JavaDoc[] bucket = fHashTable[hash];
2676
2677            if (bucket == null) {
2678                bucket = new Object JavaDoc[1 + 2*INITIAL_BUCKET_SIZE];
2679                bucket[0] = new int[]{1};
2680                bucket[1] = key;
2681                bucket[2] = new int[]{value};
2682                fHashTable[hash] = bucket;
2683            } else {
2684                int count = ((int[])bucket[0])[0];
2685                int offset = 1 + 2*count;
2686                if (offset == bucket.length) {
2687                    int newSize = count + INITIAL_BUCKET_SIZE;
2688                    Object JavaDoc[] newBucket = new Object JavaDoc[1 + 2*newSize];
2689                    System.arraycopy(bucket, 0, newBucket, 0, offset);
2690                    bucket = newBucket;
2691                    fHashTable[hash] = bucket;
2692                }
2693                boolean found = false;
2694                int j=1;
2695                for (int i=0; i<count; i++){
2696                    if ((String JavaDoc)bucket[j] == key) {
2697                        ((int[])bucket[j+1])[0] = value;
2698                        found = true;
2699                        break;
2700                    }
2701                    j += 2;
2702                }
2703                if (! found) {
2704                    bucket[offset++] = key;
2705                    bucket[offset]= new int[]{value};
2706                    ((int[])bucket[0])[0] = ++count;
2707                }
2708
2709            }
2710            //System.out.println("put("+key+" -> "+value+')');
2711
//System.out.println("get("+key+") -> "+get(key));
2712

2713        } // put(int,String,String,int)
2714

2715        /** Returns the value associated with the specified key tuple. */
2716        public int get(String JavaDoc key) {
2717            int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE;
2718            Object JavaDoc[] bucket = fHashTable[hash];
2719
2720            if (bucket == null) {
2721                return -1;
2722            }
2723            int count = ((int[])bucket[0])[0];
2724
2725            int j=1;
2726            for (int i=0; i<count; i++){
2727                if ((String JavaDoc)bucket[j] == key) {
2728                    return ((int[])bucket[j+1])[0];
2729                }
2730                j += 2;
2731            }
2732            return -1;
2733
2734        } // get(int,String,String)
2735

2736    } // class QNameHashtable
2737

2738    //
2739
// EntityState methods
2740
//
2741
public boolean isEntityDeclared (String JavaDoc name){
2742        return (getEntityDeclIndex(name)!=-1)?true:false;
2743    }
2744
2745    public boolean isEntityUnparsed (String JavaDoc name){
2746        int entityIndex = getEntityDeclIndex(name);
2747        if (entityIndex >-1) {
2748            int chunk = entityIndex >> CHUNK_SHIFT;
2749            int index = entityIndex & CHUNK_MASK;
2750            //for unparsed entity notation!=null
2751
return (fEntityNotation[chunk][index]!=null)?true:false;
2752        }
2753        return false;
2754    }
2755} // class DTDGrammar
2756
Popular Tags