diff options
Diffstat (limited to 'src/share/classes/com/sun/org/apache/xerces/internal/impl/dtd/DTDGrammar.java')
-rw-r--r-- | src/share/classes/com/sun/org/apache/xerces/internal/impl/dtd/DTDGrammar.java | 2791 |
1 files changed, 2791 insertions, 0 deletions
diff --git a/src/share/classes/com/sun/org/apache/xerces/internal/impl/dtd/DTDGrammar.java b/src/share/classes/com/sun/org/apache/xerces/internal/impl/dtd/DTDGrammar.java new file mode 100644 index 0000000..71a9231 --- /dev/null +++ b/src/share/classes/com/sun/org/apache/xerces/internal/impl/dtd/DTDGrammar.java @@ -0,0 +1,2791 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * The Apache Software License, Version 1.1 + * + * + * Copyright (c) 1999-2002 The Apache Software Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Xerces" and "Apache Software Foundation" must + * not be used to endorse or promote products derived from this + * software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * nor may "Apache" appear in their name, without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation and was + * originally based on software copyright (c) 1999, International + * Business Machines, Inc., http://www.apache.org. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +package com.sun.org.apache.xerces.internal.impl.dtd; + +import java.util.ArrayList; +import java.util.Hashtable; + +import com.sun.org.apache.xerces.internal.impl.dtd.models.CMAny; +import com.sun.org.apache.xerces.internal.impl.dtd.models.CMBinOp; +import com.sun.org.apache.xerces.internal.impl.dtd.models.CMLeaf; +import com.sun.org.apache.xerces.internal.impl.dtd.models.CMNode; +import com.sun.org.apache.xerces.internal.impl.dtd.models.CMUniOp; +import com.sun.org.apache.xerces.internal.impl.dtd.models.ContentModelValidator; +import com.sun.org.apache.xerces.internal.impl.dtd.models.DFAContentModel; +import com.sun.org.apache.xerces.internal.impl.dtd.models.MixedContentModel; +import com.sun.org.apache.xerces.internal.impl.dtd.models.SimpleContentModel; +import com.sun.org.apache.xerces.internal.impl.dv.DatatypeValidator; +import com.sun.org.apache.xerces.internal.impl.validation.EntityState; +import com.sun.org.apache.xerces.internal.util.SymbolTable; +import com.sun.org.apache.xerces.internal.xni.Augmentations; +import com.sun.org.apache.xerces.internal.xni.QName; +import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; +import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; +import com.sun.org.apache.xerces.internal.xni.XMLLocator; +import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; +import com.sun.org.apache.xerces.internal.xni.XMLString; +import com.sun.org.apache.xerces.internal.xni.XNIException; +import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; +import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; +import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource; +import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource; + +/** + * A DTD grammar. This class implements the XNI handler interfaces + * for DTD information so that it can build the approprate validation + * structures automatically from the callbacks. + * + * @xerces.internal + * + * @author Eric Ye, IBM + * @author Jeffrey Rodriguez, IBM + * @author Andy Clark, IBM + * @author Neil Graham, IBM + * + * @version $Id: DTDGrammar.java,v 1.4 2010/08/11 07:18:37 joehw Exp $ + */ +public class DTDGrammar + implements XMLDTDHandler, XMLDTDContentModelHandler, EntityState, Grammar { + + // + // Constants + // + + /** Top level scope (-1). */ + public static final int TOP_LEVEL_SCOPE = -1; + + // private + + /** Chunk shift (8). */ + private static final int CHUNK_SHIFT = 8; // 2^8 = 256 + + /** Chunk size (1 << CHUNK_SHIFT). */ + private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT); + + /** Chunk mask (CHUNK_SIZE - 1). */ + private static final int CHUNK_MASK = CHUNK_SIZE - 1; + + /** Initial chunk count (1 << (10 - CHUNK_SHIFT)). */ + private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k + + /** List flag (0x80). */ + private static final short LIST_FLAG = 0x80; + + /** List mask (~LIST_FLAG). */ + private static final short LIST_MASK = ~LIST_FLAG; + + // debugging + + /** Debug DTDGrammar. */ + private static final boolean DEBUG = false; + + // + // Data + // + + protected XMLDTDSource fDTDSource = null; + protected XMLDTDContentModelSource fDTDContentModelSource = null; + + /** Current element index. */ + protected int fCurrentElementIndex; + + /** Current attribute index. */ + protected int fCurrentAttributeIndex; + + /** fReadingExternalDTD */ + protected boolean fReadingExternalDTD = false; + + /** Symbol table. */ + private SymbolTable fSymbolTable; + + // The XMLDTDDescription with which this Grammar is associated + protected XMLDTDDescription fGrammarDescription = null; + + // element declarations + + /** Number of element declarations. */ + private int fElementDeclCount = 0; + + /** Element declaration name. */ + private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][]; + + /** + * Element declaration type. + * @see XMLElementDecl + */ + private short fElementDeclType[][] = new short[INITIAL_CHUNK_COUNT][]; + + /** + * Element declaration content spec index. This index value is used + * to refer to the content spec information tables. + */ + private int fElementDeclContentSpecIndex[][] = new int[INITIAL_CHUNK_COUNT][]; + + /** + * Element declaration content model validator. This validator is + * constructed from the content spec nodes. + */ + private ContentModelValidator fElementDeclContentModelValidator[][] = new ContentModelValidator[INITIAL_CHUNK_COUNT][]; + + /** First attribute declaration of an element declaration. */ + private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][]; + + /** Last attribute declaration of an element declaration. */ + private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][]; + + // attribute declarations + + /** Number of attribute declarations. */ + private int fAttributeDeclCount = 0 ; + + /** Attribute declaration name. */ + private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][]; + + // is this grammar immutable? (fully constructed and not changeable) + private boolean fIsImmutable = false; + + /** + * Attribute declaration type. + * @see XMLAttributeDecl + */ + private short fAttributeDeclType[][] = new short[INITIAL_CHUNK_COUNT][]; + + /** Attribute declaration enumeration values. */ + private String[] fAttributeDeclEnumeration[][] = new String[INITIAL_CHUNK_COUNT][][]; + private short fAttributeDeclDefaultType[][] = new short[INITIAL_CHUNK_COUNT][]; + private DatatypeValidator fAttributeDeclDatatypeValidator[][] = new DatatypeValidator[INITIAL_CHUNK_COUNT][]; + private String fAttributeDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][]; + private String fAttributeDeclNonNormalizedDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][]; + private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][]; + + // content specs + + // here saves the content spec binary trees for element decls, + // each element with a content model will hold a pointer which is + // the index of the head node of the content spec tree. + + private int fContentSpecCount = 0; + private short fContentSpecType[][] = new short[INITIAL_CHUNK_COUNT][]; + private Object fContentSpecValue[][] = new Object[INITIAL_CHUNK_COUNT][]; + private Object fContentSpecOtherValue[][] = new Object[INITIAL_CHUNK_COUNT][]; + + // entities + + private int fEntityCount = 0; + private String fEntityName[][] = new String[INITIAL_CHUNK_COUNT][]; + private String[][] fEntityValue = new String[INITIAL_CHUNK_COUNT][]; + private String[][] fEntityPublicId = new String[INITIAL_CHUNK_COUNT][]; + private String[][] fEntitySystemId = new String[INITIAL_CHUNK_COUNT][]; + private String[][] fEntityBaseSystemId = new String[INITIAL_CHUNK_COUNT][]; + private String[][] fEntityNotation = new String[INITIAL_CHUNK_COUNT][]; + private byte[][] fEntityIsPE = new byte[INITIAL_CHUNK_COUNT][]; + private byte[][] fEntityInExternal = new byte[INITIAL_CHUNK_COUNT][]; + + // notations + + private int fNotationCount = 0; + private String fNotationName[][] = new String[INITIAL_CHUNK_COUNT][]; + private String[][] fNotationPublicId = new String[INITIAL_CHUNK_COUNT][]; + private String[][] fNotationSystemId = new String[INITIAL_CHUNK_COUNT][]; + private String[][] fNotationBaseSystemId = new String[INITIAL_CHUNK_COUNT][]; + + // other information + + /** Element index mapping table. */ + private QNameHashtable fElementIndexMap = new QNameHashtable(); + + /** Entity index mapping table. */ + private QNameHashtable fEntityIndexMap = new QNameHashtable(); + + /** Notation index mapping table. */ + private QNameHashtable fNotationIndexMap = new QNameHashtable(); + + // temp variables + + /** Mixed. */ + private boolean fMixed; + + /** Temporary qualified name. */ + private final QName fQName = new QName(); + + /** Temporary qualified name. */ + private final QName fQName2 = new QName(); + + /** Temporary Attribute decl. */ + protected final XMLAttributeDecl fAttributeDecl = new XMLAttributeDecl(); + + // for buildSyntaxTree method + + private int fLeafCount = 0; + private int fEpsilonIndex = -1; + + /** Element declaration. */ + private XMLElementDecl fElementDecl = new XMLElementDecl(); + + /** Entity declaration. */ + private XMLEntityDecl fEntityDecl = new XMLEntityDecl(); + + /** Simple type. */ + private XMLSimpleType fSimpleType = new XMLSimpleType(); + + /** Content spec node. */ + private XMLContentSpec fContentSpec = new XMLContentSpec(); + + /** table of XMLElementDecl */ + Hashtable fElementDeclTab = new Hashtable(); + + /** Children content model operation stack. */ + private short[] fOpStack = null; + + /** Children content model index stack. */ + private int[] fNodeIndexStack = null; + + /** Children content model previous node index stack. */ + private int[] fPrevNodeIndexStack = null; + + /** Stack depth */ + private int fDepth = 0; + + /** Entity stack. */ + private boolean[] fPEntityStack = new boolean[4]; + private int fPEDepth = 0; + + // additional fields(columns) for the element Decl pool in the Grammar + + /** flag if the elementDecl is External. */ + private int fElementDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][]; + + + // additional fields(columns) for the attribute Decl pool in the Grammar + + /** flag if the AttributeDecl is External. */ + private int fAttributeDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][]; + + // for mixedElement method + + int valueIndex = -1; + int prevNodeIndex = -1; + int nodeIndex = -1; + + // + // Constructors + // + + /** Default constructor. */ + public DTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) { + fSymbolTable = symbolTable; + fGrammarDescription = desc; + } // <init>(SymbolTable) + + // Grammar methods + + // return the XMLDTDDescription object with which this is associated + public XMLGrammarDescription getGrammarDescription() { + return fGrammarDescription; + } // getGrammarDescription(): XMLGrammarDescription + + // + // Public methods + // + + /** + * Returns true if the specified element declaration is external. + * + * @param elementDeclIndex The element declaration index. + */ + public boolean getElementDeclIsExternal(int elementDeclIndex) { + + if (elementDeclIndex < 0) { + return false; + } + + int chunk = elementDeclIndex >> CHUNK_SHIFT; + int index = elementDeclIndex & CHUNK_MASK; + return (fElementDeclIsExternal[chunk][index] != 0); + + } // getElementDeclIsExternal(int):boolean + + /** + * Returns true if the specified attribute declaration is external. + * + * @param attributeDeclIndex Attribute declaration index. + */ + public boolean getAttributeDeclIsExternal(int attributeDeclIndex) { + + if (attributeDeclIndex < 0) { + return false; + } + + int chunk = attributeDeclIndex >> CHUNK_SHIFT; + int index = attributeDeclIndex & CHUNK_MASK; + return (fAttributeDeclIsExternal[chunk][index] != 0); + } + + public int getAttributeDeclIndex(int elementDeclIndex, String attributeDeclName) { + if (elementDeclIndex == -1) { + return -1; + } + int attDefIndex = getFirstAttributeDeclIndex(elementDeclIndex); + while (attDefIndex != -1) { + getAttributeDecl(attDefIndex, fAttributeDecl); + + if (fAttributeDecl.name.rawname == attributeDeclName + || attributeDeclName.equals(fAttributeDecl.name.rawname) ) { + return attDefIndex; + } + attDefIndex = getNextAttributeDeclIndex(attDefIndex); + } + return -1; + } // getAttributeDeclIndex (int,QName) + + // + // XMLDTDHandler methods + // + + /** + * The start of the DTD. + * + * @param locator The document locator, or null if the document + * location cannot be reported during the parsing of + * the document DTD. However, it is <em>strongly</em> + * recommended that a locator be supplied that can + * at least report the base system identifier of the + * DTD. + * + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException { + //Initialize stack + fOpStack = null; + fNodeIndexStack = null; + fPrevNodeIndexStack = null; + } // startDTD(XMLLocator) + + /** + * This method notifies of the start of an entity. The DTD has the + * pseudo-name of "[dtd]" and parameter entity names start with '%'. + * <p> + * <strong>Note:</strong> Since the DTD is an entity, the handler + * will be notified of the start of the DTD entity by calling the + * startParameterEntity method with the entity name "[dtd]" <em>before</em> calling + * the startDTD method. + * + * @param name The name of the parameter entity. + * @param identifier The resource identifier. + * @param encoding The auto-detected IANA encoding name of the entity + * stream. This value will be null in those situations + * where the entity encoding is not auto-detected (e.g. + * internal parameter entities). + * @param augs Additional information that may include infoset + * augmentations. + * + * @throws XNIException Thrown by handler to signal an error. + */ + public void startParameterEntity(String name, + XMLResourceIdentifier identifier, + String encoding, + Augmentations augs) throws XNIException { + + // keep track of this entity before fEntityDepth is increased + if (fPEDepth == fPEntityStack.length) { + boolean[] entityarray = new boolean[fPEntityStack.length * 2]; + System.arraycopy(fPEntityStack, 0, entityarray, 0, fPEntityStack.length); + fPEntityStack = entityarray; + } + fPEntityStack[fPEDepth] = fReadingExternalDTD; + fPEDepth++; + + } // startParameterEntity(String,XMLResourceIdentifier,String,Augmentations) + + /** + * The start of the DTD external subset. + * + * @param augs Additional information that may include infoset + * augmentations. + * + * @throws XNIException Thrown by handler to signal an error. + */ + public void startExternalSubset(XMLResourceIdentifier identifier, + Augmentations augs) throws XNIException { + fReadingExternalDTD = true; + } // startExternalSubset(Augmentations) + + /** + * This method notifies the end of an entity. The DTD has the pseudo-name + * of "[dtd]" and parameter entity names start with '%'. + * <p> + * <strong>Note:</strong> Since the DTD is an entity, the handler + * will be notified of the end of the DTD entity by calling the + * endEntity method with the entity name "[dtd]" <em>after</em> calling + * the endDTD method. + * + * @param name The name of the entity. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void endParameterEntity(String name, Augmentations augs) throws XNIException { + + fPEDepth--; + fReadingExternalDTD = fPEntityStack[fPEDepth]; + + } // endParameterEntity(String,Augmentations) + + /** + * The end of the DTD external subset. + * + * @param augs Additional information that may include infoset + * augmentations. + * + * @throws XNIException Thrown by handler to signal an error. + */ + public void endExternalSubset(Augmentations augs) throws XNIException { + fReadingExternalDTD = false; + } // endExternalSubset(Augmentations) + + /** + * An element declaration. + * + * @param name The name of the element. + * @param contentModel The element content model. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void elementDecl(String name, String contentModel, Augmentations augs) + throws XNIException { + + XMLElementDecl tmpElementDecl = (XMLElementDecl) fElementDeclTab.get(name) ; + + // check if it is already defined + if ( tmpElementDecl != null ) { + if (tmpElementDecl.type == -1) { + fCurrentElementIndex = getElementDeclIndex(name); + } + else { + // duplicate element, ignored. + return; + } + } + else { + fCurrentElementIndex = createElementDecl();//create element decl + } + + XMLElementDecl elementDecl = new XMLElementDecl(); + + fQName.setValues(null, name, name, null); + + elementDecl.name.setValues(fQName); + + elementDecl.contentModelValidator = null; + elementDecl.scope= -1; + if (contentModel.equals("EMPTY")) { + elementDecl.type = XMLElementDecl.TYPE_EMPTY; + } + else if (contentModel.equals("ANY")) { + elementDecl.type = XMLElementDecl.TYPE_ANY; + } + else if (contentModel.startsWith("(") ) { + if (contentModel.indexOf("#PCDATA") > 0 ) { + elementDecl.type = XMLElementDecl.TYPE_MIXED; + } + else { + elementDecl.type = XMLElementDecl.TYPE_CHILDREN; + } + } + + + //add(or set) this elementDecl to the local cache + this.fElementDeclTab.put(name, elementDecl ); + + fElementDecl = elementDecl; + addContentSpecToElement(elementDecl); + + if ( DEBUG ) { + System.out.println( "name = " + fElementDecl.name.localpart ); + System.out.println( "Type = " + fElementDecl.type ); + } + + setElementDecl(fCurrentElementIndex, fElementDecl );//set internal structure + + int chunk = fCurrentElementIndex >> CHUNK_SHIFT; + int index = fCurrentElementIndex & CHUNK_MASK; + ensureElementDeclCapacity(chunk); + fElementDeclIsExternal[chunk][index] = (fReadingExternalDTD || fPEDepth > 0) ? 1 : 0; + + } // elementDecl(String,String) + + /** + * An attribute declaration. + * + * @param elementName The name of the element that this attribute + * is associated with. + * @param attributeName The name of the attribute. + * @param type The attribute type. This value will be one of + * the following: "CDATA", "ENTITY", "ENTITIES", + * "ENUMERATION", "ID", "IDREF", "IDREFS", + * "NMTOKEN", "NMTOKENS", or "NOTATION". + * @param enumeration If the type has the value "ENUMERATION", this + * array holds the allowed attribute values; + * otherwise, this array is null. + * @param defaultType The attribute default type. This value will be + * one of the following: "#FIXED", "#IMPLIED", + * "#REQUIRED", or null. + * @param defaultValue The attribute default value, or null if no + * default value is specified. + * @param nonNormalizedDefaultValue The attribute default value with no normalization + * performed, or null if no default value is specified. + * + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void attributeDecl(String elementName, String attributeName, + String type, String[] enumeration, + String defaultType, XMLString defaultValue, + XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException { + + if ( this.fElementDeclTab.containsKey( (String) elementName) ) { + //if ElementDecl has already being created in the Grammar then remove from table, + //this.fElementDeclTab.remove( (String) elementName ); + } + // then it is forward reference to a element decl, create the elementDecl first. + else { + fCurrentElementIndex = createElementDecl();//create element decl + + XMLElementDecl elementDecl = new XMLElementDecl(); + elementDecl.name.setValues(null, elementName, elementName, null); + + elementDecl.scope= -1; + + //add(or set) this elementDecl to the local cache + this.fElementDeclTab.put(elementName, elementDecl ); + + //set internal structure + setElementDecl(fCurrentElementIndex, elementDecl ); + } + + //Get Grammar index to grammar array + int elementIndex = getElementDeclIndex(elementName); + + //return, when more than one definition is provided for the same attribute of given element type + //only the first declaration is binding and later declarations are ignored + if (getAttributeDeclIndex(elementIndex, attributeName) != -1) { + return; + } + + fCurrentAttributeIndex = createAttributeDecl();// Create current Attribute Decl + + fSimpleType.clear(); + if ( defaultType != null ) { + if ( defaultType.equals( "#FIXED") ) { + fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_FIXED; + } else if ( defaultType.equals( "#IMPLIED") ) { + fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_IMPLIED; + } else if ( defaultType.equals( "#REQUIRED") ) { + fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_REQUIRED; + } + } + if ( DEBUG ) { + System.out.println("defaultvalue = " + defaultValue.toString() ); + } + fSimpleType.defaultValue = defaultValue!=null ? defaultValue.toString() : null; + fSimpleType.nonNormalizedDefaultValue = nonNormalizedDefaultValue!=null ? nonNormalizedDefaultValue.toString() : null; + fSimpleType.enumeration = enumeration; + + if (type.equals("CDATA")) { + fSimpleType.type = XMLSimpleType.TYPE_CDATA; + } + else if ( type.equals("ID") ) { + fSimpleType.type = XMLSimpleType.TYPE_ID; + } + else if ( type.startsWith("IDREF") ) { + fSimpleType.type = XMLSimpleType.TYPE_IDREF; + if (type.indexOf("S") > 0) { + fSimpleType.list = true; + } + } + else if (type.equals("ENTITIES")) { + fSimpleType.type = XMLSimpleType.TYPE_ENTITY; + fSimpleType.list = true; + } + else if (type.equals("ENTITY")) { + fSimpleType.type = XMLSimpleType.TYPE_ENTITY; + } + else if (type.equals("NMTOKENS")) { + fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN; + fSimpleType.list = true; + } + else if (type.equals("NMTOKEN")) { + fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN; + } + else if (type.startsWith("NOTATION") ) { + fSimpleType.type = XMLSimpleType.TYPE_NOTATION; + } + else if (type.startsWith("ENUMERATION") ) { + fSimpleType.type = XMLSimpleType.TYPE_ENUMERATION; + } + else { + // REVISIT: Report error message. -Ac + System.err.println("!!! unknown attribute type "+type); + } + // REVISIT: The datatype should be stored with the attribute value + // and not special-cased in the XMLValidator. -Ac + //fSimpleType.datatypeValidator = fDatatypeValidatorFactory.createDatatypeValidator(type, null, facets, fSimpleType.list); + + fQName.setValues(null, attributeName, attributeName, null); + fAttributeDecl.setValues( fQName, fSimpleType, false ); + + setAttributeDecl(elementIndex, fCurrentAttributeIndex, fAttributeDecl); + + int chunk = fCurrentAttributeIndex >> CHUNK_SHIFT; + int index = fCurrentAttributeIndex & CHUNK_MASK; + ensureAttributeDeclCapacity(chunk); + fAttributeDeclIsExternal[chunk][index] = (fReadingExternalDTD || fPEDepth > 0) ? 1 : 0; + + } // attributeDecl(String,String,String,String[],String,XMLString,XMLString, Augmentations) + + /** + * An internal entity declaration. + * + * @param name The name of the entity. Parameter entity names start with + * '%', whereas the name of a general entity is just the + * entity name. + * @param text The value of the entity. + * @param nonNormalizedText The non-normalized value of the entity. This + * value contains the same sequence of characters that was in + * the internal entity declaration, without any entity + * references expanded. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void internalEntityDecl(String name, XMLString text, + XMLString nonNormalizedText, + Augmentations augs) throws XNIException { + + int entityIndex = getEntityDeclIndex(name); + if( entityIndex == -1){ + entityIndex = createEntityDecl(); + boolean isPE = name.startsWith("%"); + boolean inExternal = (fReadingExternalDTD || fPEDepth > 0); + XMLEntityDecl entityDecl = new XMLEntityDecl(); + entityDecl.setValues(name,null,null, null, null, + text.toString(), isPE, inExternal); + + setEntityDecl(entityIndex, entityDecl); + } + + } // internalEntityDecl(String,XMLString,XMLString) + + /** + * An external entity declaration. + * + * @param name The name of the entity. Parameter entity names start + * with '%', whereas the name of a general entity is just + * the entity name. + * @param identifier An object containing all location information + * pertinent to this external entity declaration. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void externalEntityDecl(String name, + XMLResourceIdentifier identifier, + Augmentations augs) throws XNIException { + + int entityIndex = getEntityDeclIndex(name); + if( entityIndex == -1){ + entityIndex = createEntityDecl(); + boolean isPE = name.startsWith("%"); + boolean inExternal = (fReadingExternalDTD || fPEDepth > 0); + + XMLEntityDecl entityDecl = new XMLEntityDecl(); + entityDecl.setValues(name, identifier.getPublicId(), identifier.getLiteralSystemId(), + identifier.getBaseSystemId(), + null, null, isPE, inExternal); + + setEntityDecl(entityIndex, entityDecl); + } + } // externalEntityDecl(String, XMLResourceIdentifier, Augmentations) + + /** + * An unparsed entity declaration. + * + * @param name The name of the entity. + * @param identifier An object containing all location information + * pertinent to this entity. + * @param notation The name of the notation. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier, + String notation, + Augmentations augs) throws XNIException { + + XMLEntityDecl entityDecl = new XMLEntityDecl(); + boolean isPE = name.startsWith("%"); + boolean inExternal = (fReadingExternalDTD || fPEDepth > 0); + + entityDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(), + identifier.getBaseSystemId(), notation, + null, isPE, inExternal); + int entityIndex = getEntityDeclIndex(name); + if (entityIndex == -1) { + entityIndex = createEntityDecl(); + setEntityDecl(entityIndex, entityDecl); + } + + } // unparsedEntityDecl(String,StringXMLResourceIdentifier,Augmentations) + + /** + * A notation declaration + * + * @param name The name of the notation. + * @param identifier An object containing all location information + * pertinent to this notation. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void notationDecl(String name, XMLResourceIdentifier identifier, + Augmentations augs) throws XNIException { + + XMLNotationDecl notationDecl = new XMLNotationDecl(); + notationDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(), + identifier.getBaseSystemId()); + int notationIndex = getNotationDeclIndex(name); + if (notationIndex == -1) { + notationIndex = createNotationDecl(); + setNotationDecl(notationIndex, notationDecl); + } + + } // notationDecl(String,XMLResourceIdentifier,Augmentations) + + /** + * The end of the DTD. + * + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void endDTD(Augmentations augs) throws XNIException { + fIsImmutable = true; + // make sure our description contains useful stuff... + if (fGrammarDescription.getRootName() == null) { + // we don't know what the root is; so use possibleRoots... + int chunk, index = 0; + String currName = null; + final int size = fElementDeclCount; + ArrayList elements = new ArrayList(size); + for (int i = 0; i < size; ++i) { + chunk = i >> CHUNK_SHIFT; + index = i & CHUNK_MASK; + currName = fElementDeclName[chunk][index].rawname; + elements.add(currName); + } + fGrammarDescription.setPossibleRoots(elements); + } + } // endDTD() + + // sets the source of this handler + public void setDTDSource(XMLDTDSource source) { + fDTDSource = source; + } // setDTDSource(XMLDTDSource) + + // returns the source of this handler + public XMLDTDSource getDTDSource() { + return fDTDSource; + } // getDTDSource(): XMLDTDSource + + // no-op methods + + /** + * Notifies of the presence of a TextDecl line in an entity. If present, + * this method will be called immediately following the startEntity call. + * <p> + * <strong>Note:</strong> This method is only called for external + * parameter entities referenced in the DTD. + * + * @param version The XML version, or null if not specified. + * @param encoding The IANA encoding name of the entity. + * + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void textDecl(String version, String encoding, Augmentations augs) + throws XNIException {} + + /** + * A comment. + * + * @param text The text in the comment. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by application to signal an error. + */ + public void comment(XMLString text, Augmentations augs) throws XNIException {} + + /** + * A processing instruction. Processing instructions consist of a + * target name and, optionally, text data. The data is only meaningful + * to the application. + * <p> + * Typically, a processing instruction's data will contain a series + * of pseudo-attributes. These pseudo-attributes follow the form of + * element attributes but are <strong>not</strong> parsed or presented + * to the application as anything other than text. The application is + * responsible for parsing the data. + * + * @param target The target. + * @param data The data or null if none specified. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void processingInstruction(String target, XMLString data, + Augmentations augs) throws XNIException {} + + /** + * The start of an attribute list. + * + * @param elementName The name of the element that this attribute + * list is associated with. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void startAttlist(String elementName, Augmentations augs) + throws XNIException {} + + /** + * The end of an attribute list. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void endAttlist(Augmentations augs) throws XNIException {} + + /** + * The start of a conditional section. + * + * @param type The type of the conditional section. This value will + * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + * + * @see XMLDTDHandler#CONDITIONAL_INCLUDE + * @see XMLDTDHandler#CONDITIONAL_IGNORE + */ + public void startConditional(short type, Augmentations augs) + throws XNIException {} + + /** + * Characters within an IGNORE conditional section. + * + * @param text The ignored text. + * @param augs Additional information that may include infoset + * augmentations. + */ + public void ignoredCharacters(XMLString text, Augmentations augs) + throws XNIException {} + + /** + * The end of a conditional section. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void endConditional(Augmentations augs) throws XNIException {} + + // + // XMLDTDContentModelHandler methods + // + + // set content model source + public void setDTDContentModelSource(XMLDTDContentModelSource source) { + fDTDContentModelSource = source; + } + + // get content model source + public XMLDTDContentModelSource getDTDContentModelSource() { + return fDTDContentModelSource; + } + + /** + * The start of a content model. Depending on the type of the content + * model, specific methods may be called between the call to the + * startContentModel method and the call to the endContentModel method. + * + * @param elementName The name of the element. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void startContentModel(String elementName, Augmentations augs) + throws XNIException { + + XMLElementDecl elementDecl = (XMLElementDecl) this.fElementDeclTab.get( elementName); + if ( elementDecl != null ) { + fElementDecl = elementDecl; + } + fDepth = 0; + initializeContentModelStack(); + + } // startContentModel(String) + + /** + * A start of either a mixed or children content model. A mixed + * content model will immediately be followed by a call to the + * <code>pcdata()</code> method. A children content model will + * contain additional groups and/or elements. + * + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + * + * @see #any + * @see #empty + */ + public void startGroup(Augmentations augs) throws XNIException { + fDepth++; + initializeContentModelStack(); + fMixed = false; + } // startGroup() + + /** + * The appearance of "#PCDATA" within a group signifying a + * mixed content model. This method will be the first called + * following the content model's <code>startGroup()</code>. + * + *@param augs Additional information that may include infoset + * augmentations. + * + * @throws XNIException Thrown by handler to signal an error. + * + * @see #startGroup + */ + public void pcdata(Augmentations augs) throws XNIException { + fMixed = true; + } // pcdata() + + /** + * A referenced element in a mixed or children content model. + * + * @param elementName The name of the referenced element. + * @param augs Additional information that may include infoset + * augmentations. + * + * @throws XNIException Thrown by handler to signal an error. + */ + public void element(String elementName, Augmentations augs) throws XNIException { + if (fMixed) { + if (fNodeIndexStack[fDepth] == -1 ) { + fNodeIndexStack[fDepth] = addUniqueLeafNode(elementName); + } + else { + fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, + fNodeIndexStack[fDepth], + addUniqueLeafNode(elementName)); + } + } + else { + fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, elementName); + } + } // element(String) + + /** + * The separator between choices or sequences of a mixed or children + * content model. + * + * @param separator The type of children separator. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + * + * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE + * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE + */ + public void separator(short separator, Augmentations augs) throws XNIException { + + if (!fMixed) { + if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_SEQ && separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE ) { + if (fPrevNodeIndexStack[fDepth] != -1) { + fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]); + } + fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth]; + fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE; + } else if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_CHOICE && separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) { + if (fPrevNodeIndexStack[fDepth] != -1) { + fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]); + } + fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth]; + fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ; + } + } + + } // separator(short) + + /** + * The occurrence count for a child in a children content model or + * for the mixed content model group. + * + * @param occurrence The occurrence count for the last element + * or group. + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + * + * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE + * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE + * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE + */ + public void occurrence(short occurrence, Augmentations augs) throws XNIException { + + if (!fMixed) { + if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE ) { + fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[fDepth], -1); + } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE ) { + fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[fDepth], -1 ); + } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) { + fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[fDepth], -1 ); + } + } + + } // occurrence(short) + + /** + * The end of a group for mixed or children content models. + * + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + */ + public void endGroup(Augmentations augs) throws XNIException { + + if (!fMixed) { + if (fPrevNodeIndexStack[fDepth] != -1) { + fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]); + } + int nodeIndex = fNodeIndexStack[fDepth--]; + fNodeIndexStack[fDepth] = nodeIndex; + } + + } // endGroup() + + // no-op methods + + /** + * A content model of ANY. + * + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + * + * @see #empty + * @see #startGroup + */ + public void any(Augmentations augs) throws XNIException {} + + /** + * A content model of EMPTY. + * + * @param augs Additional information that may include infoset + * augmentations. + * @throws XNIException Thrown by handler to signal an error. + * + * @see #any + * @see #startGroup + */ + public void empty(Augmentations augs) throws XNIException {} + + /** + * The end of a content model. + * @param augs Additional information that may include infoset + * augmentations. + * + * @throws XNIException Thrown by handler to signal an error. + */ + public void endContentModel(Augmentations augs) throws XNIException {} + + // + // Grammar methods + // + + /** Returns true if this grammar is namespace aware. */ + public boolean isNamespaceAware() { + return false; + } // isNamespaceAware():boolean + + /** Returns the symbol table. */ + public SymbolTable getSymbolTable() { + return fSymbolTable; + } // getSymbolTable():SymbolTable + + /** + * Returns the index of the first element declaration. This index + * is then used to query more information about the element declaration. + * + * @see #getNextElementDeclIndex + * @see #getElementDecl + */ + public int getFirstElementDeclIndex() { + return fElementDeclCount >= 0 ? 0 : -1; + } // getFirstElementDeclIndex():int + + /** + * Returns the next index of the element declaration following the + * specified element declaration. + * + * @param elementDeclIndex The element declaration index. + */ + public int getNextElementDeclIndex(int elementDeclIndex) { + return elementDeclIndex < fElementDeclCount - 1 + ? elementDeclIndex + 1 : -1; + } // getNextElementDeclIndex(int):int + + /** + * getElementDeclIndex + * + * @param elementDeclName + * + * @return index of the elementDeclName in scope + */ + public int getElementDeclIndex(String elementDeclName) { + int mapping = fElementIndexMap.get(elementDeclName); + //System.out.println("getElementDeclIndex("+elementDeclName+") -> "+mapping); + return mapping; + } // getElementDeclIndex(String):int + + /** Returns the element decl index. + * @param elementDeclQName qualilfied name of the element + */ + public int getElementDeclIndex(QName elementDeclQName) { + return getElementDeclIndex(elementDeclQName.rawname); + } // getElementDeclIndex(QName):int + + /** make separate function for getting contentSpecType of element. + * we can avoid setting of the element values. + */ + + public short getContentSpecType(int elementIndex){ + if (elementIndex < 0 || elementIndex >= fElementDeclCount) { + return -1 ; + } + + int chunk = elementIndex >> CHUNK_SHIFT; + int index = elementIndex & CHUNK_MASK; + + if(fElementDeclType[chunk][index] == -1){ + return -1 ; + } + else{ + return (short) (fElementDeclType[chunk][index] & LIST_MASK); + } + + }//getContentSpecType + + /** + * getElementDecl + * + * @param elementDeclIndex + * @param elementDecl The values of this structure are set by this call. + * + * @return True if find the element, False otherwise. + */ + public boolean getElementDecl(int elementDeclIndex, + XMLElementDecl elementDecl) { + + if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { + return false; + } + + int chunk = elementDeclIndex >> CHUNK_SHIFT; + int index = elementDeclIndex & CHUNK_MASK; + + elementDecl.name.setValues(fElementDeclName[chunk][index]); + + if (fElementDeclType[chunk][index] == -1) { + elementDecl.type = -1; + elementDecl.simpleType.list = false; + } else { + elementDecl.type = (short) (fElementDeclType[chunk][index] & LIST_MASK); + elementDecl.simpleType.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0; + } + + /* Validators are null until we add that code */ + if (elementDecl.type == XMLElementDecl.TYPE_CHILDREN || elementDecl.type == XMLElementDecl.TYPE_MIXED) { + elementDecl.contentModelValidator = getElementContentModelValidator(elementDeclIndex); + } + + elementDecl.simpleType.datatypeValidator = null; + elementDecl.simpleType.defaultType = -1; + elementDecl.simpleType.defaultValue = null; + + return true; + + } // getElementDecl(int,XMLElementDecl):boolean + + QName getElementDeclName(int elementDeclIndex) { + if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { + return null; + } + int chunk = elementDeclIndex >> CHUNK_SHIFT; + int index = elementDeclIndex & CHUNK_MASK; + return fElementDeclName[chunk][index]; + } + + // REVISIT: Make this getAttributeDeclCount/getAttributeDeclAt. -Ac + + /** + * getFirstAttributeDeclIndex + * + * @param elementDeclIndex + * + * @return index of the first attribute for element declaration elementDeclIndex + */ + public int getFirstAttributeDeclIndex(int elementDeclIndex) { + int chunk = elementDeclIndex >> CHUNK_SHIFT; + int index = elementDeclIndex & CHUNK_MASK; + + return fElementDeclFirstAttributeDeclIndex[chunk][index]; + } // getFirstAttributeDeclIndex + + /** + * getNextAttributeDeclIndex + * + * @param attributeDeclIndex + * + * @return index of the next attribute of the attribute at attributeDeclIndex + */ + public int getNextAttributeDeclIndex(int attributeDeclIndex) { + int chunk = attributeDeclIndex >> CHUNK_SHIFT; + int index = attributeDeclIndex & CHUNK_MASK; + + return fAttributeDeclNextAttributeDeclIndex[chunk][index]; + } // getNextAttributeDeclIndex + + /** + * getAttributeDecl + * + * @param attributeDeclIndex + * @param attributeDecl The values of this structure are set by this call. + * + * @return true if getAttributeDecl was able to fill in the value of attributeDecl + */ + public boolean getAttributeDecl(int attributeDeclIndex, XMLAttributeDecl attributeDecl) { + if (attributeDeclIndex < 0 || attributeDeclIndex >= fAttributeDeclCount) { + return false; + } + int chunk = attributeDeclIndex >> CHUNK_SHIFT; + int index = attributeDeclIndex & CHUNK_MASK; + + attributeDecl.name.setValues(fAttributeDeclName[chunk][index]); + + short attributeType; + boolean isList; + + if (fAttributeDeclType[chunk][index] == -1) { + + attributeType = -1; + isList = false; + } else { + attributeType = (short) (fAttributeDeclType[chunk][index] & LIST_MASK); + isList = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0; + } + attributeDecl.simpleType.setValues(attributeType,fAttributeDeclName[chunk][index].localpart, + fAttributeDeclEnumeration[chunk][index], + isList, fAttributeDeclDefaultType[chunk][index], + fAttributeDeclDefaultValue[chunk][index], + fAttributeDeclNonNormalizedDefaultValue[chunk][index], + fAttributeDeclDatatypeValidator[chunk][index]); + return true; + + } // getAttributeDecl + + + /** + * Returns whether the given attribute is of type CDATA or not + * + * @param elName The element name. + * @param atName The attribute name. + * + * @return true if the attribute is of type CDATA + */ + public boolean isCDATAAttribute(QName elName, QName atName) { + int elDeclIdx = getElementDeclIndex(elName); + if (getAttributeDecl(elDeclIdx, fAttributeDecl) + && fAttributeDecl.simpleType.type != XMLSimpleType.TYPE_CDATA){ + return false; + } + return true; + } + + /** + * getEntityDeclIndex + * + * @param entityDeclName + * + * @return the index of the EntityDecl + */ + public int getEntityDeclIndex(String entityDeclName) { + if (entityDeclName == null) { + return -1; + } + + return fEntityIndexMap.get(entityDeclName); + } // getEntityDeclIndex + + /** + * getEntityDecl + * + * @param entityDeclIndex + * @param entityDecl + * + * @return true if getEntityDecl was able to fill entityDecl with the contents of the entity + * with index entityDeclIndex + */ + public boolean getEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) { + if (entityDeclIndex < 0 || entityDeclIndex >= fEntityCount) { + return false; + } + int chunk = entityDeclIndex >> CHUNK_SHIFT; + int index = entityDeclIndex & CHUNK_MASK; + + entityDecl.setValues(fEntityName[chunk][index], + fEntityPublicId[chunk][index], + fEntitySystemId[chunk][index], + fEntityBaseSystemId[chunk][index], + fEntityNotation[chunk][index], + fEntityValue[chunk][index], + fEntityIsPE[chunk][index] == 0 ? false : true , + fEntityInExternal[chunk][index] == 0 ? false : true ); + + return true; + } // getEntityDecl + + /** + * getNotationDeclIndex + * + * @param notationDeclName + * + * @return the index if found a notation with the name, otherwise -1. + */ + public int getNotationDeclIndex(String notationDeclName) { + if (notationDeclName == null) { + return -1; + } + + return fNotationIndexMap.get(notationDeclName); + } // getNotationDeclIndex + + /** + * getNotationDecl + * + * @param notationDeclIndex + * @param notationDecl + * + * @return return true of getNotationDecl can fill notationDecl with information about + * the notation at notationDeclIndex. + */ + public boolean getNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) { + if (notationDeclIndex < 0 || notationDeclIndex >= fNotationCount) { + return false; + } + int chunk = notationDeclIndex >> CHUNK_SHIFT; + int index = notationDeclIndex & CHUNK_MASK; + + notationDecl.setValues(fNotationName[chunk][index], + fNotationPublicId[chunk][index], + fNotationSystemId[chunk][index], + fNotationBaseSystemId[chunk][index]); + + return true; + + } // getNotationDecl + + /** + * getContentSpec + * + * @param contentSpecIndex + * @param contentSpec + * + * @return true if find the requested contentSpec node, false otherwise + */ + public boolean getContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) { + if (contentSpecIndex < 0 || contentSpecIndex >= fContentSpecCount ) + return false; + + int chunk = contentSpecIndex >> CHUNK_SHIFT; + int index = contentSpecIndex & CHUNK_MASK; + + contentSpec.type = fContentSpecType[chunk][index]; + contentSpec.value = fContentSpecValue[chunk][index]; + contentSpec.otherValue = fContentSpecOtherValue[chunk][index]; + return true; + } + + /** + * Returns the index to the content spec for the given element + * declaration, or <code>-1</code> if the element declaration + * index was invalid. + */ + public int getContentSpecIndex(int elementDeclIndex) { + if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { + return -1; + } + final int chunk = elementDeclIndex >> CHUNK_SHIFT; + final int index = elementDeclIndex & CHUNK_MASK; + return fElementDeclContentSpecIndex[chunk][index]; + } + + /** + * getContentSpecAsString + * + * @param elementDeclIndex + * + * @return String + */ + public String getContentSpecAsString(int elementDeclIndex){ + + if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { + return null; + } + + int chunk = elementDeclIndex >> CHUNK_SHIFT; + int index = elementDeclIndex & CHUNK_MASK; + + int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index]; + + // lookup content spec node + XMLContentSpec contentSpec = new XMLContentSpec(); + + if (getContentSpec(contentSpecIndex, contentSpec)) { + + // build string + StringBuffer str = new StringBuffer(); + int parentContentSpecType = contentSpec.type & 0x0f; + int nextContentSpec; + switch (parentContentSpecType) { + case XMLContentSpec.CONTENTSPECNODE_LEAF: { + str.append('('); + if (contentSpec.value == null && contentSpec.otherValue == null) { + str.append("#PCDATA"); + } + else { + str.append(contentSpec.value); + } + str.append(')'); + break; + } + case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: { + getContentSpec(((int[])contentSpec.value)[0], contentSpec); + nextContentSpec = contentSpec.type; + + if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) { + str.append('('); + str.append(contentSpec.value); + str.append(')'); + } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || + nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || + nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { + str.append('(' ); + appendContentSpec(contentSpec, str, + true, parentContentSpecType ); + str.append(')'); + } else { + appendContentSpec(contentSpec, str, + true, parentContentSpecType ); + } + str.append('?'); + break; + } + case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: { + getContentSpec(((int[])contentSpec.value)[0], contentSpec); + nextContentSpec = contentSpec.type; + + if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) { + str.append('('); + if (contentSpec.value == null && contentSpec.otherValue == null) { + str.append("#PCDATA"); + } + else if (contentSpec.otherValue != null) { + str.append("##any:uri=").append(contentSpec.otherValue); + } + else if (contentSpec.value == null) { + str.append("##any"); + } + else { + appendContentSpec(contentSpec, str, + true, parentContentSpecType ); + } + str.append(')'); + } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || + nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || + nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { + str.append('(' ); + appendContentSpec(contentSpec, str, + true, parentContentSpecType ); + str.append(')'); + } else { + appendContentSpec(contentSpec, str, + true, parentContentSpecType ); + } + str.append('*'); + break; + } + case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: { + getContentSpec(((int[])contentSpec.value)[0], contentSpec); + nextContentSpec = contentSpec.type; + + if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) { + str.append('('); + if (contentSpec.value == null && contentSpec.otherValue == null) { + str.append("#PCDATA"); + } + else if (contentSpec.otherValue != null) { + str.append("##any:uri=").append(contentSpec.otherValue); + } + else if (contentSpec.value == null) { + str.append("##any"); + } + else { + str.append(contentSpec.value); + } + str.append(')'); + } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || + nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || + nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { + str.append('(' ); + appendContentSpec(contentSpec, str, + true, parentContentSpecType ); + str.append(')'); + } else { + appendContentSpec(contentSpec, str, + true, parentContentSpecType); + } + str.append('+'); + break; + } + case XMLContentSpec.CONTENTSPECNODE_CHOICE: + case XMLContentSpec.CONTENTSPECNODE_SEQ: { + appendContentSpec(contentSpec, str, + true, parentContentSpecType ); + break; + } + case XMLContentSpec.CONTENTSPECNODE_ANY: { + str.append("##any"); + if (contentSpec.otherValue != null) { + str.append(":uri="); + str.append(contentSpec.otherValue); + } + break; + } + case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: { + str.append("##other:uri="); + str.append(contentSpec.otherValue); + break; + } + case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: { + str.append("##local"); + break; + } + default: { + str.append("???"); + } + + } // switch type + + // return string + return str.toString(); + } + + // not found + return null; + + } // getContentSpecAsString(int):String + + // debugging + + public void printElements( ) { + int elementDeclIndex = 0; + XMLElementDecl elementDecl = new XMLElementDecl(); + while (getElementDecl(elementDeclIndex++, elementDecl)) { + + System.out.println("element decl: "+elementDecl.name+ + ", "+ elementDecl.name.rawname ); + + // ", "+ elementDecl.contentModelValidator.toString()); + } + } + + public void printAttributes(int elementDeclIndex) { + int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex); + System.out.print(elementDeclIndex); + System.out.print(" ["); + while (attributeDeclIndex != -1) { + System.out.print(' '); + System.out.print(attributeDeclIndex); + printAttribute(attributeDeclIndex); + attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex); + if (attributeDeclIndex != -1) { + System.out.print(","); + } + } + System.out.println(" ]"); + } + + // + // Protected methods + // + + /** + * Adds the content spec to the given element declaration. + */ + protected void addContentSpecToElement(XMLElementDecl elementDecl) { + if ((fDepth == 0 || (fDepth == 1 && elementDecl.type == XMLElementDecl.TYPE_MIXED)) && + fNodeIndexStack != null) { + if (elementDecl.type == XMLElementDecl.TYPE_MIXED) { + int pcdata = addUniqueLeafNode(null); + if (fNodeIndexStack[0] == -1) { + fNodeIndexStack[0] = pcdata; + } + else { + fNodeIndexStack[0] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, + pcdata, fNodeIndexStack[0]); + } + } + setContentSpecIndex(fCurrentElementIndex, fNodeIndexStack[fDepth]); + } + } + + /** + * getElementContentModelValidator + * + * @param elementDeclIndex + * + * @return its ContentModelValidator if any. + */ + protected ContentModelValidator getElementContentModelValidator(int elementDeclIndex) { + + int chunk = elementDeclIndex >> CHUNK_SHIFT; + int index = elementDeclIndex & CHUNK_MASK; + + ContentModelValidator contentModel = fElementDeclContentModelValidator[chunk][index]; + + // If we have one, just return that. Otherwise, gotta create one + if (contentModel != null) { + return contentModel; + } + + int contentType = fElementDeclType[chunk][index]; + if (contentType == XMLElementDecl.TYPE_SIMPLE) { + return null; + } + + // Get the type of content this element has + int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index]; + + /*** + if ( contentSpecIndex == -1 ) + return null; + /***/ + + XMLContentSpec contentSpec = new XMLContentSpec(); + getContentSpec( contentSpecIndex, contentSpec ); + + // And create the content model according to the spec type + if ( contentType == XMLElementDecl.TYPE_MIXED ) { + // + // Just create a mixel content model object. This type of + // content model is optimized for mixed content validation. + // + ChildrenList children = new ChildrenList(); + contentSpecTree(contentSpecIndex, contentSpec, children); + contentModel = new MixedContentModel(children.qname, + children.type, + 0, children.length, + false); + } else if (contentType == XMLElementDecl.TYPE_CHILDREN) { + // This method will create an optimal model for the complexity + // of the element's defined model. If its simple, it will create + // a SimpleContentModel object. If its a simple list, it will + // create a SimpleListContentModel object. If its complex, it + // will create a DFAContentModel object. + // + contentModel = createChildModel(contentSpecIndex); + } else { + throw new RuntimeException("Unknown content type for a element decl " + + "in getElementContentModelValidator() in AbstractDTDGrammar class"); + } + + // Add the new model to the content model for this element + fElementDeclContentModelValidator[chunk][index] = contentModel; + + return contentModel; + + } // getElementContentModelValidator(int):ContentModelValidator + + protected int createElementDecl() { + int chunk = fElementDeclCount >> CHUNK_SHIFT; + int index = fElementDeclCount & CHUNK_MASK; + ensureElementDeclCapacity(chunk); + fElementDeclName[chunk][index] = new QName(); + fElementDeclType[chunk][index] = -1; + fElementDeclContentModelValidator[chunk][index] = null; + fElementDeclFirstAttributeDeclIndex[chunk][index] = -1; + fElementDeclLastAttributeDeclIndex[chunk][index] = -1; + return fElementDeclCount++; + } + + protected void setElementDecl(int elementDeclIndex, XMLElementDecl elementDecl) { + if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { + return; + } + int chunk = elementDeclIndex >> CHUNK_SHIFT; + int index = elementDeclIndex & CHUNK_MASK; + + fElementDeclName[chunk][index].setValues(elementDecl.name); + fElementDeclType[chunk][index] = elementDecl.type; + + fElementDeclContentModelValidator[chunk][index] = elementDecl.contentModelValidator; + + if (elementDecl.simpleType.list == true ) { + fElementDeclType[chunk][index] |= LIST_FLAG; + } + + fElementIndexMap.put(elementDecl.name.rawname, elementDeclIndex); + } + + + + + protected void putElementNameMapping(QName name, int scope, + int elementDeclIndex) { + } + + protected void setFirstAttributeDeclIndex(int elementDeclIndex, int newFirstAttrIndex){ + + if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { + return; + } + + int chunk = elementDeclIndex >> CHUNK_SHIFT; + int index = elementDeclIndex & CHUNK_MASK; + + fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex; + } + + protected void setContentSpecIndex(int elementDeclIndex, int contentSpecIndex){ + + if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) { + return; + } + + int chunk = elementDeclIndex >> CHUNK_SHIFT; + int index = elementDeclIndex & CHUNK_MASK; + + fElementDeclContentSpecIndex[chunk][index] = contentSpecIndex; + } + + + protected int createAttributeDecl() { + int chunk = fAttributeDeclCount >> CHUNK_SHIFT; + int index = fAttributeDeclCount & CHUNK_MASK; + + ensureAttributeDeclCapacity(chunk); + fAttributeDeclName[chunk][index] = new QName(); + fAttributeDeclType[chunk][index] = -1; + fAttributeDeclDatatypeValidator[chunk][index] = null; + fAttributeDeclEnumeration[chunk][index] = null; + fAttributeDeclDefaultType[chunk][index] = XMLSimpleType.DEFAULT_TYPE_IMPLIED; + fAttributeDeclDefaultValue[chunk][index] = null; + fAttributeDeclNonNormalizedDefaultValue[chunk][index] = null; + fAttributeDeclNextAttributeDeclIndex[chunk][index] = -1; + return fAttributeDeclCount++; + } + + + protected void setAttributeDecl(int elementDeclIndex, int attributeDeclIndex, + XMLAttributeDecl attributeDecl) { + int attrChunk = attributeDeclIndex >> CHUNK_SHIFT; + int attrIndex = attributeDeclIndex & CHUNK_MASK; + fAttributeDeclName[attrChunk][attrIndex].setValues(attributeDecl.name); + fAttributeDeclType[attrChunk][attrIndex] = attributeDecl.simpleType.type; + + if (attributeDecl.simpleType.list) { + fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG; + } + fAttributeDeclEnumeration[attrChunk][attrIndex] = attributeDecl.simpleType.enumeration; + fAttributeDeclDefaultType[attrChunk][attrIndex] = attributeDecl.simpleType.defaultType; + fAttributeDeclDatatypeValidator[attrChunk][attrIndex] = attributeDecl.simpleType.datatypeValidator; + + fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.defaultValue; + fAttributeDeclNonNormalizedDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.nonNormalizedDefaultValue; + + int elemChunk = elementDeclIndex >> CHUNK_SHIFT; + int elemIndex = elementDeclIndex & CHUNK_MASK; + int index = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex]; + while (index != -1) { + if (index == attributeDeclIndex) { + break; + } + attrChunk = index >> CHUNK_SHIFT; + attrIndex = index & CHUNK_MASK; + index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex]; + } + if (index == -1) { + if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) { + fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex; + } else { + index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex]; + attrChunk = index >> CHUNK_SHIFT; + attrIndex = index & CHUNK_MASK; + fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex; + } + fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex; + } + } + + protected int createContentSpec() { + int chunk = fContentSpecCount >> CHUNK_SHIFT; + int index = fContentSpecCount & CHUNK_MASK; + + ensureContentSpecCapacity(chunk); + fContentSpecType[chunk][index] = -1; + fContentSpecValue[chunk][index] = null; + fContentSpecOtherValue[chunk][index] = null; + + return fContentSpecCount++; + } + + protected void setContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) { + int chunk = contentSpecIndex >> CHUNK_SHIFT; + int index = contentSpecIndex & CHUNK_MASK; + + fContentSpecType[chunk][index] = contentSpec.type; + fContentSpecValue[chunk][index] = contentSpec.value; + fContentSpecOtherValue[chunk][index] = contentSpec.otherValue; + } + + + protected int createEntityDecl() { + int chunk = fEntityCount >> CHUNK_SHIFT; + int index = fEntityCount & CHUNK_MASK; + + ensureEntityDeclCapacity(chunk); + fEntityIsPE[chunk][index] = 0; + fEntityInExternal[chunk][index] = 0; + + return fEntityCount++; + } + + protected void setEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) { + int chunk = entityDeclIndex >> CHUNK_SHIFT; + int index = entityDeclIndex & CHUNK_MASK; + + fEntityName[chunk][index] = entityDecl.name; + fEntityValue[chunk][index] = entityDecl.value; + fEntityPublicId[chunk][index] = entityDecl.publicId; + fEntitySystemId[chunk][index] = entityDecl.systemId; + fEntityBaseSystemId[chunk][index] = entityDecl.baseSystemId; + fEntityNotation[chunk][index] = entityDecl.notation; + fEntityIsPE[chunk][index] = entityDecl.isPE ? (byte)1 : (byte)0; + fEntityInExternal[chunk][index] = entityDecl.inExternal ? (byte)1 : (byte)0; + + fEntityIndexMap.put(entityDecl.name, entityDeclIndex); + } + + protected int createNotationDecl() { + int chunk = fNotationCount >> CHUNK_SHIFT; + ensureNotationDeclCapacity(chunk); + return fNotationCount++; + } + + protected void setNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) { + int chunk = notationDeclIndex >> CHUNK_SHIFT; + int index = notationDeclIndex & CHUNK_MASK; + + fNotationName[chunk][index] = notationDecl.name; + fNotationPublicId[chunk][index] = notationDecl.publicId; + fNotationSystemId[chunk][index] = notationDecl.systemId; + fNotationBaseSystemId[chunk][index] = notationDecl.baseSystemId; + + fNotationIndexMap.put(notationDecl.name, notationDeclIndex); + } + + /** + * Create an XMLContentSpec for a single non-leaf + * + * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_* + * @param nodeValue handle to an XMLContentSpec + * @return handle to the newly create XMLContentSpec + */ + protected int addContentSpecNode(short nodeType, String nodeValue) { + + // create content spec node + int contentSpecIndex = createContentSpec(); + + // set content spec node values + fContentSpec.setValues(nodeType, nodeValue, null); + setContentSpec(contentSpecIndex, fContentSpec); + + // return index + return contentSpecIndex; + + } // addContentSpecNode(short,String):int + + /** + * create an XMLContentSpec for a leaf + * + * @param elementName the name (Element) for the node + * @return handle to the newly create XMLContentSpec + */ + protected int addUniqueLeafNode(String elementName) { + + // create content spec node + int contentSpecIndex = createContentSpec(); + + // set content spec node values + fContentSpec.setValues( XMLContentSpec.CONTENTSPECNODE_LEAF, + elementName, null); + setContentSpec(contentSpecIndex, fContentSpec); + + // return index + return contentSpecIndex; + + } // addUniqueLeafNode(String):int + + /** + * Create an XMLContentSpec for a two child leaf + * + * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_* + * @param leftNodeIndex handle to an XMLContentSpec + * @param rightNodeIndex handle to an XMLContentSpec + * @return handle to the newly create XMLContentSpec + */ + protected int addContentSpecNode(short nodeType, + int leftNodeIndex, int rightNodeIndex) { + + // create content spec node + int contentSpecIndex = createContentSpec(); + + // set content spec node values + int[] leftIntArray = new int[1]; + int[] rightIntArray = new int[1]; + + leftIntArray[0] = leftNodeIndex; + rightIntArray[0] = rightNodeIndex; + fContentSpec.setValues(nodeType, leftIntArray, rightIntArray); + setContentSpec(contentSpecIndex, fContentSpec); + + // return index + return contentSpecIndex; + + } // addContentSpecNode(short,int,int):int + + /** Initialize content model stack. */ + protected void initializeContentModelStack() { + + if (fOpStack == null) { + fOpStack = new short[8]; + fNodeIndexStack = new int[8]; + fPrevNodeIndexStack = new int[8]; + } else if (fDepth == fOpStack.length) { + short[] newStack = new short[fDepth * 2]; + System.arraycopy(fOpStack, 0, newStack, 0, fDepth); + fOpStack = newStack; + int[] newIntStack = new int[fDepth * 2]; + System.arraycopy(fNodeIndexStack, 0, newIntStack, 0, fDepth); + fNodeIndexStack = newIntStack; + newIntStack = new int[fDepth * 2]; + System.arraycopy(fPrevNodeIndexStack, 0, newIntStack, 0, fDepth); + fPrevNodeIndexStack = newIntStack; + } + fOpStack[fDepth] = -1; + fNodeIndexStack[fDepth] = -1; + fPrevNodeIndexStack[fDepth] = -1; + + } // initializeContentModelStack() + + boolean isImmutable() { + return fIsImmutable; + } + + // + // Private methods + // + + private void appendContentSpec(XMLContentSpec contentSpec, + StringBuffer str, boolean parens, + int parentContentSpecType ) { + + int thisContentSpec = contentSpec.type & 0x0f; + switch (thisContentSpec) { + case XMLContentSpec.CONTENTSPECNODE_LEAF: { + if (contentSpec.value == null && contentSpec.otherValue == null) { + str.append("#PCDATA"); + } + else if (contentSpec.value == null && contentSpec.otherValue != null) { + str.append("##any:uri=").append(contentSpec.otherValue); + } + else if (contentSpec.value == null) { + str.append("##any"); + } + else { + str.append(contentSpec.value); + } + break; + } + case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: { + if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || + parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || + parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { + getContentSpec(((int[])contentSpec.value)[0], contentSpec); + str.append('('); + appendContentSpec(contentSpec, str, true, thisContentSpec ); + str.append(')'); + } + else { + getContentSpec(((int[])contentSpec.value)[0], contentSpec); + appendContentSpec( contentSpec, str, true, thisContentSpec ); + } + str.append('?'); + break; + } + case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: { + if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || + parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || + parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { + getContentSpec(((int[])contentSpec.value)[0], contentSpec); + str.append('('); + appendContentSpec(contentSpec, str, true, thisContentSpec); + str.append(')' ); + } + else { + getContentSpec(((int[])contentSpec.value)[0], contentSpec); + appendContentSpec(contentSpec, str, true, thisContentSpec); + } + str.append('*'); + break; + } + case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: { + if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE || + parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || + parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) { + + str.append('('); + getContentSpec(((int[])contentSpec.value)[0], contentSpec); + appendContentSpec(contentSpec, str, true, thisContentSpec); + str.append(')' ); + } + else { + getContentSpec(((int[])contentSpec.value)[0], contentSpec); + appendContentSpec(contentSpec, str, true, thisContentSpec); + } + str.append('+'); + break; + } + case XMLContentSpec.CONTENTSPECNODE_CHOICE: + case XMLContentSpec.CONTENTSPECNODE_SEQ: { + if (parens) { + str.append('('); + } + int type = contentSpec.type; + int otherValue = ((int[])contentSpec.otherValue)[0]; + getContentSpec(((int[])contentSpec.value)[0], contentSpec); + appendContentSpec(contentSpec, str, contentSpec.type != type, thisContentSpec); + if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) { + str.append('|'); + } + else { + str.append(','); + } + getContentSpec(otherValue, contentSpec); + appendContentSpec(contentSpec, str, true, thisContentSpec); + if (parens) { + str.append(')'); + } + break; + } + case XMLContentSpec.CONTENTSPECNODE_ANY: { + str.append("##any"); + if (contentSpec.otherValue != null) { + str.append(":uri="); + str.append(contentSpec.otherValue); + } + break; + } + case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: { + str.append("##other:uri="); + str.append(contentSpec.otherValue); + break; + } + case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: { + str.append("##local"); + break; + } + default: { + str.append("???"); + break; + } + + } // switch type + + } // appendContentSpec(XMLContentSpec.Provider,StringPool,XMLContentSpec,StringBuffer,boolean) + + // debugging + + private void printAttribute(int attributeDeclIndex) { + + XMLAttributeDecl attributeDecl = new XMLAttributeDecl(); + if (getAttributeDecl(attributeDeclIndex, attributeDecl)) { + System.out.print(" { "); + System.out.print(attributeDecl.name.localpart); + System.out.print(" }"); + } + + } // printAttribute(int) + + // content models + + /** + * When the element has a 'CHILDREN' model, this method is called to + * create the content model object. It looks for some special case simple + * models and creates SimpleContentModel objects for those. For the rest + * it creates the standard DFA style model. + */ + private synchronized ContentModelValidator createChildModel(int contentSpecIndex) { + + // + // Get the content spec node for the element we are working on. + // This will tell us what kind of node it is, which tells us what + // kind of model we will try to create. + // + XMLContentSpec contentSpec = new XMLContentSpec(); + getContentSpec(contentSpecIndex, contentSpec); + + if ((contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY || + (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER || + (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) { + // let fall through to build a DFAContentModel + } + + else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) { + // + // Check that the left value is not -1, since any content model + // with PCDATA should be MIXED, so we should not have gotten here. + // + if (contentSpec.value == null && contentSpec.otherValue == null) + throw new RuntimeException("ImplementationMessages.VAL_NPCD"); + + // + // Its a single leaf, so its an 'a' type of content model, i.e. + // just one instance of one element. That one is definitely a + // simple content model. + // + + fQName.setValues(null, (String)contentSpec.value, + (String)contentSpec.value, (String)contentSpec.otherValue); + return new SimpleContentModel(contentSpec.type, fQName, null); + } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE) + || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) { + // + // Lets see if both of the children are leafs. If so, then it + // it has to be a simple content model + // + XMLContentSpec contentSpecLeft = new XMLContentSpec(); + XMLContentSpec contentSpecRight = new XMLContentSpec(); + + getContentSpec( ((int[])contentSpec.value)[0], contentSpecLeft); + getContentSpec( ((int[])contentSpec.otherValue)[0], contentSpecRight); + + if ((contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) + && (contentSpecRight.type == XMLContentSpec.CONTENTSPECNODE_LEAF)) { + // + // Its a simple choice or sequence, so we can do a simple + // content model for it. + // + fQName.setValues(null, (String)contentSpecLeft.value, + (String)contentSpecLeft.value, (String)contentSpecLeft.otherValue); + fQName2.setValues(null, (String)contentSpecRight.value, + (String)contentSpecRight.value, (String)contentSpecRight.otherValue); + return new SimpleContentModel(contentSpec.type, fQName, fQName2); + } + } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) + || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) + || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE)) { + // + // Its a repetition, so see if its one child is a leaf. If so + // its a repetition of a single element, so we can do a simple + // content model for that. + // + XMLContentSpec contentSpecLeft = new XMLContentSpec(); + getContentSpec(((int[])contentSpec.value)[0], contentSpecLeft); + + if (contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) { + // + // It is, so we can create a simple content model here that + // will check for this repetition. We pass -1 for the unused + // right node. + // + fQName.setValues(null, (String)contentSpecLeft.value, + (String)contentSpecLeft.value, (String)contentSpecLeft.otherValue); + return new SimpleContentModel(contentSpec.type, fQName, null); + } + } else { + throw new RuntimeException("ImplementationMessages.VAL_CST"); + } + + // + // Its not a simple content model, so here we have to create a DFA + // for this element. So we create a DFAContentModel object. He + // encapsulates all of the work to create the DFA. + // + + fLeafCount = 0; + //int leafCount = countLeaves(contentSpecIndex); + fLeafCount = 0; + CMNode cmn = buildSyntaxTree(contentSpecIndex, contentSpec); + + // REVISIT: has to be fLeafCount because we convert x+ to x,x*, one more leaf + return new DFAContentModel( cmn, fLeafCount, false); + + } // createChildModel(int):ContentModelValidator + + private final CMNode buildSyntaxTree(int startNode, + XMLContentSpec contentSpec) { + + // We will build a node at this level for the new tree + CMNode nodeRet = null; + getContentSpec(startNode, contentSpec); + if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY) { + //nodeRet = new CMAny(contentSpec.type, -1, fLeafCount++); + nodeRet = new CMAny(contentSpec.type, (String)contentSpec.otherValue, fLeafCount++); + } + else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) { + nodeRet = new CMAny(contentSpec.type, (String)contentSpec.otherValue, fLeafCount++); + } + else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) { + nodeRet = new CMAny(contentSpec.type, null, fLeafCount++); + } + // + // If this node is a leaf, then its an easy one. We just add it + // to the tree. + // + else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) { + // + // Create a new leaf node, and pass it the current leaf count, + // which is its DFA state position. Bump the leaf count after + // storing it. This makes the positions zero based since we + // store first and then increment. + // + fQName.setValues(null, (String)contentSpec.value, + (String)contentSpec.value, (String)contentSpec.otherValue); + nodeRet = new CMLeaf(fQName, fLeafCount++); + } + else { + // + // Its not a leaf, so we have to recurse its left and maybe right + // nodes. Save both values before we recurse and trash the node. + final int leftNode = ((int[])contentSpec.value)[0]; + final int rightNode = ((int[])contentSpec.otherValue)[0]; + + if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE) + || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) { + // + // Recurse on both children, and return a binary op node + // with the two created sub nodes as its children. The node + // type is the same type as the source. + // + + nodeRet = new CMBinOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec) + , buildSyntaxTree(rightNode, contentSpec)); + } + else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) { + nodeRet = new CMUniOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec)); + } + else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE + || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE + || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) { + nodeRet = new CMUniOp(contentSpec.type, buildSyntaxTree(leftNode, contentSpec)); + } + else { + throw new RuntimeException("ImplementationMessages.VAL_CST"); + } + } + // And return our new node for this level + return nodeRet; + } + + /** + * Build a vector of valid QNames from Content Spec + * table. + * + * @param contentSpecIndex + * Content Spec index + * @param vectorQName + * Array of QName + * @exception RuntimeException + */ + private void contentSpecTree(int contentSpecIndex, + XMLContentSpec contentSpec, + ChildrenList children) { + + // Handle any and leaf nodes + getContentSpec( contentSpecIndex, contentSpec); + if ( contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF || + (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY || + (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL || + (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) { + + // resize arrays, if needed + if (children.length == children.qname.length) { + QName[] newQName = new QName[children.length * 2]; + System.arraycopy(children.qname, 0, newQName, 0, children.length); + children.qname = newQName; + int[] newType = new int[children.length * 2]; + System.arraycopy(children.type, 0, newType, 0, children.length); + children.type = newType; + } + + // save values and return length + children.qname[children.length] = new QName(null, (String)contentSpec.value, + (String) contentSpec.value, + (String) contentSpec.otherValue); + children.type[children.length] = contentSpec.type; + children.length++; + return; + } + + // + // Its not a leaf, so we have to recurse its left and maybe right + // nodes. Save both values before we recurse and trash the node. + // + final int leftNode = contentSpec.value != null + ? ((int[])(contentSpec.value))[0] : -1; + int rightNode = -1 ; + if (contentSpec.otherValue != null ) + rightNode = ((int[])(contentSpec.otherValue))[0]; + else + return; + + if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE || + contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ) { + contentSpecTree(leftNode, contentSpec, children); + contentSpecTree(rightNode, contentSpec, children); + return; + } + + if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE || + contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE || + contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) { + contentSpecTree(leftNode, contentSpec, children); + return; + } + + // error + throw new RuntimeException("Invalid content spec type seen in contentSpecTree() method of AbstractDTDGrammar class : "+contentSpec.type); + + } // contentSpecTree(int,XMLContentSpec,ChildrenList) + + // ensure capacity + + private void ensureElementDeclCapacity(int chunk) { + if (chunk >= fElementDeclName.length) { + fElementDeclIsExternal = resize(fElementDeclIsExternal, + fElementDeclIsExternal.length * 2); + + fElementDeclName = resize(fElementDeclName, fElementDeclName.length * 2); + fElementDeclType = resize(fElementDeclType, fElementDeclType.length * 2); + fElementDeclContentModelValidator = resize(fElementDeclContentModelValidator, fElementDeclContentModelValidator.length * 2); + fElementDeclContentSpecIndex = resize(fElementDeclContentSpecIndex,fElementDeclContentSpecIndex.length * 2); + fElementDeclFirstAttributeDeclIndex = resize(fElementDeclFirstAttributeDeclIndex, fElementDeclFirstAttributeDeclIndex.length * 2); + fElementDeclLastAttributeDeclIndex = resize(fElementDeclLastAttributeDeclIndex, fElementDeclLastAttributeDeclIndex.length * 2); + } + else if (fElementDeclName[chunk] != null) { + return; + } + + fElementDeclIsExternal[chunk] = new int[CHUNK_SIZE]; + fElementDeclName[chunk] = new QName[CHUNK_SIZE]; + fElementDeclType[chunk] = new short[CHUNK_SIZE]; + fElementDeclContentModelValidator[chunk] = new ContentModelValidator[CHUNK_SIZE]; + fElementDeclContentSpecIndex[chunk] = new int[CHUNK_SIZE]; + fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE]; + fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE]; + return; + } + + private void ensureAttributeDeclCapacity(int chunk) { + + if (chunk >= fAttributeDeclName.length) { + fAttributeDeclIsExternal = resize(fAttributeDeclIsExternal, + fAttributeDeclIsExternal.length * 2); + fAttributeDeclName = resize(fAttributeDeclName, fAttributeDeclName.length * 2); + fAttributeDeclType = resize(fAttributeDeclType, fAttributeDeclType.length * 2); + fAttributeDeclEnumeration = resize(fAttributeDeclEnumeration, fAttributeDeclEnumeration.length * 2); + fAttributeDeclDefaultType = resize(fAttributeDeclDefaultType, fAttributeDeclDefaultType.length * 2); + fAttributeDeclDatatypeValidator = resize(fAttributeDeclDatatypeValidator, fAttributeDeclDatatypeValidator.length * 2); + fAttributeDeclDefaultValue = resize(fAttributeDeclDefaultValue, fAttributeDeclDefaultValue.length * 2); + fAttributeDeclNonNormalizedDefaultValue = resize(fAttributeDeclNonNormalizedDefaultValue, fAttributeDeclNonNormalizedDefaultValue.length * 2); + fAttributeDeclNextAttributeDeclIndex = resize(fAttributeDeclNextAttributeDeclIndex, fAttributeDeclNextAttributeDeclIndex.length * 2); + } + else if (fAttributeDeclName[chunk] != null) { + return; + } + + fAttributeDeclIsExternal[chunk] = new int[CHUNK_SIZE]; + fAttributeDeclName[chunk] = new QName[CHUNK_SIZE]; + fAttributeDeclType[chunk] = new short[CHUNK_SIZE]; + fAttributeDeclEnumeration[chunk] = new String[CHUNK_SIZE][]; + fAttributeDeclDefaultType[chunk] = new short[CHUNK_SIZE]; + fAttributeDeclDatatypeValidator[chunk] = new DatatypeValidator[CHUNK_SIZE]; + fAttributeDeclDefaultValue[chunk] = new String[CHUNK_SIZE]; + fAttributeDeclNonNormalizedDefaultValue[chunk] = new String[CHUNK_SIZE]; + fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE]; + return; + } + + private void ensureEntityDeclCapacity(int chunk) { + if (chunk >= fEntityName.length) { + fEntityName = resize(fEntityName, fEntityName.length * 2); + fEntityValue = resize(fEntityValue, fEntityValue.length * 2); + fEntityPublicId = resize(fEntityPublicId, fEntityPublicId.length * 2); + fEntitySystemId = resize(fEntitySystemId, fEntitySystemId.length * 2); + fEntityBaseSystemId = resize(fEntityBaseSystemId, fEntityBaseSystemId.length * 2); + fEntityNotation = resize(fEntityNotation, fEntityNotation.length * 2); + fEntityIsPE = resize(fEntityIsPE, fEntityIsPE.length * 2); + fEntityInExternal = resize(fEntityInExternal, fEntityInExternal.length * 2); + } + else if (fEntityName[chunk] != null) { + return; + } + + fEntityName[chunk] = new String[CHUNK_SIZE]; + fEntityValue[chunk] = new String[CHUNK_SIZE]; + fEntityPublicId[chunk] = new String[CHUNK_SIZE]; + fEntitySystemId[chunk] = new String[CHUNK_SIZE]; + fEntityBaseSystemId[chunk] = new String[CHUNK_SIZE]; + fEntityNotation[chunk] = new String[CHUNK_SIZE]; + fEntityIsPE[chunk] = new byte[CHUNK_SIZE]; + fEntityInExternal[chunk] = new byte[CHUNK_SIZE]; + return; + } + + private void ensureNotationDeclCapacity(int chunk) { + if (chunk >= fNotationName.length) { + fNotationName = resize(fNotationName, fNotationName.length * 2); + fNotationPublicId = resize(fNotationPublicId, fNotationPublicId.length * 2); + fNotationSystemId = resize(fNotationSystemId, fNotationSystemId.length * 2); + fNotationBaseSystemId = resize(fNotationBaseSystemId, fNotationBaseSystemId.length * 2); + } + else if (fNotationName[chunk] != null) { + return; + } + + fNotationName[chunk] = new String[CHUNK_SIZE]; + fNotationPublicId[chunk] = new String[CHUNK_SIZE]; + fNotationSystemId[chunk] = new String[CHUNK_SIZE]; + fNotationBaseSystemId[chunk] = new String[CHUNK_SIZE]; + return; + } + + private void ensureContentSpecCapacity(int chunk) { + if (chunk >= fContentSpecType.length) { + fContentSpecType = resize(fContentSpecType, fContentSpecType.length * 2); + fContentSpecValue = resize(fContentSpecValue, fContentSpecValue.length * 2); + fContentSpecOtherValue = resize(fContentSpecOtherValue, fContentSpecOtherValue.length * 2); + } + else if (fContentSpecType[chunk] != null) { + return; + } + + fContentSpecType[chunk] = new short[CHUNK_SIZE]; + fContentSpecValue[chunk] = new Object[CHUNK_SIZE]; + fContentSpecOtherValue[chunk] = new Object[CHUNK_SIZE]; + return; + } + + // + // Private static methods + // + + // resize chunks + + private static byte[][] resize(byte array[][], int newsize) { + byte newarray[][] = new byte[newsize][]; + System.arraycopy(array, 0, newarray, 0, array.length); + return newarray; + } + + private static short[][] resize(short array[][], int newsize) { + short newarray[][] = new short[newsize][]; + System.arraycopy(array, 0, newarray, 0, array.length); + return newarray; + } + + private static int[][] resize(int array[][], int newsize) { + int newarray[][] = new int[newsize][]; + System.arraycopy(array, 0, newarray, 0, array.length); + return newarray; + } + + private static DatatypeValidator[][] resize(DatatypeValidator array[][], int newsize) { + DatatypeValidator newarray[][] = new DatatypeValidator[newsize][]; + System.arraycopy(array, 0, newarray, 0, array.length); + return newarray; + } + + private static ContentModelValidator[][] resize(ContentModelValidator array[][], int newsize) { + ContentModelValidator newarray[][] = new ContentModelValidator[newsize][]; + System.arraycopy(array, 0, newarray, 0, array.length); + return newarray; + } + + private static Object[][] resize(Object array[][], int newsize) { + Object newarray[][] = new Object[newsize][]; + System.arraycopy(array, 0, newarray, 0, array.length); + return newarray; + } + + private static QName[][] resize(QName array[][], int newsize) { + QName newarray[][] = new QName[newsize][]; + System.arraycopy(array, 0, newarray, 0, array.length); + return newarray; + } + + private static String[][] resize(String array[][], int newsize) { + String newarray[][] = new String[newsize][]; + System.arraycopy(array, 0, newarray, 0, array.length); + return newarray; + } + + private static String[][][] resize(String array[][][], int newsize) { + String newarray[][][] = new String[newsize] [][]; + System.arraycopy(array, 0, newarray, 0, array.length); + return newarray; + } + + // + // Classes + // + + /** + * Children list for <code>contentSpecTree</code> method. + * + * @xerces.internal + * + * @author Eric Ye, IBM + */ + private static class ChildrenList { + + // + // Data + // + + /** Length. */ + public int length = 0; + + // NOTE: The following set of data is mutually exclusive. It is + // written this way because Java doesn't have a native + // union data structure. -Ac + + /** Left and right children names. */ + public QName[] qname = new QName[2]; + + /** Left and right children types. */ + public int[] type = new int[2]; + + // + // Constructors + // + + public ChildrenList () {} + + } // class ChildrenList + + // + // Classes + // + + /** + * A simple Hashtable implementation that takes a tuple (String, String) + * as the key and a int as value. + * + * @xerces.internal + * + * @author Eric Ye, IBM + * @author Andy Clark, IBM + */ + protected static final class QNameHashtable { + + // + // Constants + // + + /** Initial bucket size (4). */ + private static final int INITIAL_BUCKET_SIZE = 4; + + // NOTE: Changed previous hashtable size from 512 to 101 so + // that we get a better distribution for hashing. -Ac + /** Hashtable size (101). */ + private static final int HASHTABLE_SIZE = 101; + + // + // Data + // + private Object[][] fHashTable = new Object[HASHTABLE_SIZE][]; + + // + // Public methods + // + /** Associates the given value with the specified key tuple. */ + public void put(String key, int value) { + + int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE; + Object[] bucket = fHashTable[hash]; + + if (bucket == null) { + bucket = new Object[1 + 2*INITIAL_BUCKET_SIZE]; + bucket[0] = new int[]{1}; + bucket[1] = key; + bucket[2] = new int[]{value}; + fHashTable[hash] = bucket; + } else { + int count = ((int[])bucket[0])[0]; + int offset = 1 + 2*count; + if (offset == bucket.length) { + int newSize = count + INITIAL_BUCKET_SIZE; + Object[] newBucket = new Object[1 + 2*newSize]; + System.arraycopy(bucket, 0, newBucket, 0, offset); + bucket = newBucket; + fHashTable[hash] = bucket; + } + boolean found = false; + int j=1; + for (int i=0; i<count; i++){ + if ((String)bucket[j] == key) { + ((int[])bucket[j+1])[0] = value; + found = true; + break; + } + j += 2; + } + if (! found) { + bucket[offset++] = key; + bucket[offset]= new int[]{value}; + ((int[])bucket[0])[0] = ++count; + } + + } + //System.out.println("put("+key+" -> "+value+')'); + //System.out.println("get("+key+") -> "+get(key)); + + } // put(int,String,String,int) + + /** Returns the value associated with the specified key tuple. */ + public int get(String key) { + int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE; + Object[] bucket = fHashTable[hash]; + + if (bucket == null) { + return -1; + } + int count = ((int[])bucket[0])[0]; + + int j=1; + for (int i=0; i<count; i++){ + if ((String)bucket[j] == key) { + return ((int[])bucket[j+1])[0]; + } + j += 2; + } + return -1; + + } // get(int,String,String) + + } // class QNameHashtable + + // + // EntityState methods + // + public boolean isEntityDeclared (String name){ + return (getEntityDeclIndex(name)!=-1)?true:false; + } + + public boolean isEntityUnparsed (String name){ + int entityIndex = getEntityDeclIndex(name); + if (entityIndex >-1) { + int chunk = entityIndex >> CHUNK_SHIFT; + int index = entityIndex & CHUNK_MASK; + //for unparsed entity notation!=null + return (fEntityNotation[chunk][index]!=null)?true:false; + } + return false; + } +} // class DTDGrammar |