286N/A/*
286N/A * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
286N/A */
286N/A
286N/A/*
286N/A * Copyright 2005 The Apache Software Foundation.
286N/A *
286N/A * Licensed under the Apache License, Version 2.0 (the "License");
286N/A * you may not use this file except in compliance with the License.
286N/A * You may obtain a copy of the License at
286N/A *
286N/A * http://www.apache.org/licenses/LICENSE-2.0
286N/A *
286N/A * Unless required by applicable law or agreed to in writing, software
286N/A * distributed under the License is distributed on an "AS IS" BASIS,
286N/A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
286N/A * See the License for the specific language governing permissions and
286N/A * limitations under the License.
286N/A */
286N/A
286N/Apackage com.sun.xml.internal.stream.dtd.nonvalidating;
286N/A
286N/Aimport java.util.Hashtable;
286N/Aimport java.util.ArrayList;
286N/Aimport java.util.List;
286N/A
286N/Aimport com.sun.org.apache.xerces.internal.util.SymbolTable;
286N/Aimport com.sun.org.apache.xerces.internal.xni.Augmentations;
286N/Aimport com.sun.org.apache.xerces.internal.xni.QName;
286N/Aimport com.sun.org.apache.xerces.internal.util.XMLSymbols;
286N/Aimport com.sun.org.apache.xerces.internal.xni.XMLLocator;
286N/Aimport com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
286N/Aimport com.sun.org.apache.xerces.internal.xni.XMLString;
286N/Aimport com.sun.org.apache.xerces.internal.xni.XNIException;
286N/Aimport com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource;
286N/Aimport com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource;
286N/A
286N/A/**
286N/A * A DTD grammar. This class implements the XNI handler interfaces
286N/A * for DTD information so that it can build the approprate validation
286N/A * structures automatically from the callbacks.
286N/A *
286N/A * @author Eric Ye, IBM
286N/A * @author Jeffrey Rodriguez, IBM
286N/A * @author Andy Clark, IBM
286N/A * @author Neil Graham, IBM
286N/A *
286N/A */
286N/Apublic class DTDGrammar {
286N/A
286N/A
286N/A /** Top level scope (-1). */
286N/A public static final int TOP_LEVEL_SCOPE = -1;
286N/A
286N/A // private
286N/A
286N/A /** Chunk shift (8). */
286N/A private static final int CHUNK_SHIFT = 8; // 2^8 = 256
286N/A
286N/A /** Chunk size (1 << CHUNK_SHIFT). */
286N/A private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
286N/A
286N/A /** Chunk mask (CHUNK_SIZE - 1). */
286N/A private static final int CHUNK_MASK = CHUNK_SIZE - 1;
286N/A
286N/A /** Initial chunk count (1 << (10 - CHUNK_SHIFT)). */
286N/A private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k
286N/A
286N/A /** List flag (0x80). */
286N/A private static final short LIST_FLAG = 0x80;
286N/A
286N/A /** List mask (~LIST_FLAG). */
286N/A private static final short LIST_MASK = ~LIST_FLAG;
286N/A
286N/A // debugging
286N/A
286N/A /** Debug DTDGrammar. */
286N/A private static final boolean DEBUG = false;
286N/A
286N/A //
286N/A // Data
286N/A //
286N/A
286N/A protected XMLDTDSource fDTDSource = null;
286N/A protected XMLDTDContentModelSource fDTDContentModelSource = null;
286N/A
286N/A /** Current element index. */
286N/A protected int fCurrentElementIndex;
286N/A
286N/A /** Current attribute index. */
286N/A protected int fCurrentAttributeIndex;
286N/A
286N/A /** fReadingExternalDTD */
286N/A protected boolean fReadingExternalDTD = false;
286N/A
286N/A /** Symbol table. */
286N/A private SymbolTable fSymbolTable;
286N/A private ArrayList notationDecls = new ArrayList();
286N/A
286N/A // element declarations
286N/A
286N/A /** Number of element declarations. */
286N/A private int fElementDeclCount = 0;
286N/A
286N/A /** Element declaration name. */
286N/A private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
286N/A
286N/A /**
286N/A * Element declaration type.
286N/A * @see XMLElementDecl
286N/A */
286N/A private short fElementDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
286N/A
286N/A
286N/A /** First attribute declaration of an element declaration. */
286N/A private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
286N/A
286N/A /** Last attribute declaration of an element declaration. */
286N/A private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
286N/A
286N/A // attribute declarations
286N/A
286N/A /** Number of attribute declarations. */
286N/A private int fAttributeDeclCount = 0 ;
286N/A
286N/A /** Attribute declaration name. */
286N/A private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
286N/A
286N/A /**
286N/A * Attribute declaration type.
286N/A * @see XMLAttributeDecl
286N/A */
286N/A private short fAttributeDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
286N/A
286N/A /** Attribute declaration enumeration values. */
286N/A private String[] fAttributeDeclEnumeration[][] = new String[INITIAL_CHUNK_COUNT][][];
286N/A private short fAttributeDeclDefaultType[][] = new short[INITIAL_CHUNK_COUNT][];
286N/A private String fAttributeDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
286N/A private String fAttributeDeclNonNormalizedDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
286N/A private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
286N/A
286N/A /** Element index mapping table. */
286N/A private QNameHashtable fElementIndexMap = new QNameHashtable();
286N/A
286N/A /** Temporary qualified name. */
286N/A private QName fQName = new QName();
286N/A
286N/A /** Temporary Attribute decl. */
286N/A protected XMLAttributeDecl fAttributeDecl = new XMLAttributeDecl();
286N/A
286N/A /** Element declaration. */
286N/A private XMLElementDecl fElementDecl = new XMLElementDecl();
286N/A
286N/A /** Simple type. */
286N/A private XMLSimpleType fSimpleType = new XMLSimpleType();
286N/A
286N/A
286N/A /** table of XMLElementDecl */
286N/A Hashtable fElementDeclTab = new Hashtable();
286N/A
286N/A /** Default constructor. */
286N/A public DTDGrammar(SymbolTable symbolTable) {
286N/A fSymbolTable = symbolTable;
286N/A }
286N/A
286N/A public int getAttributeDeclIndex(int elementDeclIndex, String attributeDeclName) {
286N/A if (elementDeclIndex == -1) {
286N/A return -1;
286N/A }
286N/A int attDefIndex = getFirstAttributeDeclIndex(elementDeclIndex);
286N/A while (attDefIndex != -1) {
286N/A getAttributeDecl(attDefIndex, fAttributeDecl);
286N/A
286N/A if (fAttributeDecl.name.rawname == attributeDeclName
286N/A || attributeDeclName.equals(fAttributeDecl.name.rawname) ) {
286N/A return attDefIndex;
286N/A }
286N/A attDefIndex = getNextAttributeDeclIndex(attDefIndex);
286N/A }
286N/A return -1;
286N/A }
286N/A
286N/A /**
286N/A * The start of the DTD.
286N/A *
286N/A * @param locator The document locator, or null if the document
286N/A * location cannot be reported during the parsing of
286N/A * the document DTD. However, it is <em>strongly</em>
286N/A * recommended that a locator be supplied that can
286N/A * at least report the base system identifier of the
286N/A * DTD.
286N/A *
286N/A * @param augs Additional information that may include infoset
286N/A * augmentations.
286N/A * @throws XNIException Thrown by handler to signal an error.
286N/A */
286N/A public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
286N/A } // startDTD(XMLLocator)
286N/A
286N/A // startExternalSubset(Augmentations)
286N/A
286N/A // endExternalSubset(Augmentations)
286N/A
286N/A /**
286N/A * An element declaration.
286N/A *
286N/A * @param name The name of the element.
286N/A * @param contentModel The element content model.
286N/A * @param augs Additional information that may include infoset
286N/A * augmentations.
286N/A * @throws XNIException Thrown by handler to signal an error.
286N/A */
286N/A public void elementDecl(String name, String contentModel, Augmentations augs)
286N/A throws XNIException {
286N/A
286N/A XMLElementDecl tmpElementDecl = (XMLElementDecl) fElementDeclTab.get(name) ;
286N/A if ( tmpElementDecl != null ) {
286N/A if (tmpElementDecl.type == -1) {
286N/A fCurrentElementIndex = getElementDeclIndex(name);
286N/A }
286N/A else {
286N/A // duplicate element, ignored.
286N/A return;
286N/A }
286N/A }
286N/A else {
286N/A fCurrentElementIndex = createElementDecl();//create element decl
286N/A }
286N/A
286N/A XMLElementDecl elementDecl = new XMLElementDecl();
286N/A QName elementName = new QName(null, name, name, null);
286N/A
286N/A elementDecl.name.setValues(elementName);
286N/A elementDecl.scope= -1;
286N/A if (contentModel.equals("EMPTY")) {
286N/A elementDecl.type = XMLElementDecl.TYPE_EMPTY;
286N/A }
286N/A else if (contentModel.equals("ANY")) {
286N/A elementDecl.type = XMLElementDecl.TYPE_ANY;
286N/A }
286N/A else if (contentModel.startsWith("(") ) {
286N/A if (contentModel.indexOf("#PCDATA") > 0 ) {
286N/A elementDecl.type = XMLElementDecl.TYPE_MIXED;
286N/A }
286N/A else {
286N/A elementDecl.type = XMLElementDecl.TYPE_CHILDREN;
286N/A }
286N/A }
286N/A
286N/A
286N/A //add(or set) this elementDecl to the local cache
286N/A this.fElementDeclTab.put(name, elementDecl );
286N/A
286N/A fElementDecl = elementDecl;
286N/A
286N/A
286N/A if ( DEBUG ) {
286N/A System.out.println( "name = " + fElementDecl.name.localpart );
286N/A System.out.println( "Type = " + fElementDecl.type );
286N/A }
286N/A
286N/A setElementDecl(fCurrentElementIndex, fElementDecl );//set internal structure
286N/A
286N/A int chunk = fCurrentElementIndex >> CHUNK_SHIFT;
286N/A ensureElementDeclCapacity(chunk);
286N/A }
286N/A
286N/A /**
286N/A * An attribute declaration.
286N/A *
286N/A * @param elementName The name of the element that this attribute
286N/A * is associated with.
286N/A * @param attributeName The name of the attribute.
286N/A * @param type The attribute type. This value will be one of
286N/A * the following: "CDATA", "ENTITY", "ENTITIES",
286N/A * "ENUMERATION", "ID", "IDREF", "IDREFS",
286N/A * "NMTOKEN", "NMTOKENS", or "NOTATION".
286N/A * @param enumeration If the type has the value "ENUMERATION", this
286N/A * array holds the allowed attribute values;
286N/A * otherwise, this array is null.
286N/A * @param defaultType The attribute default type. This value will be
286N/A * one of the following: "#FIXED", "#IMPLIED",
286N/A * "#REQUIRED", or null.
286N/A * @param defaultValue The attribute default value, or null if no
286N/A * default value is specified.
286N/A * @param nonNormalizedDefaultValue The attribute default value with no normalization
286N/A * performed, or null if no default value is specified.
286N/A *
286N/A * @param augs Additional information that may include infoset
286N/A * augmentations.
286N/A * @throws XNIException Thrown by handler to signal an error.
286N/A */
286N/A public void attributeDecl(String elementName, String attributeName,
286N/A String type, String[] enumeration,
286N/A String defaultType, XMLString defaultValue,
286N/A XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
286N/A
286N/A if (type != XMLSymbols.fCDATASymbol && defaultValue != null) {
286N/A normalizeDefaultAttrValue(defaultValue);
286N/A }
286N/A
286N/A if ( this.fElementDeclTab.containsKey( (String) elementName) ) {
286N/A //if ElementDecl has already being created in the Grammar then remove from table,
286N/A //this.fElementDeclTab.remove( (String) elementName );
286N/A }
286N/A // then it is forward reference to a element decl, create the elementDecl first.
286N/A else {
286N/A fCurrentElementIndex = createElementDecl();//create element decl
286N/A
286N/A XMLElementDecl elementDecl = new XMLElementDecl();
286N/A elementDecl.name.setValues(null, elementName, elementName, null);
286N/A
286N/A elementDecl.scope= -1;
286N/A
286N/A //add(or set) this elementDecl to the local cache
286N/A this.fElementDeclTab.put(elementName, elementDecl );
286N/A
286N/A //set internal structure
286N/A setElementDecl(fCurrentElementIndex, elementDecl );
286N/A }
286N/A
286N/A //Get Grammar index to grammar array
286N/A int elementIndex = getElementDeclIndex(elementName);
286N/A
286N/A //return, when more than one definition is provided for the same attribute of given element type
286N/A //only the first declaration is binding and later declarations are ignored
286N/A if (getAttributeDeclIndex(elementIndex, attributeName) != -1) {
286N/A return;
286N/A }
286N/A
286N/A fCurrentAttributeIndex = createAttributeDecl();// Create current Attribute Decl
286N/A
286N/A fSimpleType.clear();
286N/A if ( defaultType != null ) {
286N/A if ( defaultType.equals( "#FIXED") ) {
286N/A fSimpleType.defaultType = fSimpleType.DEFAULT_TYPE_FIXED;
286N/A } else if ( defaultType.equals( "#IMPLIED") ) {
286N/A fSimpleType.defaultType = fSimpleType.DEFAULT_TYPE_IMPLIED;
286N/A } else if ( defaultType.equals( "#REQUIRED") ) {
286N/A fSimpleType.defaultType = fSimpleType.DEFAULT_TYPE_REQUIRED;
286N/A }
286N/A }
286N/A if ( DEBUG ) {
286N/A System.out.println("defaultvalue = " + defaultValue.toString() );
286N/A }
286N/A fSimpleType.defaultValue = defaultValue!=null ? defaultValue.toString() : null;
286N/A fSimpleType.nonNormalizedDefaultValue = nonNormalizedDefaultValue!=null ? nonNormalizedDefaultValue.toString() : null;
286N/A fSimpleType.enumeration = enumeration;
286N/A
286N/A if (type.equals("CDATA")) {
286N/A fSimpleType.type = XMLSimpleType.TYPE_CDATA;
286N/A }
286N/A else if ( type.equals("ID") ) {
286N/A fSimpleType.type = XMLSimpleType.TYPE_ID;
286N/A }
286N/A else if ( type.startsWith("IDREF") ) {
286N/A fSimpleType.type = XMLSimpleType.TYPE_IDREF;
286N/A if (type.indexOf("S") > 0) {
286N/A fSimpleType.list = true;
286N/A }
286N/A }
286N/A else if (type.equals("ENTITIES")) {
286N/A fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
286N/A fSimpleType.list = true;
286N/A }
286N/A else if (type.equals("ENTITY")) {
286N/A fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
286N/A }
286N/A else if (type.equals("NMTOKENS")) {
286N/A fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
286N/A fSimpleType.list = true;
286N/A }
286N/A else if (type.equals("NMTOKEN")) {
286N/A fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
286N/A }
286N/A else if (type.startsWith("NOTATION") ) {
286N/A fSimpleType.type = XMLSimpleType.TYPE_NOTATION;
286N/A }
286N/A else if (type.startsWith("ENUMERATION") ) {
286N/A fSimpleType.type = XMLSimpleType.TYPE_ENUMERATION;
286N/A }
286N/A else {
286N/A // REVISIT: Report error message. -Ac
286N/A System.err.println("!!! unknown attribute type "+type);
286N/A }
286N/A // REVISIT: The datatype should be stored with the attribute value
286N/A // and not special-cased in the XMLValidator. -Ac
286N/A //fSimpleType.datatypeValidator = fDatatypeValidatorFactory.createDatatypeValidator(type, null, facets, fSimpleType.list);
286N/A
286N/A fQName.setValues(null, attributeName, attributeName, null);
286N/A fAttributeDecl.setValues( fQName, fSimpleType, false );
286N/A
286N/A setAttributeDecl(elementIndex, fCurrentAttributeIndex, fAttributeDecl);
286N/A
286N/A int chunk = fCurrentAttributeIndex >> CHUNK_SHIFT;
286N/A ensureAttributeDeclCapacity(chunk);
286N/A } // attributeDecl(String,String,String,String[],String,XMLString,XMLString, Augmentations)
286N/A
286N/A /** Returns the symbol table. */
286N/A public SymbolTable getSymbolTable() {
286N/A return fSymbolTable;
286N/A } // getSymbolTable():SymbolTable
286N/A
286N/A /**
286N/A * Returns the index of the first element declaration. This index
286N/A * is then used to query more information about the element declaration.
286N/A *
286N/A * @see #getNextElementDeclIndex
286N/A * @see #getElementDecl
286N/A */
286N/A public int getFirstElementDeclIndex() {
286N/A return fElementDeclCount >= 0 ? 0 : -1;
286N/A } // getFirstElementDeclIndex():int
286N/A
286N/A /**
286N/A * Returns the next index of the element declaration following the
286N/A * specified element declaration.
286N/A *
286N/A * @param elementDeclIndex The element declaration index.
286N/A */
286N/A public int getNextElementDeclIndex(int elementDeclIndex) {
286N/A return elementDeclIndex < fElementDeclCount - 1
286N/A ? elementDeclIndex + 1 : -1;
286N/A } // getNextElementDeclIndex(int):int
286N/A
286N/A /**
286N/A * getElementDeclIndex
286N/A *
286N/A * @param elementDeclName
286N/A *
286N/A * @return index of the elementDeclName in scope
286N/A */
286N/A public int getElementDeclIndex(String elementDeclName) {
286N/A int mapping = fElementIndexMap.get(elementDeclName);
286N/A //System.out.println("getElementDeclIndex("+elementDeclName+") -> "+mapping);
286N/A return mapping;
286N/A } // getElementDeclIndex(String):int
286N/A
286N/A /** Returns the element decl index.
286N/A * @param elementDeclQName qualilfied name of the element
286N/A */
286N/A public int getElementDeclIndex(QName elementDeclQName) {
286N/A return getElementDeclIndex(elementDeclQName.rawname);
286N/A } // getElementDeclIndex(QName):int
286N/A
286N/A /** make separate function for getting contentSpecType of element.
286N/A * we can avoid setting of the element values.
286N/A */
286N/A
286N/A public short getContentSpecType(int elementIndex){
286N/A if (elementIndex < 0 || elementIndex >= fElementDeclCount) {
286N/A return -1 ;
286N/A }
286N/A
286N/A int chunk = elementIndex >> CHUNK_SHIFT;
286N/A int index = elementIndex & CHUNK_MASK;
286N/A
286N/A if(fElementDeclType[chunk][index] == -1){
286N/A return -1 ;
286N/A }
286N/A else{
286N/A return (short) (fElementDeclType[chunk][index] & LIST_MASK);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * getElementDecl
286N/A *
286N/A * @param elementDeclIndex
286N/A * @param elementDecl The values of this structure are set by this call.
286N/A *
286N/A * @return True if find the element, False otherwise.
286N/A */
286N/A public boolean getElementDecl(int elementDeclIndex,
286N/A XMLElementDecl elementDecl) {
286N/A
286N/A if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
286N/A return false;
286N/A }
286N/A
286N/A int chunk = elementDeclIndex >> CHUNK_SHIFT;
286N/A int index = elementDeclIndex & CHUNK_MASK;
286N/A
286N/A elementDecl.name.setValues(fElementDeclName[chunk][index]);
286N/A
286N/A if (fElementDeclType[chunk][index] == -1) {
286N/A elementDecl.type = -1;
286N/A elementDecl.simpleType.list = false;
286N/A } else {
286N/A elementDecl.type = (short) (fElementDeclType[chunk][index] & LIST_MASK);
286N/A elementDecl.simpleType.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0;
286N/A }
286N/A
286N/A elementDecl.simpleType.defaultType = -1;
286N/A elementDecl.simpleType.defaultValue = null;
286N/A return true;
286N/A
286N/A }
286N/A
286N/A // REVISIT: Make this getAttributeDeclCount/getAttributeDeclAt. -Ac
286N/A
286N/A /**
286N/A * getFirstAttributeDeclIndex
286N/A *
286N/A * @param elementDeclIndex
286N/A *
286N/A * @return index of the first attribute for element declaration elementDeclIndex
286N/A */
286N/A public int getFirstAttributeDeclIndex(int elementDeclIndex) {
286N/A int chunk = elementDeclIndex >> CHUNK_SHIFT;
286N/A int index = elementDeclIndex & CHUNK_MASK;
286N/A
286N/A return fElementDeclFirstAttributeDeclIndex[chunk][index];
286N/A } // getFirstAttributeDeclIndex
286N/A
286N/A /**
286N/A * getNextAttributeDeclIndex
286N/A *
286N/A * @param attributeDeclIndex
286N/A *
286N/A * @return index of the next attribute of the attribute at attributeDeclIndex
286N/A */
286N/A public int getNextAttributeDeclIndex(int attributeDeclIndex) {
286N/A int chunk = attributeDeclIndex >> CHUNK_SHIFT;
286N/A int index = attributeDeclIndex & CHUNK_MASK;
286N/A
286N/A return fAttributeDeclNextAttributeDeclIndex[chunk][index];
286N/A }
286N/A
286N/A /**
286N/A * getAttributeDecl
286N/A *
286N/A * @param attributeDeclIndex
286N/A * @param attributeDecl The values of this structure are set by this call.
286N/A *
286N/A * @return true if getAttributeDecl was able to fill in the value of attributeDecl
286N/A */
286N/A public boolean getAttributeDecl(int attributeDeclIndex, XMLAttributeDecl attributeDecl) {
286N/A if (attributeDeclIndex < 0 || attributeDeclIndex >= fAttributeDeclCount) {
286N/A return false;
286N/A }
286N/A int chunk = attributeDeclIndex >> CHUNK_SHIFT;
286N/A int index = attributeDeclIndex & CHUNK_MASK;
286N/A
286N/A attributeDecl.name.setValues(fAttributeDeclName[chunk][index]);
286N/A
286N/A short attributeType;
286N/A boolean isList;
286N/A
286N/A if (fAttributeDeclType[chunk][index] == -1) {
286N/A
286N/A attributeType = -1;
286N/A isList = false;
286N/A } else {
286N/A attributeType = (short) (fAttributeDeclType[chunk][index] & LIST_MASK);
286N/A isList = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0;
286N/A }
286N/A attributeDecl.simpleType.setValues(attributeType,fAttributeDeclName[chunk][index].localpart,
286N/A fAttributeDeclEnumeration[chunk][index],
286N/A isList, fAttributeDeclDefaultType[chunk][index],
286N/A fAttributeDeclDefaultValue[chunk][index],
286N/A fAttributeDeclNonNormalizedDefaultValue[chunk][index]);
286N/A return true;
286N/A
286N/A } // getAttributeDecl
286N/A
286N/A
286N/A /**
286N/A * Returns whether the given attribute is of type CDATA or not
286N/A *
286N/A * @param elName The element name.
286N/A * @param atName The attribute name.
286N/A *
286N/A * @return true if the attribute is of type CDATA
286N/A */
286N/A public boolean isCDATAAttribute(QName elName, QName atName) {
286N/A int elDeclIdx = getElementDeclIndex(elName);
286N/A if (getAttributeDecl(elDeclIdx, fAttributeDecl)
286N/A && fAttributeDecl.simpleType.type != XMLSimpleType.TYPE_CDATA){
286N/A return false;
286N/A }
286N/A return true;
286N/A }
286N/A
286N/A
286N/A
286N/A public void printElements( ) {
286N/A int elementDeclIndex = 0;
286N/A XMLElementDecl elementDecl = new XMLElementDecl();
286N/A while (getElementDecl(elementDeclIndex++, elementDecl)) {
286N/A
286N/A System.out.println("element decl: "+elementDecl.name+
286N/A ", "+ elementDecl.name.rawname );
286N/A
286N/A }
286N/A }
286N/A
286N/A public void printAttributes(int elementDeclIndex) {
286N/A int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex);
286N/A System.out.print(elementDeclIndex);
286N/A System.out.print(" [");
286N/A while (attributeDeclIndex != -1) {
286N/A System.out.print(' ');
286N/A System.out.print(attributeDeclIndex);
286N/A printAttribute(attributeDeclIndex);
286N/A attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex);
286N/A if (attributeDeclIndex != -1) {
286N/A System.out.print(",");
286N/A }
286N/A }
286N/A System.out.println(" ]");
286N/A }
286N/A
286N/A
286N/A protected int createElementDecl() {
286N/A int chunk = fElementDeclCount >> CHUNK_SHIFT;
286N/A int index = fElementDeclCount & CHUNK_MASK;
286N/A ensureElementDeclCapacity(chunk);
286N/A fElementDeclName[chunk][index] = new QName();
286N/A fElementDeclType[chunk][index] = -1;
286N/A fElementDeclFirstAttributeDeclIndex[chunk][index] = -1;
286N/A fElementDeclLastAttributeDeclIndex[chunk][index] = -1;
286N/A return fElementDeclCount++;
286N/A }
286N/A
286N/A protected void setElementDecl(int elementDeclIndex, XMLElementDecl elementDecl) {
286N/A if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
286N/A return;
286N/A }
286N/A int chunk = elementDeclIndex >> CHUNK_SHIFT;
286N/A int index = elementDeclIndex & CHUNK_MASK;
286N/A
286N/A int scope = elementDecl.scope;
286N/A
286N/A
286N/A fElementDeclName[chunk][index].setValues(elementDecl.name);
286N/A fElementDeclType[chunk][index] = elementDecl.type;
286N/A
286N/A
286N/A
286N/A if (elementDecl.simpleType.list == true ) {
286N/A fElementDeclType[chunk][index] |= LIST_FLAG;
286N/A }
286N/A
286N/A fElementIndexMap.put(elementDecl.name.rawname, elementDeclIndex);
286N/A }
286N/A
286N/A
286N/A
286N/A
286N/A protected void setFirstAttributeDeclIndex(int elementDeclIndex, int newFirstAttrIndex){
286N/A
286N/A if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
286N/A return;
286N/A }
286N/A
286N/A int chunk = elementDeclIndex >> CHUNK_SHIFT;
286N/A int index = elementDeclIndex & CHUNK_MASK;
286N/A
286N/A fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex;
286N/A }
286N/A
286N/A
286N/A protected int createAttributeDecl() {
286N/A int chunk = fAttributeDeclCount >> CHUNK_SHIFT;
286N/A int index = fAttributeDeclCount & CHUNK_MASK;
286N/A
286N/A ensureAttributeDeclCapacity(chunk);
286N/A fAttributeDeclName[chunk][index] = new QName();
286N/A fAttributeDeclType[chunk][index] = -1;
286N/A fAttributeDeclEnumeration[chunk][index] = null;
286N/A fAttributeDeclDefaultType[chunk][index] = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
286N/A fAttributeDeclDefaultValue[chunk][index] = null;
286N/A fAttributeDeclNonNormalizedDefaultValue[chunk][index] = null;
286N/A fAttributeDeclNextAttributeDeclIndex[chunk][index] = -1;
286N/A return fAttributeDeclCount++;
286N/A }
286N/A
286N/A
286N/A protected void setAttributeDecl(int elementDeclIndex, int attributeDeclIndex,
286N/A XMLAttributeDecl attributeDecl) {
286N/A int attrChunk = attributeDeclIndex >> CHUNK_SHIFT;
286N/A int attrIndex = attributeDeclIndex & CHUNK_MASK;
286N/A fAttributeDeclName[attrChunk][attrIndex].setValues(attributeDecl.name);
286N/A fAttributeDeclType[attrChunk][attrIndex] = attributeDecl.simpleType.type;
286N/A
286N/A if (attributeDecl.simpleType.list) {
286N/A fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG;
286N/A }
286N/A fAttributeDeclEnumeration[attrChunk][attrIndex] = attributeDecl.simpleType.enumeration;
286N/A fAttributeDeclDefaultType[attrChunk][attrIndex] = attributeDecl.simpleType.defaultType;
286N/A
286N/A fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.defaultValue;
286N/A fAttributeDeclNonNormalizedDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.nonNormalizedDefaultValue;
286N/A
286N/A int elemChunk = elementDeclIndex >> CHUNK_SHIFT;
286N/A int elemIndex = elementDeclIndex & CHUNK_MASK;
286N/A int index = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex];
286N/A while (index != -1) {
286N/A if (index == attributeDeclIndex) {
286N/A break;
286N/A }
286N/A attrChunk = index >> CHUNK_SHIFT;
286N/A attrIndex = index & CHUNK_MASK;
286N/A index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex];
286N/A }
286N/A if (index == -1) {
286N/A if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) {
286N/A fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
286N/A } else {
286N/A index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex];
286N/A attrChunk = index >> CHUNK_SHIFT;
286N/A attrIndex = index & CHUNK_MASK;
286N/A fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex;
286N/A }
286N/A fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
286N/A }
286N/A }
286N/A
286N/A public void notationDecl(String name, XMLResourceIdentifier identifier,
286N/A Augmentations augs) throws XNIException {
286N/A
286N/A
286N/A XMLNotationDecl notationDecl = new XMLNotationDecl();
286N/A notationDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(),
286N/A identifier.getBaseSystemId());
286N/A notationDecls.add(notationDecl);
286N/A }
286N/A
286N/A public List getNotationDecls(){
286N/A return notationDecls;
286N/A }
286N/A
286N/A //
286N/A // Private methods
286N/A //
286N/A private void printAttribute(int attributeDeclIndex) {
286N/A
286N/A XMLAttributeDecl attributeDecl = new XMLAttributeDecl();
286N/A if (getAttributeDecl(attributeDeclIndex, attributeDecl)) {
286N/A System.out.print(" { ");
286N/A System.out.print(attributeDecl.name.localpart);
286N/A System.out.print(" }");
286N/A }
286N/A
286N/A } // printAttribute(int)
286N/A
286N/A
286N/A
286N/A private void ensureElementDeclCapacity(int chunk) {
286N/A if (chunk >= fElementDeclName.length) {
286N/A
286N/A fElementDeclName = resize(fElementDeclName, fElementDeclName.length * 2);
286N/A fElementDeclType = resize(fElementDeclType, fElementDeclType.length * 2);
286N/A fElementDeclFirstAttributeDeclIndex = resize(fElementDeclFirstAttributeDeclIndex, fElementDeclFirstAttributeDeclIndex.length * 2);
286N/A fElementDeclLastAttributeDeclIndex = resize(fElementDeclLastAttributeDeclIndex, fElementDeclLastAttributeDeclIndex.length * 2);
286N/A }
286N/A else if (fElementDeclName[chunk] != null) {
286N/A return;
286N/A }
286N/A
286N/A fElementDeclName[chunk] = new QName[CHUNK_SIZE];
286N/A fElementDeclType[chunk] = new short[CHUNK_SIZE];
286N/A fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
286N/A fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
286N/A return;
286N/A }
286N/A
286N/A private void ensureAttributeDeclCapacity(int chunk) {
286N/A
286N/A if (chunk >= fAttributeDeclName.length) {
286N/A fAttributeDeclName = resize(fAttributeDeclName, fAttributeDeclName.length * 2);
286N/A fAttributeDeclType = resize(fAttributeDeclType, fAttributeDeclType.length * 2);
286N/A fAttributeDeclEnumeration = resize(fAttributeDeclEnumeration, fAttributeDeclEnumeration.length * 2);
286N/A fAttributeDeclDefaultType = resize(fAttributeDeclDefaultType, fAttributeDeclDefaultType.length * 2);
286N/A fAttributeDeclDefaultValue = resize(fAttributeDeclDefaultValue, fAttributeDeclDefaultValue.length * 2);
286N/A fAttributeDeclNonNormalizedDefaultValue = resize(fAttributeDeclNonNormalizedDefaultValue, fAttributeDeclNonNormalizedDefaultValue.length * 2);
286N/A fAttributeDeclNextAttributeDeclIndex = resize(fAttributeDeclNextAttributeDeclIndex, fAttributeDeclNextAttributeDeclIndex.length * 2);
286N/A }
286N/A else if (fAttributeDeclName[chunk] != null) {
286N/A return;
286N/A }
286N/A
286N/A fAttributeDeclName[chunk] = new QName[CHUNK_SIZE];
286N/A fAttributeDeclType[chunk] = new short[CHUNK_SIZE];
286N/A fAttributeDeclEnumeration[chunk] = new String[CHUNK_SIZE][];
286N/A fAttributeDeclDefaultType[chunk] = new short[CHUNK_SIZE];
286N/A fAttributeDeclDefaultValue[chunk] = new String[CHUNK_SIZE];
286N/A fAttributeDeclNonNormalizedDefaultValue[chunk] = new String[CHUNK_SIZE];
286N/A fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
286N/A return;
286N/A }
286N/A
286N/A
286N/A // resize chunks
286N/A
286N/A private static short[][] resize(short array[][], int newsize) {
286N/A short newarray[][] = new short[newsize][];
286N/A System.arraycopy(array, 0, newarray, 0, array.length);
286N/A return newarray;
286N/A }
286N/A
286N/A private static int[][] resize(int array[][], int newsize) {
286N/A int newarray[][] = new int[newsize][];
286N/A System.arraycopy(array, 0, newarray, 0, array.length);
286N/A return newarray;
286N/A }
286N/A
286N/A private static QName[][] resize(QName array[][], int newsize) {
286N/A QName newarray[][] = new QName[newsize][];
286N/A System.arraycopy(array, 0, newarray, 0, array.length);
286N/A return newarray;
286N/A }
286N/A
286N/A private static String[][] resize(String array[][], int newsize) {
286N/A String newarray[][] = new String[newsize][];
286N/A System.arraycopy(array, 0, newarray, 0, array.length);
286N/A return newarray;
286N/A }
286N/A
286N/A private static String[][][] resize(String array[][][], int newsize) {
286N/A String newarray[][][] = new String[newsize] [][];
286N/A System.arraycopy(array, 0, newarray, 0, array.length);
286N/A return newarray;
286N/A }
286N/A
286N/A //
286N/A // Classes
286N/A //
286N/A
286N/A
286N/A /**
286N/A * A simple Hashtable implementation that takes a tuple (String, String)
286N/A * as the key and a int as value.
286N/A *
286N/A * @author Eric Ye, IBM
286N/A * @author Andy Clark, IBM
286N/A */
286N/A protected static final class QNameHashtable {
286N/A
286N/A //
286N/A // Constants
286N/A //
286N/A public static final boolean UNIQUE_STRINGS = true;
286N/A
286N/A /** Initial bucket size (4). */
286N/A private static final int INITIAL_BUCKET_SIZE = 4;
286N/A
286N/A // NOTE: Changed previous hashtable size from 512 to 101 so
286N/A // that we get a better distribution for hashing. -Ac
286N/A /** Hashtable size (101). */
286N/A private static final int HASHTABLE_SIZE = 101;
286N/A
286N/A //
286N/A // Data
286N/A //
286N/A private Object[][] fHashTable = new Object[HASHTABLE_SIZE][];
286N/A
286N/A //
286N/A // Public methods
286N/A //
286N/A /** Associates the given value with the specified key tuple. */
286N/A public void put(String key, int value) {
286N/A
286N/A // REVISIT: Why +2? -Ac
286N/A int hash = (hash(key)+2) % HASHTABLE_SIZE;
286N/A Object[] bucket = fHashTable[hash];
286N/A
286N/A if (bucket == null) {
286N/A bucket = new Object[1 + 2*INITIAL_BUCKET_SIZE];
286N/A bucket[0] = new int[]{1};
286N/A bucket[1] = key;
286N/A bucket[2] = new int[]{value};
286N/A fHashTable[hash] = bucket;
286N/A } else {
286N/A int count = ((int[])bucket[0])[0];
286N/A int offset = 1 + 2*count;
286N/A if (offset == bucket.length) {
286N/A int newSize = count + INITIAL_BUCKET_SIZE;
286N/A Object[] newBucket = new Object[1 + 2*newSize];
286N/A System.arraycopy(bucket, 0, newBucket, 0, offset);
286N/A bucket = newBucket;
286N/A fHashTable[hash] = bucket;
286N/A }
286N/A boolean found = false;
286N/A int j=1;
286N/A for (int i=0; i<count; i++){
286N/A if ((String)bucket[j] == key) {
286N/A ((int[])bucket[j+1])[0] = value;
286N/A found = true;
286N/A break;
286N/A }
286N/A j += 2;
286N/A }
286N/A if (! found) {
286N/A bucket[offset++] = key;
286N/A bucket[offset]= new int[]{value};
286N/A ((int[])bucket[0])[0] = ++count;
286N/A }
286N/A
286N/A }
286N/A //System.out.println("put("+key+" -> "+value+')');
286N/A //System.out.println("get("+key+") -> "+get(key));
286N/A
286N/A } // put(int,String,String,int)
286N/A
286N/A /** Returns the value associated with the specified key tuple. */
286N/A public int get(String key) {
286N/A int hash = (hash(key)+2) % HASHTABLE_SIZE;
286N/A Object[] bucket = fHashTable[hash];
286N/A
286N/A if (bucket == null) {
286N/A return -1;
286N/A }
286N/A int count = ((int[])bucket[0])[0];
286N/A
286N/A int j=1;
286N/A for (int i=0; i<count; i++){
286N/A if ((String)bucket[j] == key) {
286N/A return ((int[])bucket[j+1])[0];
286N/A }
286N/A j += 2;
286N/A }
286N/A return -1;
286N/A
286N/A } // get(int,String,String)
286N/A
286N/A //
286N/A // Protected methods
286N/A //
286N/A
286N/A /** Returns a hash value for the specified symbol. */
286N/A protected int hash(String symbol) {
286N/A
286N/A if (symbol == null) {
286N/A return 0;
286N/A }
286N/A int code = 0;
286N/A int length = symbol.length();
286N/A for (int i = 0; i < length; i++) {
286N/A code = code * 37 + symbol.charAt(i);
286N/A }
286N/A return code & 0x7FFFFFF;
286N/A
286N/A } // hash(String):int
286N/A
286N/A } // class QNameHashtable
286N/A /**
286N/A * Normalize the attribute value of a non CDATA default attribute
286N/A * collapsing sequences of space characters (x20)
286N/A *
286N/A * @param value The value to normalize
286N/A * @return Whether the value was changed or not.
286N/A */
286N/A private boolean normalizeDefaultAttrValue(XMLString value) {
286N/A
286N/A int oldLength = value.length;
286N/A
286N/A boolean skipSpace = true; // skip leading spaces
286N/A int current = value.offset;
286N/A int end = value.offset + value.length;
286N/A for (int i = value.offset; i < end; i++) {
286N/A if (value.ch[i] == ' ') {
286N/A if (!skipSpace) {
286N/A // take the first whitespace as a space and skip the others
286N/A value.ch[current++] = ' ';
286N/A skipSpace = true;
286N/A }
286N/A else {
286N/A // just skip it.
286N/A }
286N/A }
286N/A else {
286N/A // simply shift non space chars if needed
286N/A if (current != i) {
286N/A value.ch[current] = value.ch[i];
286N/A }
286N/A current++;
286N/A skipSpace = false;
286N/A }
286N/A }
286N/A if (current != end) {
286N/A if (skipSpace) {
286N/A // if we finished on a space trim it
286N/A current--;
286N/A }
286N/A // set the new value length
286N/A value.length = current - value.offset;
286N/A return true;
286N/A }
286N/A return false;
286N/A }
286N/A public void endDTD(Augmentations augs) throws XNIException {
286N/A
286N/A }
286N/A}