Save This Page
Home » Xerces-J-src.2.9.1 » org.apache.xerces » impl » dtd » [javadoc | source]
    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

Save This Page
Home » Xerces-J-src.2.9.1 » org.apache.xerces » impl » dtd » [javadoc | source]