1/*
2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
3 */
4
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements.  See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License.  You may obtain a copy of the License at
12 *
13 *     http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22package com.sun.xml.internal.stream.dtd.nonvalidating;
23
24import com.sun.org.apache.xerces.internal.util.SymbolTable;
25import com.sun.org.apache.xerces.internal.util.XMLSymbols;
26import com.sun.org.apache.xerces.internal.xni.Augmentations;
27import com.sun.org.apache.xerces.internal.xni.QName;
28import com.sun.org.apache.xerces.internal.xni.XMLLocator;
29import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
30import com.sun.org.apache.xerces.internal.xni.XMLString;
31import com.sun.org.apache.xerces.internal.xni.XNIException;
32import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource;
33import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource;
34import java.util.ArrayList;
35import java.util.HashMap;
36import java.util.List;
37import java.util.Map;
38
39/**
40 * A DTD grammar. This class implements the XNI handler interfaces
41 * for DTD information so that it can build the approprate validation
42 * structures automatically from the callbacks.
43 *
44 * @author Eric Ye, IBM
45 * @author Jeffrey Rodriguez, IBM
46 * @author Andy Clark, IBM
47 * @author Neil Graham, IBM
48 *
49 */
50public class DTDGrammar {
51
52
53    /** Top level scope (-1). */
54    public static final int TOP_LEVEL_SCOPE = -1;
55
56    // private
57
58    /** Chunk shift (8). */
59    private static final int CHUNK_SHIFT = 8; // 2^8 = 256
60
61    /** Chunk size (1 << CHUNK_SHIFT). */
62    private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
63
64    /** Chunk mask (CHUNK_SIZE - 1). */
65    private static final int CHUNK_MASK = CHUNK_SIZE - 1;
66
67    /** Initial chunk count (1 << (10 - CHUNK_SHIFT)). */
68    private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k
69
70    /** List flag (0x80). */
71    private static final short LIST_FLAG = 0x80;
72
73    /** List mask (~LIST_FLAG). */
74    private static final short LIST_MASK = ~LIST_FLAG;
75
76    // debugging
77
78    /** Debug DTDGrammar. */
79    private static final boolean DEBUG = false;
80
81    //
82    // Data
83    //
84
85    protected XMLDTDSource fDTDSource = null;
86    protected XMLDTDContentModelSource fDTDContentModelSource = null;
87
88    /** Current element index. */
89    protected int fCurrentElementIndex;
90
91    /** Current attribute index. */
92    protected int fCurrentAttributeIndex;
93
94    /** fReadingExternalDTD */
95    protected boolean fReadingExternalDTD = false;
96
97    /** Symbol table. */
98    private final SymbolTable fSymbolTable;
99    private final ArrayList<XMLNotationDecl> notationDecls = new ArrayList<>();
100
101    // element declarations
102
103    /** Number of element declarations. */
104    private int fElementDeclCount = 0;
105
106    /** Element declaration name. */
107    private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
108
109    /**
110     * Element declaration type.
111     * @see XMLElementDecl
112     */
113    private short fElementDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
114
115
116    /** First attribute declaration of an element declaration. */
117    private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
118
119    /** Last attribute declaration of an element declaration. */
120    private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
121
122    // attribute declarations
123
124    /** Number of attribute declarations. */
125    private int fAttributeDeclCount = 0 ;
126
127    /** Attribute declaration name. */
128    private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
129
130    /**
131     * Attribute declaration type.
132     * @see XMLAttributeDecl
133     */
134    private short fAttributeDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
135
136    /** Attribute declaration enumeration values. */
137    private String[] fAttributeDeclEnumeration[][] = new String[INITIAL_CHUNK_COUNT][][];
138    private short fAttributeDeclDefaultType[][] = new short[INITIAL_CHUNK_COUNT][];
139    private String fAttributeDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
140    private String fAttributeDeclNonNormalizedDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
141    private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
142
143    /** Element index mapping table. */
144    private final Map<String, Integer> fElementIndexMap = new HashMap<>();
145
146    /** Temporary qualified name. */
147    private final QName fQName = new QName();
148
149    /** Temporary Attribute decl. */
150    protected XMLAttributeDecl fAttributeDecl = new XMLAttributeDecl();
151
152    /** Element declaration. */
153    private XMLElementDecl fElementDecl = new XMLElementDecl();
154
155    /** Simple type. */
156    private XMLSimpleType fSimpleType = new XMLSimpleType();
157
158
159    /** table of XMLElementDecl   */
160    Map<String, XMLElementDecl> fElementDeclTab = new HashMap<>();
161
162    /** Default constructor. */
163    public DTDGrammar(SymbolTable symbolTable) {
164        fSymbolTable = symbolTable;
165    }
166
167    public int getAttributeDeclIndex(int elementDeclIndex, String attributeDeclName) {
168        if (elementDeclIndex == -1) {
169            return -1;
170        }
171        int attDefIndex = getFirstAttributeDeclIndex(elementDeclIndex);
172        while (attDefIndex != -1) {
173            getAttributeDecl(attDefIndex, fAttributeDecl);
174
175            if (fAttributeDecl.name.rawname == attributeDeclName
176            || attributeDeclName.equals(fAttributeDecl.name.rawname) ) {
177                return attDefIndex;
178            }
179            attDefIndex = getNextAttributeDeclIndex(attDefIndex);
180        }
181        return -1;
182    }
183
184    /**
185     * The start of the DTD.
186     *
187     * @param locator  The document locator, or null if the document
188     *                 location cannot be reported during the parsing of
189     *                 the document DTD. However, it is <em>strongly</em>
190     *                 recommended that a locator be supplied that can
191     *                 at least report the base system identifier of the
192     *                 DTD.
193     *
194     * @param augs Additional information that may include infoset
195     *                      augmentations.
196     * @throws XNIException Thrown by handler to signal an error.
197     */
198    public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
199    } // startDTD(XMLLocator)
200
201    // startExternalSubset(Augmentations)
202
203    // endExternalSubset(Augmentations)
204
205    /**
206     * An element declaration.
207     *
208     * @param name         The name of the element.
209     * @param contentModel The element content model.
210     * @param augs Additional information that may include infoset
211     *                      augmentations.
212     * @throws XNIException Thrown by handler to signal an error.
213     */
214    public void elementDecl(String name, String contentModel, Augmentations augs)
215    throws XNIException {
216
217        XMLElementDecl tmpElementDecl = fElementDeclTab.get(name) ;
218        if ( tmpElementDecl != null ) {
219            if (tmpElementDecl.type == -1) {
220                fCurrentElementIndex = getElementDeclIndex(name);
221            }
222            else {
223                // duplicate element, ignored.
224                return;
225            }
226        }
227        else {
228            fCurrentElementIndex = createElementDecl();//create element decl
229        }
230
231        XMLElementDecl elementDecl       = new XMLElementDecl();
232        QName          elementName       = new QName(null, name, name, null);
233
234        elementDecl.name.setValues(elementName);
235        elementDecl.scope= -1;
236        if (contentModel.equals("EMPTY")) {
237            elementDecl.type = XMLElementDecl.TYPE_EMPTY;
238        }
239        else if (contentModel.equals("ANY")) {
240            elementDecl.type = XMLElementDecl.TYPE_ANY;
241        }
242        else if (contentModel.startsWith("(") ) {
243            if (contentModel.indexOf("#PCDATA") > 0 ) {
244                elementDecl.type = XMLElementDecl.TYPE_MIXED;
245            }
246            else {
247                elementDecl.type = XMLElementDecl.TYPE_CHILDREN;
248            }
249        }
250
251
252        //add(or set) this elementDecl to the local cache
253        this.fElementDeclTab.put(name, elementDecl );
254
255        fElementDecl = elementDecl;
256
257
258        if ( DEBUG ) {
259            System.out.println(  "name = " + fElementDecl.name.localpart );
260            System.out.println(  "Type = " + fElementDecl.type );
261        }
262
263        setElementDecl(fCurrentElementIndex, fElementDecl );//set internal structure
264
265        int chunk = fCurrentElementIndex >> CHUNK_SHIFT;
266        ensureElementDeclCapacity(chunk);
267    }
268
269    /**
270     * An attribute declaration.
271     *
272     * @param elementName   The name of the element that this attribute
273     *                      is associated with.
274     * @param attributeName The name of the attribute.
275     * @param type          The attribute type. This value will be one of
276     *                      the following: "CDATA", "ENTITY", "ENTITIES",
277     *                      "ENUMERATION", "ID", "IDREF", "IDREFS",
278     *                      "NMTOKEN", "NMTOKENS", or "NOTATION".
279     * @param enumeration   If the type has the value "ENUMERATION", this
280     *                      array holds the allowed attribute values;
281     *                      otherwise, this array is null.
282     * @param defaultType   The attribute default type. This value will be
283     *                      one of the following: "#FIXED", "#IMPLIED",
284     *                      "#REQUIRED", or null.
285     * @param defaultValue  The attribute default value, or null if no
286     *                      default value is specified.
287     * @param nonNormalizedDefaultValue  The attribute default value with no normalization
288     *                      performed, or null if no default value is specified.
289     *
290     * @param augs Additional information that may include infoset
291     *                      augmentations.
292     * @throws XNIException Thrown by handler to signal an error.
293     */
294    public void attributeDecl(String elementName, String attributeName,
295    String type, String[] enumeration,
296    String defaultType, XMLString defaultValue,
297    XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
298
299        if (type != XMLSymbols.fCDATASymbol && defaultValue != null) {
300            normalizeDefaultAttrValue(defaultValue);
301        }
302
303        if ( this.fElementDeclTab.containsKey(elementName)) {
304            //if ElementDecl has already being created in the Grammar then remove from table,
305            //this.fElementDeclTab.remove( (String) elementName );
306        }
307        // then it is forward reference to a element decl, create the elementDecl first.
308        else {
309            fCurrentElementIndex = createElementDecl();//create element decl
310
311            XMLElementDecl elementDecl       = new XMLElementDecl();
312            elementDecl.name.setValues(null, elementName, elementName, null);
313
314            elementDecl.scope= -1;
315
316            //add(or set) this elementDecl to the local cache
317            this.fElementDeclTab.put(elementName, elementDecl );
318
319            //set internal structure
320            setElementDecl(fCurrentElementIndex, elementDecl );
321        }
322
323        //Get Grammar index to grammar array
324        int elementIndex       = getElementDeclIndex(elementName);
325
326        //return, when more than one definition is provided for the same attribute of given element type
327        //only the first declaration is binding and later declarations are ignored
328        if (getAttributeDeclIndex(elementIndex, attributeName) != -1) {
329            return;
330        }
331
332        fCurrentAttributeIndex = createAttributeDecl();// Create current Attribute Decl
333
334        fSimpleType.clear();
335        if ( defaultType != null ) {
336            if ( defaultType.equals( "#FIXED") ) {
337                fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_FIXED;
338            } else if ( defaultType.equals( "#IMPLIED") ) {
339                fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
340            } else if ( defaultType.equals( "#REQUIRED") ) {
341                fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_REQUIRED;
342            }
343        }
344        if ( DEBUG ) {
345            System.out.println("defaultvalue = " + defaultValue.toString() );
346        }
347        fSimpleType.defaultValue = defaultValue!=null ? defaultValue.toString() : null;
348        fSimpleType.nonNormalizedDefaultValue = nonNormalizedDefaultValue!=null ?
349                nonNormalizedDefaultValue.toString() : null;
350        fSimpleType.enumeration       = enumeration;
351
352        if (type.equals("CDATA")) {
353            fSimpleType.type = XMLSimpleType.TYPE_CDATA;
354        }
355        else if ( type.equals("ID") ) {
356            fSimpleType.type = XMLSimpleType.TYPE_ID;
357        }
358        else if ( type.startsWith("IDREF") ) {
359            fSimpleType.type = XMLSimpleType.TYPE_IDREF;
360            if (type.indexOf("S") > 0) {
361                fSimpleType.list = true;
362            }
363        }
364        else if (type.equals("ENTITIES")) {
365            fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
366            fSimpleType.list = true;
367        }
368        else if (type.equals("ENTITY")) {
369            fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
370        }
371        else if (type.equals("NMTOKENS")) {
372            fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
373            fSimpleType.list = true;
374        }
375        else if (type.equals("NMTOKEN")) {
376            fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
377        }
378        else if (type.startsWith("NOTATION") ) {
379            fSimpleType.type = XMLSimpleType.TYPE_NOTATION;
380        }
381        else if (type.startsWith("ENUMERATION") ) {
382            fSimpleType.type = XMLSimpleType.TYPE_ENUMERATION;
383        }
384        else {
385            // REVISIT: Report error message. -Ac
386            System.err.println("!!! unknown attribute type "+type);
387        }
388        // REVISIT: The datatype should be stored with the attribute value
389        //          and not special-cased in the XMLValidator. -Ac
390        //fSimpleType.datatypeValidator = fDatatypeValidatorFactory.createDatatypeValidator(type, null, facets, fSimpleType.list);
391
392        fQName.setValues(null, attributeName, attributeName, null);
393        fAttributeDecl.setValues( fQName, fSimpleType, false );
394
395        setAttributeDecl(elementIndex, fCurrentAttributeIndex, fAttributeDecl);
396
397        int chunk = fCurrentAttributeIndex >> CHUNK_SHIFT;
398        ensureAttributeDeclCapacity(chunk);
399    } // attributeDecl(String,String,String,String[],String,XMLString,XMLString, Augmentations)
400
401    /** Returns the symbol table. */
402    public SymbolTable getSymbolTable() {
403        return fSymbolTable;
404    } // getSymbolTable():SymbolTable
405
406    /**
407     * Returns the index of the first element declaration. This index
408     * is then used to query more information about the element declaration.
409     *
410     * @see #getNextElementDeclIndex
411     * @see #getElementDecl
412     */
413    public int getFirstElementDeclIndex() {
414        return fElementDeclCount >= 0 ? 0 : -1;
415    } // getFirstElementDeclIndex():int
416
417    /**
418     * Returns the next index of the element declaration following the
419     * specified element declaration.
420     *
421     * @param elementDeclIndex The element declaration index.
422     */
423    public int getNextElementDeclIndex(int elementDeclIndex) {
424        return elementDeclIndex < fElementDeclCount - 1
425        ? elementDeclIndex + 1 : -1;
426    } // getNextElementDeclIndex(int):int
427
428    /**
429     * getElementDeclIndex
430     *
431     * @param elementDeclName
432     *
433     * @return index of the elementDeclName in scope
434     */
435    public int getElementDeclIndex(String elementDeclName) {
436        Integer mapping = fElementIndexMap.get(elementDeclName);
437        if (mapping == null) {
438            mapping = -1;
439        }
440        //System.out.println("getElementDeclIndex("+elementDeclName+") -> "+mapping);
441        return mapping;
442    } // getElementDeclIndex(String):int
443
444    /** Returns the element decl index.
445     * @param elementDeclQName qualilfied name of the element
446     */
447    public int getElementDeclIndex(QName elementDeclQName) {
448        return getElementDeclIndex(elementDeclQName.rawname);
449    } // getElementDeclIndex(QName):int
450
451    /** make separate function for getting contentSpecType of element.
452     * we can avoid setting of the element values.
453     */
454
455    public short getContentSpecType(int elementIndex){
456        if (elementIndex < 0 || elementIndex >= fElementDeclCount) {
457            return -1 ;
458        }
459
460        int chunk = elementIndex >> CHUNK_SHIFT;
461        int index = elementIndex &  CHUNK_MASK;
462
463        if(fElementDeclType[chunk][index] == -1){
464            return -1 ;
465        }
466        else{
467            return (short) (fElementDeclType[chunk][index] & LIST_MASK);
468        }
469    }
470
471    /**
472     * getElementDecl
473     *
474     * @param elementDeclIndex
475     * @param elementDecl The values of this structure are set by this call.
476     *
477     * @return True if find the element, False otherwise.
478     */
479    public boolean getElementDecl(int elementDeclIndex,
480    XMLElementDecl elementDecl) {
481
482        if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
483            return false;
484        }
485
486        int chunk = elementDeclIndex >> CHUNK_SHIFT;
487        int index = elementDeclIndex &  CHUNK_MASK;
488
489        elementDecl.name.setValues(fElementDeclName[chunk][index]);
490
491        if (fElementDeclType[chunk][index] == -1) {
492            elementDecl.type                    = -1;
493            elementDecl.simpleType.list = false;
494        } else {
495            elementDecl.type            = (short) (fElementDeclType[chunk][index] & LIST_MASK);
496            elementDecl.simpleType.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0;
497        }
498
499        elementDecl.simpleType.defaultType       = -1;
500        elementDecl.simpleType.defaultValue      = null;
501        return true;
502
503    }
504
505    // REVISIT: Make this getAttributeDeclCount/getAttributeDeclAt. -Ac
506
507    /**
508     * getFirstAttributeDeclIndex
509     *
510     * @param elementDeclIndex
511     *
512     * @return index of the first attribute for element declaration elementDeclIndex
513     */
514    public int getFirstAttributeDeclIndex(int elementDeclIndex) {
515        int chunk = elementDeclIndex >> CHUNK_SHIFT;
516        int index = elementDeclIndex &  CHUNK_MASK;
517
518        return  fElementDeclFirstAttributeDeclIndex[chunk][index];
519    } // getFirstAttributeDeclIndex
520
521    /**
522     * getNextAttributeDeclIndex
523     *
524     * @param attributeDeclIndex
525     *
526     * @return index of the next attribute of the attribute at attributeDeclIndex
527     */
528    public int getNextAttributeDeclIndex(int attributeDeclIndex) {
529        int chunk = attributeDeclIndex >> CHUNK_SHIFT;
530        int index = attributeDeclIndex &  CHUNK_MASK;
531
532        return fAttributeDeclNextAttributeDeclIndex[chunk][index];
533    }
534
535    /**
536     * getAttributeDecl
537     *
538     * @param attributeDeclIndex
539     * @param attributeDecl The values of this structure are set by this call.
540     *
541     * @return true if getAttributeDecl was able to fill in the value of attributeDecl
542     */
543    public boolean getAttributeDecl(int attributeDeclIndex, XMLAttributeDecl attributeDecl) {
544        if (attributeDeclIndex < 0 || attributeDeclIndex >= fAttributeDeclCount) {
545            return false;
546        }
547        int chunk = attributeDeclIndex >> CHUNK_SHIFT;
548        int index = attributeDeclIndex & CHUNK_MASK;
549
550        attributeDecl.name.setValues(fAttributeDeclName[chunk][index]);
551
552        short attributeType;
553        boolean isList;
554
555        if (fAttributeDeclType[chunk][index] == -1) {
556
557            attributeType = -1;
558            isList = false;
559        } else {
560            attributeType = (short) (fAttributeDeclType[chunk][index] & LIST_MASK);
561            isList = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0;
562        }
563        attributeDecl.simpleType.setValues(attributeType,fAttributeDeclName[chunk][index].localpart,
564        fAttributeDeclEnumeration[chunk][index],
565        isList, fAttributeDeclDefaultType[chunk][index],
566        fAttributeDeclDefaultValue[chunk][index],
567        fAttributeDeclNonNormalizedDefaultValue[chunk][index]);
568        return true;
569
570    } // getAttributeDecl
571
572
573    /**
574     * Returns whether the given attribute is of type CDATA or not
575     *
576     * @param elName The element name.
577     * @param atName The attribute name.
578     *
579     * @return true if the attribute is of type CDATA
580     */
581    public boolean isCDATAAttribute(QName elName, QName atName) {
582        int elDeclIdx = getElementDeclIndex(elName);
583        if (getAttributeDecl(elDeclIdx, fAttributeDecl)
584        && fAttributeDecl.simpleType.type != XMLSimpleType.TYPE_CDATA){
585            return false;
586        }
587        return true;
588    }
589
590
591
592    public void printElements(  ) {
593        int elementDeclIndex = 0;
594        XMLElementDecl elementDecl = new XMLElementDecl();
595        while (getElementDecl(elementDeclIndex++, elementDecl)) {
596
597            System.out.println("element decl: "+elementDecl.name+
598            ", "+ elementDecl.name.rawname  );
599
600        }
601    }
602
603    public void printAttributes(int elementDeclIndex) {
604        int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex);
605        System.out.print(elementDeclIndex);
606        System.out.print(" [");
607        while (attributeDeclIndex != -1) {
608            System.out.print(' ');
609            System.out.print(attributeDeclIndex);
610            printAttribute(attributeDeclIndex);
611            attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex);
612            if (attributeDeclIndex != -1) {
613                System.out.print(",");
614            }
615        }
616        System.out.println(" ]");
617    }
618
619
620    protected int createElementDecl() {
621        int chunk = fElementDeclCount >> CHUNK_SHIFT;
622        int index = fElementDeclCount & CHUNK_MASK;
623        ensureElementDeclCapacity(chunk);
624        fElementDeclName[chunk][index]                    = new QName();
625        fElementDeclType[chunk][index]                    = -1;
626        fElementDeclFirstAttributeDeclIndex[chunk][index] = -1;
627        fElementDeclLastAttributeDeclIndex[chunk][index]  = -1;
628        return fElementDeclCount++;
629    }
630
631    protected void setElementDecl(int elementDeclIndex, XMLElementDecl elementDecl) {
632        if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
633            return;
634        }
635        int     chunk       = elementDeclIndex >> CHUNK_SHIFT;
636        int     index       = elementDeclIndex &  CHUNK_MASK;
637
638        int     scope       = elementDecl.scope;
639
640
641        fElementDeclName[chunk][index].setValues(elementDecl.name);
642        fElementDeclType[chunk][index]                  = elementDecl.type;
643
644
645
646        if (elementDecl.simpleType.list  == true ) {
647            fElementDeclType[chunk][index] |= LIST_FLAG;
648        }
649
650        fElementIndexMap.put(elementDecl.name.rawname, elementDeclIndex);
651    }
652
653
654
655
656    protected void setFirstAttributeDeclIndex(int elementDeclIndex, int newFirstAttrIndex){
657
658        if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
659            return;
660        }
661
662        int chunk = elementDeclIndex >> CHUNK_SHIFT;
663        int index = elementDeclIndex &  CHUNK_MASK;
664
665        fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex;
666    }
667
668
669    protected int createAttributeDecl() {
670        int chunk = fAttributeDeclCount >> CHUNK_SHIFT;
671        int index = fAttributeDeclCount & CHUNK_MASK;
672
673        ensureAttributeDeclCapacity(chunk);
674        fAttributeDeclName[chunk][index]                    = new QName();
675        fAttributeDeclType[chunk][index]                    = -1;
676        fAttributeDeclEnumeration[chunk][index]             = null;
677        fAttributeDeclDefaultType[chunk][index]             = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
678        fAttributeDeclDefaultValue[chunk][index]            = null;
679        fAttributeDeclNonNormalizedDefaultValue[chunk][index]            = null;
680        fAttributeDeclNextAttributeDeclIndex[chunk][index]  = -1;
681        return fAttributeDeclCount++;
682    }
683
684
685    protected void setAttributeDecl(int elementDeclIndex, int attributeDeclIndex,
686    XMLAttributeDecl attributeDecl) {
687        int attrChunk = attributeDeclIndex >> CHUNK_SHIFT;
688        int attrIndex = attributeDeclIndex &  CHUNK_MASK;
689        fAttributeDeclName[attrChunk][attrIndex].setValues(attributeDecl.name);
690        fAttributeDeclType[attrChunk][attrIndex]  =  attributeDecl.simpleType.type;
691
692        if (attributeDecl.simpleType.list) {
693            fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG;
694        }
695        fAttributeDeclEnumeration[attrChunk][attrIndex]  =  attributeDecl.simpleType.enumeration;
696        fAttributeDeclDefaultType[attrChunk][attrIndex]  =  attributeDecl.simpleType.defaultType;
697
698        fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.defaultValue;
699        fAttributeDeclNonNormalizedDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.nonNormalizedDefaultValue;
700
701        int elemChunk     = elementDeclIndex >> CHUNK_SHIFT;
702        int elemIndex     = elementDeclIndex &  CHUNK_MASK;
703        int index         = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex];
704        while (index != -1) {
705            if (index == attributeDeclIndex) {
706                break;
707            }
708            attrChunk = index >> CHUNK_SHIFT;
709            attrIndex = index & CHUNK_MASK;
710            index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex];
711        }
712        if (index == -1) {
713            if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) {
714                fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
715            } else {
716                index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex];
717                attrChunk = index >> CHUNK_SHIFT;
718                attrIndex = index & CHUNK_MASK;
719                fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex;
720            }
721            fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
722        }
723    }
724
725    public void notationDecl(String name, XMLResourceIdentifier identifier,
726    Augmentations augs) throws XNIException {
727
728
729        XMLNotationDecl  notationDecl = new XMLNotationDecl();
730        notationDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(),
731        identifier.getBaseSystemId());
732        notationDecls.add(notationDecl);
733    }
734
735    public List<XMLNotationDecl> getNotationDecls() {
736        return notationDecls;
737    }
738
739    //
740    // Private methods
741    //
742    private void printAttribute(int attributeDeclIndex) {
743
744        XMLAttributeDecl attributeDecl = new XMLAttributeDecl();
745        if (getAttributeDecl(attributeDeclIndex, attributeDecl)) {
746            System.out.print(" { ");
747            System.out.print(attributeDecl.name.localpart);
748            System.out.print(" }");
749        }
750
751    } // printAttribute(int)
752
753
754
755    private void ensureElementDeclCapacity(int chunk) {
756        if (chunk >= fElementDeclName.length) {
757
758            fElementDeclName = resize(fElementDeclName, fElementDeclName.length * 2);
759            fElementDeclType = resize(fElementDeclType, fElementDeclType.length * 2);
760            fElementDeclFirstAttributeDeclIndex = resize(fElementDeclFirstAttributeDeclIndex, fElementDeclFirstAttributeDeclIndex.length * 2);
761            fElementDeclLastAttributeDeclIndex = resize(fElementDeclLastAttributeDeclIndex, fElementDeclLastAttributeDeclIndex.length * 2);
762        }
763        else if (fElementDeclName[chunk] != null) {
764            return;
765        }
766
767        fElementDeclName[chunk] = new QName[CHUNK_SIZE];
768        fElementDeclType[chunk] = new short[CHUNK_SIZE];
769        fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
770        fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
771        return;
772    }
773
774    private void ensureAttributeDeclCapacity(int chunk) {
775
776        if (chunk >= fAttributeDeclName.length) {
777            fAttributeDeclName = resize(fAttributeDeclName, fAttributeDeclName.length * 2);
778            fAttributeDeclType = resize(fAttributeDeclType, fAttributeDeclType.length * 2);
779            fAttributeDeclEnumeration = resize(fAttributeDeclEnumeration, fAttributeDeclEnumeration.length * 2);
780            fAttributeDeclDefaultType = resize(fAttributeDeclDefaultType, fAttributeDeclDefaultType.length * 2);
781            fAttributeDeclDefaultValue = resize(fAttributeDeclDefaultValue, fAttributeDeclDefaultValue.length * 2);
782            fAttributeDeclNonNormalizedDefaultValue = resize(fAttributeDeclNonNormalizedDefaultValue, fAttributeDeclNonNormalizedDefaultValue.length * 2);
783            fAttributeDeclNextAttributeDeclIndex = resize(fAttributeDeclNextAttributeDeclIndex, fAttributeDeclNextAttributeDeclIndex.length * 2);
784        }
785        else if (fAttributeDeclName[chunk] != null) {
786            return;
787        }
788
789        fAttributeDeclName[chunk] = new QName[CHUNK_SIZE];
790        fAttributeDeclType[chunk] = new short[CHUNK_SIZE];
791        fAttributeDeclEnumeration[chunk] = new String[CHUNK_SIZE][];
792        fAttributeDeclDefaultType[chunk] = new short[CHUNK_SIZE];
793        fAttributeDeclDefaultValue[chunk] = new String[CHUNK_SIZE];
794        fAttributeDeclNonNormalizedDefaultValue[chunk] = new String[CHUNK_SIZE];
795        fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
796        return;
797    }
798
799
800    // resize chunks
801
802    private static short[][] resize(short array[][], int newsize) {
803        short newarray[][] = new short[newsize][];
804        System.arraycopy(array, 0, newarray, 0, array.length);
805        return newarray;
806    }
807
808    private static int[][] resize(int array[][], int newsize) {
809        int newarray[][] = new int[newsize][];
810        System.arraycopy(array, 0, newarray, 0, array.length);
811        return newarray;
812    }
813
814    private static QName[][] resize(QName array[][], int newsize) {
815        QName newarray[][] = new QName[newsize][];
816        System.arraycopy(array, 0, newarray, 0, array.length);
817        return newarray;
818    }
819
820    private static String[][] resize(String array[][], int newsize) {
821        String newarray[][] = new String[newsize][];
822        System.arraycopy(array, 0, newarray, 0, array.length);
823        return newarray;
824    }
825
826    private static String[][][] resize(String array[][][], int newsize) {
827        String newarray[][][] = new String[newsize] [][];
828        System.arraycopy(array, 0, newarray, 0, array.length);
829        return newarray;
830    }
831
832    /**
833     * Normalize the attribute value of a non CDATA default attribute
834     * collapsing sequences of space characters (x20)
835     *
836     * @param value The value to normalize
837     * @return Whether the value was changed or not.
838     */
839    private boolean normalizeDefaultAttrValue(XMLString value) {
840
841        int oldLength = value.length;
842
843        boolean skipSpace = true; // skip leading spaces
844        int current = value.offset;
845        int end = value.offset + value.length;
846        for (int i = value.offset; i < end; i++) {
847            if (value.ch[i] == ' ') {
848                if (!skipSpace) {
849                    // take the first whitespace as a space and skip the others
850                    value.ch[current++] = ' ';
851                    skipSpace = true;
852                }
853                else {
854                    // just skip it.
855                }
856            }
857            else {
858                // simply shift non space chars if needed
859                if (current != i) {
860                    value.ch[current] = value.ch[i];
861                }
862                current++;
863                skipSpace = false;
864            }
865        }
866        if (current != end) {
867            if (skipSpace) {
868                // if we finished on a space trim it
869                current--;
870            }
871            // set the new value length
872            value.length = current - value.offset;
873            return true;
874        }
875        return false;
876    }
877    public void endDTD(Augmentations augs) throws XNIException {
878
879    }
880}
881