1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.xerces.impl.dtd;
19
20 import java.util.Hashtable;
21 import java.util.Vector;
22
23 import org.apache.xerces.impl.dtd.models.CMAny;
24 import org.apache.xerces.impl.dtd.models.CMBinOp;
25 import org.apache.xerces.impl.dtd.models.CMLeaf;
26 import org.apache.xerces.impl.dtd.models.CMNode;
27 import org.apache.xerces.impl.dtd.models.CMUniOp;
28 import org.apache.xerces.impl.dtd.models.ContentModelValidator;
29 import org.apache.xerces.impl.dtd.models.DFAContentModel;
30 import org.apache.xerces.impl.dtd.models.MixedContentModel;
31 import org.apache.xerces.impl.dtd.models.SimpleContentModel;
32 import org.apache.xerces.impl.dv.DatatypeValidator;
33 import org.apache.xerces.impl.validation.EntityState;
34 import org.apache.xerces.util.SymbolTable;
35 import org.apache.xerces.xni.Augmentations;
36 import org.apache.xerces.xni.QName;
37 import org.apache.xerces.xni.XMLDTDContentModelHandler;
38 import org.apache.xerces.xni.XMLDTDHandler;
39 import org.apache.xerces.xni.XMLLocator;
40 import org.apache.xerces.xni.XMLResourceIdentifier;
41 import org.apache.xerces.xni.XMLString;
42 import org.apache.xerces.xni.XNIException;
43 import org.apache.xerces.xni.grammars.Grammar;
44 import org.apache.xerces.xni.grammars.XMLGrammarDescription;
45 import org.apache.xerces.xni.parser.XMLDTDContentModelSource;
46 import org.apache.xerces.xni.parser.XMLDTDSource;
47
48 /**
49 * A DTD grammar. This class implements the XNI handler interfaces
50 * for DTD information so that it can build the approprate validation
51 * structures automatically from the callbacks.
52 *
53 * @xerces.internal
54 *
55 * @author Eric Ye, IBM
56 * @author Jeffrey Rodriguez, IBM
57 * @author Andy Clark, IBM
58 * @author Neil Graham, IBM
59 *
60 * @version $Id: DTDGrammar.java 572055 2007-09-02 17:55:43Z mrglavas $
61 */
62 public class DTDGrammar
63 implements XMLDTDHandler, XMLDTDContentModelHandler, EntityState, Grammar {
64
65 //
66 // Constants
67 //
68
69 /** Top level scope (-1). */
70 public static final int TOP_LEVEL_SCOPE = -1;
71
72 // private
73
74 /** Chunk shift (8). */
75 private static final int CHUNK_SHIFT = 8; // 2^8 = 256
76
77 /** Chunk size (1 << CHUNK_SHIFT). */
78 private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
79
80 /** Chunk mask (CHUNK_SIZE - 1). */
81 private static final int CHUNK_MASK = CHUNK_SIZE - 1;
82
83 /** Initial chunk count (1 << (10 - CHUNK_SHIFT)). */
84 private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k
85
86 /** List flag (0x80). */
87 private static final short LIST_FLAG = 0x80;
88
89 /** List mask (~LIST_FLAG). */
90 private static final short LIST_MASK = ~LIST_FLAG;
91
92 // debugging
93
94 /** Debug DTDGrammar. */
95 private static final boolean DEBUG = false;
96
97 //
98 // Data
99 //
100
101 protected XMLDTDSource fDTDSource = null;
102 protected XMLDTDContentModelSource fDTDContentModelSource = null;
103
104 /** Current element index. */
105 protected int fCurrentElementIndex;
106
107 /** Current attribute index. */
108 protected int fCurrentAttributeIndex;
109
110 /** fReadingExternalDTD */
111 protected boolean fReadingExternalDTD = false;
112
113 /** Symbol table. */
114 private SymbolTable fSymbolTable;
115
116 // The XMLDTDDescription with which this Grammar is associated
117 protected XMLDTDDescription fGrammarDescription = null;
118
119 // element declarations
120
121 /** Number of element declarations. */
122 private int fElementDeclCount = 0;
123
124 /** Element declaration name. */
125 private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
126
127 /**
128 * Element declaration type.
129 * @see XMLElementDecl
130 */
131 private short fElementDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
132
133 /**
134 * Element declaration content spec index. This index value is used
135 * to refer to the content spec information tables.
136 */
137 private int fElementDeclContentSpecIndex[][] = new int[INITIAL_CHUNK_COUNT][];
138
139 /**
140 * Element declaration content model validator. This validator is
141 * constructed from the content spec nodes.
142 */
143 private ContentModelValidator fElementDeclContentModelValidator[][] = new ContentModelValidator[INITIAL_CHUNK_COUNT][];
144
145 /** First attribute declaration of an element declaration. */
146 private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
147
148 /** Last attribute declaration of an element declaration. */
149 private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
150
151 // attribute declarations
152
153 /** Number of attribute declarations. */
154 private int fAttributeDeclCount = 0 ;
155
156 /** Attribute declaration name. */
157 private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
158
159 // is this grammar immutable? (fully constructed and not changeable)
160 private boolean fIsImmutable = false;
161
162 /**
163 * Attribute declaration type.
164 * @see XMLAttributeDecl
165 */
166 private short fAttributeDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
167
168 /** Attribute declaration enumeration values. */
169 private String[] fAttributeDeclEnumeration[][] = new String[INITIAL_CHUNK_COUNT][][];
170 private short fAttributeDeclDefaultType[][] = new short[INITIAL_CHUNK_COUNT][];
171 private DatatypeValidator fAttributeDeclDatatypeValidator[][] = new DatatypeValidator[INITIAL_CHUNK_COUNT][];
172 private String fAttributeDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
173 private String fAttributeDeclNonNormalizedDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
174 private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
175
176 // content specs
177
178 // here saves the content spec binary trees for element decls,
179 // each element with a content model will hold a pointer which is
180 // the index of the head node of the content spec tree.
181
182 private int fContentSpecCount = 0;
183 private short fContentSpecType[][] = new short[INITIAL_CHUNK_COUNT][];
184 private Object fContentSpecValue[][] = new Object[INITIAL_CHUNK_COUNT][];
185 private Object fContentSpecOtherValue[][] = new Object[INITIAL_CHUNK_COUNT][];
186
187 // entities
188
189 private int fEntityCount = 0;
190 private String fEntityName[][] = new String[INITIAL_CHUNK_COUNT][];
191 private String[][] fEntityValue = new String[INITIAL_CHUNK_COUNT][];
192 private String[][] fEntityPublicId = new String[INITIAL_CHUNK_COUNT][];
193 private String[][] fEntitySystemId = new String[INITIAL_CHUNK_COUNT][];
194 private String[][] fEntityBaseSystemId = new String[INITIAL_CHUNK_COUNT][];
195 private String[][] fEntityNotation = new String[INITIAL_CHUNK_COUNT][];
196 private byte[][] fEntityIsPE = new byte[INITIAL_CHUNK_COUNT][];
197 private byte[][] fEntityInExternal = new byte[INITIAL_CHUNK_COUNT][];
198
199 // notations
200
201 private int fNotationCount = 0;
202 private String fNotationName[][] = new String[INITIAL_CHUNK_COUNT][];
203 private String[][] fNotationPublicId = new String[INITIAL_CHUNK_COUNT][];
204 private String[][] fNotationSystemId = new String[INITIAL_CHUNK_COUNT][];
205 private String[][] fNotationBaseSystemId = new String[INITIAL_CHUNK_COUNT][];
206
207 // other information
208
209 /** Element index mapping table. */
210 private QNameHashtable fElementIndexMap = new QNameHashtable();
211
212 /** Entity index mapping table. */
213 private QNameHashtable fEntityIndexMap = new QNameHashtable();
214
215 /** Notation index mapping table. */
216 private QNameHashtable fNotationIndexMap = new QNameHashtable();
217
218 // temp variables
219
220 /** Mixed. */
221 private boolean fMixed;
222
223 /** Temporary qualified name. */
224 private final QName fQName = new QName();
225
226 /** Temporary qualified name. */
227 private final QName fQName2 = new QName();
228
229 /** Temporary Attribute decl. */
230 protected final XMLAttributeDecl fAttributeDecl = new XMLAttributeDecl();
231
232 // for buildSyntaxTree method
233
234 private int fLeafCount = 0;
235 private int fEpsilonIndex = -1;
236
237 /** Element declaration. */
238 private XMLElementDecl fElementDecl = new XMLElementDecl();
239
240 /** Entity declaration. */
241 private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
242
243 /** Simple type. */
244 private XMLSimpleType fSimpleType = new XMLSimpleType();
245
246 /** Content spec node. */
247 private XMLContentSpec fContentSpec = new XMLContentSpec();
248
249 /** table of XMLElementDecl */
250 Hashtable fElementDeclTab = new Hashtable();
251
252 /** Children content model operation stack. */
253 private short[] fOpStack = null;
254
255 /** Children content model index stack. */
256 private int[] fNodeIndexStack = null;
257
258 /** Children content model previous node index stack. */
259 private int[] fPrevNodeIndexStack = null;
260
261 /** Stack depth */
262 private int fDepth = 0;
263
264 /** Entity stack. */
265 private boolean[] fPEntityStack = new boolean[4];
266 private int fPEDepth = 0;
267
268 // additional fields(columns) for the element Decl pool in the Grammar
269
270 /** flag if the elementDecl is External. */
271 private int fElementDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][];
272
273
274 // additional fields(columns) for the attribute Decl pool in the Grammar
275
276 /** flag if the AttributeDecl is External. */
277 private int fAttributeDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][];
278
279 // for mixedElement method
280
281 int valueIndex = -1;
282 int prevNodeIndex = -1;
283 int nodeIndex = -1;
284
285 //
286 // Constructors
287 //
288
289 /** Default constructor. */
290 public DTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) {
291 fSymbolTable = symbolTable;
292 fGrammarDescription = desc;
293 } // <init>(SymbolTable)
294
295 // Grammar methods
296
297 // return the XMLDTDDescription object with which this is associated
298 public XMLGrammarDescription getGrammarDescription() {
299 return fGrammarDescription;
300 } // getGrammarDescription(): XMLGrammarDescription
301
302 //
303 // Public methods
304 //
305
306 /**
307 * Returns true if the specified element declaration is external.
308 *
309 * @param elementDeclIndex The element declaration index.
310 */
311 public boolean getElementDeclIsExternal(int elementDeclIndex) {
312
313 if (elementDeclIndex < 0) {
314 return false;
315 }
316
317 int chunk = elementDeclIndex >> CHUNK_SHIFT;
318 int index = elementDeclIndex & CHUNK_MASK;
319 return (fElementDeclIsExternal[chunk][index] != 0);
320
321 } // getElementDeclIsExternal(int):boolean
322
323 /**
324 * Returns true if the specified attribute declaration is external.
325 *
326 * @param attributeDeclIndex Attribute declaration index.
327 */
328 public boolean getAttributeDeclIsExternal(int attributeDeclIndex) {
329
330 if (attributeDeclIndex < 0) {
331 return false;
332 }
333
334 int chunk = attributeDeclIndex >> CHUNK_SHIFT;
335 int index = attributeDeclIndex & CHUNK_MASK;
336 return (fAttributeDeclIsExternal[chunk][index] != 0);
337 }
338
339 public int getAttributeDeclIndex(int elementDeclIndex, String attributeDeclName) {
340 if (elementDeclIndex == -1) {
341 return -1;
342 }
343 int attDefIndex = getFirstAttributeDeclIndex(elementDeclIndex);
344 while (attDefIndex != -1) {
345 getAttributeDecl(attDefIndex, fAttributeDecl);
346
347 if (fAttributeDecl.name.rawname == attributeDeclName
348 || attributeDeclName.equals(fAttributeDecl.name.rawname) ) {
349 return attDefIndex;
350 }
351 attDefIndex = getNextAttributeDeclIndex(attDefIndex);
352 }
353 return -1;
354 } // getAttributeDeclIndex (int,QName)
355
356 //
357 // XMLDTDHandler methods
358 //
359
360 /**
361 * The start of the DTD.
362 *
363 * @param locator The document locator, or null if the document
364 * location cannot be reported during the parsing of
365 * the document DTD. However, it is <em>strongly</em>
366 * recommended that a locator be supplied that can
367 * at least report the base system identifier of the
368 * DTD.
369 *
370 * @param augs Additional information that may include infoset
371 * augmentations.
372 * @throws XNIException Thrown by handler to signal an error.
373 */
374 public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
375 //Initialize stack
376 fOpStack = null;
377 fNodeIndexStack = null;
378 fPrevNodeIndexStack = null;
379 } // startDTD(XMLLocator)
380
381 /**
382 * This method notifies of the start of an entity. The DTD has the
383 * pseudo-name of "[dtd]" and parameter entity names start with '%'.
384 * <p>
385 * <strong>Note:</strong> Since the DTD is an entity, the handler
386 * will be notified of the start of the DTD entity by calling the
387 * startParameterEntity method with the entity name "[dtd]" <em>before</em> calling
388 * the startDTD method.
389 *
390 * @param name The name of the parameter entity.
391 * @param identifier The resource identifier.
392 * @param encoding The auto-detected IANA encoding name of the entity
393 * stream. This value will be null in those situations
394 * where the entity encoding is not auto-detected (e.g.
395 * internal parameter entities).
396 * @param augs Additional information that may include infoset
397 * augmentations.
398 *
399 * @throws XNIException Thrown by handler to signal an error.
400 */
401 public void startParameterEntity(String name,
402 XMLResourceIdentifier identifier,
403 String encoding,
404 Augmentations augs) throws XNIException {
405
406 // keep track of this entity before fEntityDepth is increased
407 if (fPEDepth == fPEntityStack.length) {
408 boolean[] entityarray = new boolean[fPEntityStack.length * 2];
409 System.arraycopy(fPEntityStack, 0, entityarray, 0, fPEntityStack.length);
410 fPEntityStack = entityarray;
411 }
412 fPEntityStack[fPEDepth] = fReadingExternalDTD;
413 fPEDepth++;
414
415 } // startParameterEntity(String,XMLResourceIdentifier,String,Augmentations)
416
417 /**
418 * The start of the DTD external subset.
419 *
420 * @param augs Additional information that may include infoset
421 * augmentations.
422 *
423 * @throws XNIException Thrown by handler to signal an error.
424 */
425 public void startExternalSubset(XMLResourceIdentifier identifier,
426 Augmentations augs) throws XNIException {
427 fReadingExternalDTD = true;
428 } // startExternalSubset(Augmentations)
429
430 /**
431 * This method notifies the end of an entity. The DTD has the pseudo-name
432 * of "[dtd]" and parameter entity names start with '%'.
433 * <p>
434 * <strong>Note:</strong> Since the DTD is an entity, the handler
435 * will be notified of the end of the DTD entity by calling the
436 * endEntity method with the entity name "[dtd]" <em>after</em> calling
437 * the endDTD method.
438 *
439 * @param name The name of the entity.
440 * @param augs Additional information that may include infoset
441 * augmentations.
442 * @throws XNIException Thrown by handler to signal an error.
443 */
444 public void endParameterEntity(String name, Augmentations augs) throws XNIException {
445
446 fPEDepth--;
447 fReadingExternalDTD = fPEntityStack[fPEDepth];
448
449 } // endParameterEntity(String,Augmentations)
450
451 /**
452 * The end of the DTD external subset.
453 *
454 * @param augs Additional information that may include infoset
455 * augmentations.
456 *
457 * @throws XNIException Thrown by handler to signal an error.
458 */
459 public void endExternalSubset(Augmentations augs) throws XNIException {
460 fReadingExternalDTD = false;
461 } // endExternalSubset(Augmentations)
462
463 /**
464 * An element declaration.
465 *
466 * @param name The name of the element.
467 * @param contentModel The element content model.
468 * @param augs Additional information that may include infoset
469 * augmentations.
470 * @throws XNIException Thrown by handler to signal an error.
471 */
472 public void elementDecl(String name, String contentModel, Augmentations augs)
473 throws XNIException {
474
475 XMLElementDecl tmpElementDecl = (XMLElementDecl) fElementDeclTab.get(name) ;
476
477 // check if it is already defined
478 if ( tmpElementDecl != null ) {
479 if (tmpElementDecl.type == -1) {
480 fCurrentElementIndex = getElementDeclIndex(name);
481 }
482 else {
483 // duplicate element, ignored.
484 return;
485 }
486 }
487 else {
488 fCurrentElementIndex = createElementDecl();//create element decl
489 }
490
491 XMLElementDecl elementDecl = new XMLElementDecl();
492
493 fQName.setValues(null, name, name, null);
494
495 elementDecl.name.setValues(fQName);
496
497 elementDecl.contentModelValidator = null;
498 elementDecl.scope= -1;
499 if (contentModel.equals("EMPTY")) {
500 elementDecl.type = XMLElementDecl.TYPE_EMPTY;
501 }
502 else if (contentModel.equals("ANY")) {
503 elementDecl.type = XMLElementDecl.TYPE_ANY;
504 }
505 else if (contentModel.startsWith("(") ) {
506 if (contentModel.indexOf("#PCDATA") > 0 ) {
507 elementDecl.type = XMLElementDecl.TYPE_MIXED;
508 }
509 else {
510 elementDecl.type = XMLElementDecl.TYPE_CHILDREN;
511 }
512 }
513
514
515 //add(or set) this elementDecl to the local cache
516 this.fElementDeclTab.put(name, elementDecl );
517
518 fElementDecl = elementDecl;
519 addContentSpecToElement(elementDecl);
520
521 if ( DEBUG ) {
522 System.out.println( "name = " + fElementDecl.name.localpart );
523 System.out.println( "Type = " + fElementDecl.type );
524 }
525
526 setElementDecl(fCurrentElementIndex, fElementDecl );//set internal structure
527
528 int chunk = fCurrentElementIndex >> CHUNK_SHIFT;
529 int index = fCurrentElementIndex & CHUNK_MASK;
530 ensureElementDeclCapacity(chunk);
531 fElementDeclIsExternal[chunk][index] = (fReadingExternalDTD || fPEDepth > 0) ? 1 : 0;
532
533 } // elementDecl(String,String)
534
535 /**
536 * An attribute declaration.
537 *
538 * @param elementName The name of the element that this attribute
539 * is associated with.
540 * @param attributeName The name of the attribute.
541 * @param type The attribute type. This value will be one of
542 * the following: "CDATA", "ENTITY", "ENTITIES",
543 * "ENUMERATION", "ID", "IDREF", "IDREFS",
544 * "NMTOKEN", "NMTOKENS", or "NOTATION".
545 * @param enumeration If the type has the value "ENUMERATION", this
546 * array holds the allowed attribute values;
547 * otherwise, this array is null.
548 * @param defaultType The attribute default type. This value will be
549 * one of the following: "#FIXED", "#IMPLIED",
550 * "#REQUIRED", or null.
551 * @param defaultValue The attribute default value, or null if no
552 * default value is specified.
553 * @param nonNormalizedDefaultValue The attribute default value with no normalization
554 * performed, or null if no default value is specified.
555 *
556 * @param augs Additional information that may include infoset
557 * augmentations.
558 * @throws XNIException Thrown by handler to signal an error.
559 */
560 public void attributeDecl(String elementName, String attributeName,
561 String type, String[] enumeration,
562 String defaultType, XMLString defaultValue,
563 XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
564
565 if ( this.fElementDeclTab.containsKey( (String) elementName) ) {
566 //if ElementDecl has already being created in the Grammar then remove from table,
567 //this.fElementDeclTab.remove( (String) elementName );
568 }
569 // then it is forward reference to a element decl, create the elementDecl first.
570 else {
571 fCurrentElementIndex = createElementDecl();//create element decl
572
573 XMLElementDecl elementDecl = new XMLElementDecl();
574 elementDecl.name.setValues(null, elementName, elementName, null);
575
576 elementDecl.scope= -1;
577
578 //add(or set) this elementDecl to the local cache
579 this.fElementDeclTab.put(elementName, elementDecl );
580
581 //set internal structure
582 setElementDecl(fCurrentElementIndex, elementDecl );
583 }
584
585 //Get Grammar index to grammar array
586 int elementIndex = getElementDeclIndex(elementName);
587
588 //return, when more than one definition is provided for the same attribute of given element type
589 //only the first declaration is binding and later declarations are ignored
590 if (getAttributeDeclIndex(elementIndex, attributeName) != -1) {
591 return;
592 }
593
594 fCurrentAttributeIndex = createAttributeDecl();// Create current Attribute Decl
595
596 fSimpleType.clear();
597 if ( defaultType != null ) {
598 if ( defaultType.equals( "#FIXED") ) {
599 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_FIXED;
600 } else if ( defaultType.equals( "#IMPLIED") ) {
601 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
602 } else if ( defaultType.equals( "#REQUIRED") ) {
603 fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_REQUIRED;
604 }
605 }
606 if ( DEBUG ) {
607 System.out.println("defaultvalue = " + defaultValue.toString() );
608 }
609 fSimpleType.defaultValue = defaultValue!=null ? defaultValue.toString() : null;
610 fSimpleType.nonNormalizedDefaultValue = nonNormalizedDefaultValue!=null ? nonNormalizedDefaultValue.toString() : null;
611 fSimpleType.enumeration = enumeration;
612
613 if (type.equals("CDATA")) {
614 fSimpleType.type = XMLSimpleType.TYPE_CDATA;
615 }
616 else if ( type.equals("ID") ) {
617 fSimpleType.type = XMLSimpleType.TYPE_ID;
618 }
619 else if ( type.startsWith("IDREF") ) {
620 fSimpleType.type = XMLSimpleType.TYPE_IDREF;
621 if (type.indexOf("S") > 0) {
622 fSimpleType.list = true;
623 }
624 }
625 else if (type.equals("ENTITIES")) {
626 fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
627 fSimpleType.list = true;
628 }
629 else if (type.equals("ENTITY")) {
630 fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
631 }
632 else if (type.equals("NMTOKENS")) {
633 fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
634 fSimpleType.list = true;
635 }
636 else if (type.equals("NMTOKEN")) {
637 fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
638 }
639 else if (type.startsWith("NOTATION") ) {
640 fSimpleType.type = XMLSimpleType.TYPE_NOTATION;
641 }
642 else if (type.startsWith("ENUMERATION") ) {
643 fSimpleType.type = XMLSimpleType.TYPE_ENUMERATION;
644 }
645 else {
646 // REVISIT: Report error message. -Ac
647 System.err.println("!!! unknown attribute type "+type);
648 }
649 // REVISIT: The datatype should be stored with the attribute value
650 // and not special-cased in the XMLValidator. -Ac
651 //fSimpleType.datatypeValidator = fDatatypeValidatorFactory.createDatatypeValidator(type, null, facets, fSimpleType.list);
652
653 fQName.setValues(null, attributeName, attributeName, null);
654 fAttributeDecl.setValues( fQName, fSimpleType, false );
655
656 setAttributeDecl(elementIndex, fCurrentAttributeIndex, fAttributeDecl);
657
658 int chunk = fCurrentAttributeIndex >> CHUNK_SHIFT;
659 int index = fCurrentAttributeIndex & CHUNK_MASK;
660 ensureAttributeDeclCapacity(chunk);
661 fAttributeDeclIsExternal[chunk][index] = (fReadingExternalDTD || fPEDepth > 0) ? 1 : 0;
662
663 } // attributeDecl(String,String,String,String[],String,XMLString,XMLString, Augmentations)
664
665 /**
666 * An internal entity declaration.
667 *
668 * @param name The name of the entity. Parameter entity names start with
669 * '%', whereas the name of a general entity is just the
670 * entity name.
671 * @param text The value of the entity.
672 * @param nonNormalizedText The non-normalized value of the entity. This
673 * value contains the same sequence of characters that was in
674 * the internal entity declaration, without any entity
675 * references expanded.
676 * @param augs Additional information that may include infoset
677 * augmentations.
678 * @throws XNIException Thrown by handler to signal an error.
679 */
680 public void internalEntityDecl(String name, XMLString text,
681 XMLString nonNormalizedText,
682 Augmentations augs) throws XNIException {
683
684 int entityIndex = getEntityDeclIndex(name);
685 if( entityIndex == -1){
686 entityIndex = createEntityDecl();
687 boolean isPE = name.startsWith("%");
688 boolean inExternal = (fReadingExternalDTD || fPEDepth > 0);
689 XMLEntityDecl entityDecl = new XMLEntityDecl();
690 entityDecl.setValues(name,null,null, null, null,
691 text.toString(), isPE, inExternal);
692
693 setEntityDecl(entityIndex, entityDecl);
694 }
695
696 } // internalEntityDecl(String,XMLString,XMLString)
697
698 /**
699 * An external entity declaration.
700 *
701 * @param name The name of the entity. Parameter entity names start
702 * with '%', whereas the name of a general entity is just
703 * the entity name.
704 * @param identifier An object containing all location information
705 * pertinent to this external entity declaration.
706 * @param augs Additional information that may include infoset
707 * augmentations.
708 * @throws XNIException Thrown by handler to signal an error.
709 */
710 public void externalEntityDecl(String name,
711 XMLResourceIdentifier identifier,
712 Augmentations augs) throws XNIException {
713
714 int entityIndex = getEntityDeclIndex(name);
715 if( entityIndex == -1){
716 entityIndex = createEntityDecl();
717 boolean isPE = name.startsWith("%");
718 boolean inExternal = (fReadingExternalDTD || fPEDepth > 0);
719
720 XMLEntityDecl entityDecl = new XMLEntityDecl();
721 entityDecl.setValues(name, identifier.getPublicId(), identifier.getLiteralSystemId(),
722 identifier.getBaseSystemId(),
723 null, null, isPE, inExternal);
724
725 setEntityDecl(entityIndex, entityDecl);
726 }
727 } // externalEntityDecl(String, XMLResourceIdentifier, Augmentations)
728
729 /**
730 * An unparsed entity declaration.
731 *
732 * @param name The name of the entity.
733 * @param identifier An object containing all location information
734 * pertinent to this entity.
735 * @param notation The name of the notation.
736 * @param augs Additional information that may include infoset
737 * augmentations.
738 * @throws XNIException Thrown by handler to signal an error.
739 */
740 public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier,
741 String notation,
742 Augmentations augs) throws XNIException {
743
744 XMLEntityDecl entityDecl = new XMLEntityDecl();
745 boolean isPE = name.startsWith("%");
746 boolean inExternal = (fReadingExternalDTD || fPEDepth > 0);
747
748 entityDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(),
749 identifier.getBaseSystemId(), notation,
750 null, isPE, inExternal);
751 int entityIndex = getEntityDeclIndex(name);
752 if (entityIndex == -1) {
753 entityIndex = createEntityDecl();
754 setEntityDecl(entityIndex, entityDecl);
755 }
756
757 } // unparsedEntityDecl(String,StringXMLResourceIdentifier,Augmentations)
758
759 /**
760 * A notation declaration
761 *
762 * @param name The name of the notation.
763 * @param identifier An object containing all location information
764 * pertinent to this notation.
765 * @param augs Additional information that may include infoset
766 * augmentations.
767 * @throws XNIException Thrown by handler to signal an error.
768 */
769 public void notationDecl(String name, XMLResourceIdentifier identifier,
770 Augmentations augs) throws XNIException {
771
772 XMLNotationDecl notationDecl = new XMLNotationDecl();
773 notationDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(),
774 identifier.getBaseSystemId());
775 int notationIndex = getNotationDeclIndex(name);
776 if (notationIndex == -1) {
777 notationIndex = createNotationDecl();
778 setNotationDecl(notationIndex, notationDecl);
779 }
780
781 } // notationDecl(String,XMLResourceIdentifier,Augmentations)
782
783 /**
784 * The end of the DTD.
785 *
786 * @param augs Additional information that may include infoset
787 * augmentations.
788 * @throws XNIException Thrown by handler to signal an error.
789 */
790 public void endDTD(Augmentations augs) throws XNIException {
791 fIsImmutable = true;
792 // make sure our description contains useful stuff...
793 if(fGrammarDescription.getRootName() == null) {
794 // we don't know what the root is; so use possibleRoots...
795 int chunk, index = 0;
796 String currName = null;
797 Vector elements = new Vector();
798 for (int i=0; i < fElementDeclCount; i++) {
799 chunk = i >> CHUNK_SHIFT;
800 index = i & CHUNK_MASK;
801 currName = fElementDeclName[chunk][index].rawname;
802 elements.addElement(currName);
803 }
804 fGrammarDescription.setPossibleRoots(elements);
805 }
806 } // endDTD()
807
808 // sets the source of this handler
809 public void setDTDSource(XMLDTDSource source) {
810 fDTDSource = source;
811 } // setDTDSource(XMLDTDSource)
812
813 // returns the source of this handler
814 public XMLDTDSource getDTDSource() {
815 return fDTDSource;
816 } // getDTDSource(): XMLDTDSource
817
818 // no-op methods
819
820 /**
821 * Notifies of the presence of a TextDecl line in an entity. If present,
822 * this method will be called immediately following the startEntity call.
823 * <p>
824 * <strong>Note:</strong> This method is only called for external
825 * parameter entities referenced in the DTD.
826 *
827 * @param version The XML version, or null if not specified.
828 * @param encoding The IANA encoding name of the entity.
829 *
830 * @param augs Additional information that may include infoset
831 * augmentations.
832 * @throws XNIException Thrown by handler to signal an error.
833 */
834 public void textDecl(String version, String encoding, Augmentations augs)
835 throws XNIException {}
836
837 /**
838 * A comment.
839 *
840 * @param text The text in the comment.
841 * @param augs Additional information that may include infoset
842 * augmentations.
843 * @throws XNIException Thrown by application to signal an error.
844 */
845 public void comment(XMLString text, Augmentations augs) throws XNIException {}
846
847 /**
848 * A processing instruction. Processing instructions consist of a
849 * target name and, optionally, text data. The data is only meaningful
850 * to the application.
851 * <p>
852 * Typically, a processing instruction's data will contain a series
853 * of pseudo-attributes. These pseudo-attributes follow the form of
854 * element attributes but are <strong>not</strong> parsed or presented
855 * to the application as anything other than text. The application is
856 * responsible for parsing the data.
857 *
858 * @param target The target.
859 * @param data The data or null if none specified.
860 * @param augs Additional information that may include infoset
861 * augmentations.
862 * @throws XNIException Thrown by handler to signal an error.
863 */
864 public void processingInstruction(String target, XMLString data,
865 Augmentations augs) throws XNIException {}
866
867 /**
868 * The start of an attribute list.
869 *
870 * @param elementName The name of the element that this attribute
871 * list is associated with.
872 * @param augs Additional information that may include infoset
873 * augmentations.
874 * @throws XNIException Thrown by handler to signal an error.
875 */
876 public void startAttlist(String elementName, Augmentations augs)
877 throws XNIException {}
878
879 /**
880 * The end of an attribute list.
881 * @param augs Additional information that may include infoset
882 * augmentations.
883 * @throws XNIException Thrown by handler to signal an error.
884 */
885 public void endAttlist(Augmentations augs) throws XNIException {}
886
887 /**
888 * The start of a conditional section.
889 *
890 * @param type The type of the conditional section. This value will
891 * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
892 * @param augs Additional information that may include infoset
893 * augmentations.
894 * @throws XNIException Thrown by handler to signal an error.
895 *
896 * @see XMLDTDHandler#CONDITIONAL_INCLUDE
897 * @see XMLDTDHandler#CONDITIONAL_IGNORE
898 */
899 public void startConditional(short type, Augmentations augs)
900 throws XNIException {}
901
902 /**
903 * Characters within an IGNORE conditional section.
904 *
905 * @param text The ignored text.
906 * @param augs Additional information that may include infoset
907 * augmentations.
908 */
909 public void ignoredCharacters(XMLString text, Augmentations augs)
910 throws XNIException {}
911
912 /**
913 * The end of a conditional section.
914 * @param augs Additional information that may include infoset
915 * augmentations.
916 * @throws XNIException Thrown by handler to signal an error.
917 */
918 public void endConditional(Augmentations augs) throws XNIException {}
919
920 //
921 // XMLDTDContentModelHandler methods
922 //
923
924 // set content model source
925 public void setDTDContentModelSource(XMLDTDContentModelSource source) {
926 fDTDContentModelSource = source;
927 }
928
929 // get content model source
930 public XMLDTDContentModelSource getDTDContentModelSource() {
931 return fDTDContentModelSource;
932 }
933
934 /**
935 * The start of a content model. Depending on the type of the content
936 * model, specific methods may be called between the call to the
937 * startContentModel method and the call to the endContentModel method.
938 *
939 * @param elementName The name of the element.
940 * @param augs Additional information that may include infoset
941 * augmentations.
942 * @throws XNIException Thrown by handler to signal an error.
943 */
944 public void startContentModel(String elementName, Augmentations augs)
945 throws XNIException {
946
947 XMLElementDecl elementDecl = (XMLElementDecl) this.fElementDeclTab.get( elementName);
948 if ( elementDecl != null ) {
949 fElementDecl = elementDecl;
950 }
951 fDepth = 0;
952 initializeContentModelStack();
953
954 } // startContentModel(String)
955
956 /**
957 * A start of either a mixed or children content model. A mixed
958 * content model will immediately be followed by a call to the
959 * <code>pcdata()</code> method. A children content model will
960 * contain additional groups and/or elements.
961 *
962 * @param augs Additional information that may include infoset
963 * augmentations.
964 * @throws XNIException Thrown by handler to signal an error.
965 *
966 * @see #any
967 * @see #empty
968 */
969 public void startGroup(Augmentations augs) throws XNIException {
970 fDepth++;
971 initializeContentModelStack();
972 fMixed = false;
973 } // startGroup()
974
975 /**
976 * The appearance of "#PCDATA" within a group signifying a
977 * mixed content model. This method will be the first called
978 * following the content model's <code>startGroup()</code>.
979 *
980 *@param augs Additional information that may include infoset
981 * augmentations.
982 *
983 * @throws XNIException Thrown by handler to signal an error.
984 *
985 * @see #startGroup
986 */
987 public void pcdata(Augmentations augs) throws XNIException {
988 fMixed = true;
989 } // pcdata()
990
991 /**
992 * A referenced element in a mixed or children content model.
993 *
994 * @param elementName The name of the referenced element.
995 * @param augs Additional information that may include infoset
996 * augmentations.
997 *
998 * @throws XNIException Thrown by handler to signal an error.
999 */
1000 public void element(String elementName, Augmentations augs) throws XNIException {
1001 if (fMixed) {
1002 if (fNodeIndexStack[fDepth] == -1 ) {
1003 fNodeIndexStack[fDepth] = addUniqueLeafNode(elementName);
1004 }
1005 else {
1006 fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
1007 fNodeIndexStack[fDepth],
1008 addUniqueLeafNode(elementName));
1009 }
1010 }
1011 else {
1012 fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, elementName);
1013 }
1014 } // element(String)
1015
1016 /**
1017 * The separator between choices or sequences of a mixed or children
1018 * content model.
1019 *
1020 * @param separator The type of children separator.
1021 * @param augs Additional information that may include infoset
1022 * augmentations.
1023 * @throws XNIException Thrown by handler to signal an error.
1024 *
1025 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE
1026 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE
1027 */
1028 public void separator(short separator, Augmentations augs) throws XNIException {
1029
1030 if (!fMixed) {
1031 if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_SEQ && separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE ) {
1032 if (fPrevNodeIndexStack[fDepth] != -1) {
1033 fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
1034 }
1035 fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth];
1036 fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
1037 } else if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_CHOICE && separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) {
1038 if (fPrevNodeIndexStack[fDepth] != -1) {
1039 fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
1040 }
1041 fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth];
1042 fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
1043 }
1044 }
1045
1046 } // separator(short)
1047
1048 /**
1049 * The occurrence count for a child in a children content model or
1050 * for the mixed content model group.
1051 *
1052 * @param occurrence The occurrence count for the last element
1053 * or group.
1054 * @param augs Additional information that may include infoset
1055 * augmentations.
1056 * @throws XNIException Thrown by handler to signal an error.
1057 *
1058 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE
1059 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE
1060 * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE
1061 */
1062 public void occurrence(short occurrence, Augmentations augs) throws XNIException {
1063
1064 if (!fMixed) {
1065 if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE ) {
1066 fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[fDepth], -1);
1067 } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE ) {
1068 fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[fDepth], -1 );
1069 } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) {
1070 fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[fDepth], -1 );
1071 }
1072 }
1073
1074 } // occurrence(short)
1075
1076 /**
1077 * The end of a group for mixed or children content models.
1078 *
1079 * @param augs Additional information that may include infoset
1080 * augmentations.
1081 * @throws XNIException Thrown by handler to signal an error.
1082 */
1083 public void endGroup(Augmentations augs) throws XNIException {
1084
1085 if (!fMixed) {
1086 if (fPrevNodeIndexStack[fDepth] != -1) {
1087 fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
1088 }
1089 int nodeIndex = fNodeIndexStack[fDepth--];
1090 fNodeIndexStack[fDepth] = nodeIndex;
1091 }
1092
1093 } // endGroup()
1094
1095 // no-op methods
1096
1097 /**
1098 * A content model of ANY.
1099 *
1100 * @param augs Additional information that may include infoset
1101 * augmentations.
1102 * @throws XNIException Thrown by handler to signal an error.
1103 *
1104 * @see #empty
1105 * @see #startGroup
1106 */
1107 public void any(Augmentations augs) throws XNIException {}
1108
1109 /**
1110 * A content model of EMPTY.
1111 *
1112 * @param augs Additional information that may include infoset
1113 * augmentations.
1114 * @throws XNIException Thrown by handler to signal an error.
1115 *
1116 * @see #any
1117 * @see #startGroup
1118 */
1119 public void empty(Augmentations augs) throws XNIException {}
1120
1121 /**
1122 * The end of a content model.
1123 * @param augs Additional information that may include infoset
1124 * augmentations.
1125 *
1126 * @throws XNIException Thrown by handler to signal an error.
1127 */
1128 public void endContentModel(Augmentations augs) throws XNIException {}
1129
1130 //
1131 // Grammar methods
1132 //
1133
1134 /** Returns true if this grammar is namespace aware. */
1135 public boolean isNamespaceAware() {
1136 return false;
1137 } // isNamespaceAware():boolean
1138
1139 /** Returns the symbol table. */
1140 public SymbolTable getSymbolTable() {
1141 return fSymbolTable;
1142 } // getSymbolTable():SymbolTable
1143
1144 /**
1145 * Returns the index of the first element declaration. This index
1146 * is then used to query more information about the element declaration.
1147 *
1148 * @see #getNextElementDeclIndex
1149 * @see #getElementDecl
1150 */
1151 public int getFirstElementDeclIndex() {
1152 return fElementDeclCount >= 0 ? 0 : -1;
1153 } // getFirstElementDeclIndex():int
1154
1155 /**
1156 * Returns the next index of the element declaration following the
1157 * specified element declaration.
1158 *
1159 * @param elementDeclIndex The element declaration index.
1160 */
1161 public int getNextElementDeclIndex(int elementDeclIndex) {
1162 return elementDeclIndex < fElementDeclCount - 1
1163 ? elementDeclIndex + 1 : -1;
1164 } // getNextElementDeclIndex(int):int
1165
1166 /**
1167 * getElementDeclIndex
1168 *
1169 * @param elementDeclName
1170 *
1171 * @return index of the elementDeclName in scope
1172 */
1173 public int getElementDeclIndex(String elementDeclName) {
1174 int mapping = fElementIndexMap.get(elementDeclName);
1175 //System.out.println("getElementDeclIndex("+elementDeclName+") -> "+mapping);
1176 return mapping;
1177 } // getElementDeclIndex(String):int
1178
1179 /** Returns the element decl index.
1180 * @param elementDeclQName qualilfied name of the element
1181 */
1182 public int getElementDeclIndex(QName elementDeclQName) {
1183 return getElementDeclIndex(elementDeclQName.rawname);
1184 } // getElementDeclIndex(QName):int
1185
1186 /** make separate function for getting contentSpecType of element.
1187 * we can avoid setting of the element values.
1188 */
1189
1190 public short getContentSpecType(int elementIndex){
1191 if (elementIndex < 0 || elementIndex >= fElementDeclCount) {
1192 return -1 ;
1193 }
1194
1195 int chunk = elementIndex >> CHUNK_SHIFT;
1196 int index = elementIndex & CHUNK_MASK;
1197
1198 if(fElementDeclType[chunk][index] == -1){
1199 return -1 ;
1200 }
1201 else{
1202 return (short) (fElementDeclType[chunk][index] & LIST_MASK);
1203 }
1204
1205 }//getContentSpecType
1206
1207 /**
1208 * getElementDecl
1209 *
1210 * @param elementDeclIndex
1211 * @param elementDecl The values of this structure are set by this call.
1212 *
1213 * @return True if find the element, False otherwise.
1214 */
1215 public boolean getElementDecl(int elementDeclIndex,
1216 XMLElementDecl elementDecl) {
1217
1218 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1219 return false;
1220 }
1221
1222 int chunk = elementDeclIndex >> CHUNK_SHIFT;
1223 int index = elementDeclIndex & CHUNK_MASK;
1224
1225 elementDecl.name.setValues(fElementDeclName[chunk][index]);
1226
1227 if (fElementDeclType[chunk][index] == -1) {
1228 elementDecl.type = -1;
1229 elementDecl.simpleType.list = false;
1230 } else {
1231 elementDecl.type = (short) (fElementDeclType[chunk][index] & LIST_MASK);
1232 elementDecl.simpleType.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0;
1233 }
1234
1235 /* Validators are null until we add that code */
1236 if (elementDecl.type == XMLElementDecl.TYPE_CHILDREN || elementDecl.type == XMLElementDecl.TYPE_MIXED) {
1237 elementDecl.contentModelValidator = getElementContentModelValidator(elementDeclIndex);
1238 }
1239
1240 elementDecl.simpleType.datatypeValidator = null;
1241 elementDecl.simpleType.defaultType = -1;
1242 elementDecl.simpleType.defaultValue = null;
1243
1244 return true;
1245
1246 } // getElementDecl(int,XMLElementDecl):boolean
1247
1248 QName getElementDeclName(int elementDeclIndex) {
1249 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1250 return null;
1251 }
1252 int chunk = elementDeclIndex >> CHUNK_SHIFT;
1253 int index = elementDeclIndex & CHUNK_MASK;
1254 return fElementDeclName[chunk][index];
1255 }
1256
1257 // REVISIT: Make this getAttributeDeclCount/getAttributeDeclAt. -Ac
1258
1259 /**
1260 * getFirstAttributeDeclIndex
1261 *
1262 * @param elementDeclIndex
1263 *
1264 * @return index of the first attribute for element declaration elementDeclIndex
1265 */
1266 public int getFirstAttributeDeclIndex(int elementDeclIndex) {
1267 int chunk = elementDeclIndex >> CHUNK_SHIFT;
1268 int index = elementDeclIndex & CHUNK_MASK;
1269
1270 return fElementDeclFirstAttributeDeclIndex[chunk][index];
1271 } // getFirstAttributeDeclIndex
1272
1273 /**
1274 * getNextAttributeDeclIndex
1275 *
1276 * @param attributeDeclIndex
1277 *
1278 * @return index of the next attribute of the attribute at attributeDeclIndex
1279 */
1280 public int getNextAttributeDeclIndex(int attributeDeclIndex) {
1281 int chunk = attributeDeclIndex >> CHUNK_SHIFT;
1282 int index = attributeDeclIndex & CHUNK_MASK;
1283
1284 return fAttributeDeclNextAttributeDeclIndex[chunk][index];
1285 } // getNextAttributeDeclIndex
1286
1287 /**
1288 * getAttributeDecl
1289 *
1290 * @param attributeDeclIndex
1291 * @param attributeDecl The values of this structure are set by this call.
1292 *
1293 * @return true if getAttributeDecl was able to fill in the value of attributeDecl
1294 */
1295 public boolean getAttributeDecl(int attributeDeclIndex, XMLAttributeDecl attributeDecl) {
1296 if (attributeDeclIndex < 0 || attributeDeclIndex >= fAttributeDeclCount) {
1297 return false;
1298 }
1299 int chunk = attributeDeclIndex >> CHUNK_SHIFT;
1300 int index = attributeDeclIndex & CHUNK_MASK;
1301
1302 attributeDecl.name.setValues(fAttributeDeclName[chunk][index]);
1303
1304 short attributeType;
1305 boolean isList;
1306
1307 if (fAttributeDeclType[chunk][index] == -1) {
1308
1309 attributeType = -1;
1310 isList = false;
1311 } else {
1312 attributeType = (short) (fAttributeDeclType[chunk][index] & LIST_MASK);
1313 isList = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0;
1314 }
1315 attributeDecl.simpleType.setValues(attributeType,fAttributeDeclName[chunk][index].localpart,
1316 fAttributeDeclEnumeration[chunk][index],
1317 isList, fAttributeDeclDefaultType[chunk][index],
1318 fAttributeDeclDefaultValue[chunk][index],
1319 fAttributeDeclNonNormalizedDefaultValue[chunk][index],
1320 fAttributeDeclDatatypeValidator[chunk][index]);
1321 return true;
1322
1323 } // getAttributeDecl
1324
1325
1326 /**
1327 * Returns whether the given attribute is of type CDATA or not
1328 *
1329 * @param elName The element name.
1330 * @param atName The attribute name.
1331 *
1332 * @return true if the attribute is of type CDATA
1333 */
1334 public boolean isCDATAAttribute(QName elName, QName atName) {
1335 int elDeclIdx = getElementDeclIndex(elName);
1336 if (getAttributeDecl(elDeclIdx, fAttributeDecl)
1337 && fAttributeDecl.simpleType.type != XMLSimpleType.TYPE_CDATA){
1338 return false;
1339 }
1340 return true;
1341 }
1342
1343 /**
1344 * getEntityDeclIndex
1345 *
1346 * @param entityDeclName
1347 *
1348 * @return the index of the EntityDecl
1349 */
1350 public int getEntityDeclIndex(String entityDeclName) {
1351 if (entityDeclName == null) {
1352 return -1;
1353 }
1354
1355 return fEntityIndexMap.get(entityDeclName);
1356 } // getEntityDeclIndex
1357
1358 /**
1359 * getEntityDecl
1360 *
1361 * @param entityDeclIndex
1362 * @param entityDecl
1363 *
1364 * @return true if getEntityDecl was able to fill entityDecl with the contents of the entity
1365 * with index entityDeclIndex
1366 */
1367 public boolean getEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) {
1368 if (entityDeclIndex < 0 || entityDeclIndex >= fEntityCount) {
1369 return false;
1370 }
1371 int chunk = entityDeclIndex >> CHUNK_SHIFT;
1372 int index = entityDeclIndex & CHUNK_MASK;
1373
1374 entityDecl.setValues(fEntityName[chunk][index],
1375 fEntityPublicId[chunk][index],
1376 fEntitySystemId[chunk][index],
1377 fEntityBaseSystemId[chunk][index],
1378 fEntityNotation[chunk][index],
1379 fEntityValue[chunk][index],
1380 fEntityIsPE[chunk][index] == 0 ? false : true ,
1381 fEntityInExternal[chunk][index] == 0 ? false : true );
1382
1383 return true;
1384 } // getEntityDecl
1385
1386 /**
1387 * getNotationDeclIndex
1388 *
1389 * @param notationDeclName
1390 *
1391 * @return the index if found a notation with the name, otherwise -1.
1392 */
1393 public int getNotationDeclIndex(String notationDeclName) {
1394 if (notationDeclName == null) {
1395 return -1;
1396 }
1397
1398 return fNotationIndexMap.get(notationDeclName);
1399 } // getNotationDeclIndex
1400
1401 /**
1402 * getNotationDecl
1403 *
1404 * @param notationDeclIndex
1405 * @param notationDecl
1406 *
1407 * @return return true of getNotationDecl can fill notationDecl with information about
1408 * the notation at notationDeclIndex.
1409 */
1410 public boolean getNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) {
1411 if (notationDeclIndex < 0 || notationDeclIndex >= fNotationCount) {
1412 return false;
1413 }
1414 int chunk = notationDeclIndex >> CHUNK_SHIFT;
1415 int index = notationDeclIndex & CHUNK_MASK;
1416
1417 notationDecl.setValues(fNotationName[chunk][index],
1418 fNotationPublicId[chunk][index],
1419 fNotationSystemId[chunk][index],
1420 fNotationBaseSystemId[chunk][index]);
1421
1422 return true;
1423
1424 } // getNotationDecl
1425
1426 /**
1427 * getContentSpec
1428 *
1429 * @param contentSpecIndex
1430 * @param contentSpec
1431 *
1432 * @return true if find the requested contentSpec node, false otherwise
1433 */
1434 public boolean getContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) {
1435 if (contentSpecIndex < 0 || contentSpecIndex >= fContentSpecCount )
1436 return false;
1437
1438 int chunk = contentSpecIndex >> CHUNK_SHIFT;
1439 int index = contentSpecIndex & CHUNK_MASK;
1440
1441 contentSpec.type = fContentSpecType[chunk][index];
1442 contentSpec.value = fContentSpecValue[chunk][index];
1443 contentSpec.otherValue = fContentSpecOtherValue[chunk][index];
1444 return true;
1445 }
1446
1447 /**
1448 * Returns the index to the content spec for the given element
1449 * declaration, or <code>-1</code> if the element declaration
1450 * index was invalid.
1451 */
1452 public int getContentSpecIndex(int elementDeclIndex) {
1453 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1454 return -1;
1455 }
1456 final int chunk = elementDeclIndex >> CHUNK_SHIFT;
1457 final int index = elementDeclIndex & CHUNK_MASK;
1458 return fElementDeclContentSpecIndex[chunk][index];
1459 }
1460
1461 /**
1462 * getContentSpecAsString
1463 *
1464 * @param elementDeclIndex
1465 *
1466 * @return String
1467 */
1468 public String getContentSpecAsString(int elementDeclIndex){
1469
1470 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1471 return null;
1472 }
1473
1474 int chunk = elementDeclIndex >> CHUNK_SHIFT;
1475 int index = elementDeclIndex & CHUNK_MASK;
1476
1477 int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
1478
1479 // lookup content spec node
1480 XMLContentSpec contentSpec = new XMLContentSpec();
1481
1482 if (getContentSpec(contentSpecIndex, contentSpec)) {
1483
1484 // build string
1485 StringBuffer str = new StringBuffer();
1486 int parentContentSpecType = contentSpec.type & 0x0f;
1487 int nextContentSpec;
1488 switch (parentContentSpecType) {
1489 case XMLContentSpec.CONTENTSPECNODE_LEAF: {
1490 str.append('(');
1491 if (contentSpec.value == null && contentSpec.otherValue == null) {
1492 str.append("#PCDATA");
1493 }
1494 else {
1495 str.append(contentSpec.value);
1496 }
1497 str.append(')');
1498 break;
1499 }
1500 case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
1501 getContentSpec(((int[])contentSpec.value)[0], contentSpec);
1502 nextContentSpec = contentSpec.type;
1503
1504 if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1505 str.append('(');
1506 str.append(contentSpec.value);
1507 str.append(')');
1508 } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
1509 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
1510 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
1511 str.append('(' );
1512 appendContentSpec(contentSpec, str,
1513 true, parentContentSpecType );
1514 str.append(')');
1515 } else {
1516 appendContentSpec(contentSpec, str,
1517 true, parentContentSpecType );
1518 }
1519 str.append('?');
1520 break;
1521 }
1522 case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
1523 getContentSpec(((int[])contentSpec.value)[0], contentSpec);
1524 nextContentSpec = contentSpec.type;
1525
1526 if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1527 str.append('(');
1528 if (contentSpec.value == null && contentSpec.otherValue == null) {
1529 str.append("#PCDATA");
1530 }
1531 else if (contentSpec.otherValue != null) {
1532 str.append("##any:uri=").append(contentSpec.otherValue);
1533 }
1534 else if (contentSpec.value == null) {
1535 str.append("##any");
1536 }
1537 else {
1538 appendContentSpec(contentSpec, str,
1539 true, parentContentSpecType );
1540 }
1541 str.append(')');
1542 } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
1543 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
1544 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
1545 str.append('(' );
1546 appendContentSpec(contentSpec, str,
1547 true, parentContentSpecType );
1548 str.append(')');
1549 } else {
1550 appendContentSpec(contentSpec, str,
1551 true, parentContentSpecType );
1552 }
1553 str.append('*');
1554 break;
1555 }
1556 case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
1557 getContentSpec(((int[])contentSpec.value)[0], contentSpec);
1558 nextContentSpec = contentSpec.type;
1559
1560 if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1561 str.append('(');
1562 if (contentSpec.value == null && contentSpec.otherValue == null) {
1563 str.append("#PCDATA");
1564 }
1565 else if (contentSpec.otherValue != null) {
1566 str.append("##any:uri=").append(contentSpec.otherValue);
1567 }
1568 else if (contentSpec.value == null) {
1569 str.append("##any");
1570 }
1571 else {
1572 str.append(contentSpec.value);
1573 }
1574 str.append(')');
1575 } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
1576 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
1577 nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
1578 str.append('(' );
1579 appendContentSpec(contentSpec, str,
1580 true, parentContentSpecType );
1581 str.append(')');
1582 } else {
1583 appendContentSpec(contentSpec, str,
1584 true, parentContentSpecType);
1585 }
1586 str.append('+');
1587 break;
1588 }
1589 case XMLContentSpec.CONTENTSPECNODE_CHOICE:
1590 case XMLContentSpec.CONTENTSPECNODE_SEQ: {
1591 appendContentSpec(contentSpec, str,
1592 true, parentContentSpecType );
1593 break;
1594 }
1595 case XMLContentSpec.CONTENTSPECNODE_ANY: {
1596 str.append("##any");
1597 if (contentSpec.otherValue != null) {
1598 str.append(":uri=");
1599 str.append(contentSpec.otherValue);
1600 }
1601 break;
1602 }
1603 case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: {
1604 str.append("##other:uri=");
1605 str.append(contentSpec.otherValue);
1606 break;
1607 }
1608 case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: {
1609 str.append("##local");
1610 break;
1611 }
1612 default: {
1613 str.append("???");
1614 }
1615
1616 } // switch type
1617
1618 // return string
1619 return str.toString();
1620 }
1621
1622 // not found
1623 return null;
1624
1625 } // getContentSpecAsString(int):String
1626
1627 // debugging
1628
1629 public void printElements( ) {
1630 int elementDeclIndex = 0;
1631 XMLElementDecl elementDecl = new XMLElementDecl();
1632 while (getElementDecl(elementDeclIndex++, elementDecl)) {
1633
1634 System.out.println("element decl: "+elementDecl.name+
1635 ", "+ elementDecl.name.rawname );
1636
1637 // ", "+ elementDecl.contentModelValidator.toString());
1638 }
1639 }
1640
1641 public void printAttributes(int elementDeclIndex) {
1642 int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex);
1643 System.out.print(elementDeclIndex);
1644 System.out.print(" [");
1645 while (attributeDeclIndex != -1) {
1646 System.out.print(' ');
1647 System.out.print(attributeDeclIndex);
1648 printAttribute(attributeDeclIndex);
1649 attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex);
1650 if (attributeDeclIndex != -1) {
1651 System.out.print(",");
1652 }
1653 }
1654 System.out.println(" ]");
1655 }
1656
1657 //
1658 // Protected methods
1659 //
1660
1661 /**
1662 * Adds the content spec to the given element declaration.
1663 */
1664 protected void addContentSpecToElement(XMLElementDecl elementDecl) {
1665 if ((fDepth == 0 || (fDepth == 1 && elementDecl.type == XMLElementDecl.TYPE_MIXED)) &&
1666 fNodeIndexStack != null) {
1667 if (elementDecl.type == XMLElementDecl.TYPE_MIXED) {
1668 int pcdata = addUniqueLeafNode(null);
1669 if (fNodeIndexStack[0] == -1) {
1670 fNodeIndexStack[0] = pcdata;
1671 }
1672 else {
1673 fNodeIndexStack[0] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
1674 pcdata, fNodeIndexStack[0]);
1675 }
1676 }
1677 setContentSpecIndex(fCurrentElementIndex, fNodeIndexStack[fDepth]);
1678 }
1679 }
1680
1681 /**
1682 * getElementContentModelValidator
1683 *
1684 * @param elementDeclIndex
1685 *
1686 * @return its ContentModelValidator if any.
1687 */
1688 protected ContentModelValidator getElementContentModelValidator(int elementDeclIndex) {
1689
1690 int chunk = elementDeclIndex >> CHUNK_SHIFT;
1691 int index = elementDeclIndex & CHUNK_MASK;
1692
1693 ContentModelValidator contentModel = fElementDeclContentModelValidator[chunk][index];
1694
1695 // If we have one, just return that. Otherwise, gotta create one
1696 if (contentModel != null) {
1697 return contentModel;
1698 }
1699
1700 int contentType = fElementDeclType[chunk][index];
1701 if (contentType == XMLElementDecl.TYPE_SIMPLE) {
1702 return null;
1703 }
1704
1705 // Get the type of content this element has
1706 int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
1707
1708 /***
1709 if ( contentSpecIndex == -1 )
1710 return null;
1711 /***/
1712
1713 XMLContentSpec contentSpec = new XMLContentSpec();
1714 getContentSpec( contentSpecIndex, contentSpec );
1715
1716 // And create the content model according to the spec type
1717 if ( contentType == XMLElementDecl.TYPE_MIXED ) {
1718 //
1719 // Just create a mixel content model object. This type of
1720 // content model is optimized for mixed content validation.
1721 //
1722 ChildrenList children = new ChildrenList();
1723 contentSpecTree(contentSpecIndex, contentSpec, children);
1724 contentModel = new MixedContentModel(children.qname,
1725 children.type,
1726 0, children.length,
1727 false);
1728 } else if (contentType == XMLElementDecl.TYPE_CHILDREN) {
1729 // This method will create an optimal model for the complexity
1730 // of the element's defined model. If its simple, it will create
1731 // a SimpleContentModel object. If its a simple list, it will
1732 // create a SimpleListContentModel object. If its complex, it
1733 // will create a DFAContentModel object.
1734 //
1735 contentModel = createChildModel(contentSpecIndex);
1736 } else {
1737 throw new RuntimeException("Unknown content type for a element decl "
1738 + "in getElementContentModelValidator() in AbstractDTDGrammar class");
1739 }
1740
1741 // Add the new model to the content model for this element
1742 fElementDeclContentModelValidator[chunk][index] = contentModel;
1743
1744 return contentModel;
1745
1746 } // getElementContentModelValidator(int):ContentModelValidator
1747
1748 protected int createElementDecl() {
1749 int chunk = fElementDeclCount >> CHUNK_SHIFT;
1750 int index = fElementDeclCount & CHUNK_MASK;
1751 ensureElementDeclCapacity(chunk);
1752 fElementDeclName[chunk][index] = new QName();
1753 fElementDeclType[chunk][index] = -1;
1754 fElementDeclContentModelValidator[chunk][index] = null;
1755 fElementDeclFirstAttributeDeclIndex[chunk][index] = -1;
1756 fElementDeclLastAttributeDeclIndex[chunk][index] = -1;
1757 return fElementDeclCount++;
1758 }
1759
1760 protected void setElementDecl(int elementDeclIndex, XMLElementDecl elementDecl) {
1761 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1762 return;
1763 }
1764 int chunk = elementDeclIndex >> CHUNK_SHIFT;
1765 int index = elementDeclIndex & CHUNK_MASK;
1766
1767 fElementDeclName[chunk][index].setValues(elementDecl.name);
1768 fElementDeclType[chunk][index] = elementDecl.type;
1769
1770 fElementDeclContentModelValidator[chunk][index] = elementDecl.contentModelValidator;
1771
1772 if (elementDecl.simpleType.list == true ) {
1773 fElementDeclType[chunk][index] |= LIST_FLAG;
1774 }
1775
1776 fElementIndexMap.put(elementDecl.name.rawname, elementDeclIndex);
1777 }
1778
1779
1780
1781
1782 protected void putElementNameMapping(QName name, int scope,
1783 int elementDeclIndex) {
1784 }
1785
1786 protected void setFirstAttributeDeclIndex(int elementDeclIndex, int newFirstAttrIndex){
1787
1788 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1789 return;
1790 }
1791
1792 int chunk = elementDeclIndex >> CHUNK_SHIFT;
1793 int index = elementDeclIndex & CHUNK_MASK;
1794
1795 fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex;
1796 }
1797
1798 protected void setContentSpecIndex(int elementDeclIndex, int contentSpecIndex){
1799
1800 if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
1801 return;
1802 }
1803
1804 int chunk = elementDeclIndex >> CHUNK_SHIFT;
1805 int index = elementDeclIndex & CHUNK_MASK;
1806
1807 fElementDeclContentSpecIndex[chunk][index] = contentSpecIndex;
1808 }
1809
1810
1811 protected int createAttributeDecl() {
1812 int chunk = fAttributeDeclCount >> CHUNK_SHIFT;
1813 int index = fAttributeDeclCount & CHUNK_MASK;
1814
1815 ensureAttributeDeclCapacity(chunk);
1816 fAttributeDeclName[chunk][index] = new QName();
1817 fAttributeDeclType[chunk][index] = -1;
1818 fAttributeDeclDatatypeValidator[chunk][index] = null;
1819 fAttributeDeclEnumeration[chunk][index] = null;
1820 fAttributeDeclDefaultType[chunk][index] = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
1821 fAttributeDeclDefaultValue[chunk][index] = null;
1822 fAttributeDeclNonNormalizedDefaultValue[chunk][index] = null;
1823 fAttributeDeclNextAttributeDeclIndex[chunk][index] = -1;
1824 return fAttributeDeclCount++;
1825 }
1826
1827
1828 protected void setAttributeDecl(int elementDeclIndex, int attributeDeclIndex,
1829 XMLAttributeDecl attributeDecl) {
1830 int attrChunk = attributeDeclIndex >> CHUNK_SHIFT;
1831 int attrIndex = attributeDeclIndex & CHUNK_MASK;
1832 fAttributeDeclName[attrChunk][attrIndex].setValues(attributeDecl.name);
1833 fAttributeDeclType[attrChunk][attrIndex] = attributeDecl.simpleType.type;
1834
1835 if (attributeDecl.simpleType.list) {
1836 fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG;
1837 }
1838 fAttributeDeclEnumeration[attrChunk][attrIndex] = attributeDecl.simpleType.enumeration;
1839 fAttributeDeclDefaultType[attrChunk][attrIndex] = attributeDecl.simpleType.defaultType;
1840 fAttributeDeclDatatypeValidator[attrChunk][attrIndex] = attributeDecl.simpleType.datatypeValidator;
1841
1842 fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.defaultValue;
1843 fAttributeDeclNonNormalizedDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.nonNormalizedDefaultValue;
1844
1845 int elemChunk = elementDeclIndex >> CHUNK_SHIFT;
1846 int elemIndex = elementDeclIndex & CHUNK_MASK;
1847 int index = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex];
1848 while (index != -1) {
1849 if (index == attributeDeclIndex) {
1850 break;
1851 }
1852 attrChunk = index >> CHUNK_SHIFT;
1853 attrIndex = index & CHUNK_MASK;
1854 index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex];
1855 }
1856 if (index == -1) {
1857 if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) {
1858 fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
1859 } else {
1860 index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex];
1861 attrChunk = index >> CHUNK_SHIFT;
1862 attrIndex = index & CHUNK_MASK;
1863 fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex;
1864 }
1865 fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
1866 }
1867 }
1868
1869 protected int createContentSpec() {
1870 int chunk = fContentSpecCount >> CHUNK_SHIFT;
1871 int index = fContentSpecCount & CHUNK_MASK;
1872
1873 ensureContentSpecCapacity(chunk);
1874 fContentSpecType[chunk][index] = -1;
1875 fContentSpecValue[chunk][index] = null;
1876 fContentSpecOtherValue[chunk][index] = null;
1877
1878 return fContentSpecCount++;
1879 }
1880
1881 protected void setContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) {
1882 int chunk = contentSpecIndex >> CHUNK_SHIFT;
1883 int index = contentSpecIndex & CHUNK_MASK;
1884
1885 fContentSpecType[chunk][index] = contentSpec.type;
1886 fContentSpecValue[chunk][index] = contentSpec.value;
1887 fContentSpecOtherValue[chunk][index] = contentSpec.otherValue;
1888 }
1889
1890
1891 protected int createEntityDecl() {
1892 int chunk = fEntityCount >> CHUNK_SHIFT;
1893 int index = fEntityCount & CHUNK_MASK;
1894
1895 ensureEntityDeclCapacity(chunk);
1896 fEntityIsPE[chunk][index] = 0;
1897 fEntityInExternal[chunk][index] = 0;
1898
1899 return fEntityCount++;
1900 }
1901
1902 protected void setEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) {
1903 int chunk = entityDeclIndex >> CHUNK_SHIFT;
1904 int index = entityDeclIndex & CHUNK_MASK;
1905
1906 fEntityName[chunk][index] = entityDecl.name;
1907 fEntityValue[chunk][index] = entityDecl.value;
1908 fEntityPublicId[chunk][index] = entityDecl.publicId;
1909 fEntitySystemId[chunk][index] = entityDecl.systemId;
1910 fEntityBaseSystemId[chunk][index] = entityDecl.baseSystemId;
1911 fEntityNotation[chunk][index] = entityDecl.notation;
1912 fEntityIsPE[chunk][index] = entityDecl.isPE ? (byte)1 : (byte)0;
1913 fEntityInExternal[chunk][index] = entityDecl.inExternal ? (byte)1 : (byte)0;
1914
1915 fEntityIndexMap.put(entityDecl.name, entityDeclIndex);
1916 }
1917
1918 protected int createNotationDecl() {
1919 int chunk = fNotationCount >> CHUNK_SHIFT;
1920 ensureNotationDeclCapacity(chunk);
1921 return fNotationCount++;
1922 }
1923
1924 protected void setNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) {
1925 int chunk = notationDeclIndex >> CHUNK_SHIFT;
1926 int index = notationDeclIndex & CHUNK_MASK;
1927
1928 fNotationName[chunk][index] = notationDecl.name;
1929 fNotationPublicId[chunk][index] = notationDecl.publicId;
1930 fNotationSystemId[chunk][index] = notationDecl.systemId;
1931 fNotationBaseSystemId[chunk][index] = notationDecl.baseSystemId;
1932
1933 fNotationIndexMap.put(notationDecl.name, notationDeclIndex);
1934 }
1935
1936 /**
1937 * Create an XMLContentSpec for a single non-leaf
1938 *
1939 * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
1940 * @param nodeValue handle to an XMLContentSpec
1941 * @return handle to the newly create XMLContentSpec
1942 */
1943 protected int addContentSpecNode(short nodeType, String nodeValue) {
1944
1945 // create content spec node
1946 int contentSpecIndex = createContentSpec();
1947
1948 // set content spec node values
1949 fContentSpec.setValues(nodeType, nodeValue, null);
1950 setContentSpec(contentSpecIndex, fContentSpec);
1951
1952 // return index
1953 return contentSpecIndex;
1954
1955 } // addContentSpecNode(short,String):int
1956
1957 /**
1958 * create an XMLContentSpec for a leaf
1959 *
1960 * @param elementName the name (Element) for the node
1961 * @return handle to the newly create XMLContentSpec
1962 */
1963 protected int addUniqueLeafNode(String elementName) {
1964
1965 // create content spec node
1966 int contentSpecIndex = createContentSpec();
1967
1968 // set content spec node values
1969 fContentSpec.setValues( XMLContentSpec.CONTENTSPECNODE_LEAF,
1970 elementName, null);
1971 setContentSpec(contentSpecIndex, fContentSpec);
1972
1973 // return index
1974 return contentSpecIndex;
1975
1976 } // addUniqueLeafNode(String):int
1977
1978 /**
1979 * Create an XMLContentSpec for a two child leaf
1980 *
1981 * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
1982 * @param leftNodeIndex handle to an XMLContentSpec
1983 * @param rightNodeIndex handle to an XMLContentSpec
1984 * @return handle to the newly create XMLContentSpec
1985 */
1986 protected int addContentSpecNode(short nodeType,
1987 int leftNodeIndex, int rightNodeIndex) {
1988
1989 // create content spec node
1990 int contentSpecIndex = createContentSpec();
1991
1992 // set content spec node values
1993 int[] leftIntArray = new int[1];
1994 int[] rightIntArray = new int[1];
1995
1996 leftIntArray[0] = leftNodeIndex;
1997 rightIntArray[0] = rightNodeIndex;
1998 fContentSpec.setValues(nodeType, leftIntArray, rightIntArray);
1999 setContentSpec(contentSpecIndex, fContentSpec);
2000
2001 // return index
2002 return contentSpecIndex;
2003
2004 } // addContentSpecNode(short,int,int):int
2005
2006 /** Initialize content model stack. */
2007 protected void initializeContentModelStack() {
2008
2009 if (fOpStack == null) {
2010 fOpStack = new short[8];
2011 fNodeIndexStack = new int[8];
2012 fPrevNodeIndexStack = new int[8];
2013 } else if (fDepth == fOpStack.length) {
2014 short[] newStack = new short[fDepth * 2];
2015 System.arraycopy(fOpStack, 0, newStack, 0, fDepth);
2016 fOpStack = newStack;
2017 int[] newIntStack = new int[fDepth * 2];
2018 System.arraycopy(fNodeIndexStack, 0, newIntStack, 0, fDepth);
2019 fNodeIndexStack = newIntStack;
2020 newIntStack = new int[fDepth * 2];
2021 System.arraycopy(fPrevNodeIndexStack, 0, newIntStack, 0, fDepth);
2022 fPrevNodeIndexStack = newIntStack;
2023 }
2024 fOpStack[fDepth] = -1;
2025 fNodeIndexStack[fDepth] = -1;
2026 fPrevNodeIndexStack[fDepth] = -1;
2027
2028 } // initializeContentModelStack()
2029
2030 boolean isImmutable() {
2031 return fIsImmutable;
2032 }
2033
2034 //
2035 // Private methods
2036 //
2037
2038 private void appendContentSpec(XMLContentSpec contentSpec,
2039 StringBuffer str, boolean parens,
2040 int parentContentSpecType ) {
2041
2042 int thisContentSpec = contentSpec.type & 0x0f;
2043 switch (thisContentSpec) {
2044 case XMLContentSpec.CONTENTSPECNODE_LEAF: {
2045 if (contentSpec.value == null && contentSpec.otherValue == null) {
2046 str.append("#PCDATA");
2047 }
2048 else if (contentSpec.value == null && contentSpec.otherValue != null) {
2049 str.append("##any:uri=").append(contentSpec.otherValue);
2050 }
2051 else if (contentSpec.value == null) {
2052 str.append("##any");
2053 }
2054 else {
2055 str.append(contentSpec.value);
2056 }
2057 break;
2058 }
2059 case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
2060 if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
2061 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2062 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
2063 getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2064 str.append('(');
2065 appendContentSpec(contentSpec, str, true, thisContentSpec );
2066 str.append(')');
2067 }
2068 else {
2069 getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2070 appendContentSpec( contentSpec, str, true, thisContentSpec );
2071 }
2072 str.append('?');
2073 break;
2074 }
2075 case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
2076 if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
2077 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2078 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
2079 getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2080 str.append('(');
2081 appendContentSpec(contentSpec, str, true, thisContentSpec);
2082 str.append(')' );
2083 }
2084 else {
2085 getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2086 appendContentSpec(contentSpec, str, true, thisContentSpec);
2087 }
2088 str.append('*');
2089 break;
2090 }
2091 case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
2092 if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
2093 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2094 parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
2095
2096 str.append('(');
2097 getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2098 appendContentSpec(contentSpec, str, true, thisContentSpec);
2099 str.append(')' );
2100 }
2101 else {
2102 getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2103 appendContentSpec(contentSpec, str, true, thisContentSpec);
2104 }
2105 str.append('+');
2106 break;
2107 }
2108 case XMLContentSpec.CONTENTSPECNODE_CHOICE:
2109 case XMLContentSpec.CONTENTSPECNODE_SEQ: {
2110 if (parens) {
2111 str.append('(');
2112 }
2113 int type = contentSpec.type;
2114 int otherValue = ((int[])contentSpec.otherValue)[0];
2115 getContentSpec(((int[])contentSpec.value)[0], contentSpec);
2116 appendContentSpec(contentSpec, str, contentSpec.type != type, thisContentSpec);
2117 if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) {
2118 str.append('|');
2119 }
2120 else {
2121 str.append(',');
2122 }
2123 getContentSpec(otherValue, contentSpec);
2124 appendContentSpec(contentSpec, str, true, thisContentSpec);
2125 if (parens) {
2126 str.append(')');
2127 }
2128 break;
2129 }
2130 case XMLContentSpec.CONTENTSPECNODE_ANY: {
2131 str.append("##any");
2132 if (contentSpec.otherValue != null) {
2133 str.append(":uri=");
2134 str.append(contentSpec.otherValue);
2135 }
2136 break;
2137 }
2138 case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: {
2139 str.append("##other:uri=");
2140 str.append(contentSpec.otherValue);
2141 break;
2142 }
2143 case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: {
2144 str.append("##local");
2145 break;
2146 }
2147 default: {
2148 str.append("???");
2149 break;
2150 }
2151
2152 } // switch type
2153
2154 } // appendContentSpec(XMLContentSpec.Provider,StringPool,XMLContentSpec,StringBuffer,boolean)
2155
2156 // debugging
2157
2158 private void printAttribute(int attributeDeclIndex) {
2159
2160 XMLAttributeDecl attributeDecl = new XMLAttributeDecl();
2161 if (getAttributeDecl(attributeDeclIndex, attributeDecl)) {
2162 System.out.print(" { ");
2163 System.out.print(attributeDecl.name.localpart);
2164 System.out.print(" }");
2165 }
2166
2167 } // printAttribute(int)
2168
2169 // content models
2170
2171 /**
2172 * When the element has a 'CHILDREN' model, this method is called to
2173 * create the content model object. It looks for some special case simple
2174 * models and creates SimpleContentModel objects for those. For the rest
2175 * it creates the standard DFA style model.
2176 */
2177 private synchronized ContentModelValidator createChildModel(int contentSpecIndex) {
2178
2179 //
2180 // Get the content spec node for the element we are working on.
2181 // This will tell us what kind of node it is, which tells us what
2182 // kind of model we will try to create.
2183 //
2184 XMLContentSpec contentSpec = new XMLContentSpec();
2185 getContentSpec(contentSpecIndex, contentSpec);
2186
2187 if ((contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY ||
2188 (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER ||
2189 (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
2190 // let fall through to build a DFAContentModel
2191 }
2192
2193 else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2194 //
2195 // Check that the left value is not -1, since any content model
2196 // with PCDATA should be MIXED, so we should not have gotten here.
2197 //
2198 if (contentSpec.value == null && contentSpec.otherValue == null)
2199 throw new RuntimeException("ImplementationMessages.VAL_NPCD");
2200
2201 //
2202 // Its a single leaf, so its an 'a' type of content model, i.e.
2203 // just one instance of one element. That one is definitely a
2204 // simple content model.
2205 //
2206
2207 fQName.setValues(null, (String)contentSpec.value,
2208 (String)contentSpec.value, (String)contentSpec.otherValue);
2209 return new SimpleContentModel(contentSpec.type, fQName, null);
2210 } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
2211 || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
2212 //
2213 // Lets see if both of the children are leafs. If so, then it
2214 // it has to be a simple content model
2215 //
2216 XMLContentSpec contentSpecLeft = new XMLContentSpec();
2217 XMLContentSpec contentSpecRight = new XMLContentSpec();
2218
2219 getContentSpec( ((int[])contentSpec.value)[0], contentSpecLeft);
2220 getContentSpec( ((int[])contentSpec.otherValue)[0], contentSpecRight);
2221
2222 if ((contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
2223 && (contentSpecRight.type == XMLContentSpec.CONTENTSPECNODE_LEAF)) {
2224 //
2225 // Its a simple choice or sequence, so we can do a simple
2226 // content model for it.
2227 //
2228 fQName.setValues(null, (String)contentSpecLeft.value,
2229 (String)contentSpecLeft.value, (String)contentSpecLeft.otherValue);
2230 fQName2.setValues(null, (String)contentSpecRight.value,
2231 (String)contentSpecRight.value, (String)contentSpecRight.otherValue);
2232 return new SimpleContentModel(contentSpec.type, fQName, fQName2);
2233 }
2234 } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE)
2235 || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE)
2236 || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE)) {
2237 //
2238 // Its a repetition, so see if its one child is a leaf. If so
2239 // its a repetition of a single element, so we can do a simple
2240 // content model for that.
2241 //
2242 XMLContentSpec contentSpecLeft = new XMLContentSpec();
2243 getContentSpec(((int[])contentSpec.value)[0], contentSpecLeft);
2244
2245 if (contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2246 //
2247 // It is, so we can create a simple content model here that
2248 // will check for this repetition. We pass -1 for the unused
2249 // right node.
2250 //
2251 fQName.setValues(null, (String)contentSpecLeft.value,
2252 (String)contentSpecLeft.value, (String)contentSpecLeft.otherValue);
2253 return new SimpleContentModel(contentSpec.type, fQName, null);
2254 }
2255 } else {
2256 throw new RuntimeException("ImplementationMessages.VAL_CST");
2257 }
2258
2259 //
2260 // Its not a simple content model, so here we have to create a DFA
2261 // for this element. So we create a DFAContentModel object. He
2262 // encapsulates all of the work to create the DFA.
2263 //
2264
2265 fLeafCount = 0;
2266 //int leafCount = countLeaves(contentSpecIndex);
2267 fLeafCount = 0;
2268 CMNode cmn = buildSyntaxTree(contentSpecIndex, contentSpec);
2269
2270 // REVISIT: has to be fLeafCount because we convert x+ to x,x*, one more leaf
2271 return new DFAContentModel( cmn, fLeafCount, false);
2272
2273 } // createChildModel(int):ContentModelValidator
2274
2275 private final CMNode buildSyntaxTree(int startNode,
2276 XMLContentSpec contentSpec) {
2277
2278 // We will build a node at this level for the new tree
2279 CMNode nodeRet = null;
2280 getContentSpec(startNode, contentSpec);
2281 if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY) {
2282 //nodeRet = new CMAny(contentSpec.type, -1, fLeafCount++);
2283 nodeRet = new CMAny(contentSpec.type, (String)contentSpec.otherValue, fLeafCount++);
2284 }
2285 else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
2286 nodeRet = new CMAny(contentSpec.type, (String)contentSpec.otherValue, fLeafCount++);
2287 }
2288 else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
2289 nodeRet = new CMAny(contentSpec.type, null, fLeafCount++);
2290 }
2291 //
2292 // If this node is a leaf, then its an easy one. We just add it
2293 // to the tree.
2294 //
2295 else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2296 //
2297 // Create a new leaf node, and pass it the current leaf count,
2298 // which is its DFA state position. Bump the leaf count after
2299 // storing it. This makes the positions zero based since we
2300 // store first and then increment.
2301 //
2302 fQName.setValues(null, (String)contentSpec.value,
2303 (String)contentSpec.value, (String)contentSpec.otherValue);
2304 nodeRet = new CMLeaf(fQName, fLeafCount++);
2305 }
2306 else {
2307 //
2308 // Its not a leaf, so we have to recurse its left and maybe right
2309 // nodes. Save both values before we recurse and trash the node.
2310 final int leftNode = ((int[])contentSpec.value)[0];
2311 final int rightNode = ((int[])contentSpec.otherValue)[0];
2312
2313 if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
2314 || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
2315 //
2316 // Recurse on both children, and return a binary op node
2317 // with the two created sub nodes as its children. The node
2318 // type is the same type as the source.
2319 //
2320
2321 nodeRet = new CMBinOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec)
2322 , buildSyntaxTree(rightNode, contentSpec));
2323 }
2324 else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) {
2325 nodeRet = new CMUniOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec));
2326 }
2327 else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
2328 || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE
2329 || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
2330 nodeRet = new CMUniOp(contentSpec.type, buildSyntaxTree(leftNode, contentSpec));
2331 }
2332 else {
2333 throw new RuntimeException("ImplementationMessages.VAL_CST");
2334 }
2335 }
2336 // And return our new node for this level
2337 return nodeRet;
2338 }
2339
2340 /**
2341 * Build a vector of valid QNames from Content Spec
2342 * table.
2343 *
2344 * @param contentSpecIndex
2345 * Content Spec index
2346 * @param vectorQName
2347 * Array of QName
2348 * @exception RuntimeException
2349 */
2350 private void contentSpecTree(int contentSpecIndex,
2351 XMLContentSpec contentSpec,
2352 ChildrenList children) {
2353
2354 // Handle any and leaf nodes
2355 getContentSpec( contentSpecIndex, contentSpec);
2356 if ( contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF ||
2357 (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY ||
2358 (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL ||
2359 (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
2360
2361 // resize arrays, if needed
2362 if (children.length == children.qname.length) {
2363 QName[] newQName = new QName[children.length * 2];
2364 System.arraycopy(children.qname, 0, newQName, 0, children.length);
2365 children.qname = newQName;
2366 int[] newType = new int[children.length * 2];
2367 System.arraycopy(children.type, 0, newType, 0, children.length);
2368 children.type = newType;
2369 }
2370
2371 // save values and return length
2372 children.qname[children.length] = new QName(null, (String)contentSpec.value,
2373 (String) contentSpec.value,
2374 (String) contentSpec.otherValue);
2375 children.type[children.length] = contentSpec.type;
2376 children.length++;
2377 return;
2378 }
2379
2380 //
2381 // Its not a leaf, so we have to recurse its left and maybe right
2382 // nodes. Save both values before we recurse and trash the node.
2383 //
2384 final int leftNode = contentSpec.value != null
2385 ? ((int[])(contentSpec.value))[0] : -1;
2386 int rightNode = -1 ;
2387 if (contentSpec.otherValue != null )
2388 rightNode = ((int[])(contentSpec.otherValue))[0];
2389 else
2390 return;
2391
2392 if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE ||
2393 contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
2394 contentSpecTree(leftNode, contentSpec, children);
2395 contentSpecTree(rightNode, contentSpec, children);
2396 return;
2397 }
2398
2399 if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ||
2400 contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
2401 contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
2402 contentSpecTree(leftNode, contentSpec, children);
2403 return;
2404 }
2405
2406 // error
2407 throw new RuntimeException("Invalid content spec type seen in contentSpecTree() method of AbstractDTDGrammar class : "+contentSpec.type);
2408
2409 } // contentSpecTree(int,XMLContentSpec,ChildrenList)
2410
2411 // ensure capacity
2412
2413 private void ensureElementDeclCapacity(int chunk) {
2414 if (chunk >= fElementDeclName.length) {
2415 fElementDeclIsExternal = resize(fElementDeclIsExternal,
2416 fElementDeclIsExternal.length * 2);
2417
2418 fElementDeclName = resize(fElementDeclName, fElementDeclName.length * 2);
2419 fElementDeclType = resize(fElementDeclType, fElementDeclType.length * 2);
2420 fElementDeclContentModelValidator = resize(fElementDeclContentModelValidator, fElementDeclContentModelValidator.length * 2);
2421 fElementDeclContentSpecIndex = resize(fElementDeclContentSpecIndex,fElementDeclContentSpecIndex.length * 2);
2422 fElementDeclFirstAttributeDeclIndex = resize(fElementDeclFirstAttributeDeclIndex, fElementDeclFirstAttributeDeclIndex.length * 2);
2423 fElementDeclLastAttributeDeclIndex = resize(fElementDeclLastAttributeDeclIndex, fElementDeclLastAttributeDeclIndex.length * 2);
2424 }
2425 else if (fElementDeclName[chunk] != null) {
2426 return;
2427 }
2428
2429 fElementDeclIsExternal[chunk] = new int[CHUNK_SIZE];
2430 fElementDeclName[chunk] = new QName[CHUNK_SIZE];
2431 fElementDeclType[chunk] = new short[CHUNK_SIZE];
2432 fElementDeclContentModelValidator[chunk] = new ContentModelValidator[CHUNK_SIZE];
2433 fElementDeclContentSpecIndex[chunk] = new int[CHUNK_SIZE];
2434 fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2435 fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2436 return;
2437 }
2438
2439 private void ensureAttributeDeclCapacity(int chunk) {
2440
2441 if (chunk >= fAttributeDeclName.length) {
2442 fAttributeDeclIsExternal = resize(fAttributeDeclIsExternal,
2443 fAttributeDeclIsExternal.length * 2);
2444 fAttributeDeclName = resize(fAttributeDeclName, fAttributeDeclName.length * 2);
2445 fAttributeDeclType = resize(fAttributeDeclType, fAttributeDeclType.length * 2);
2446 fAttributeDeclEnumeration = resize(fAttributeDeclEnumeration, fAttributeDeclEnumeration.length * 2);
2447 fAttributeDeclDefaultType = resize(fAttributeDeclDefaultType, fAttributeDeclDefaultType.length * 2);
2448 fAttributeDeclDatatypeValidator = resize(fAttributeDeclDatatypeValidator, fAttributeDeclDatatypeValidator.length * 2);
2449 fAttributeDeclDefaultValue = resize(fAttributeDeclDefaultValue, fAttributeDeclDefaultValue.length * 2);
2450 fAttributeDeclNonNormalizedDefaultValue = resize(fAttributeDeclNonNormalizedDefaultValue, fAttributeDeclNonNormalizedDefaultValue.length * 2);
2451 fAttributeDeclNextAttributeDeclIndex = resize(fAttributeDeclNextAttributeDeclIndex, fAttributeDeclNextAttributeDeclIndex.length * 2);
2452 }
2453 else if (fAttributeDeclName[chunk] != null) {
2454 return;
2455 }
2456
2457 fAttributeDeclIsExternal[chunk] = new int[CHUNK_SIZE];
2458 fAttributeDeclName[chunk] = new QName[CHUNK_SIZE];
2459 fAttributeDeclType[chunk] = new short[CHUNK_SIZE];
2460 fAttributeDeclEnumeration[chunk] = new String[CHUNK_SIZE][];
2461 fAttributeDeclDefaultType[chunk] = new short[CHUNK_SIZE];
2462 fAttributeDeclDatatypeValidator[chunk] = new DatatypeValidator[CHUNK_SIZE];
2463 fAttributeDeclDefaultValue[chunk] = new String[CHUNK_SIZE];
2464 fAttributeDeclNonNormalizedDefaultValue[chunk] = new String[CHUNK_SIZE];
2465 fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2466 return;
2467 }
2468
2469 private void ensureEntityDeclCapacity(int chunk) {
2470 if (chunk >= fEntityName.length) {
2471 fEntityName = resize(fEntityName, fEntityName.length * 2);
2472 fEntityValue = resize(fEntityValue, fEntityValue.length * 2);
2473 fEntityPublicId = resize(fEntityPublicId, fEntityPublicId.length * 2);
2474 fEntitySystemId = resize(fEntitySystemId, fEntitySystemId.length * 2);
2475 fEntityBaseSystemId = resize(fEntityBaseSystemId, fEntityBaseSystemId.length * 2);
2476 fEntityNotation = resize(fEntityNotation, fEntityNotation.length * 2);
2477 fEntityIsPE = resize(fEntityIsPE, fEntityIsPE.length * 2);
2478 fEntityInExternal = resize(fEntityInExternal, fEntityInExternal.length * 2);
2479 }
2480 else if (fEntityName[chunk] != null) {
2481 return;
2482 }
2483
2484 fEntityName[chunk] = new String[CHUNK_SIZE];
2485 fEntityValue[chunk] = new String[CHUNK_SIZE];
2486 fEntityPublicId[chunk] = new String[CHUNK_SIZE];
2487 fEntitySystemId[chunk] = new String[CHUNK_SIZE];
2488 fEntityBaseSystemId[chunk] = new String[CHUNK_SIZE];
2489 fEntityNotation[chunk] = new String[CHUNK_SIZE];
2490 fEntityIsPE[chunk] = new byte[CHUNK_SIZE];
2491 fEntityInExternal[chunk] = new byte[CHUNK_SIZE];
2492 return;
2493 }
2494
2495 private void ensureNotationDeclCapacity(int chunk) {
2496 if (chunk >= fNotationName.length) {
2497 fNotationName = resize(fNotationName, fNotationName.length * 2);
2498 fNotationPublicId = resize(fNotationPublicId, fNotationPublicId.length * 2);
2499 fNotationSystemId = resize(fNotationSystemId, fNotationSystemId.length * 2);
2500 fNotationBaseSystemId = resize(fNotationBaseSystemId, fNotationBaseSystemId.length * 2);
2501 }
2502 else if (fNotationName[chunk] != null) {
2503 return;
2504 }
2505
2506 fNotationName[chunk] = new String[CHUNK_SIZE];
2507 fNotationPublicId[chunk] = new String[CHUNK_SIZE];
2508 fNotationSystemId[chunk] = new String[CHUNK_SIZE];
2509 fNotationBaseSystemId[chunk] = new String[CHUNK_SIZE];
2510 return;
2511 }
2512
2513 private void ensureContentSpecCapacity(int chunk) {
2514 if (chunk >= fContentSpecType.length) {
2515 fContentSpecType = resize(fContentSpecType, fContentSpecType.length * 2);
2516 fContentSpecValue = resize(fContentSpecValue, fContentSpecValue.length * 2);
2517 fContentSpecOtherValue = resize(fContentSpecOtherValue, fContentSpecOtherValue.length * 2);
2518 }
2519 else if (fContentSpecType[chunk] != null) {
2520 return;
2521 }
2522
2523 fContentSpecType[chunk] = new short[CHUNK_SIZE];
2524 fContentSpecValue[chunk] = new Object[CHUNK_SIZE];
2525 fContentSpecOtherValue[chunk] = new Object[CHUNK_SIZE];
2526 return;
2527 }
2528
2529 //
2530 // Private static methods
2531 //
2532
2533 // resize chunks
2534
2535 private static byte[][] resize(byte array[][], int newsize) {
2536 byte newarray[][] = new byte[newsize][];
2537 System.arraycopy(array, 0, newarray, 0, array.length);
2538 return newarray;
2539 }
2540
2541 private static short[][] resize(short array[][], int newsize) {
2542 short newarray[][] = new short[newsize][];
2543 System.arraycopy(array, 0, newarray, 0, array.length);
2544 return newarray;
2545 }
2546
2547 private static int[][] resize(int array[][], int newsize) {
2548 int newarray[][] = new int[newsize][];
2549 System.arraycopy(array, 0, newarray, 0, array.length);
2550 return newarray;
2551 }
2552
2553 private static DatatypeValidator[][] resize(DatatypeValidator array[][], int newsize) {
2554 DatatypeValidator newarray[][] = new DatatypeValidator[newsize][];
2555 System.arraycopy(array, 0, newarray, 0, array.length);
2556 return newarray;
2557 }
2558
2559 private static ContentModelValidator[][] resize(ContentModelValidator array[][], int newsize) {
2560 ContentModelValidator newarray[][] = new ContentModelValidator[newsize][];
2561 System.arraycopy(array, 0, newarray, 0, array.length);
2562 return newarray;
2563 }
2564
2565 private static Object[][] resize(Object array[][], int newsize) {
2566 Object newarray[][] = new Object[newsize][];
2567 System.arraycopy(array, 0, newarray, 0, array.length);
2568 return newarray;
2569 }
2570
2571 private static QName[][] resize(QName array[][], int newsize) {
2572 QName newarray[][] = new QName[newsize][];
2573 System.arraycopy(array, 0, newarray, 0, array.length);
2574 return newarray;
2575 }
2576
2577 private static String[][] resize(String array[][], int newsize) {
2578 String newarray[][] = new String[newsize][];
2579 System.arraycopy(array, 0, newarray, 0, array.length);
2580 return newarray;
2581 }
2582
2583 private static String[][][] resize(String array[][][], int newsize) {
2584 String newarray[][][] = new String[newsize] [][];
2585 System.arraycopy(array, 0, newarray, 0, array.length);
2586 return newarray;
2587 }
2588
2589 //
2590 // Classes
2591 //
2592
2593 /**
2594 * Children list for <code>contentSpecTree</code> method.
2595 *
2596 * @xerces.internal
2597 *
2598 * @author Eric Ye, IBM
2599 */
2600 private static class ChildrenList {
2601
2602 //
2603 // Data
2604 //
2605
2606 /** Length. */
2607 public int length = 0;
2608
2609 // NOTE: The following set of data is mutually exclusive. It is
2610 // written this way because Java doesn't have a native
2611 // union data structure. -Ac
2612
2613 /** Left and right children names. */
2614 public QName[] qname = new QName[2];
2615
2616 /** Left and right children types. */
2617 public int[] type = new int[2];
2618
2619 //
2620 // Constructors
2621 //
2622
2623 public ChildrenList () {}
2624
2625 } // class ChildrenList
2626
2627 //
2628 // Classes
2629 //
2630
2631 /**
2632 * A simple Hashtable implementation that takes a tuple (String, String)
2633 * as the key and a int as value.
2634 *
2635 * @xerces.internal
2636 *
2637 * @author Eric Ye, IBM
2638 * @author Andy Clark, IBM
2639 */
2640 protected static final class QNameHashtable {
2641
2642 //
2643 // Constants
2644 //
2645
2646 /** Initial bucket size (4). */
2647 private static final int INITIAL_BUCKET_SIZE = 4;
2648
2649 // NOTE: Changed previous hashtable size from 512 to 101 so
2650 // that we get a better distribution for hashing. -Ac
2651 /** Hashtable size (101). */
2652 private static final int HASHTABLE_SIZE = 101;
2653
2654 //
2655 // Data
2656 //
2657 private Object[][] fHashTable = new Object[HASHTABLE_SIZE][];
2658
2659 //
2660 // Public methods
2661 //
2662 /** Associates the given value with the specified key tuple. */
2663 public void put(String key, int value) {
2664
2665 int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE;
2666 Object[] bucket = fHashTable[hash];
2667
2668 if (bucket == null) {
2669 bucket = new Object[1 + 2*INITIAL_BUCKET_SIZE];
2670 bucket[0] = new int[]{1};
2671 bucket[1] = key;
2672 bucket[2] = new int[]{value};
2673 fHashTable[hash] = bucket;
2674 } else {
2675 int count = ((int[])bucket[0])[0];
2676 int offset = 1 + 2*count;
2677 if (offset == bucket.length) {
2678 int newSize = count + INITIAL_BUCKET_SIZE;
2679 Object[] newBucket = new Object[1 + 2*newSize];
2680 System.arraycopy(bucket, 0, newBucket, 0, offset);
2681 bucket = newBucket;
2682 fHashTable[hash] = bucket;
2683 }
2684 boolean found = false;
2685 int j=1;
2686 for (int i=0; i<count; i++){
2687 if ((String)bucket[j] == key) {
2688 ((int[])bucket[j+1])[0] = value;
2689 found = true;
2690 break;
2691 }
2692 j += 2;
2693 }
2694 if (! found) {
2695 bucket[offset++] = key;
2696 bucket[offset]= new int[]{value};
2697 ((int[])bucket[0])[0] = ++count;
2698 }
2699
2700 }
2701 //System.out.println("put("+key+" -> "+value+')');
2702 //System.out.println("get("+key+") -> "+get(key));
2703
2704 } // put(int,String,String,int)
2705
2706 /** Returns the value associated with the specified key tuple. */
2707 public int get(String key) {
2708 int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE;
2709 Object[] bucket = fHashTable[hash];
2710
2711 if (bucket == null) {
2712 return -1;
2713 }
2714 int count = ((int[])bucket[0])[0];
2715
2716 int j=1;
2717 for (int i=0; i<count; i++){
2718 if ((String)bucket[j] == key) {
2719 return ((int[])bucket[j+1])[0];
2720 }
2721 j += 2;
2722 }
2723 return -1;
2724
2725 } // get(int,String,String)
2726
2727 } // class QNameHashtable
2728
2729 //
2730 // EntityState methods
2731 //
2732 public boolean isEntityDeclared (String name){
2733 return (getEntityDeclIndex(name)!=-1)?true:false;
2734 }
2735
2736 public boolean isEntityUnparsed (String name){
2737 int entityIndex = getEntityDeclIndex(name);
2738 if (entityIndex >-1) {
2739 int chunk = entityIndex >> CHUNK_SHIFT;
2740 int index = entityIndex & CHUNK_MASK;
2741 //for unparsed entity notation!=null
2742 return (fEntityNotation[chunk][index]!=null)?true:false;
2743 }
2744 return false;
2745 }
2746 } // class DTDGrammar