KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * Copyright 1999-2002,2004,2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.impl.dtd;
18
19 import java.util.Hashtable JavaDoc;
20 import java.util.Vector JavaDoc;
21
22 import org.apache.xerces.impl.dtd.models.CMAny;
23 import org.apache.xerces.impl.dtd.models.CMBinOp;
24 import org.apache.xerces.impl.dtd.models.CMLeaf;
25 import org.apache.xerces.impl.dtd.models.CMNode;
26 import org.apache.xerces.impl.dtd.models.CMUniOp;
27 import org.apache.xerces.impl.dtd.models.ContentModelValidator;
28 import org.apache.xerces.impl.dtd.models.DFAContentModel;
29 import org.apache.xerces.impl.dtd.models.MixedContentModel;
30 import org.apache.xerces.impl.dtd.models.SimpleContentModel;
31 import org.apache.xerces.impl.dv.DatatypeValidator;
32 import org.apache.xerces.impl.validation.EntityState;
33 import org.apache.xerces.util.SymbolTable;
34 import org.apache.xerces.xni.Augmentations;
35 import org.apache.xerces.xni.QName;
36 import org.apache.xerces.xni.XMLDTDContentModelHandler;
37 import org.apache.xerces.xni.XMLDTDHandler;
38 import org.apache.xerces.xni.XMLLocator;
39 import org.apache.xerces.xni.XMLResourceIdentifier;
40 import org.apache.xerces.xni.XMLString;
41 import org.apache.xerces.xni.XNIException;
42 import org.apache.xerces.xni.grammars.Grammar;
43 import org.apache.xerces.xni.grammars.XMLGrammarDescription;
44 import org.apache.xerces.xni.parser.XMLDTDContentModelSource;
45 import org.apache.xerces.xni.parser.XMLDTDSource;
46
47 /**
48  * A DTD grammar. This class implements the XNI handler interfaces
49  * for DTD information so that it can build the approprate validation
50  * structures automatically from the callbacks.
51  *
52  * @xerces.internal
53  *
54  * @author Eric Ye, IBM
55  * @author Jeffrey Rodriguez, IBM
56  * @author Andy Clark, IBM
57  * @author Neil Graham, IBM
58  *
59  * @version $Id: DTDGrammar.java,v 1.32 2005/03/07 23:28:41 mrglavas Exp $
60  */

61 public class DTDGrammar
62     implements XMLDTDHandler, XMLDTDContentModelHandler, EntityState, Grammar {
63
64     //
65
// Constants
66
//
67

68     /** Top level scope (-1). */
69     public static final int TOP_LEVEL_SCOPE = -1;
70
71     // private
72

73     /** Chunk shift (8). */
74     private static final int CHUNK_SHIFT = 8; // 2^8 = 256
75

76     /** Chunk size (1 << CHUNK_SHIFT). */
77     private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
78
79     /** Chunk mask (CHUNK_SIZE - 1). */
80     private static final int CHUNK_MASK = CHUNK_SIZE - 1;
81
82     /** Initial chunk count (1 << (10 - CHUNK_SHIFT)). */
83     private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k
84

85     /** List flag (0x80). */
86     private static final short LIST_FLAG = 0x80;
87
88     /** List mask (~LIST_FLAG). */
89     private static final short LIST_MASK = ~LIST_FLAG;
90
91     // debugging
92

93     /** Debug DTDGrammar. */
94     private static final boolean DEBUG = false;
95
96     //
97
// Data
98
//
99

100     protected XMLDTDSource fDTDSource = null;
101     protected XMLDTDContentModelSource fDTDContentModelSource = null;
102
103     /** Current element index. */
104     protected int fCurrentElementIndex;
105
106     /** Current attribute index. */
107     protected int fCurrentAttributeIndex;
108
109     /** fReadingExternalDTD */
110     protected boolean fReadingExternalDTD = false;
111
112     /** Symbol table. */
113     private SymbolTable fSymbolTable;
114
115     // The XMLDTDDescription with which this Grammar is associated
116
protected XMLDTDDescription fGrammarDescription = null;
117
118     // element declarations
119

120     /** Number of element declarations. */
121     private int fElementDeclCount = 0;
122
123     /** Element declaration name. */
124     private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
125
126     /**
127      * Element declaration type.
128      * @see XMLElementDecl
129      */

130     private short fElementDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
131
132     /**
133      * Element declaration content spec index. This index value is used
134      * to refer to the content spec information tables.
135      */

136     private int fElementDeclContentSpecIndex[][] = new int[INITIAL_CHUNK_COUNT][];
137
138     /**
139      * Element declaration content model validator. This validator is
140      * constructed from the content spec nodes.
141      */

142     private ContentModelValidator fElementDeclContentModelValidator[][] = new ContentModelValidator[INITIAL_CHUNK_COUNT][];
143
144     /** First attribute declaration of an element declaration. */
145     private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
146
147     /** Last attribute declaration of an element declaration. */
148     private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
149
150     // attribute declarations
151

152     /** Number of attribute declarations. */
153     private int fAttributeDeclCount = 0 ;
154
155     /** Attribute declaration name. */
156     private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
157
158     // is this grammar immutable? (fully constructed and not changeable)
159
private boolean fIsImmutable = false;
160
161     /**
162      * Attribute declaration type.
163      * @see XMLAttributeDecl
164      */

165     private short fAttributeDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
166
167     /** Attribute declaration enumeration values. */
168     private String JavaDoc[] fAttributeDeclEnumeration[][] = new String JavaDoc[INITIAL_CHUNK_COUNT][][];
169     private short fAttributeDeclDefaultType[][] = new short[INITIAL_CHUNK_COUNT][];
170     private DatatypeValidator fAttributeDeclDatatypeValidator[][] = new DatatypeValidator[INITIAL_CHUNK_COUNT][];
171     private String JavaDoc fAttributeDeclDefaultValue[][] = new String JavaDoc[INITIAL_CHUNK_COUNT][];
172     private String JavaDoc fAttributeDeclNonNormalizedDefaultValue[][] = new String JavaDoc[INITIAL_CHUNK_COUNT][];
173     private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
174
175     // content specs
176

177     // here saves the content spec binary trees for element decls,
178
// each element with a content model will hold a pointer which is
179
// the index of the head node of the content spec tree.
180

181     private int fContentSpecCount = 0;
182     private short fContentSpecType[][] = new short[INITIAL_CHUNK_COUNT][];
183     private Object JavaDoc fContentSpecValue[][] = new Object JavaDoc[INITIAL_CHUNK_COUNT][];
184     private Object JavaDoc fContentSpecOtherValue[][] = new Object JavaDoc[INITIAL_CHUNK_COUNT][];
185
186     // entities
187

188     private int fEntityCount = 0;
189     private String JavaDoc fEntityName[][] = new String JavaDoc[INITIAL_CHUNK_COUNT][];
190     private String JavaDoc[][] fEntityValue = new String JavaDoc[INITIAL_CHUNK_COUNT][];
191     private String JavaDoc[][] fEntityPublicId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
192     private String JavaDoc[][] fEntitySystemId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
193     private String JavaDoc[][] fEntityBaseSystemId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
194     private String JavaDoc[][] fEntityNotation = new String JavaDoc[INITIAL_CHUNK_COUNT][];
195     private byte[][] fEntityIsPE = new byte[INITIAL_CHUNK_COUNT][];
196     private byte[][] fEntityInExternal = new byte[INITIAL_CHUNK_COUNT][];
197
198     // notations
199

200     private int fNotationCount = 0;
201     private String JavaDoc fNotationName[][] = new String JavaDoc[INITIAL_CHUNK_COUNT][];
202     private String JavaDoc[][] fNotationPublicId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
203     private String JavaDoc[][] fNotationSystemId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
204     private String JavaDoc[][] fNotationBaseSystemId = new String JavaDoc[INITIAL_CHUNK_COUNT][];
205
206     // other information
207

208     /** Element index mapping table. */
209     private QNameHashtable fElementIndexMap = new QNameHashtable();
210
211     /** Entity index mapping table. */
212     private QNameHashtable fEntityIndexMap = new QNameHashtable();
213
214     /** Notation index mapping table. */
215     private QNameHashtable fNotationIndexMap = new QNameHashtable();
216
217     // temp variables
218

219     /** Mixed. */
220     private boolean fMixed;
221
222     /** Temporary qualified name. */
223     private QName fQName = new QName();
224     
225     /** Temporary qualified name. */
226     private QName fQName2 = new QName();
227
228     /** Temporary Attribute decl. */
229     protected XMLAttributeDecl fAttributeDecl = new XMLAttributeDecl();
230
231     // for buildSyntaxTree method
232

233     private int fLeafCount = 0;
234     private int fEpsilonIndex = -1;
235     
236     /** Element declaration. */
237     private XMLElementDecl fElementDecl = new XMLElementDecl();
238
239     /** Entity declaration. */
240     private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
241
242     /** Simple type. */
243     private XMLSimpleType fSimpleType = new XMLSimpleType();
244
245     /** Content spec node. */
246     private XMLContentSpec fContentSpec = new XMLContentSpec();
247
248     /** table of XMLElementDecl */
249     Hashtable JavaDoc fElementDeclTab = new Hashtable JavaDoc();
250
251     /** Children content model operation stack. */
252     private short[] fOpStack = null;
253
254     /** Children content model index stack. */
255     private int[] fNodeIndexStack = null;
256
257     /** Children content model previous node index stack. */
258     private int[] fPrevNodeIndexStack = null;
259
260     /** Stack depth */
261     private int fDepth = 0;
262
263     /** Entity stack. */
264     private boolean[] fPEntityStack = new boolean[4];
265     private int fPEDepth = 0;
266
267     // additional fields(columns) for the element Decl pool in the Grammar
268

269     /** flag if the elementDecl is External. */
270     private int fElementDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][];
271
272
273     // additional fields(columns) for the attribute Decl pool in the Grammar
274

275     /** flag if the AttributeDecl is External. */
276     private int fAttributeDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][];
277
278     // for mixedElement method
279

280     int valueIndex = -1;
281     int prevNodeIndex = -1;
282     int nodeIndex = -1;
283
284     //
285
// Constructors
286
//
287

288     /** Default constructor. */
289     public DTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) {
290         fSymbolTable = symbolTable;
291         fGrammarDescription = desc;
292     } // <init>(SymbolTable)
293

294     // Grammar methods
295

296     // return the XMLDTDDescription object with which this is associated
297
public XMLGrammarDescription getGrammarDescription() {
298         return fGrammarDescription;
299     } // getGrammarDescription(): XMLGrammarDescription
300

301     //
302
// Public methods
303
//
304

305     /**
306      * Returns true if the specified element declaration is external.
307      *
308      * @param elementDeclIndex The element declaration index.
309      */

310     public boolean getElementDeclIsExternal(int elementDeclIndex) {
311
312         if (elementDeclIndex < 0) {
313             return false;
314         }
315
316         int chunk = elementDeclIndex >> CHUNK_SHIFT;
317         int index = elementDeclIndex & CHUNK_MASK;
318         return (fElementDeclIsExternal[chunk][index] != 0);
319
320     } // getElementDeclIsExternal(int):boolean
321

322     /**
323      * Returns true if the specified attribute declaration is external.
324      *
325      * @param attributeDeclIndex Attribute declaration index.
326      */

327     public boolean getAttributeDeclIsExternal(int attributeDeclIndex) {
328
329         if (attributeDeclIndex < 0) {
330             return false;
331         }
332
333         int chunk = attributeDeclIndex >> CHUNK_SHIFT;
334         int index = attributeDeclIndex & CHUNK_MASK;
335         return (fAttributeDeclIsExternal[chunk][index] != 0);
336     }
337
338     public int getAttributeDeclIndex(int elementDeclIndex, String JavaDoc attributeDeclName) {
339         if (elementDeclIndex == -1) {
340             return -1;
341         }
342         int attDefIndex = getFirstAttributeDeclIndex(elementDeclIndex);
343         while (attDefIndex != -1) {
344             getAttributeDecl(attDefIndex, fAttributeDecl);
345
346             if (fAttributeDecl.name.rawname == attributeDeclName
347                 || attributeDeclName.equals(fAttributeDecl.name.rawname) ) {
348                 return attDefIndex;
349             }
350             attDefIndex = getNextAttributeDeclIndex(attDefIndex);
351         }
352         return -1;
353     } // getAttributeDeclIndex (int,QName)
354

355     //
356
// XMLDTDHandler methods
357
//
358

359     /**
360      * The start of the DTD.
361      *
362      * @param locator The document locator, or null if the document
363      * location cannot be reported during the parsing of
364      * the document DTD. However, it is <em>strongly</em>
365      * recommended that a locator be supplied that can
366      * at least report the base system identifier of the
367      * DTD.
368      *
369      * @param augs Additional information that may include infoset
370      * augmentations.
371      * @throws XNIException Thrown by handler to signal an error.
372      */

373     public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
374         //Initialize stack
375
fOpStack = null;
376         fNodeIndexStack = null;
377         fPrevNodeIndexStack = null;
378     } // startDTD(XMLLocator)
379

380     /**
381      * This method notifies of the start of an entity. The DTD has the
382      * pseudo-name of "[dtd]" and parameter entity names start with '%'.
383      * <p>
384      * <strong>Note:</strong> Since the DTD is an entity, the handler
385      * will be notified of the start of the DTD entity by calling the
386      * startParameterEntity method with the entity name "[dtd]" <em>before</em> calling
387      * the startDTD method.
388      *
389      * @param name The name of the parameter entity.
390      * @param identifier The resource identifier.
391      * @param encoding The auto-detected IANA encoding name of the entity
392      * stream. This value will be null in those situations
393      * where the entity encoding is not auto-detected (e.g.
394      * internal parameter entities).
395      * @param augs Additional information that may include infoset
396      * augmentations.
397      *
398      * @throws XNIException Thrown by handler to signal an error.
399      */

400     public void startParameterEntity(String JavaDoc name,
401                                      XMLResourceIdentifier identifier,
402                                      String JavaDoc encoding,
403                                      Augmentations augs) throws XNIException {
404
405         // keep track of this entity before fEntityDepth is increased
406
if (fPEDepth == fPEntityStack.length) {
407             boolean[] entityarray = new boolean[fPEntityStack.length * 2];
408             System.arraycopy(fPEntityStack, 0, entityarray, 0, fPEntityStack.length);
409             fPEntityStack = entityarray;
410         }
411         fPEntityStack[fPEDepth] = fReadingExternalDTD;
412         fPEDepth++;
413
414     } // startParameterEntity(String,XMLResourceIdentifier,String,Augmentations)
415

416     /**
417      * The start of the DTD external subset.
418      *
419      * @param augs Additional information that may include infoset
420      * augmentations.
421      *
422      * @throws XNIException Thrown by handler to signal an error.
423      */

424     public void startExternalSubset(XMLResourceIdentifier identifier,
425                                     Augmentations augs) throws XNIException {
426         fReadingExternalDTD = true;
427     } // startExternalSubset(Augmentations)
428

429     /**
430      * This method notifies the end of an entity. The DTD has the pseudo-name
431      * of "[dtd]" and parameter entity names start with '%'.
432      * <p>
433      * <strong>Note:</strong> Since the DTD is an entity, the handler
434      * will be notified of the end of the DTD entity by calling the
435      * endEntity method with the entity name "[dtd]" <em>after</em> calling
436      * the endDTD method.
437      *
438      * @param name The name of the entity.
439      * @param augs Additional information that may include infoset
440      * augmentations.
441      * @throws XNIException Thrown by handler to signal an error.
442      */

443     public void endParameterEntity(String JavaDoc name, Augmentations augs) throws XNIException {
444
445         fPEDepth--;
446         fReadingExternalDTD = fPEntityStack[fPEDepth];
447
448     } // endParameterEntity(String,Augmentations)
449

450     /**
451      * The end of the DTD external subset.
452      *
453      * @param augs Additional information that may include infoset
454      * augmentations.
455      *
456      * @throws XNIException Thrown by handler to signal an error.
457      */

458     public void endExternalSubset(Augmentations augs) throws XNIException {
459         fReadingExternalDTD = false;
460     } // endExternalSubset(Augmentations)
461

462     /**
463      * An element declaration.
464      *
465      * @param name The name of the element.
466      * @param contentModel The element content model.
467      * @param augs Additional information that may include infoset
468      * augmentations.
469      * @throws XNIException Thrown by handler to signal an error.
470      */

471     public void elementDecl(String JavaDoc name, String JavaDoc contentModel, Augmentations augs)
472         throws XNIException {
473
474         XMLElementDecl tmpElementDecl = (XMLElementDecl) fElementDeclTab.get(name) ;
475
476         // check if it is already defined
477
if ( tmpElementDecl != null ) {
478             if (tmpElementDecl.type == -1) {
479                 fCurrentElementIndex = getElementDeclIndex(name);
480             }
481             else {
482                 // duplicate element, ignored.
483
return;
484             }
485         }
486         else {
487             fCurrentElementIndex = createElementDecl();//create element decl
488
}
489
490         XMLElementDecl elementDecl = new XMLElementDecl();
491         
492         fQName.setValues(null, name, name, null);
493        
494         elementDecl.name.setValues(fQName);
495
496         elementDecl.contentModelValidator = null;
497         elementDecl.scope= -1;
498         if (contentModel.equals("EMPTY")) {
499             elementDecl.type = XMLElementDecl.TYPE_EMPTY;
500         }
501         else if (contentModel.equals("ANY")) {
502             elementDecl.type = XMLElementDecl.TYPE_ANY;
503         }
504         else if (contentModel.startsWith("(") ) {
505             if (contentModel.indexOf("#PCDATA") > 0 ) {
506                 elementDecl.type = XMLElementDecl.TYPE_MIXED;
507             }
508             else {
509                 elementDecl.type = XMLElementDecl.TYPE_CHILDREN;
510             }
511         }
512
513
514         //add(or set) this elementDecl to the local cache
515
this.fElementDeclTab.put(name, elementDecl );
516
517         fElementDecl = elementDecl;
518
519         if ((fDepth == 0 ||
520             (fDepth == 1 && elementDecl.type == XMLElementDecl.TYPE_MIXED)) &&
521             fNodeIndexStack != null) {
522             if (elementDecl.type == XMLElementDecl.TYPE_MIXED) {
523                 int pcdata = addUniqueLeafNode(null);
524                 if (fNodeIndexStack[0] == -1) {
525                     fNodeIndexStack[0] = pcdata;
526                 }
527                 else {
528                     fNodeIndexStack[0] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
529                                                             pcdata, fNodeIndexStack[0]);
530                 }
531             }
532             setContentSpecIndex(fCurrentElementIndex, fNodeIndexStack[fDepth]);
533         }
534
535         if ( DEBUG ) {
536             System.out.println( "name = " + fElementDecl.name.localpart );
537             System.out.println( "Type = " + fElementDecl.type );
538         }
539
540         setElementDecl(fCurrentElementIndex, fElementDecl );//set internal structure
541

542         int chunk = fCurrentElementIndex >> CHUNK_SHIFT;
543         int index = fCurrentElementIndex & CHUNK_MASK;
544         ensureElementDeclCapacity(chunk);
545         fElementDeclIsExternal[chunk][index] = fReadingExternalDTD? 1 : 0;
546
547     } // elementDecl(String,String)
548

549     /**
550      * An attribute declaration.
551      *
552      * @param elementName The name of the element that this attribute
553      * is associated with.
554      * @param attributeName The name of the attribute.
555      * @param type The attribute type. This value will be one of
556      * the following: "CDATA", "ENTITY", "ENTITIES",
557      * "ENUMERATION", "ID", "IDREF", "IDREFS",
558      * "NMTOKEN", "NMTOKENS", or "NOTATION".
559      * @param enumeration If the type has the value "ENUMERATION", this
560      * array holds the allowed attribute values;
561      * otherwise, this array is null.
562      * @param defaultType The attribute default type. This value will be
563      * one of the following: "#FIXED", "#IMPLIED",
564      * "#REQUIRED", or null.
565      * @param defaultValue The attribute default value, or null if no
566      * default value is specified.
567      * @param nonNormalizedDefaultValue The attribute default value with no normalization
568      * performed, or null if no default value is specified.
569      *
570      * @param augs Additional information that may include infoset
571      * augmentations.
572      * @throws XNIException Thrown by handler to signal an error.
573      */

574     public void attributeDecl(String JavaDoc elementName, String JavaDoc attributeName,
575                               String JavaDoc type, String JavaDoc[] enumeration,
576                               String JavaDoc defaultType, XMLString defaultValue,
577                               XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
578
579         if ( this.fElementDeclTab.containsKey( (String JavaDoc) elementName) ) {
580             //if ElementDecl has already being created in the Grammar then remove from table,
581
//this.fElementDeclTab.remove( (String) elementName );
582
}
583         // then it is forward reference to a element decl, create the elementDecl first.
584
else {
585             fCurrentElementIndex = createElementDecl();//create element decl
586

587             XMLElementDecl elementDecl = new XMLElementDecl();
588             elementDecl.name.setValues(null, elementName, elementName, null);
589
590             elementDecl.scope= -1;
591
592             //add(or set) this elementDecl to the local cache
593
this.fElementDeclTab.put(elementName, elementDecl );
594
595             //set internal structure
596
setElementDecl(fCurrentElementIndex, elementDecl );
597         }
598
599         //Get Grammar index to grammar array
600
int elementIndex = getElementDeclIndex(elementName);
601         
602         //return, when more than one definition is provided for the same attribute of given element type
603
//only the first declaration is binding and later declarations are ignored
604
if (getAttributeDeclIndex(elementIndex, attributeName) != -1) {
605             return;
606         }
607
608         fCurrentAttributeIndex = createAttributeDecl();// Create current Attribute Decl
609

610         fSimpleType.clear();
611         if ( defaultType != null ) {
612             if ( defaultType.equals( "#FIXED") ) {
613                 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_FIXED;
614             } else if ( defaultType.equals( "#IMPLIED") ) {
615                 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
616             } else if ( defaultType.equals( "#REQUIRED") ) {
617                 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_REQUIRED;
618             }
619         }
620         if ( DEBUG ) {
621             System.out.println("defaultvalue = " + defaultValue.toString() );
622         }
623         fSimpleType.defaultValue = defaultValue!=null ? defaultValue.toString() : null;
624         fSimpleType.nonNormalizedDefaultValue = nonNormalizedDefaultValue!=null ? nonNormalizedDefaultValue.toString() : null;
625         fSimpleType.enumeration = enumeration;
626
627         if (type.equals("CDATA")) {
628             fSimpleType.type = XMLSimpleType.TYPE_CDATA;
629         }
630         else if ( type.equals("ID") ) {
631             fSimpleType.type = XMLSimpleType.TYPE_ID;
632         }
633         else if ( type.startsWith("IDREF") ) {
634             fSimpleType.type = XMLSimpleType.TYPE_IDREF;
635             if (type.indexOf("S") > 0) {
636                 fSimpleType.list = true;
637             }
638         }
639         else if (type.equals("ENTITIES")) {
640             fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
641             fSimpleType.list = true;
642         }
643         else if (type.equals("ENTITY")) {
644             fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
645         }
646         else if (type.equals("NMTOKENS")) {
647             fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
648             fSimpleType.list = true;
649         }
650         else if (type.equals("NMTOKEN")) {
651             fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
652         }
653         else if (type.startsWith("NOTATION") ) {
654             fSimpleType.type = XMLSimpleType.TYPE_NOTATION;
655         }
656         else if (type.startsWith("ENUMERATION") ) {
657             fSimpleType.type = XMLSimpleType.TYPE_ENUMERATION;
658         }
659         else {
660             // REVISIT: Report error message. -Ac
661
System.err.println("!!! unknown attribute type "+type);
662         }
663         // REVISIT: The datatype should be stored with the attribute value
664
// and not special-cased in the XMLValidator. -Ac
665
//fSimpleType.datatypeValidator = fDatatypeValidatorFactory.createDatatypeValidator(type, null, facets, fSimpleType.list);
666

667         fQName.setValues(null, attributeName, attributeName, null);
668         fAttributeDecl.setValues( fQName, fSimpleType, false );
669
670         setAttributeDecl(elementIndex, fCurrentAttributeIndex, fAttributeDecl);
671
672         int chunk = fCurrentAttributeIndex >> CHUNK_SHIFT;
673         int index = fCurrentAttributeIndex & CHUNK_MASK;
674         ensureAttributeDeclCapacity(chunk);
675         fAttributeDeclIsExternal[chunk][index] = fReadingExternalDTD ? 1 : 0;
676
677     } // attributeDecl(String,String,String,String[],String,XMLString,XMLString, Augmentations)
678

679     /**
680      * An internal entity declaration.
681      *
682      * @param name The name of the entity. Parameter entity names start with
683      * '%', whereas the name of a general entity is just the
684      * entity name.
685      * @param text The value of the entity.
686      * @param nonNormalizedText The non-normalized value of the entity. This
687      * value contains the same sequence of characters that was in
688      * the internal entity declaration, without any entity
689      * references expanded.
690      * @param augs Additional information that may include infoset
691      * augmentations.
692      * @throws XNIException Thrown by handler to signal an error.
693      */

694     public void internalEntityDecl(String JavaDoc name, XMLString text,
695                                    XMLString nonNormalizedText,
696                                    Augmentations augs) throws XNIException {
697
698         int entityIndex = getEntityDeclIndex(name);
699         if( entityIndex == -1){
700             entityIndex = createEntityDecl();
701             boolean isPE = name.startsWith("%");
702             boolean inExternal = fReadingExternalDTD;
703             XMLEntityDecl entityDecl = new XMLEntityDecl();
704             entityDecl.setValues(name,null,null, null, null,
705                                  text.toString(), isPE, inExternal);
706
707             setEntityDecl(entityIndex, entityDecl);
708         }
709
710     } // internalEntityDecl(String,XMLString,XMLString)
711

712     /**
713      * An external entity declaration.
714      *
715      * @param name The name of the entity. Parameter entity names start
716      * with '%', whereas the name of a general entity is just
717      * the entity name.
718      * @param identifier An object containing all location information
719      * pertinent to this external entity declaration.
720      * @param augs Additional information that may include infoset
721      * augmentations.
722      * @throws XNIException Thrown by handler to signal an error.
723      */

724     public void externalEntityDecl(String JavaDoc name,
725                                    XMLResourceIdentifier identifier,
726                                    Augmentations augs) throws XNIException {
727
728         int entityIndex = getEntityDeclIndex(name);
729         if( entityIndex == -1){
730             entityIndex = createEntityDecl();
731             boolean isPE = name.startsWith("%");
732             boolean inExternal = fReadingExternalDTD;
733
734             XMLEntityDecl entityDecl = new XMLEntityDecl();
735             entityDecl.setValues(name, identifier.getPublicId(), identifier.getLiteralSystemId(),
736                                 identifier.getBaseSystemId(),
737                                 null, null, isPE, inExternal);
738
739             setEntityDecl(entityIndex, entityDecl);
740         }
741     } // externalEntityDecl(String, XMLResourceIdentifier, Augmentations)
742

743     /**
744      * An unparsed entity declaration.
745      *
746      * @param name The name of the entity.
747      * @param identifier An object containing all location information
748      * pertinent to this entity.
749      * @param notation The name of the notation.
750      * @param augs Additional information that may include infoset
751      * augmentations.
752      * @throws XNIException Thrown by handler to signal an error.
753      */

754     public void unparsedEntityDecl(String JavaDoc name, XMLResourceIdentifier identifier,
755                                    String JavaDoc notation,
756                                    Augmentations augs) throws XNIException {
757
758         XMLEntityDecl entityDecl = new XMLEntityDecl();
759         boolean isPE = name.startsWith("%");
760         boolean inExternal = fReadingExternalDTD;
761
762         entityDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(),
763                             identifier.getBaseSystemId(), notation,
764                             null, isPE, inExternal);
765         int entityIndex = getEntityDeclIndex(name);
766         if (entityIndex == -1) {
767             entityIndex = createEntityDecl();
768             setEntityDecl(entityIndex, entityDecl);
769         }
770
771     } // unparsedEntityDecl(String,StringXMLResourceIdentifier,Augmentations)
772

773     /**
774      * A notation declaration
775      *
776      * @param name The name of the notation.
777      * @param identifier An object containing all location information
778      * pertinent to this notation.
779      * @param augs Additional information that may include infoset
780      * augmentations.
781      * @throws XNIException Thrown by handler to signal an error.
782      */

783     public void notationDecl(String JavaDoc name, XMLResourceIdentifier identifier,
784                              Augmentations augs) throws XNIException {
785
786         XMLNotationDecl notationDecl = new XMLNotationDecl();
787         notationDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(),
788                 identifier.getBaseSystemId());
789         int notationIndex = getNotationDeclIndex(name);
790         if (notationIndex == -1) {
791             notationIndex = createNotationDecl();
792             setNotationDecl(notationIndex, notationDecl);
793         }
794
795     } // notationDecl(String,XMLResourceIdentifier,Augmentations)
796

797     /**
798      * The end of the DTD.
799      *
800      * @param augs Additional information that may include infoset
801      * augmentations.
802      * @throws XNIException Thrown by handler to signal an error.
803      */

804     public void endDTD(Augmentations augs) throws XNIException {
805         fIsImmutable = true;
806         // make sure our description contains useful stuff...
807
if(fGrammarDescription.getRootName() == null) {
808             // we don't know what the root is; so use possibleRoots...
809
int chunk, index = 0;
810             String JavaDoc currName = null;
811             Vector JavaDoc elements = new Vector JavaDoc();
812             for (int i=0; i < fElementDeclCount; i++) {
813                 chunk = i >> CHUNK_SHIFT;
814                 index = i & CHUNK_MASK;
815                 currName = fElementDeclName[chunk][index].rawname;
816                 elements.addElement(currName);
817             }
818             fGrammarDescription.setPossibleRoots(elements);
819         }
820     } // endDTD()
821

822     // sets the source of this handler
823
public void setDTDSource(XMLDTDSource source) {
824         fDTDSource = source;
825     } // setDTDSource(XMLDTDSource)
826

827     // returns the source of this handler
828
public XMLDTDSource getDTDSource() {
829         return fDTDSource;
830     } // getDTDSource(): XMLDTDSource
831

832     // no-op methods
833

834     /**
835      * Notifies of the presence of a TextDecl line in an entity. If present,
836      * this method will be called immediately following the startEntity call.
837      * <p>
838      * <strong>Note:</strong> This method is only called for external
839      * parameter entities referenced in the DTD.
840      *
841      * @param version The XML version, or null if not specified.
842      * @param encoding The IANA encoding name of the entity.
843      *
844      * @param augs Additional information that may include infoset
845      * augmentations.
846      * @throws XNIException Thrown by handler to signal an error.
847      */

848     public void textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs)
849         throws XNIException {}
850
851     /**
852      * A comment.
853      *
854      * @param text The text in the comment.
855      * @param augs Additional information that may include infoset
856      * augmentations.
857      * @throws XNIException Thrown by application to signal an error.
858      */

859     public void comment(XMLString text, Augmentations augs) throws XNIException {}
860
861     /**
862      * A processing instruction. Processing instructions consist of a
863      * target name and, optionally, text data. The data is only meaningful
864      * to the application.
865      * <p>
866      * Typically, a processing instruction's data will contain a series
867      * of pseudo-attributes. These pseudo-attributes follow the form of
868      * element attributes but are <strong>not</strong> parsed or presented
869      * to the application as anything other than text. The application is
870      * responsible for parsing the data.
871      *
872      * @param target The target.
873      * @param data The data or null if none specified.
874      * @param augs Additional information that may include infoset
875      * augmentations.
876      * @throws XNIException Thrown by handler to signal an error.
877      */

878     public void processingInstruction(String JavaDoc target, XMLString data,
879                                       Augmentations augs) throws XNIException {}
880
881     /**
882      * The start of an attribute list.
883      *
884      * @param elementName The name of the element that this attribute
885      * list is associated with.
886      * @param augs Additional information that may include infoset
887      * augmentations.
888      * @throws XNIException Thrown by handler to signal an error.
889      */

890     public void startAttlist(String JavaDoc elementName, Augmentations augs)
891         throws XNIException {}
892
893     /**
894      * The end of an attribute list.
895      * @param augs Additional information that may include infoset
896      * augmentations.
897      * @throws XNIException Thrown by handler to signal an error.
898      */

899     public void endAttlist(Augmentations augs) throws XNIException {}
900
901     /**
902      * The start of a conditional section.
903      *
904      * @param type The type of the conditional section. This value will
905      * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
906      * @param augs Additional information that may include infoset
907      * augmentations.
908      * @throws XNIException Thrown by handler to signal an error.
909      *
910      * @see XMLDTDHandler#CONDITIONAL_INCLUDE
911      * @see XMLDTDHandler#CONDITIONAL_IGNORE
912      */

913     public void startConditional(short type, Augmentations augs)
914         throws XNIException {}
915
916     /**
917      * Characters within an IGNORE conditional section.
918      *
919      * @param text The ignored text.
920      * @param augs Additional information that may include infoset
921      * augmentations.
922      */

923     public void ignoredCharacters(XMLString text, Augmentations augs)
924         throws XNIException {}
925
926     /**
927      * The end of a conditional section.
928      * @param augs Additional information that may include infoset
929      * augmentations.
930      * @throws XNIException Thrown by handler to signal an error.
931      */

932     public void endConditional(Augmentations augs) throws XNIException {}
933
934     //
935
// XMLDTDContentModelHandler methods
936
//
937

938     // set content model source
939
public void setDTDContentModelSource(XMLDTDContentModelSource source) {
940         fDTDContentModelSource = source;
941     }
942
943     // get content model source
944
public XMLDTDContentModelSource getDTDContentModelSource() {
945         return fDTDContentModelSource;
946     }
947
948     /**
949      * The start of a content model. Depending on the type of the content
950      * model, specific methods may be called between the call to the
951      * startContentModel method and the call to the endContentModel method.
952      *
953      * @param elementName The name of the element.
954      * @param augs Additional information that may include infoset
955      * augmentations.
956      * @throws XNIException Thrown by handler to signal an error.
957      */

958     public void startContentModel(String JavaDoc elementName, Augmentations augs)
959         throws XNIException {
960
961         XMLElementDecl elementDecl = (XMLElementDecl) this.fElementDeclTab.get( elementName);
962         if ( elementDecl != null ) {
963             fElementDecl = elementDecl;
964         }
965         fDepth = 0;
966         initializeContentModelStack();
967
968     } // startContentModel(String)
969

970     /**
971      * A start of either a mixed or children content model. A mixed
972      * content model will immediately be followed by a call to the
973      * <code>pcdata()</code> method. A children content model will
974      * contain additional groups and/or elements.
975      *
976      * @param augs Additional information that may include infoset
977      * augmentations.
978      * @throws XNIException Thrown by handler to signal an error.
979      *
980      * @see #any
981      * @see #empty
982      */

983     public void startGroup(Augmentations augs) throws XNIException {
984         fDepth++;
985         initializeContentModelStack();
986         fMixed = false;
987     } // startGroup()
988

989     /**
990      * The appearance of "#PCDATA" within a group signifying a
991      * mixed content model. This method will be the first called
992      * following the content model's <code>startGroup()</code>.
993      *
994      *@param augs Additional information that may include infoset
995      * augmentations.
996      *
997      * @throws XNIException Thrown by handler to signal an error.
998      *
999      * @see #startGroup
1000     */

1001    public void pcdata(Augmentations augs) throws XNIException {
1002        fMixed = true;
1003    } // pcdata()
1004

1005    /**
1006     * A referenced element in a mixed or children content model.
1007     *
1008     * @param elementName The name of the referenced element.
1009     * @param augs Additional information that may include infoset
1010     * augmentations.
1011     *
1012     * @throws XNIException Thrown by handler to signal an error.
1013     */

1014    public void element(String JavaDoc elementName, Augmentations augs) throws XNIException {
1015        if (fMixed) {
1016            if (fNodeIndexStack[fDepth] == -1 ) {
1017                fNodeIndexStack[fDepth] = addUniqueLeafNode(elementName);
1018            }
1019            else {
1020                fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
1021                                                             fNodeIndexStack[fDepth],
1022                                                             addUniqueLeafNode(elementName));
1023            }
1024        }
1025        else {
1026            fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, elementName);
1027        }
1028    } // element(String)
1029

1030    /**
1031     * The separator between choices or sequences of a mixed or children
1032     * content model.
1033     *
1034     * @param separator The type of children separator.
1035     * @param augs Additional information that may include infoset
1036     * augmentations.
1037     * @throws XNIException Thrown by handler to signal an error.
1038     *
1039     * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE
1040     * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE
1041     */

1042    public void separator(short separator, Augmentations augs) throws XNIException {
1043
1044        if (!fMixed) {
1045            if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_SEQ && separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE ) {
1046                if (fPrevNodeIndexStack[fDepth] != -1) {
1047                    fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
1048                }
1049                fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth];
1050                fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
1051            } else if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_CHOICE && separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) {
1052                if (fPrevNodeIndexStack[fDepth] != -1) {
1053                    fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
1054                }
1055                fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth];
1056                fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
1057            }
1058        }
1059
1060    } // separator(short)
1061

1062    /**
1063     * The occurrence count for a child in a children content model or
1064     * for the mixed content model group.
1065     *
1066     * @param occurrence The occurrence count for the last element
1067     * or group.
1068     * @param augs Additional information that may include infoset
1069     * augmentations.
1070     * @throws XNIException Thrown by handler to signal an error.
1071     *
1072     * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE
1073     * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE
1074     * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE
1075     */

1076    public void occurrence(short occurrence, Augmentations augs) throws XNIException {
1077
1078        if (!fMixed) {
1079            if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE ) {
1080                fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[fDepth], -1);
1081            } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE ) {
1082                fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[fDepth], -1 );
1083            } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) {
1084                fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[fDepth], -1 );
1085            }
1086        }
1087
1088    } // occurrence(short)
1089

1090    /**
1091     * The end of a group for mixed or children content models.
1092     *
1093     * @param augs Additional information that may include infoset
1094     * augmentations.
1095     * @throws XNIException Thrown by handler to signal an error.
1096     */

1097    public void endGroup(Augmentations augs) throws XNIException {
1098
1099        if (!fMixed) {
1100            if (fPrevNodeIndexStack[fDepth] != -1) {
1101                fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
1102            }
1103            int nodeIndex = fNodeIndexStack[fDepth--];
1104            fNodeIndexStack[fDepth] = nodeIndex;
1105        }
1106
1107    } // endGroup()
1108

1109    // no-op methods
1110

1111    /**
1112     * A content model of ANY.
1113     *
1114     * @param augs Additional information that may include infoset
1115     * augmentations.
1116     * @throws XNIException Thrown by handler to signal an error.
1117     *
1118     * @see #empty
1119     * @see #startGroup
1120     */

1121    public void any(Augmentations augs) throws XNIException {}
1122
1123    /**
1124     * A content model of EMPTY.
1125     *
1126     * @param augs Additional information that may include infoset
1127     * augmentations.
1128     * @throws XNIException Thrown by handler to signal an error.
1129     *
1130     * @see #any
1131     * @see #startGroup
1132     */

1133    public void empty(Augmentations augs) throws XNIException {}
1134
1135    /**
1136     * The end of a content model.
1137     * @param augs Additional information that may include infoset
1138     * augmentations.
1139     *
1140     * @throws XNIException Thrown by handler to signal an error.
1141     */

1142    public void endContentModel(Augmentations augs) throws XNIException {}
1143
1144    //
1145
// Grammar methods
1146
//
1147

1148    /** Returns true if this grammar is namespace aware. */
1149    public boolean isNamespaceAware() {
1150        return false;
1151    } // isNamespaceAware():boolean
1152

1153    /** Returns the symbol table. */
1154    public SymbolTable getSymbolTable() {
1155        return fSymbolTable;
1156    } // getSymbolTable():SymbolTable
1157

1158    /**
1159     * Returns the index of the first element declaration. This index
1160     * is then used to query more information about the element declaration.
1161     *
1162     * @see #getNextElementDeclIndex
1163     * @see #getElementDecl
1164     */

1165    public int getFirstElementDeclIndex() {
1166        return fElementDeclCount >= 0 ? 0 : -1;
1167    } // getFirstElementDeclIndex():int
1168

1169    /**
1170     * Returns the next index of the element declaration following the
1171     * specified element declaration.
1172     *
1173     * @param elementDeclIndex The element declaration index.
1174     */

1175    public int getNextElementDeclIndex(int elementDeclIndex) {
1176        return elementDeclIndex < fElementDeclCount - 1
1177             ? elementDeclIndex + 1 : -1;
1178    } // getNextElementDeclIndex(int):int
1179

1180    /**
1181     * getElementDeclIndex
1182     *
1183     * @param elementDeclName
1184     *
1185     * @return index of the elementDeclName in scope
1186     */

1187    public int getElementDeclIndex(String JavaDoc elementDeclName) {
1188        int mapping = fElementIndexMap.get(elementDeclName);
1189        //System.out.println("getElementDeclIndex("+elementDeclName+") -> "+mapping);
1190
return mapping;
1191    } // getElementDeclIndex(String):int
1192

1193    /** Returns the element decl index.
1194     * @param elementDeclQName qualilfied name of the element
1195     */

1196    public int getElementDeclIndex(QName elementDeclQName) {
1197        return getElementDeclIndex(elementDeclQName.rawname);
1198    } // getElementDeclIndex(QName):int
1199

1200        /** make separate function for getting contentSpecType of element.
1201      * we can avoid setting of the element values.
1202        */

1203
1204        public short getContentSpecType(int elementIndex){
1205        if (elementIndex < 0 || elementIndex >= fElementDeclCount) {
1206            return -1 ;
1207        }
1208
1209        int chunk = elementIndex >> CHUNK_SHIFT;
1210        int index = elementIndex & CHUNK_MASK;
1211            
1212        if(fElementDeclType[chunk][index] == -1){
1213            return -1 ;
1214                }
1215        else{
1216                       return (short) (fElementDeclType[chunk][index] & LIST_MASK);
1217                }
1218
1219        }//getContentSpecType
1220

1221    /**
1222     * getElementDecl
1223     *
1224     * @param elementDeclIndex
1225     * @param elementDecl The values of this structure are set by this call.
1226     *
1227     * @return True if find the element, False otherwise.
1228     */

1229    public boolean getElementDecl(int elementDeclIndex,
1230                                  XMLElementDecl elementDecl) {
1231
1232        if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1233            return false;
1234        }
1235
1236        int chunk = elementDeclIndex >> CHUNK_SHIFT;
1237        int index = elementDeclIndex & CHUNK_MASK;
1238
1239        elementDecl.name.setValues(fElementDeclName[chunk][index]);
1240
1241        if (fElementDeclType[chunk][index] == -1) {
1242            elementDecl.type = -1;
1243            elementDecl.simpleType.list = false;
1244        } else {
1245            elementDecl.type = (short) (fElementDeclType[chunk][index] & LIST_MASK);
1246            elementDecl.simpleType.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0;
1247        }
1248
1249        /* Validators are null until we add that code */
1250        if (elementDecl.type == XMLElementDecl.TYPE_CHILDREN || elementDecl.type == XMLElementDecl.TYPE_MIXED) {
1251            elementDecl.contentModelValidator = getElementContentModelValidator(elementDeclIndex);
1252        }
1253              
1254        elementDecl.simpleType.datatypeValidator = null;
1255        elementDecl.simpleType.defaultType = -1;
1256        elementDecl.simpleType.defaultValue = null;
1257
1258        return true;
1259
1260    } // getElementDecl(int,XMLElementDecl):boolean
1261

1262    // REVISIT: Make this getAttributeDeclCount/getAttributeDeclAt. -Ac
1263

1264    /**
1265     * getFirstAttributeDeclIndex
1266     *
1267     * @param elementDeclIndex
1268     *
1269     * @return index of the first attribute for element declaration elementDeclIndex
1270     */

1271    public int getFirstAttributeDeclIndex(int elementDeclIndex) {
1272        int chunk = elementDeclIndex >> CHUNK_SHIFT;
1273        int index = elementDeclIndex & CHUNK_MASK;
1274
1275        return fElementDeclFirstAttributeDeclIndex[chunk][index];
1276    } // getFirstAttributeDeclIndex
1277

1278    /**
1279     * getNextAttributeDeclIndex
1280     *
1281     * @param attributeDeclIndex
1282     *
1283     * @return index of the next attribute of the attribute at attributeDeclIndex
1284     */

1285    public int getNextAttributeDeclIndex(int attributeDeclIndex) {
1286        int chunk = attributeDeclIndex >> CHUNK_SHIFT;
1287        int index = attributeDeclIndex & CHUNK_MASK;
1288
1289        return fAttributeDeclNextAttributeDeclIndex[chunk][index];
1290    } // getNextAttributeDeclIndex
1291

1292    /**
1293     * getAttributeDecl
1294     *
1295     * @param attributeDeclIndex
1296     * @param attributeDecl The values of this structure are set by this call.
1297     *
1298     * @return true if getAttributeDecl was able to fill in the value of attributeDecl
1299     */

1300    public boolean getAttributeDecl(int attributeDeclIndex, XMLAttributeDecl attributeDecl) {
1301        if (attributeDeclIndex < 0 || attributeDeclIndex >= fAttributeDeclCount) {
1302            return false;
1303        }
1304        int chunk = attributeDeclIndex >> CHUNK_SHIFT;
1305        int index = attributeDeclIndex & CHUNK_MASK;
1306
1307        attributeDecl.name.setValues(fAttributeDeclName[chunk][index]);
1308
1309        short attributeType;
1310        boolean isList;
1311
1312        if (fAttributeDeclType[chunk][index] == -1) {
1313
1314            attributeType = -1;
1315            isList = false;
1316        } else {
1317            attributeType = (short) (fAttributeDeclType[chunk][index] & LIST_MASK);
1318            isList = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0;
1319        }
1320        attributeDecl.simpleType.setValues(attributeType,fAttributeDeclName[chunk][index].localpart,
1321                                           fAttributeDeclEnumeration[chunk][index],
1322                                           isList, fAttributeDeclDefaultType[chunk][index],
1323                                           fAttributeDeclDefaultValue[chunk][index],
1324                                           fAttributeDeclNonNormalizedDefaultValue[chunk][index],
1325                                           fAttributeDeclDatatypeValidator[chunk][index]);
1326        return true;
1327
1328    } // getAttributeDecl
1329

1330
1331    /**
1332     * Returns whether the given attribute is of type CDATA or not
1333     *
1334     * @param elName The element name.
1335     * @param atName The attribute name.
1336     *
1337     * @return true if the attribute is of type CDATA
1338     */

1339    public boolean isCDATAAttribute(QName elName, QName atName) {
1340        int elDeclIdx = getElementDeclIndex(elName);
1341        if (getAttributeDecl(elDeclIdx, fAttributeDecl)
1342            && fAttributeDecl.simpleType.type != XMLSimpleType.TYPE_CDATA){
1343            return false;
1344        }
1345        return true;
1346    }
1347
1348    /**
1349     * getEntityDeclIndex
1350     *
1351     * @param entityDeclName
1352     *
1353     * @return the index of the EntityDecl
1354     */

1355    public int getEntityDeclIndex(String JavaDoc entityDeclName) {
1356        if (entityDeclName == null) {
1357            return -1;
1358        }
1359
1360        return fEntityIndexMap.get(entityDeclName);
1361    } // getEntityDeclIndex
1362

1363    /**
1364     * getEntityDecl
1365     *
1366     * @param entityDeclIndex
1367     * @param entityDecl
1368     *
1369     * @return true if getEntityDecl was able to fill entityDecl with the contents of the entity
1370     * with index entityDeclIndex
1371     */

1372    public boolean getEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) {
1373        if (entityDeclIndex < 0 || entityDeclIndex >= fEntityCount) {
1374            return false;
1375        }
1376        int chunk = entityDeclIndex >> CHUNK_SHIFT;
1377        int index = entityDeclIndex & CHUNK_MASK;
1378
1379        entityDecl.setValues(fEntityName[chunk][index],
1380                             fEntityPublicId[chunk][index],
1381                             fEntitySystemId[chunk][index],
1382                             fEntityBaseSystemId[chunk][index],
1383                             fEntityNotation[chunk][index],
1384                             fEntityValue[chunk][index],
1385                             fEntityIsPE[chunk][index] == 0 ? false : true ,
1386                             fEntityInExternal[chunk][index] == 0 ? false : true );
1387
1388        return true;
1389    } // getEntityDecl
1390

1391    /**
1392     * getNotationDeclIndex
1393     *
1394     * @param notationDeclName
1395     *
1396     * @return the index if found a notation with the name, otherwise -1.
1397     */

1398    public int getNotationDeclIndex(String JavaDoc notationDeclName) {
1399        if (notationDeclName == null) {
1400            return -1;
1401        }
1402
1403        return fNotationIndexMap.get(notationDeclName);
1404    } // getNotationDeclIndex
1405

1406    /**
1407     * getNotationDecl
1408     *
1409     * @param notationDeclIndex
1410     * @param notationDecl
1411     *
1412     * @return return true of getNotationDecl can fill notationDecl with information about
1413     * the notation at notationDeclIndex.
1414     */

1415    public boolean getNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) {
1416        if (notationDeclIndex < 0 || notationDeclIndex >= fNotationCount) {
1417            return false;
1418        }
1419        int chunk = notationDeclIndex >> CHUNK_SHIFT;
1420        int index = notationDeclIndex & CHUNK_MASK;
1421
1422        notationDecl.setValues(fNotationName[chunk][index],
1423                               fNotationPublicId[chunk][index],
1424                               fNotationSystemId[chunk][index],
1425                               fNotationBaseSystemId[chunk][index]);
1426
1427        return true;
1428
1429    } // getNotationDecl
1430

1431    /**
1432     * getContentSpec
1433     *
1434     * @param contentSpecIndex
1435     * @param contentSpec
1436     *
1437     * @return true if find the requested contentSpec node, false otherwise
1438     */

1439    public boolean getContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) {
1440        if (contentSpecIndex < 0 || contentSpecIndex >= fContentSpecCount )
1441            return false;
1442
1443        int chunk = contentSpecIndex >> CHUNK_SHIFT;
1444        int index = contentSpecIndex & CHUNK_MASK;
1445
1446        contentSpec.type = fContentSpecType[chunk][index];
1447        contentSpec.value = fContentSpecValue[chunk][index];
1448        contentSpec.otherValue = fContentSpecOtherValue[chunk][index];
1449        return true;
1450    }
1451
1452    /**
1453     * getContentSpecAsString
1454     *
1455     * @param elementDeclIndex
1456     *
1457     * @return String
1458     */

1459    public String JavaDoc getContentSpecAsString(int elementDeclIndex){
1460
1461        if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1462            return null;
1463        }
1464
1465        int chunk = elementDeclIndex >> CHUNK_SHIFT;
1466        int index = elementDeclIndex & CHUNK_MASK;
1467
1468        int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
1469
1470        // lookup content spec node
1471
XMLContentSpec contentSpec = new XMLContentSpec();
1472
1473        if (getContentSpec(contentSpecIndex, contentSpec)) {
1474
1475            // build string
1476
StringBuffer JavaDoc str = new StringBuffer JavaDoc();
1477            int parentContentSpecType = contentSpec.type & 0x0f;
1478            int nextContentSpec;
1479            switch (parentContentSpecType) {
1480                case XMLContentSpec.CONTENTSPECNODE_LEAF: {
1481                    str.append('(');
1482                    if (contentSpec.value == null && contentSpec.otherValue == null) {
1483                        str.append("#PCDATA");
1484                    }
1485                    else {
1486                        str.append(contentSpec.value);
1487                    }
1488                    str.append(')');
1489                    break;
1490                }
1491                case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
1492                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
1493                    nextContentSpec = contentSpec.type;
1494
1495                    if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1496                        str.append('(');
1497                        str.append(contentSpec.value);
1498                        str.append(')');
1499                    } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
1500                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
1501                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
1502                        str.append('(' );
1503                        appendContentSpec(contentSpec, str,
1504                                          true, parentContentSpecType );
1505                        str.append(')');
1506                    } else {
1507                        appendContentSpec(contentSpec, str,
1508                                          true, parentContentSpecType );
1509                    }
1510                    str.append('?');
1511                    break;
1512                }
1513                case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
1514                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
1515                    nextContentSpec = contentSpec.type;
1516
1517                    if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1518                        str.append('(');
1519                        if (contentSpec.value == null && contentSpec.otherValue == null) {
1520                            str.append("#PCDATA");
1521                        }
1522                        else if (contentSpec.otherValue != null) {
1523                            str.append("##any:uri="+contentSpec.otherValue);
1524                        }
1525                        else if (contentSpec.value == null) {
1526                            str.append("##any");
1527                        }
1528                        else {
1529                            appendContentSpec(contentSpec, str,
1530                                              true, parentContentSpecType );
1531                        }
1532                        str.append(')');
1533                    } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
1534                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
1535                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
1536                        str.append('(' );
1537                        appendContentSpec(contentSpec, str,
1538                                          true, parentContentSpecType );
1539                        str.append(')');
1540                    } else {
1541                        appendContentSpec(contentSpec, str,
1542                                          true, parentContentSpecType );
1543                    }
1544                    str.append('*');
1545                    break;
1546                }
1547                case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
1548                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
1549                    nextContentSpec = contentSpec.type;
1550
1551                    if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1552                        str.append('(');
1553                        if (contentSpec.value == null && contentSpec.otherValue == null) {
1554                            str.append("#PCDATA");
1555                        }
1556                        else if (contentSpec.otherValue != null) {
1557                            str.append("##any:uri="+contentSpec.otherValue);
1558                        }
1559                        else if (contentSpec.value == null) {
1560                            str.append("##any");
1561                        }
1562                        else {
1563                            str.append(contentSpec.value);
1564                        }
1565                        str.append(')');
1566                    } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
1567                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
1568                        nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
1569                        str.append('(' );
1570                        appendContentSpec(contentSpec, str,
1571                                          true, parentContentSpecType );
1572                        str.append(')');
1573                    } else {
1574                        appendContentSpec(contentSpec, str,
1575                                          true, parentContentSpecType);
1576                    }
1577                    str.append('+');
1578                    break;
1579                }
1580                case XMLContentSpec.CONTENTSPECNODE_CHOICE:
1581                case XMLContentSpec.CONTENTSPECNODE_SEQ: {
1582                    appendContentSpec(contentSpec, str,
1583                                      true, parentContentSpecType );
1584                    break;
1585                }
1586                case XMLContentSpec.CONTENTSPECNODE_ANY: {
1587                    str.append("##any");
1588                    if (contentSpec.otherValue != null) {
1589                        str.append(":uri=");
1590                        str.append(contentSpec.otherValue);
1591                    }
1592                    break;
1593                }
1594                case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: {
1595                    str.append("##other:uri=");
1596                    str.append(contentSpec.otherValue);
1597                    break;
1598                }
1599                case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: {
1600                    str.append("##local");
1601                    break;
1602                }
1603                default: {
1604                    str.append("???");
1605                }
1606
1607            } // switch type
1608

1609            // return string
1610
return str.toString();
1611        }
1612
1613        // not found
1614
return null;
1615
1616    } // getContentSpecAsString(int):String
1617

1618    // debugging
1619

1620    public void printElements( ) {
1621        int elementDeclIndex = 0;
1622        XMLElementDecl elementDecl = new XMLElementDecl();
1623        while (getElementDecl(elementDeclIndex++, elementDecl)) {
1624
1625            System.out.println("element decl: "+elementDecl.name+
1626                               ", "+ elementDecl.name.rawname );
1627
1628            // ", "+ elementDecl.contentModelValidator.toString());
1629
}
1630    }
1631
1632    public void printAttributes(int elementDeclIndex) {
1633        int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex);
1634        System.out.print(elementDeclIndex);
1635        System.out.print(" [");
1636        while (attributeDeclIndex != -1) {
1637            System.out.print(' ');
1638            System.out.print(attributeDeclIndex);
1639            printAttribute(attributeDeclIndex);
1640            attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex);
1641            if (attributeDeclIndex != -1) {
1642                System.out.print(",");
1643            }
1644        }
1645        System.out.println(" ]");
1646    }
1647
1648    //
1649
// Protected methods
1650
//
1651

1652    /**
1653     * getElementContentModelValidator
1654     *
1655     * @param elementDeclIndex
1656     *
1657     * @return its ContentModelValidator if any.
1658     */

1659    protected ContentModelValidator getElementContentModelValidator(int elementDeclIndex) {
1660
1661        int chunk = elementDeclIndex >> CHUNK_SHIFT;
1662        int index = elementDeclIndex & CHUNK_MASK;
1663
1664        ContentModelValidator contentModel = fElementDeclContentModelValidator[chunk][index];
1665
1666        // If we have one, just return that. Otherwise, gotta create one
1667
if (contentModel != null) {
1668            return contentModel;
1669        }
1670
1671        int contentType = fElementDeclType[chunk][index];
1672        if (contentType == XMLElementDecl.TYPE_SIMPLE) {
1673            return null;
1674        }
1675
1676        // Get the type of content this element has
1677
int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
1678
1679        /***
1680        if ( contentSpecIndex == -1 )
1681            return null;
1682        /***/

1683
1684        XMLContentSpec contentSpec = new XMLContentSpec();
1685        getContentSpec( contentSpecIndex, contentSpec );
1686
1687        // And create the content model according to the spec type
1688
if ( contentType == XMLElementDecl.TYPE_MIXED ) {
1689            //
1690
// Just create a mixel content model object. This type of
1691
// content model is optimized for mixed content validation.
1692
//
1693
ChildrenList children = new ChildrenList();
1694            contentSpecTree(contentSpecIndex, contentSpec, children);
1695            contentModel = new MixedContentModel(children.qname,
1696                                                 children.type,
1697                                                 0, children.length,
1698                                                 false);
1699        } else if (contentType == XMLElementDecl.TYPE_CHILDREN) {
1700            // This method will create an optimal model for the complexity
1701
// of the element's defined model. If its simple, it will create
1702
// a SimpleContentModel object. If its a simple list, it will
1703
// create a SimpleListContentModel object. If its complex, it
1704
// will create a DFAContentModel object.
1705
//
1706
contentModel = createChildModel(contentSpecIndex);
1707        } else {
1708            throw new RuntimeException JavaDoc("Unknown content type for a element decl "
1709                                     + "in getElementContentModelValidator() in AbstractDTDGrammar class");
1710        }
1711
1712        // Add the new model to the content model for this element
1713
fElementDeclContentModelValidator[chunk][index] = contentModel;
1714
1715        return contentModel;
1716
1717    } // getElementContentModelValidator(int):ContentModelValidator
1718

1719   protected int createElementDecl() {
1720      int chunk = fElementDeclCount >> CHUNK_SHIFT;
1721      int index = fElementDeclCount & CHUNK_MASK;
1722      ensureElementDeclCapacity(chunk);
1723      fElementDeclName[chunk][index] = new QName();
1724      fElementDeclType[chunk][index] = -1;
1725      fElementDeclContentModelValidator[chunk][index] = null;
1726      fElementDeclFirstAttributeDeclIndex[chunk][index] = -1;
1727      fElementDeclLastAttributeDeclIndex[chunk][index] = -1;
1728      return fElementDeclCount++;
1729   }
1730
1731   protected void setElementDecl(int elementDeclIndex, XMLElementDecl elementDecl) {
1732      if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1733         return;
1734      }
1735      int chunk = elementDeclIndex >> CHUNK_SHIFT;
1736      int index = elementDeclIndex & CHUNK_MASK;
1737
1738      fElementDeclName[chunk][index].setValues(elementDecl.name);
1739      fElementDeclType[chunk][index] = elementDecl.type;
1740
1741      fElementDeclContentModelValidator[chunk][index] = elementDecl.contentModelValidator;
1742         
1743      if (elementDecl.simpleType.list == true ) {
1744         fElementDeclType[chunk][index] |= LIST_FLAG;
1745      }
1746
1747      fElementIndexMap.put(elementDecl.name.rawname, elementDeclIndex);
1748   }
1749
1750
1751
1752
1753   protected void putElementNameMapping(QName name, int scope,
1754                                        int elementDeclIndex) {
1755   }
1756
1757   protected void setFirstAttributeDeclIndex(int elementDeclIndex, int newFirstAttrIndex){
1758
1759      if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1760         return;
1761      }
1762
1763      int chunk = elementDeclIndex >> CHUNK_SHIFT;
1764      int index = elementDeclIndex & CHUNK_MASK;
1765
1766      fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex;
1767   }
1768   
1769   protected void setContentSpecIndex(int elementDeclIndex, int contentSpecIndex){
1770
1771      if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1772         return;
1773      }
1774
1775      int chunk = elementDeclIndex >> CHUNK_SHIFT;
1776      int index = elementDeclIndex & CHUNK_MASK;
1777
1778      fElementDeclContentSpecIndex[chunk][index] = contentSpecIndex;
1779   }
1780
1781
1782   protected int createAttributeDecl() {
1783      int chunk = fAttributeDeclCount >> CHUNK_SHIFT;
1784      int index = fAttributeDeclCount & CHUNK_MASK;
1785
1786      ensureAttributeDeclCapacity(chunk);
1787      fAttributeDeclName[chunk][index] = new QName();
1788      fAttributeDeclType[chunk][index] = -1;
1789      fAttributeDeclDatatypeValidator[chunk][index] = null;
1790      fAttributeDeclEnumeration[chunk][index] = null;
1791      fAttributeDeclDefaultType[chunk][index] = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
1792      fAttributeDeclDefaultValue[chunk][index] = null;
1793      fAttributeDeclNonNormalizedDefaultValue[chunk][index] = null;
1794      fAttributeDeclNextAttributeDeclIndex[chunk][index] = -1;
1795      return fAttributeDeclCount++;
1796   }
1797
1798
1799   protected void setAttributeDecl(int elementDeclIndex, int attributeDeclIndex,
1800                                   XMLAttributeDecl attributeDecl) {
1801      int attrChunk = attributeDeclIndex >> CHUNK_SHIFT;
1802      int attrIndex = attributeDeclIndex & CHUNK_MASK;
1803      fAttributeDeclName[attrChunk][attrIndex].setValues(attributeDecl.name);
1804      fAttributeDeclType[attrChunk][attrIndex] = attributeDecl.simpleType.type;
1805
1806      if (attributeDecl.simpleType.list) {
1807         fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG;
1808      }
1809      fAttributeDeclEnumeration[attrChunk][attrIndex] = attributeDecl.simpleType.enumeration;
1810      fAttributeDeclDefaultType[attrChunk][attrIndex] = attributeDecl.simpleType.defaultType;
1811      fAttributeDeclDatatypeValidator[attrChunk][attrIndex] = attributeDecl.simpleType.datatypeValidator;
1812
1813      fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.defaultValue;
1814      fAttributeDeclNonNormalizedDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.nonNormalizedDefaultValue;
1815
1816      int elemChunk = elementDeclIndex >> CHUNK_SHIFT;
1817      int elemIndex = elementDeclIndex & CHUNK_MASK;
1818      int index = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex];
1819      while (index != -1) {
1820         if (index == attributeDeclIndex) {
1821            break;
1822         }
1823         attrChunk = index >> CHUNK_SHIFT;
1824         attrIndex = index & CHUNK_MASK;
1825         index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex];
1826      }
1827      if (index == -1) {
1828         if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) {
1829            fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
1830         } else {
1831            index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex];
1832            attrChunk = index >> CHUNK_SHIFT;
1833            attrIndex = index & CHUNK_MASK;
1834            fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex;
1835         }
1836         fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
1837      }
1838   }
1839
1840   protected int createContentSpec() {
1841      int chunk = fContentSpecCount >> CHUNK_SHIFT;
1842      int index = fContentSpecCount & CHUNK_MASK;
1843
1844      ensureContentSpecCapacity(chunk);
1845      fContentSpecType[chunk][index] = -1;
1846      fContentSpecValue[chunk][index] = null;
1847      fContentSpecOtherValue[chunk][index] = null;
1848
1849      return fContentSpecCount++;
1850   }
1851
1852   protected void setContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) {
1853      int chunk = contentSpecIndex >> CHUNK_SHIFT;
1854      int index = contentSpecIndex & CHUNK_MASK;
1855
1856      fContentSpecType[chunk][index] = contentSpec.type;
1857      fContentSpecValue[chunk][index] = contentSpec.value;
1858      fContentSpecOtherValue[chunk][index] = contentSpec.otherValue;
1859   }
1860
1861
1862   protected int createEntityDecl() {
1863       int chunk = fEntityCount >> CHUNK_SHIFT;
1864       int index = fEntityCount & CHUNK_MASK;
1865
1866      ensureEntityDeclCapacity(chunk);
1867      fEntityIsPE[chunk][index] = 0;
1868      fEntityInExternal[chunk][index] = 0;
1869
1870      return fEntityCount++;
1871   }
1872
1873   protected void setEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) {
1874       int chunk = entityDeclIndex >> CHUNK_SHIFT;
1875       int index = entityDeclIndex & CHUNK_MASK;
1876
1877       fEntityName[chunk][index] = entityDecl.name;
1878       fEntityValue[chunk][index] = entityDecl.value;
1879       fEntityPublicId[chunk][index] = entityDecl.publicId;
1880       fEntitySystemId[chunk][index] = entityDecl.systemId;
1881       fEntityBaseSystemId[chunk][index] = entityDecl.baseSystemId;
1882       fEntityNotation[chunk][index] = entityDecl.notation;
1883       fEntityIsPE[chunk][index] = entityDecl.isPE ? (byte)1 : (byte)0;
1884       fEntityInExternal[chunk][index] = entityDecl.inExternal ? (byte)1 : (byte)0;
1885
1886       fEntityIndexMap.put(entityDecl.name, entityDeclIndex);
1887   }
1888   
1889   protected int createNotationDecl() {
1890       int chunk = fNotationCount >> CHUNK_SHIFT;
1891       ensureNotationDeclCapacity(chunk);
1892       return fNotationCount++;
1893   }
1894
1895   protected void setNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) {
1896       int chunk = notationDeclIndex >> CHUNK_SHIFT;
1897       int index = notationDeclIndex & CHUNK_MASK;
1898
1899       fNotationName[chunk][index] = notationDecl.name;
1900       fNotationPublicId[chunk][index] = notationDecl.publicId;
1901       fNotationSystemId[chunk][index] = notationDecl.systemId;
1902       fNotationBaseSystemId[chunk][index] = notationDecl.baseSystemId;
1903
1904       fNotationIndexMap.put(notationDecl.name, notationDeclIndex);
1905   }
1906
1907    /**
1908     * Create an XMLContentSpec for a single non-leaf
1909     *
1910     * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
1911     * @param nodeValue handle to an XMLContentSpec
1912     * @return handle to the newly create XMLContentSpec
1913     */

1914    protected int addContentSpecNode(short nodeType, String JavaDoc nodeValue) {
1915
1916        // create content spec node
1917
int contentSpecIndex = createContentSpec();
1918
1919        // set content spec node values
1920
fContentSpec.setValues(nodeType, nodeValue, null);
1921        setContentSpec(contentSpecIndex, fContentSpec);
1922
1923        // return index
1924
return contentSpecIndex;
1925
1926    } // addContentSpecNode(short,String):int
1927

1928    /**
1929     * create an XMLContentSpec for a leaf
1930     *
1931     * @param elementName the name (Element) for the node
1932     * @return handle to the newly create XMLContentSpec
1933     */

1934    protected int addUniqueLeafNode(String JavaDoc elementName) {
1935
1936        // create content spec node
1937
int contentSpecIndex = createContentSpec();
1938
1939        // set content spec node values
1940
fContentSpec.setValues( XMLContentSpec.CONTENTSPECNODE_LEAF,
1941                                elementName, null);
1942        setContentSpec(contentSpecIndex, fContentSpec);
1943
1944        // return index
1945
return contentSpecIndex;
1946
1947    } // addUniqueLeafNode(String):int
1948

1949    /**
1950     * Create an XMLContentSpec for a two child leaf
1951     *
1952     * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
1953     * @param leftNodeIndex handle to an XMLContentSpec
1954     * @param rightNodeIndex handle to an XMLContentSpec
1955     * @return handle to the newly create XMLContentSpec
1956     */

1957    protected int addContentSpecNode(short nodeType,
1958                                     int leftNodeIndex, int rightNodeIndex) {
1959
1960        // create content spec node
1961
int contentSpecIndex = createContentSpec();
1962
1963        // set content spec node values
1964
int[] leftIntArray = new int[1];
1965        int[] rightIntArray = new int[1];
1966
1967        leftIntArray[0] = leftNodeIndex;
1968        rightIntArray[0] = rightNodeIndex;
1969        fContentSpec.setValues(nodeType, leftIntArray, rightIntArray);
1970        setContentSpec(contentSpecIndex, fContentSpec);
1971
1972        // return index
1973
return contentSpecIndex;
1974
1975    } // addContentSpecNode(short,int,int):int
1976

1977    /** Initialize content model stack. */
1978    protected void initializeContentModelStack() {
1979
1980        if (fOpStack == null) {
1981            fOpStack = new short[8];
1982            fNodeIndexStack = new int[8];
1983            fPrevNodeIndexStack = new int[8];
1984        } else if (fDepth == fOpStack.length) {
1985            short[] newStack = new short[fDepth * 2];
1986            System.arraycopy(fOpStack, 0, newStack, 0, fDepth);
1987            fOpStack = newStack;
1988            int[] newIntStack = new int[fDepth * 2];
1989            System.arraycopy(fNodeIndexStack, 0, newIntStack, 0, fDepth);
1990            fNodeIndexStack = newIntStack;
1991            newIntStack = new int[fDepth * 2];
1992            System.arraycopy(fPrevNodeIndexStack, 0, newIntStack, 0, fDepth);
1993            fPrevNodeIndexStack = newIntStack;
1994        }
1995        fOpStack[fDepth] = -1;
1996        fNodeIndexStack[fDepth] = -1;
1997        fPrevNodeIndexStack[fDepth] = -1;
1998
1999    } // initializeContentModelStack()
2000

2001    boolean isImmutable() {
2002        return fIsImmutable;
2003    }
2004
2005    //
2006
// Private methods
2007
//
2008

2009    private void appendContentSpec(XMLContentSpec contentSpec,
2010                                   StringBuffer JavaDoc str, boolean parens,
2011                                   int parentContentSpecType ) {
2012
2013        int thisContentSpec = contentSpec.type & 0x0f;
2014        switch (thisContentSpec) {
2015            case XMLContentSpec.CONTENTSPECNODE_LEAF: {
2016                if (contentSpec.value == null && contentSpec.otherValue == null) {
2017                    str.append("#PCDATA");
2018                }
2019                else if (contentSpec.value == null && contentSpec.otherValue != null) {
2020                    str.append("##any:uri="+contentSpec.otherValue);
2021                }
2022                else if (contentSpec.value == null) {
2023                    str.append("##any");
2024                }
2025                else {
2026                    str.append(contentSpec.value);
2027                }
2028                break;
2029            }
2030            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
2031                if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
2032                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2033                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
2034                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2035                    str.append('(');
2036                    appendContentSpec(contentSpec, str, true, thisContentSpec );
2037                    str.append(')');
2038                }
2039                else {
2040                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2041                    appendContentSpec( contentSpec, str, true, thisContentSpec );
2042                }
2043                str.append('?');
2044                break;
2045            }
2046            case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
2047                if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
2048                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2049                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
2050                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2051                    str.append('(');
2052                    appendContentSpec(contentSpec, str, true, thisContentSpec);
2053                    str.append(')' );
2054                }
2055                else {
2056                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2057                    appendContentSpec(contentSpec, str, true, thisContentSpec);
2058                }
2059                str.append('*');
2060                break;
2061            }
2062            case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
2063                if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
2064                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2065                    parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
2066
2067                    str.append('(');
2068                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2069                    appendContentSpec(contentSpec, str, true, thisContentSpec);
2070                    str.append(')' );
2071                }
2072                else {
2073                    getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2074                    appendContentSpec(contentSpec, str, true, thisContentSpec);
2075                }
2076                str.append('+');
2077                break;
2078            }
2079            case XMLContentSpec.CONTENTSPECNODE_CHOICE:
2080            case XMLContentSpec.CONTENTSPECNODE_SEQ: {
2081                if (parens) {
2082                    str.append('(');
2083                }
2084                int type = contentSpec.type;
2085                int otherValue = ((int[])contentSpec.otherValue)[0];
2086                getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2087                appendContentSpec(contentSpec, str, contentSpec.type != type, thisContentSpec);
2088                if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) {
2089                    str.append('|');
2090                }
2091                else {
2092                    str.append(',');
2093                }
2094                getContentSpec(otherValue, contentSpec);
2095                appendContentSpec(contentSpec, str, true, thisContentSpec);
2096                if (parens) {
2097                    str.append(')');
2098                }
2099                break;
2100            }
2101            case XMLContentSpec.CONTENTSPECNODE_ANY: {
2102                str.append("##any");
2103                if (contentSpec.otherValue != null) {
2104                    str.append(":uri=");
2105                    str.append(contentSpec.otherValue);
2106                }
2107                break;
2108            }
2109            case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: {
2110                str.append("##other:uri=");
2111                str.append(contentSpec.otherValue);
2112                break;
2113            }
2114            case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: {
2115                str.append("##local");
2116                break;
2117            }
2118            default: {
2119                str.append("???");
2120                break;
2121            }
2122
2123        } // switch type
2124

2125    } // appendContentSpec(XMLContentSpec.Provider,StringPool,XMLContentSpec,StringBuffer,boolean)
2126

2127    // debugging
2128

2129    private void printAttribute(int attributeDeclIndex) {
2130
2131        XMLAttributeDecl attributeDecl = new XMLAttributeDecl();
2132        if (getAttributeDecl(attributeDeclIndex, attributeDecl)) {
2133            System.out.print(" { ");
2134            System.out.print(attributeDecl.name.localpart);
2135            System.out.print(" }");
2136        }
2137
2138    } // printAttribute(int)
2139

2140    // content models
2141

2142    /**
2143     * When the element has a 'CHILDREN' model, this method is called to
2144     * create the content model object. It looks for some special case simple
2145     * models and creates SimpleContentModel objects for those. For the rest
2146     * it creates the standard DFA style model.
2147     */

2148    private ContentModelValidator createChildModel(int contentSpecIndex) {
2149        
2150        //
2151
// Get the content spec node for the element we are working on.
2152
// This will tell us what kind of node it is, which tells us what
2153
// kind of model we will try to create.
2154
//
2155
XMLContentSpec contentSpec = new XMLContentSpec();
2156        getContentSpec(contentSpecIndex, contentSpec);
2157
2158        if ((contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY ||
2159            (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER ||
2160            (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
2161            // let fall through to build a DFAContentModel
2162
}
2163
2164        else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2165            //
2166
// Check that the left value is not -1, since any content model
2167
// with PCDATA should be MIXED, so we should not have gotten here.
2168
//
2169
if (contentSpec.value == null && contentSpec.otherValue == null)
2170                throw new RuntimeException JavaDoc("ImplementationMessages.VAL_NPCD");
2171
2172            //
2173
// Its a single leaf, so its an 'a' type of content model, i.e.
2174
// just one instance of one element. That one is definitely a
2175
// simple content model.
2176
//
2177

2178            fQName.setValues(null, (String JavaDoc)contentSpec.value,
2179                              (String JavaDoc)contentSpec.value, (String JavaDoc)contentSpec.otherValue);
2180            return new SimpleContentModel(contentSpec.type, fQName, null);
2181        } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
2182                    || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
2183            //
2184
// Lets see if both of the children are leafs. If so, then it
2185
// it has to be a simple content model
2186
//
2187
XMLContentSpec contentSpecLeft = new XMLContentSpec();
2188            XMLContentSpec contentSpecRight = new XMLContentSpec();
2189
2190            getContentSpec( ((int[])contentSpec.value)[0], contentSpecLeft);
2191            getContentSpec( ((int[])contentSpec.otherValue)[0], contentSpecRight);
2192
2193            if ((contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
2194                 && (contentSpecRight.type == XMLContentSpec.CONTENTSPECNODE_LEAF)) {
2195                //
2196
// Its a simple choice or sequence, so we can do a simple
2197
// content model for it.
2198
//
2199
fQName.setValues(null, (String JavaDoc)contentSpecLeft.value,
2200                                  (String JavaDoc)contentSpecLeft.value, (String JavaDoc)contentSpecLeft.otherValue);
2201                fQName2.setValues(null, (String JavaDoc)contentSpecRight.value,
2202                                  (String JavaDoc)contentSpecRight.value, (String JavaDoc)contentSpecRight.otherValue);
2203                return new SimpleContentModel(contentSpec.type, fQName, fQName2);
2204            }
2205        } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE)
2206                    || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE)
2207                    || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE)) {
2208            //
2209
// Its a repetition, so see if its one child is a leaf. If so
2210
// its a repetition of a single element, so we can do a simple
2211
// content model for that.
2212
//
2213
XMLContentSpec contentSpecLeft = new XMLContentSpec();
2214            getContentSpec(((int[])contentSpec.value)[0], contentSpecLeft);
2215    
2216            if (contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2217                //
2218
// It is, so we can create a simple content model here that
2219
// will check for this repetition. We pass -1 for the unused
2220
// right node.
2221
//
2222
fQName.setValues(null, (String JavaDoc)contentSpecLeft.value,
2223                                  (String JavaDoc)contentSpecLeft.value, (String JavaDoc)contentSpecLeft.otherValue);
2224                return new SimpleContentModel(contentSpec.type, fQName, null);
2225            }
2226        } else {
2227            throw new RuntimeException JavaDoc("ImplementationMessages.VAL_CST");
2228        }
2229
2230        //
2231
// Its not a simple content model, so here we have to create a DFA
2232
// for this element. So we create a DFAContentModel object. He
2233
// encapsulates all of the work to create the DFA.
2234
//
2235

2236        fLeafCount = 0;
2237        //int leafCount = countLeaves(contentSpecIndex);
2238
fLeafCount = 0;
2239        CMNode cmn = buildSyntaxTree(contentSpecIndex, contentSpec);
2240
2241        // REVISIT: has to be fLeafCount because we convert x+ to x,x*, one more leaf
2242
return new DFAContentModel( cmn, fLeafCount, false);
2243
2244    } // createChildModel(int):ContentModelValidator
2245

2246    private final CMNode buildSyntaxTree(int startNode,
2247                                         XMLContentSpec contentSpec) {
2248
2249        // We will build a node at this level for the new tree
2250
CMNode nodeRet = null;
2251        getContentSpec(startNode, contentSpec);
2252        if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY) {
2253            //nodeRet = new CMAny(contentSpec.type, -1, fLeafCount++);
2254
nodeRet = new CMAny(contentSpec.type, (String JavaDoc)contentSpec.otherValue, fLeafCount++);
2255        }
2256        else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
2257            nodeRet = new CMAny(contentSpec.type, (String JavaDoc)contentSpec.otherValue, fLeafCount++);
2258        }
2259        else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
2260            nodeRet = new CMAny(contentSpec.type, null, fLeafCount++);
2261        }
2262        //
2263
// If this node is a leaf, then its an easy one. We just add it
2264
// to the tree.
2265
//
2266
else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2267            //
2268
// Create a new leaf node, and pass it the current leaf count,
2269
// which is its DFA state position. Bump the leaf count after
2270
// storing it. This makes the positions zero based since we
2271
// store first and then increment.
2272
//
2273
fQName.setValues(null, (String JavaDoc)contentSpec.value,
2274                              (String JavaDoc)contentSpec.value, (String JavaDoc)contentSpec.otherValue);
2275            nodeRet = new CMLeaf(fQName, fLeafCount++);
2276        }
2277        else {
2278            //
2279
// Its not a leaf, so we have to recurse its left and maybe right
2280
// nodes. Save both values before we recurse and trash the node.
2281
final int leftNode = ((int[])contentSpec.value)[0];
2282            final int rightNode = ((int[])contentSpec.otherValue)[0];
2283
2284            if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
2285                || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
2286                //
2287
// Recurse on both children, and return a binary op node
2288
// with the two created sub nodes as its children. The node
2289
// type is the same type as the source.
2290
//
2291

2292                nodeRet = new CMBinOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec)
2293                                       , buildSyntaxTree(rightNode, contentSpec));
2294            }
2295            else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) {
2296                nodeRet = new CMUniOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec));
2297            }
2298            else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
2299                  || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE
2300                  || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
2301                nodeRet = new CMUniOp(contentSpec.type, buildSyntaxTree(leftNode, contentSpec));
2302            }
2303            else {
2304                throw new RuntimeException JavaDoc("ImplementationMessages.VAL_CST");
2305            }
2306        }
2307        // And return our new node for this level
2308
return nodeRet;
2309    }
2310   
2311    /**
2312     * Build a vector of valid QNames from Content Spec
2313     * table.
2314     *
2315     * @param contentSpecIndex
2316     * Content Spec index
2317     * @param vectorQName
2318     * Array of QName
2319     * @exception RuntimeException
2320     */

2321    private void contentSpecTree(int contentSpecIndex,
2322                                 XMLContentSpec contentSpec,
2323                                 ChildrenList children) {
2324
2325        // Handle any and leaf nodes
2326
getContentSpec( contentSpecIndex, contentSpec);
2327        if ( contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF ||
2328            (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY ||
2329            (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL ||
2330            (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
2331
2332            // resize arrays, if needed
2333
if (children.length == children.qname.length) {
2334                QName[] newQName = new QName[children.length * 2];
2335                System.arraycopy(children.qname, 0, newQName, 0, children.length);
2336                children.qname = newQName;
2337                int[] newType = new int[children.length * 2];
2338                System.arraycopy(children.type, 0, newType, 0, children.length);
2339                children.type = newType;
2340            }
2341
2342            // save values and return length
2343
children.qname[children.length] = new QName(null, (String JavaDoc)contentSpec.value,
2344                                                     (String JavaDoc) contentSpec.value,
2345                                                     (String JavaDoc) contentSpec.otherValue);
2346            children.type[children.length] = contentSpec.type;
2347            children.length++;
2348            return;
2349        }
2350
2351        //
2352
// Its not a leaf, so we have to recurse its left and maybe right
2353
// nodes. Save both values before we recurse and trash the node.
2354
//
2355
final int leftNode = contentSpec.value != null
2356                           ? ((int[])(contentSpec.value))[0] : -1;
2357        int rightNode = -1 ;
2358        if (contentSpec.otherValue != null )
2359            rightNode = ((int[])(contentSpec.otherValue))[0];
2360        else
2361            return;
2362
2363        if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE ||
2364            contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
2365            contentSpecTree(leftNode, contentSpec, children);
2366            contentSpecTree(rightNode, contentSpec, children);
2367            return;
2368        }
2369
2370        if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ||
2371            contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2372            contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
2373            contentSpecTree(leftNode, contentSpec, children);
2374            return;
2375        }
2376
2377        // error
2378
throw new RuntimeException JavaDoc("Invalid content spec type seen in contentSpecTree() method of AbstractDTDGrammar class : "+contentSpec.type);
2379
2380    } // contentSpecTree(int,XMLContentSpec,ChildrenList)
2381

2382    // ensure capacity
2383

2384    private void ensureElementDeclCapacity(int chunk) {
2385        if (chunk >= fElementDeclName.length) {
2386            fElementDeclIsExternal = resize(fElementDeclIsExternal,
2387                                     fElementDeclIsExternal.length * 2);
2388
2389            fElementDeclName = resize(fElementDeclName, fElementDeclName.length * 2);
2390            fElementDeclType = resize(fElementDeclType, fElementDeclType.length * 2);
2391            fElementDeclContentModelValidator = resize(fElementDeclContentModelValidator, fElementDeclContentModelValidator.length * 2);
2392            fElementDeclContentSpecIndex = resize(fElementDeclContentSpecIndex,fElementDeclContentSpecIndex.length * 2);
2393            fElementDeclFirstAttributeDeclIndex = resize(fElementDeclFirstAttributeDeclIndex, fElementDeclFirstAttributeDeclIndex.length * 2);
2394            fElementDeclLastAttributeDeclIndex = resize(fElementDeclLastAttributeDeclIndex, fElementDeclLastAttributeDeclIndex.length * 2);
2395        }
2396        else if (fElementDeclName[chunk] != null) {
2397            return;
2398        }
2399
2400        fElementDeclIsExternal[chunk] = new int[CHUNK_SIZE];
2401        fElementDeclName[chunk] = new QName[CHUNK_SIZE];
2402        fElementDeclType[chunk] = new short[CHUNK_SIZE];
2403        fElementDeclContentModelValidator[chunk] = new ContentModelValidator[CHUNK_SIZE];
2404        fElementDeclContentSpecIndex[chunk] = new int[CHUNK_SIZE];
2405        fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2406        fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2407        return;
2408    }
2409
2410    private void ensureAttributeDeclCapacity(int chunk) {
2411
2412        if (chunk >= fAttributeDeclName.length) {
2413            fAttributeDeclIsExternal = resize(fAttributeDeclIsExternal,
2414                                       fAttributeDeclIsExternal.length * 2);
2415            fAttributeDeclName = resize(fAttributeDeclName, fAttributeDeclName.length * 2);
2416            fAttributeDeclType = resize(fAttributeDeclType, fAttributeDeclType.length * 2);
2417            fAttributeDeclEnumeration = resize(fAttributeDeclEnumeration, fAttributeDeclEnumeration.length * 2);
2418            fAttributeDeclDefaultType = resize(fAttributeDeclDefaultType, fAttributeDeclDefaultType.length * 2);
2419            fAttributeDeclDatatypeValidator = resize(fAttributeDeclDatatypeValidator, fAttributeDeclDatatypeValidator.length * 2);
2420            fAttributeDeclDefaultValue = resize(fAttributeDeclDefaultValue, fAttributeDeclDefaultValue.length * 2);
2421            fAttributeDeclNonNormalizedDefaultValue = resize(fAttributeDeclNonNormalizedDefaultValue, fAttributeDeclNonNormalizedDefaultValue.length * 2);
2422            fAttributeDeclNextAttributeDeclIndex = resize(fAttributeDeclNextAttributeDeclIndex, fAttributeDeclNextAttributeDeclIndex.length * 2);
2423        }
2424        else if (fAttributeDeclName[chunk] != null) {
2425            return;
2426        }
2427
2428        fAttributeDeclIsExternal[chunk] = new int[CHUNK_SIZE];
2429        fAttributeDeclName[chunk] = new QName[CHUNK_SIZE];
2430        fAttributeDeclType[chunk] = new short[CHUNK_SIZE];
2431        fAttributeDeclEnumeration[chunk] = new String JavaDoc[CHUNK_SIZE][];
2432        fAttributeDeclDefaultType[chunk] = new short[CHUNK_SIZE];
2433        fAttributeDeclDatatypeValidator[chunk] = new DatatypeValidator[CHUNK_SIZE];
2434        fAttributeDeclDefaultValue[chunk] = new String JavaDoc[CHUNK_SIZE];
2435        fAttributeDeclNonNormalizedDefaultValue[chunk] = new String JavaDoc[CHUNK_SIZE];
2436        fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2437        return;
2438    }
2439   
2440    private void ensureEntityDeclCapacity(int chunk) {
2441        if (chunk >= fEntityName.length) {
2442            fEntityName = resize(fEntityName, fEntityName.length * 2);
2443            fEntityValue = resize(fEntityValue, fEntityValue.length * 2);
2444            fEntityPublicId = resize(fEntityPublicId, fEntityPublicId.length * 2);
2445            fEntitySystemId = resize(fEntitySystemId, fEntitySystemId.length * 2);
2446            fEntityBaseSystemId = resize(fEntityBaseSystemId, fEntityBaseSystemId.length * 2);
2447            fEntityNotation = resize(fEntityNotation, fEntityNotation.length * 2);
2448            fEntityIsPE = resize(fEntityIsPE, fEntityIsPE.length * 2);
2449            fEntityInExternal = resize(fEntityInExternal, fEntityInExternal.length * 2);
2450        }
2451        else if (fEntityName[chunk] != null) {
2452            return;
2453        }
2454
2455        fEntityName[chunk] = new String JavaDoc[CHUNK_SIZE];
2456        fEntityValue[chunk] = new String JavaDoc[CHUNK_SIZE];
2457        fEntityPublicId[chunk] = new String JavaDoc[CHUNK_SIZE];
2458        fEntitySystemId[chunk] = new String JavaDoc[CHUNK_SIZE];
2459        fEntityBaseSystemId[chunk] = new String JavaDoc[CHUNK_SIZE];
2460        fEntityNotation[chunk] = new String JavaDoc[CHUNK_SIZE];
2461        fEntityIsPE[chunk] = new byte[CHUNK_SIZE];
2462        fEntityInExternal[chunk] = new byte[CHUNK_SIZE];
2463        return;
2464    }
2465      
2466    private void ensureNotationDeclCapacity(int chunk) {
2467        if (chunk >= fNotationName.length) {
2468            fNotationName = resize(fNotationName, fNotationName.length * 2);
2469            fNotationPublicId = resize(fNotationPublicId, fNotationPublicId.length * 2);
2470            fNotationSystemId = resize(fNotationSystemId, fNotationSystemId.length * 2);
2471            fNotationBaseSystemId = resize(fNotationBaseSystemId, fNotationBaseSystemId.length * 2);
2472        }
2473        else if (fNotationName[chunk] != null) {
2474            return;
2475        }
2476
2477        fNotationName[chunk] = new String JavaDoc[CHUNK_SIZE];
2478        fNotationPublicId[chunk] = new String JavaDoc[CHUNK_SIZE];
2479        fNotationSystemId[chunk] = new String JavaDoc[CHUNK_SIZE];
2480        fNotationBaseSystemId[chunk] = new String JavaDoc[CHUNK_SIZE];
2481        return;
2482    }
2483
2484    private void ensureContentSpecCapacity(int chunk) {
2485        if (chunk >= fContentSpecType.length) {
2486            fContentSpecType = resize(fContentSpecType, fContentSpecType.length * 2);
2487            fContentSpecValue = resize(fContentSpecValue, fContentSpecValue.length * 2);
2488            fContentSpecOtherValue = resize(fContentSpecOtherValue, fContentSpecOtherValue.length * 2);
2489        }
2490        else if (fContentSpecType[chunk] != null) {
2491            return;
2492        }
2493
2494        fContentSpecType[chunk] = new short[CHUNK_SIZE];
2495        fContentSpecValue[chunk] = new Object JavaDoc[CHUNK_SIZE];
2496        fContentSpecOtherValue[chunk] = new Object JavaDoc[CHUNK_SIZE];
2497        return;
2498    }
2499
2500    //
2501
// Private static methods
2502
//
2503

2504    // resize chunks
2505

2506    private static byte[][] resize(byte array[][], int newsize) {
2507        byte newarray[][] = new byte[newsize][];
2508        System.arraycopy(array, 0, newarray, 0, array.length);
2509        return newarray;
2510    }
2511   
2512    private static short[][] resize(short array[][], int newsize) {
2513        short newarray[][] = new short[newsize][];
2514        System.arraycopy(array, 0, newarray, 0, array.length);
2515        return newarray;
2516    }
2517
2518    private static int[][] resize(int array[][], int newsize) {
2519        int newarray[][] = new int[newsize][];
2520        System.arraycopy(array, 0, newarray, 0, array.length);
2521        return newarray;
2522    }
2523
2524    private static DatatypeValidator[][] resize(DatatypeValidator array[][], int newsize) {
2525        DatatypeValidator newarray[][] = new DatatypeValidator[newsize][];
2526        System.arraycopy(array, 0, newarray, 0, array.length);
2527        return newarray;
2528    }
2529
2530    private static ContentModelValidator[][] resize(ContentModelValidator array[][], int newsize) {
2531        ContentModelValidator newarray[][] = new ContentModelValidator[newsize][];
2532        System.arraycopy(array, 0, newarray, 0, array.length);
2533        return newarray;
2534    }
2535
2536    private static Object JavaDoc[][] resize(Object JavaDoc array[][], int newsize) {
2537        Object JavaDoc newarray[][] = new Object JavaDoc[newsize][];
2538        System.arraycopy(array, 0, newarray, 0, array.length);
2539        return newarray;
2540    }
2541
2542    private static QName[][] resize(QName array[][], int newsize) {
2543        QName newarray[][] = new QName[newsize][];
2544        System.arraycopy(array, 0, newarray, 0, array.length);
2545        return newarray;
2546    }
2547
2548    private static String JavaDoc[][] resize(String JavaDoc array[][], int newsize) {
2549        String JavaDoc newarray[][] = new String JavaDoc[newsize][];
2550        System.arraycopy(array, 0, newarray, 0, array.length);
2551        return newarray;
2552    }
2553
2554    private static String JavaDoc[][][] resize(String JavaDoc array[][][], int newsize) {
2555        String JavaDoc newarray[][][] = new String JavaDoc[newsize] [][];
2556        System.arraycopy(array, 0, newarray, 0, array.length);
2557        return newarray;
2558    }
2559
2560    //
2561
// Classes
2562
//
2563

2564    /**
2565     * Children list for <code>contentSpecTree</code> method.
2566     *
2567     * @xerces.internal
2568     *
2569     * @author Eric Ye, IBM
2570     */

2571    private static class ChildrenList {
2572       
2573        //
2574
// Data
2575
//
2576

2577        /** Length. */
2578        public int length = 0;
2579
2580        // NOTE: The following set of data is mutually exclusive. It is
2581
// written this way because Java doesn't have a native
2582
// union data structure. -Ac
2583

2584        /** Left and right children names. */
2585        public QName[] qname = new QName[2];
2586
2587        /** Left and right children types. */
2588        public int[] type = new int[2];
2589        
2590        //
2591
// Constructors
2592
//
2593

2594        public ChildrenList () {}
2595
2596    } // class ChildrenList
2597

2598    //
2599
// Classes
2600
//
2601

2602    /**
2603     * A simple Hashtable implementation that takes a tuple (String, String)
2604     * as the key and a int as value.
2605     *
2606     * @xerces.internal
2607     *
2608     * @author Eric Ye, IBM
2609     * @author Andy Clark, IBM
2610     */

2611    protected static final class QNameHashtable {
2612    
2613        //
2614
// Constants
2615
//
2616

2617        /** Initial bucket size (4). */
2618        private static final int INITIAL_BUCKET_SIZE = 4;
2619
2620        // NOTE: Changed previous hashtable size from 512 to 101 so
2621
// that we get a better distribution for hashing. -Ac
2622
/** Hashtable size (101). */
2623        private static final int HASHTABLE_SIZE = 101;
2624
2625        //
2626
// Data
2627
//
2628
private Object JavaDoc[][] fHashTable = new Object JavaDoc[HASHTABLE_SIZE][];
2629
2630        //
2631
// Public methods
2632
//
2633
/** Associates the given value with the specified key tuple. */
2634        public void put(String JavaDoc key, int value) {
2635
2636            int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE;
2637            Object JavaDoc[] bucket = fHashTable[hash];
2638
2639            if (bucket == null) {
2640                bucket = new Object JavaDoc[1 + 2*INITIAL_BUCKET_SIZE];
2641                bucket[0] = new int[]{1};
2642                bucket[1] = key;
2643                bucket[2] = new int[]{value};
2644                fHashTable[hash] = bucket;
2645            } else {
2646                int count = ((int[])bucket[0])[0];
2647                int offset = 1 + 2*count;
2648                if (offset == bucket.length) {
2649                    int newSize = count + INITIAL_BUCKET_SIZE;
2650                    Object JavaDoc[] newBucket = new Object JavaDoc[1 + 2*newSize];
2651                    System.arraycopy(bucket, 0, newBucket, 0, offset);
2652                    bucket = newBucket;
2653                    fHashTable[hash] = bucket;
2654                }
2655                boolean found = false;
2656                int j=1;
2657                for (int i=0; i<count; i++){
2658                    if ((String JavaDoc)bucket[j] == key) {
2659                        ((int[])bucket[j+1])[0] = value;
2660                        found = true;
2661                        break;
2662                    }
2663                    j += 2;
2664                }
2665                if (! found) {
2666                    bucket[offset++] = key;
2667                    bucket[offset]= new int[]{value};
2668                    ((int[])bucket[0])[0] = ++count;
2669                }
2670
2671            }
2672            //System.out.println("put("+key+" -> "+value+')');
2673
//System.out.println("get("+key+") -> "+get(key));
2674

2675        } // put(int,String,String,int)
2676

2677        /** Returns the value associated with the specified key tuple. */
2678        public int get(String JavaDoc key) {
2679            int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE;
2680            Object JavaDoc[] bucket = fHashTable[hash];
2681
2682            if (bucket == null) {
2683                return -1;
2684            }
2685            int count = ((int[])bucket[0])[0];
2686
2687            int j=1;
2688            for (int i=0; i<count; i++){
2689                if ((String JavaDoc)bucket[j] == key) {
2690                    return ((int[])bucket[j+1])[0];
2691                }
2692                j += 2;
2693            }
2694            return -1;
2695
2696        } // get(int,String,String)
2697

2698    } // class QNameHashtable
2699

2700    //
2701
// EntityState methods
2702
//
2703
public boolean isEntityDeclared (String JavaDoc name){
2704        return (getEntityDeclIndex(name)!=-1)?true:false;
2705    }
2706
2707    public boolean isEntityUnparsed (String JavaDoc name){
2708        int entityIndex = getEntityDeclIndex(name);
2709        if (entityIndex >-1) {
2710            int chunk = entityIndex >> CHUNK_SHIFT;
2711            int index = entityIndex & CHUNK_MASK;
2712            //for unparsed entity notation!=null
2713
return (fEntityNotation[chunk][index]!=null)?true:false;
2714        }
2715        return false;
2716    }
2717} // class DTDGrammar
2718
Popular Tags