0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.xerces.impl.dtd;
0019:
0020: import java.util.Hashtable;
0021: import java.util.Vector;
0022:
0023: import org.apache.xerces.impl.dtd.models.CMAny;
0024: import org.apache.xerces.impl.dtd.models.CMBinOp;
0025: import org.apache.xerces.impl.dtd.models.CMLeaf;
0026: import org.apache.xerces.impl.dtd.models.CMNode;
0027: import org.apache.xerces.impl.dtd.models.CMUniOp;
0028: import org.apache.xerces.impl.dtd.models.ContentModelValidator;
0029: import org.apache.xerces.impl.dtd.models.DFAContentModel;
0030: import org.apache.xerces.impl.dtd.models.MixedContentModel;
0031: import org.apache.xerces.impl.dtd.models.SimpleContentModel;
0032: import org.apache.xerces.impl.dv.DatatypeValidator;
0033: import org.apache.xerces.impl.validation.EntityState;
0034: import org.apache.xerces.util.SymbolTable;
0035: import org.apache.xerces.xni.Augmentations;
0036: import org.apache.xerces.xni.QName;
0037: import org.apache.xerces.xni.XMLDTDContentModelHandler;
0038: import org.apache.xerces.xni.XMLDTDHandler;
0039: import org.apache.xerces.xni.XMLLocator;
0040: import org.apache.xerces.xni.XMLResourceIdentifier;
0041: import org.apache.xerces.xni.XMLString;
0042: import org.apache.xerces.xni.XNIException;
0043: import org.apache.xerces.xni.grammars.Grammar;
0044: import org.apache.xerces.xni.grammars.XMLGrammarDescription;
0045: import org.apache.xerces.xni.parser.XMLDTDContentModelSource;
0046: import org.apache.xerces.xni.parser.XMLDTDSource;
0047:
0048: /**
0049: * A DTD grammar. This class implements the XNI handler interfaces
0050: * for DTD information so that it can build the approprate validation
0051: * structures automatically from the callbacks.
0052: *
0053: * @xerces.internal
0054: *
0055: * @author Eric Ye, IBM
0056: * @author Jeffrey Rodriguez, IBM
0057: * @author Andy Clark, IBM
0058: * @author Neil Graham, IBM
0059: *
0060: * @version $Id: DTDGrammar.java 572055 2007-09-02 17:55:43Z mrglavas $
0061: */
0062: public class DTDGrammar implements XMLDTDHandler,
0063: XMLDTDContentModelHandler, EntityState, Grammar {
0064:
0065: //
0066: // Constants
0067: //
0068:
0069: /** Top level scope (-1). */
0070: public static final int TOP_LEVEL_SCOPE = -1;
0071:
0072: // private
0073:
0074: /** Chunk shift (8). */
0075: private static final int CHUNK_SHIFT = 8; // 2^8 = 256
0076:
0077: /** Chunk size (1 << CHUNK_SHIFT). */
0078: private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
0079:
0080: /** Chunk mask (CHUNK_SIZE - 1). */
0081: private static final int CHUNK_MASK = CHUNK_SIZE - 1;
0082:
0083: /** Initial chunk count (1 << (10 - CHUNK_SHIFT)). */
0084: private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k
0085:
0086: /** List flag (0x80). */
0087: private static final short LIST_FLAG = 0x80;
0088:
0089: /** List mask (~LIST_FLAG). */
0090: private static final short LIST_MASK = ~LIST_FLAG;
0091:
0092: // debugging
0093:
0094: /** Debug DTDGrammar. */
0095: private static final boolean DEBUG = false;
0096:
0097: //
0098: // Data
0099: //
0100:
0101: protected XMLDTDSource fDTDSource = null;
0102: protected XMLDTDContentModelSource fDTDContentModelSource = null;
0103:
0104: /** Current element index. */
0105: protected int fCurrentElementIndex;
0106:
0107: /** Current attribute index. */
0108: protected int fCurrentAttributeIndex;
0109:
0110: /** fReadingExternalDTD */
0111: protected boolean fReadingExternalDTD = false;
0112:
0113: /** Symbol table. */
0114: private SymbolTable fSymbolTable;
0115:
0116: // The XMLDTDDescription with which this Grammar is associated
0117: protected XMLDTDDescription fGrammarDescription = null;
0118:
0119: // element declarations
0120:
0121: /** Number of element declarations. */
0122: private int fElementDeclCount = 0;
0123:
0124: /** Element declaration name. */
0125: private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
0126:
0127: /**
0128: * Element declaration type.
0129: * @see XMLElementDecl
0130: */
0131: private short fElementDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
0132:
0133: /**
0134: * Element declaration content spec index. This index value is used
0135: * to refer to the content spec information tables.
0136: */
0137: private int fElementDeclContentSpecIndex[][] = new int[INITIAL_CHUNK_COUNT][];
0138:
0139: /**
0140: * Element declaration content model validator. This validator is
0141: * constructed from the content spec nodes.
0142: */
0143: private ContentModelValidator fElementDeclContentModelValidator[][] = new ContentModelValidator[INITIAL_CHUNK_COUNT][];
0144:
0145: /** First attribute declaration of an element declaration. */
0146: private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
0147:
0148: /** Last attribute declaration of an element declaration. */
0149: private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
0150:
0151: // attribute declarations
0152:
0153: /** Number of attribute declarations. */
0154: private int fAttributeDeclCount = 0;
0155:
0156: /** Attribute declaration name. */
0157: private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
0158:
0159: // is this grammar immutable? (fully constructed and not changeable)
0160: private boolean fIsImmutable = false;
0161:
0162: /**
0163: * Attribute declaration type.
0164: * @see XMLAttributeDecl
0165: */
0166: private short fAttributeDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
0167:
0168: /** Attribute declaration enumeration values. */
0169: private String[] fAttributeDeclEnumeration[][] = new String[INITIAL_CHUNK_COUNT][][];
0170: private short fAttributeDeclDefaultType[][] = new short[INITIAL_CHUNK_COUNT][];
0171: private DatatypeValidator fAttributeDeclDatatypeValidator[][] = new DatatypeValidator[INITIAL_CHUNK_COUNT][];
0172: private String fAttributeDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
0173: private String fAttributeDeclNonNormalizedDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
0174: private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
0175:
0176: // content specs
0177:
0178: // here saves the content spec binary trees for element decls,
0179: // each element with a content model will hold a pointer which is
0180: // the index of the head node of the content spec tree.
0181:
0182: private int fContentSpecCount = 0;
0183: private short fContentSpecType[][] = new short[INITIAL_CHUNK_COUNT][];
0184: private Object fContentSpecValue[][] = new Object[INITIAL_CHUNK_COUNT][];
0185: private Object fContentSpecOtherValue[][] = new Object[INITIAL_CHUNK_COUNT][];
0186:
0187: // entities
0188:
0189: private int fEntityCount = 0;
0190: private String fEntityName[][] = new String[INITIAL_CHUNK_COUNT][];
0191: private String[][] fEntityValue = new String[INITIAL_CHUNK_COUNT][];
0192: private String[][] fEntityPublicId = new String[INITIAL_CHUNK_COUNT][];
0193: private String[][] fEntitySystemId = new String[INITIAL_CHUNK_COUNT][];
0194: private String[][] fEntityBaseSystemId = new String[INITIAL_CHUNK_COUNT][];
0195: private String[][] fEntityNotation = new String[INITIAL_CHUNK_COUNT][];
0196: private byte[][] fEntityIsPE = new byte[INITIAL_CHUNK_COUNT][];
0197: private byte[][] fEntityInExternal = new byte[INITIAL_CHUNK_COUNT][];
0198:
0199: // notations
0200:
0201: private int fNotationCount = 0;
0202: private String fNotationName[][] = new String[INITIAL_CHUNK_COUNT][];
0203: private String[][] fNotationPublicId = new String[INITIAL_CHUNK_COUNT][];
0204: private String[][] fNotationSystemId = new String[INITIAL_CHUNK_COUNT][];
0205: private String[][] fNotationBaseSystemId = new String[INITIAL_CHUNK_COUNT][];
0206:
0207: // other information
0208:
0209: /** Element index mapping table. */
0210: private QNameHashtable fElementIndexMap = new QNameHashtable();
0211:
0212: /** Entity index mapping table. */
0213: private QNameHashtable fEntityIndexMap = new QNameHashtable();
0214:
0215: /** Notation index mapping table. */
0216: private QNameHashtable fNotationIndexMap = new QNameHashtable();
0217:
0218: // temp variables
0219:
0220: /** Mixed. */
0221: private boolean fMixed;
0222:
0223: /** Temporary qualified name. */
0224: private final QName fQName = new QName();
0225:
0226: /** Temporary qualified name. */
0227: private final QName fQName2 = new QName();
0228:
0229: /** Temporary Attribute decl. */
0230: protected final XMLAttributeDecl fAttributeDecl = new XMLAttributeDecl();
0231:
0232: // for buildSyntaxTree method
0233:
0234: private int fLeafCount = 0;
0235: private int fEpsilonIndex = -1;
0236:
0237: /** Element declaration. */
0238: private XMLElementDecl fElementDecl = new XMLElementDecl();
0239:
0240: /** Entity declaration. */
0241: private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
0242:
0243: /** Simple type. */
0244: private XMLSimpleType fSimpleType = new XMLSimpleType();
0245:
0246: /** Content spec node. */
0247: private XMLContentSpec fContentSpec = new XMLContentSpec();
0248:
0249: /** table of XMLElementDecl */
0250: Hashtable fElementDeclTab = new Hashtable();
0251:
0252: /** Children content model operation stack. */
0253: private short[] fOpStack = null;
0254:
0255: /** Children content model index stack. */
0256: private int[] fNodeIndexStack = null;
0257:
0258: /** Children content model previous node index stack. */
0259: private int[] fPrevNodeIndexStack = null;
0260:
0261: /** Stack depth */
0262: private int fDepth = 0;
0263:
0264: /** Entity stack. */
0265: private boolean[] fPEntityStack = new boolean[4];
0266: private int fPEDepth = 0;
0267:
0268: // additional fields(columns) for the element Decl pool in the Grammar
0269:
0270: /** flag if the elementDecl is External. */
0271: private int fElementDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][];
0272:
0273: // additional fields(columns) for the attribute Decl pool in the Grammar
0274:
0275: /** flag if the AttributeDecl is External. */
0276: private int fAttributeDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][];
0277:
0278: // for mixedElement method
0279:
0280: int valueIndex = -1;
0281: int prevNodeIndex = -1;
0282: int nodeIndex = -1;
0283:
0284: //
0285: // Constructors
0286: //
0287:
0288: /** Default constructor. */
0289: public DTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) {
0290: fSymbolTable = symbolTable;
0291: fGrammarDescription = desc;
0292: } // <init>(SymbolTable)
0293:
0294: // Grammar methods
0295:
0296: // return the XMLDTDDescription object with which this is associated
0297: public XMLGrammarDescription getGrammarDescription() {
0298: return fGrammarDescription;
0299: } // getGrammarDescription(): XMLGrammarDescription
0300:
0301: //
0302: // Public methods
0303: //
0304:
0305: /**
0306: * Returns true if the specified element declaration is external.
0307: *
0308: * @param elementDeclIndex The element declaration index.
0309: */
0310: public boolean getElementDeclIsExternal(int elementDeclIndex) {
0311:
0312: if (elementDeclIndex < 0) {
0313: return false;
0314: }
0315:
0316: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0317: int index = elementDeclIndex & CHUNK_MASK;
0318: return (fElementDeclIsExternal[chunk][index] != 0);
0319:
0320: } // getElementDeclIsExternal(int):boolean
0321:
0322: /**
0323: * Returns true if the specified attribute declaration is external.
0324: *
0325: * @param attributeDeclIndex Attribute declaration index.
0326: */
0327: public boolean getAttributeDeclIsExternal(int attributeDeclIndex) {
0328:
0329: if (attributeDeclIndex < 0) {
0330: return false;
0331: }
0332:
0333: int chunk = attributeDeclIndex >> CHUNK_SHIFT;
0334: int index = attributeDeclIndex & CHUNK_MASK;
0335: return (fAttributeDeclIsExternal[chunk][index] != 0);
0336: }
0337:
0338: public int getAttributeDeclIndex(int elementDeclIndex,
0339: String attributeDeclName) {
0340: if (elementDeclIndex == -1) {
0341: return -1;
0342: }
0343: int attDefIndex = getFirstAttributeDeclIndex(elementDeclIndex);
0344: while (attDefIndex != -1) {
0345: getAttributeDecl(attDefIndex, fAttributeDecl);
0346:
0347: if (fAttributeDecl.name.rawname == attributeDeclName
0348: || attributeDeclName
0349: .equals(fAttributeDecl.name.rawname)) {
0350: return attDefIndex;
0351: }
0352: attDefIndex = getNextAttributeDeclIndex(attDefIndex);
0353: }
0354: return -1;
0355: } // getAttributeDeclIndex (int,QName)
0356:
0357: //
0358: // XMLDTDHandler methods
0359: //
0360:
0361: /**
0362: * The start of the DTD.
0363: *
0364: * @param locator The document locator, or null if the document
0365: * location cannot be reported during the parsing of
0366: * the document DTD. However, it is <em>strongly</em>
0367: * recommended that a locator be supplied that can
0368: * at least report the base system identifier of the
0369: * DTD.
0370: *
0371: * @param augs Additional information that may include infoset
0372: * augmentations.
0373: * @throws XNIException Thrown by handler to signal an error.
0374: */
0375: public void startDTD(XMLLocator locator, Augmentations augs)
0376: throws XNIException {
0377: //Initialize stack
0378: fOpStack = null;
0379: fNodeIndexStack = null;
0380: fPrevNodeIndexStack = null;
0381: } // startDTD(XMLLocator)
0382:
0383: /**
0384: * This method notifies of the start of an entity. The DTD has the
0385: * pseudo-name of "[dtd]" and parameter entity names start with '%'.
0386: * <p>
0387: * <strong>Note:</strong> Since the DTD is an entity, the handler
0388: * will be notified of the start of the DTD entity by calling the
0389: * startParameterEntity method with the entity name "[dtd]" <em>before</em> calling
0390: * the startDTD method.
0391: *
0392: * @param name The name of the parameter entity.
0393: * @param identifier The resource identifier.
0394: * @param encoding The auto-detected IANA encoding name of the entity
0395: * stream. This value will be null in those situations
0396: * where the entity encoding is not auto-detected (e.g.
0397: * internal parameter entities).
0398: * @param augs Additional information that may include infoset
0399: * augmentations.
0400: *
0401: * @throws XNIException Thrown by handler to signal an error.
0402: */
0403: public void startParameterEntity(String name,
0404: XMLResourceIdentifier identifier, String encoding,
0405: Augmentations augs) throws XNIException {
0406:
0407: // keep track of this entity before fEntityDepth is increased
0408: if (fPEDepth == fPEntityStack.length) {
0409: boolean[] entityarray = new boolean[fPEntityStack.length * 2];
0410: System.arraycopy(fPEntityStack, 0, entityarray, 0,
0411: fPEntityStack.length);
0412: fPEntityStack = entityarray;
0413: }
0414: fPEntityStack[fPEDepth] = fReadingExternalDTD;
0415: fPEDepth++;
0416:
0417: } // startParameterEntity(String,XMLResourceIdentifier,String,Augmentations)
0418:
0419: /**
0420: * The start of the DTD external subset.
0421: *
0422: * @param augs Additional information that may include infoset
0423: * augmentations.
0424: *
0425: * @throws XNIException Thrown by handler to signal an error.
0426: */
0427: public void startExternalSubset(XMLResourceIdentifier identifier,
0428: Augmentations augs) throws XNIException {
0429: fReadingExternalDTD = true;
0430: } // startExternalSubset(Augmentations)
0431:
0432: /**
0433: * This method notifies the end of an entity. The DTD has the pseudo-name
0434: * of "[dtd]" and parameter entity names start with '%'.
0435: * <p>
0436: * <strong>Note:</strong> Since the DTD is an entity, the handler
0437: * will be notified of the end of the DTD entity by calling the
0438: * endEntity method with the entity name "[dtd]" <em>after</em> calling
0439: * the endDTD method.
0440: *
0441: * @param name The name of the entity.
0442: * @param augs Additional information that may include infoset
0443: * augmentations.
0444: * @throws XNIException Thrown by handler to signal an error.
0445: */
0446: public void endParameterEntity(String name, Augmentations augs)
0447: throws XNIException {
0448:
0449: fPEDepth--;
0450: fReadingExternalDTD = fPEntityStack[fPEDepth];
0451:
0452: } // endParameterEntity(String,Augmentations)
0453:
0454: /**
0455: * The end of the DTD external subset.
0456: *
0457: * @param augs Additional information that may include infoset
0458: * augmentations.
0459: *
0460: * @throws XNIException Thrown by handler to signal an error.
0461: */
0462: public void endExternalSubset(Augmentations augs)
0463: throws XNIException {
0464: fReadingExternalDTD = false;
0465: } // endExternalSubset(Augmentations)
0466:
0467: /**
0468: * An element declaration.
0469: *
0470: * @param name The name of the element.
0471: * @param contentModel The element content model.
0472: * @param augs Additional information that may include infoset
0473: * augmentations.
0474: * @throws XNIException Thrown by handler to signal an error.
0475: */
0476: public void elementDecl(String name, String contentModel,
0477: Augmentations augs) throws XNIException {
0478:
0479: XMLElementDecl tmpElementDecl = (XMLElementDecl) fElementDeclTab
0480: .get(name);
0481:
0482: // check if it is already defined
0483: if (tmpElementDecl != null) {
0484: if (tmpElementDecl.type == -1) {
0485: fCurrentElementIndex = getElementDeclIndex(name);
0486: } else {
0487: // duplicate element, ignored.
0488: return;
0489: }
0490: } else {
0491: fCurrentElementIndex = createElementDecl();//create element decl
0492: }
0493:
0494: XMLElementDecl elementDecl = new XMLElementDecl();
0495:
0496: fQName.setValues(null, name, name, null);
0497:
0498: elementDecl.name.setValues(fQName);
0499:
0500: elementDecl.contentModelValidator = null;
0501: elementDecl.scope = -1;
0502: if (contentModel.equals("EMPTY")) {
0503: elementDecl.type = XMLElementDecl.TYPE_EMPTY;
0504: } else if (contentModel.equals("ANY")) {
0505: elementDecl.type = XMLElementDecl.TYPE_ANY;
0506: } else if (contentModel.startsWith("(")) {
0507: if (contentModel.indexOf("#PCDATA") > 0) {
0508: elementDecl.type = XMLElementDecl.TYPE_MIXED;
0509: } else {
0510: elementDecl.type = XMLElementDecl.TYPE_CHILDREN;
0511: }
0512: }
0513:
0514: //add(or set) this elementDecl to the local cache
0515: this .fElementDeclTab.put(name, elementDecl);
0516:
0517: fElementDecl = elementDecl;
0518: addContentSpecToElement(elementDecl);
0519:
0520: if (DEBUG) {
0521: System.out.println("name = " + fElementDecl.name.localpart);
0522: System.out.println("Type = " + fElementDecl.type);
0523: }
0524:
0525: setElementDecl(fCurrentElementIndex, fElementDecl);//set internal structure
0526:
0527: int chunk = fCurrentElementIndex >> CHUNK_SHIFT;
0528: int index = fCurrentElementIndex & CHUNK_MASK;
0529: ensureElementDeclCapacity(chunk);
0530: fElementDeclIsExternal[chunk][index] = (fReadingExternalDTD || fPEDepth > 0) ? 1
0531: : 0;
0532:
0533: } // elementDecl(String,String)
0534:
0535: /**
0536: * An attribute declaration.
0537: *
0538: * @param elementName The name of the element that this attribute
0539: * is associated with.
0540: * @param attributeName The name of the attribute.
0541: * @param type The attribute type. This value will be one of
0542: * the following: "CDATA", "ENTITY", "ENTITIES",
0543: * "ENUMERATION", "ID", "IDREF", "IDREFS",
0544: * "NMTOKEN", "NMTOKENS", or "NOTATION".
0545: * @param enumeration If the type has the value "ENUMERATION", this
0546: * array holds the allowed attribute values;
0547: * otherwise, this array is null.
0548: * @param defaultType The attribute default type. This value will be
0549: * one of the following: "#FIXED", "#IMPLIED",
0550: * "#REQUIRED", or null.
0551: * @param defaultValue The attribute default value, or null if no
0552: * default value is specified.
0553: * @param nonNormalizedDefaultValue The attribute default value with no normalization
0554: * performed, or null if no default value is specified.
0555: *
0556: * @param augs Additional information that may include infoset
0557: * augmentations.
0558: * @throws XNIException Thrown by handler to signal an error.
0559: */
0560: public void attributeDecl(String elementName, String attributeName,
0561: String type, String[] enumeration, String defaultType,
0562: XMLString defaultValue,
0563: XMLString nonNormalizedDefaultValue, Augmentations augs)
0564: throws XNIException {
0565:
0566: if (this .fElementDeclTab.containsKey((String) elementName)) {
0567: //if ElementDecl has already being created in the Grammar then remove from table,
0568: //this.fElementDeclTab.remove( (String) elementName );
0569: }
0570: // then it is forward reference to a element decl, create the elementDecl first.
0571: else {
0572: fCurrentElementIndex = createElementDecl();//create element decl
0573:
0574: XMLElementDecl elementDecl = new XMLElementDecl();
0575: elementDecl.name.setValues(null, elementName, elementName,
0576: null);
0577:
0578: elementDecl.scope = -1;
0579:
0580: //add(or set) this elementDecl to the local cache
0581: this .fElementDeclTab.put(elementName, elementDecl);
0582:
0583: //set internal structure
0584: setElementDecl(fCurrentElementIndex, elementDecl);
0585: }
0586:
0587: //Get Grammar index to grammar array
0588: int elementIndex = getElementDeclIndex(elementName);
0589:
0590: //return, when more than one definition is provided for the same attribute of given element type
0591: //only the first declaration is binding and later declarations are ignored
0592: if (getAttributeDeclIndex(elementIndex, attributeName) != -1) {
0593: return;
0594: }
0595:
0596: fCurrentAttributeIndex = createAttributeDecl();// Create current Attribute Decl
0597:
0598: fSimpleType.clear();
0599: if (defaultType != null) {
0600: if (defaultType.equals("#FIXED")) {
0601: fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_FIXED;
0602: } else if (defaultType.equals("#IMPLIED")) {
0603: fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
0604: } else if (defaultType.equals("#REQUIRED")) {
0605: fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_REQUIRED;
0606: }
0607: }
0608: if (DEBUG) {
0609: System.out.println("defaultvalue = "
0610: + defaultValue.toString());
0611: }
0612: fSimpleType.defaultValue = defaultValue != null ? defaultValue
0613: .toString() : null;
0614: fSimpleType.nonNormalizedDefaultValue = nonNormalizedDefaultValue != null ? nonNormalizedDefaultValue
0615: .toString()
0616: : null;
0617: fSimpleType.enumeration = enumeration;
0618:
0619: if (type.equals("CDATA")) {
0620: fSimpleType.type = XMLSimpleType.TYPE_CDATA;
0621: } else if (type.equals("ID")) {
0622: fSimpleType.type = XMLSimpleType.TYPE_ID;
0623: } else if (type.startsWith("IDREF")) {
0624: fSimpleType.type = XMLSimpleType.TYPE_IDREF;
0625: if (type.indexOf("S") > 0) {
0626: fSimpleType.list = true;
0627: }
0628: } else if (type.equals("ENTITIES")) {
0629: fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
0630: fSimpleType.list = true;
0631: } else if (type.equals("ENTITY")) {
0632: fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
0633: } else if (type.equals("NMTOKENS")) {
0634: fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
0635: fSimpleType.list = true;
0636: } else if (type.equals("NMTOKEN")) {
0637: fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
0638: } else if (type.startsWith("NOTATION")) {
0639: fSimpleType.type = XMLSimpleType.TYPE_NOTATION;
0640: } else if (type.startsWith("ENUMERATION")) {
0641: fSimpleType.type = XMLSimpleType.TYPE_ENUMERATION;
0642: } else {
0643: // REVISIT: Report error message. -Ac
0644: System.err.println("!!! unknown attribute type " + type);
0645: }
0646: // REVISIT: The datatype should be stored with the attribute value
0647: // and not special-cased in the XMLValidator. -Ac
0648: //fSimpleType.datatypeValidator = fDatatypeValidatorFactory.createDatatypeValidator(type, null, facets, fSimpleType.list);
0649:
0650: fQName.setValues(null, attributeName, attributeName, null);
0651: fAttributeDecl.setValues(fQName, fSimpleType, false);
0652:
0653: setAttributeDecl(elementIndex, fCurrentAttributeIndex,
0654: fAttributeDecl);
0655:
0656: int chunk = fCurrentAttributeIndex >> CHUNK_SHIFT;
0657: int index = fCurrentAttributeIndex & CHUNK_MASK;
0658: ensureAttributeDeclCapacity(chunk);
0659: fAttributeDeclIsExternal[chunk][index] = (fReadingExternalDTD || fPEDepth > 0) ? 1
0660: : 0;
0661:
0662: } // attributeDecl(String,String,String,String[],String,XMLString,XMLString, Augmentations)
0663:
0664: /**
0665: * An internal entity declaration.
0666: *
0667: * @param name The name of the entity. Parameter entity names start with
0668: * '%', whereas the name of a general entity is just the
0669: * entity name.
0670: * @param text The value of the entity.
0671: * @param nonNormalizedText The non-normalized value of the entity. This
0672: * value contains the same sequence of characters that was in
0673: * the internal entity declaration, without any entity
0674: * references expanded.
0675: * @param augs Additional information that may include infoset
0676: * augmentations.
0677: * @throws XNIException Thrown by handler to signal an error.
0678: */
0679: public void internalEntityDecl(String name, XMLString text,
0680: XMLString nonNormalizedText, Augmentations augs)
0681: throws XNIException {
0682:
0683: int entityIndex = getEntityDeclIndex(name);
0684: if (entityIndex == -1) {
0685: entityIndex = createEntityDecl();
0686: boolean isPE = name.startsWith("%");
0687: boolean inExternal = (fReadingExternalDTD || fPEDepth > 0);
0688: XMLEntityDecl entityDecl = new XMLEntityDecl();
0689: entityDecl.setValues(name, null, null, null, null, text
0690: .toString(), isPE, inExternal);
0691:
0692: setEntityDecl(entityIndex, entityDecl);
0693: }
0694:
0695: } // internalEntityDecl(String,XMLString,XMLString)
0696:
0697: /**
0698: * An external entity declaration.
0699: *
0700: * @param name The name of the entity. Parameter entity names start
0701: * with '%', whereas the name of a general entity is just
0702: * the entity name.
0703: * @param identifier An object containing all location information
0704: * pertinent to this external entity declaration.
0705: * @param augs Additional information that may include infoset
0706: * augmentations.
0707: * @throws XNIException Thrown by handler to signal an error.
0708: */
0709: public void externalEntityDecl(String name,
0710: XMLResourceIdentifier identifier, Augmentations augs)
0711: throws XNIException {
0712:
0713: int entityIndex = getEntityDeclIndex(name);
0714: if (entityIndex == -1) {
0715: entityIndex = createEntityDecl();
0716: boolean isPE = name.startsWith("%");
0717: boolean inExternal = (fReadingExternalDTD || fPEDepth > 0);
0718:
0719: XMLEntityDecl entityDecl = new XMLEntityDecl();
0720: entityDecl.setValues(name, identifier.getPublicId(),
0721: identifier.getLiteralSystemId(), identifier
0722: .getBaseSystemId(), null, null, isPE,
0723: inExternal);
0724:
0725: setEntityDecl(entityIndex, entityDecl);
0726: }
0727: } // externalEntityDecl(String, XMLResourceIdentifier, Augmentations)
0728:
0729: /**
0730: * An unparsed entity declaration.
0731: *
0732: * @param name The name of the entity.
0733: * @param identifier An object containing all location information
0734: * pertinent to this entity.
0735: * @param notation The name of the notation.
0736: * @param augs Additional information that may include infoset
0737: * augmentations.
0738: * @throws XNIException Thrown by handler to signal an error.
0739: */
0740: public void unparsedEntityDecl(String name,
0741: XMLResourceIdentifier identifier, String notation,
0742: Augmentations augs) throws XNIException {
0743:
0744: XMLEntityDecl entityDecl = new XMLEntityDecl();
0745: boolean isPE = name.startsWith("%");
0746: boolean inExternal = (fReadingExternalDTD || fPEDepth > 0);
0747:
0748: entityDecl.setValues(name, identifier.getPublicId(), identifier
0749: .getLiteralSystemId(), identifier.getBaseSystemId(),
0750: notation, null, isPE, inExternal);
0751: int entityIndex = getEntityDeclIndex(name);
0752: if (entityIndex == -1) {
0753: entityIndex = createEntityDecl();
0754: setEntityDecl(entityIndex, entityDecl);
0755: }
0756:
0757: } // unparsedEntityDecl(String,StringXMLResourceIdentifier,Augmentations)
0758:
0759: /**
0760: * A notation declaration
0761: *
0762: * @param name The name of the notation.
0763: * @param identifier An object containing all location information
0764: * pertinent to this notation.
0765: * @param augs Additional information that may include infoset
0766: * augmentations.
0767: * @throws XNIException Thrown by handler to signal an error.
0768: */
0769: public void notationDecl(String name,
0770: XMLResourceIdentifier identifier, Augmentations augs)
0771: throws XNIException {
0772:
0773: XMLNotationDecl notationDecl = new XMLNotationDecl();
0774: notationDecl.setValues(name, identifier.getPublicId(),
0775: identifier.getLiteralSystemId(), identifier
0776: .getBaseSystemId());
0777: int notationIndex = getNotationDeclIndex(name);
0778: if (notationIndex == -1) {
0779: notationIndex = createNotationDecl();
0780: setNotationDecl(notationIndex, notationDecl);
0781: }
0782:
0783: } // notationDecl(String,XMLResourceIdentifier,Augmentations)
0784:
0785: /**
0786: * The end of the DTD.
0787: *
0788: * @param augs Additional information that may include infoset
0789: * augmentations.
0790: * @throws XNIException Thrown by handler to signal an error.
0791: */
0792: public void endDTD(Augmentations augs) throws XNIException {
0793: fIsImmutable = true;
0794: // make sure our description contains useful stuff...
0795: if (fGrammarDescription.getRootName() == null) {
0796: // we don't know what the root is; so use possibleRoots...
0797: int chunk, index = 0;
0798: String currName = null;
0799: Vector elements = new Vector();
0800: for (int i = 0; i < fElementDeclCount; i++) {
0801: chunk = i >> CHUNK_SHIFT;
0802: index = i & CHUNK_MASK;
0803: currName = fElementDeclName[chunk][index].rawname;
0804: elements.addElement(currName);
0805: }
0806: fGrammarDescription.setPossibleRoots(elements);
0807: }
0808: } // endDTD()
0809:
0810: // sets the source of this handler
0811: public void setDTDSource(XMLDTDSource source) {
0812: fDTDSource = source;
0813: } // setDTDSource(XMLDTDSource)
0814:
0815: // returns the source of this handler
0816: public XMLDTDSource getDTDSource() {
0817: return fDTDSource;
0818: } // getDTDSource(): XMLDTDSource
0819:
0820: // no-op methods
0821:
0822: /**
0823: * Notifies of the presence of a TextDecl line in an entity. If present,
0824: * this method will be called immediately following the startEntity call.
0825: * <p>
0826: * <strong>Note:</strong> This method is only called for external
0827: * parameter entities referenced in the DTD.
0828: *
0829: * @param version The XML version, or null if not specified.
0830: * @param encoding The IANA encoding name of the entity.
0831: *
0832: * @param augs Additional information that may include infoset
0833: * augmentations.
0834: * @throws XNIException Thrown by handler to signal an error.
0835: */
0836: public void textDecl(String version, String encoding,
0837: Augmentations augs) throws XNIException {
0838: }
0839:
0840: /**
0841: * A comment.
0842: *
0843: * @param text The text in the comment.
0844: * @param augs Additional information that may include infoset
0845: * augmentations.
0846: * @throws XNIException Thrown by application to signal an error.
0847: */
0848: public void comment(XMLString text, Augmentations augs)
0849: throws XNIException {
0850: }
0851:
0852: /**
0853: * A processing instruction. Processing instructions consist of a
0854: * target name and, optionally, text data. The data is only meaningful
0855: * to the application.
0856: * <p>
0857: * Typically, a processing instruction's data will contain a series
0858: * of pseudo-attributes. These pseudo-attributes follow the form of
0859: * element attributes but are <strong>not</strong> parsed or presented
0860: * to the application as anything other than text. The application is
0861: * responsible for parsing the data.
0862: *
0863: * @param target The target.
0864: * @param data The data or null if none specified.
0865: * @param augs Additional information that may include infoset
0866: * augmentations.
0867: * @throws XNIException Thrown by handler to signal an error.
0868: */
0869: public void processingInstruction(String target, XMLString data,
0870: Augmentations augs) throws XNIException {
0871: }
0872:
0873: /**
0874: * The start of an attribute list.
0875: *
0876: * @param elementName The name of the element that this attribute
0877: * list is associated with.
0878: * @param augs Additional information that may include infoset
0879: * augmentations.
0880: * @throws XNIException Thrown by handler to signal an error.
0881: */
0882: public void startAttlist(String elementName, Augmentations augs)
0883: throws XNIException {
0884: }
0885:
0886: /**
0887: * The end of an attribute list.
0888: * @param augs Additional information that may include infoset
0889: * augmentations.
0890: * @throws XNIException Thrown by handler to signal an error.
0891: */
0892: public void endAttlist(Augmentations augs) throws XNIException {
0893: }
0894:
0895: /**
0896: * The start of a conditional section.
0897: *
0898: * @param type The type of the conditional section. This value will
0899: * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
0900: * @param augs Additional information that may include infoset
0901: * augmentations.
0902: * @throws XNIException Thrown by handler to signal an error.
0903: *
0904: * @see XMLDTDHandler#CONDITIONAL_INCLUDE
0905: * @see XMLDTDHandler#CONDITIONAL_IGNORE
0906: */
0907: public void startConditional(short type, Augmentations augs)
0908: throws XNIException {
0909: }
0910:
0911: /**
0912: * Characters within an IGNORE conditional section.
0913: *
0914: * @param text The ignored text.
0915: * @param augs Additional information that may include infoset
0916: * augmentations.
0917: */
0918: public void ignoredCharacters(XMLString text, Augmentations augs)
0919: throws XNIException {
0920: }
0921:
0922: /**
0923: * The end of a conditional section.
0924: * @param augs Additional information that may include infoset
0925: * augmentations.
0926: * @throws XNIException Thrown by handler to signal an error.
0927: */
0928: public void endConditional(Augmentations augs) throws XNIException {
0929: }
0930:
0931: //
0932: // XMLDTDContentModelHandler methods
0933: //
0934:
0935: // set content model source
0936: public void setDTDContentModelSource(XMLDTDContentModelSource source) {
0937: fDTDContentModelSource = source;
0938: }
0939:
0940: // get content model source
0941: public XMLDTDContentModelSource getDTDContentModelSource() {
0942: return fDTDContentModelSource;
0943: }
0944:
0945: /**
0946: * The start of a content model. Depending on the type of the content
0947: * model, specific methods may be called between the call to the
0948: * startContentModel method and the call to the endContentModel method.
0949: *
0950: * @param elementName The name of the element.
0951: * @param augs Additional information that may include infoset
0952: * augmentations.
0953: * @throws XNIException Thrown by handler to signal an error.
0954: */
0955: public void startContentModel(String elementName, Augmentations augs)
0956: throws XNIException {
0957:
0958: XMLElementDecl elementDecl = (XMLElementDecl) this .fElementDeclTab
0959: .get(elementName);
0960: if (elementDecl != null) {
0961: fElementDecl = elementDecl;
0962: }
0963: fDepth = 0;
0964: initializeContentModelStack();
0965:
0966: } // startContentModel(String)
0967:
0968: /**
0969: * A start of either a mixed or children content model. A mixed
0970: * content model will immediately be followed by a call to the
0971: * <code>pcdata()</code> method. A children content model will
0972: * contain additional groups and/or elements.
0973: *
0974: * @param augs Additional information that may include infoset
0975: * augmentations.
0976: * @throws XNIException Thrown by handler to signal an error.
0977: *
0978: * @see #any
0979: * @see #empty
0980: */
0981: public void startGroup(Augmentations augs) throws XNIException {
0982: fDepth++;
0983: initializeContentModelStack();
0984: fMixed = false;
0985: } // startGroup()
0986:
0987: /**
0988: * The appearance of "#PCDATA" within a group signifying a
0989: * mixed content model. This method will be the first called
0990: * following the content model's <code>startGroup()</code>.
0991: *
0992: *@param augs Additional information that may include infoset
0993: * augmentations.
0994: *
0995: * @throws XNIException Thrown by handler to signal an error.
0996: *
0997: * @see #startGroup
0998: */
0999: public void pcdata(Augmentations augs) throws XNIException {
1000: fMixed = true;
1001: } // pcdata()
1002:
1003: /**
1004: * A referenced element in a mixed or children content model.
1005: *
1006: * @param elementName The name of the referenced element.
1007: * @param augs Additional information that may include infoset
1008: * augmentations.
1009: *
1010: * @throws XNIException Thrown by handler to signal an error.
1011: */
1012: public void element(String elementName, Augmentations augs)
1013: throws XNIException {
1014: if (fMixed) {
1015: if (fNodeIndexStack[fDepth] == -1) {
1016: fNodeIndexStack[fDepth] = addUniqueLeafNode(elementName);
1017: } else {
1018: fNodeIndexStack[fDepth] = addContentSpecNode(
1019: XMLContentSpec.CONTENTSPECNODE_CHOICE,
1020: fNodeIndexStack[fDepth],
1021: addUniqueLeafNode(elementName));
1022: }
1023: } else {
1024: fNodeIndexStack[fDepth] = addContentSpecNode(
1025: XMLContentSpec.CONTENTSPECNODE_LEAF, elementName);
1026: }
1027: } // element(String)
1028:
1029: /**
1030: * The separator between choices or sequences of a mixed or children
1031: * content model.
1032: *
1033: * @param separator The type of children separator.
1034: * @param augs Additional information that may include infoset
1035: * augmentations.
1036: * @throws XNIException Thrown by handler to signal an error.
1037: *
1038: * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE
1039: * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE
1040: */
1041: public void separator(short separator, Augmentations augs)
1042: throws XNIException {
1043:
1044: if (!fMixed) {
1045: if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_SEQ
1046: && separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE) {
1047: if (fPrevNodeIndexStack[fDepth] != -1) {
1048: fNodeIndexStack[fDepth] = addContentSpecNode(
1049: fOpStack[fDepth],
1050: fPrevNodeIndexStack[fDepth],
1051: fNodeIndexStack[fDepth]);
1052: }
1053: fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth];
1054: fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
1055: } else if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_CHOICE
1056: && separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) {
1057: if (fPrevNodeIndexStack[fDepth] != -1) {
1058: fNodeIndexStack[fDepth] = addContentSpecNode(
1059: fOpStack[fDepth],
1060: fPrevNodeIndexStack[fDepth],
1061: fNodeIndexStack[fDepth]);
1062: }
1063: fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth];
1064: fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
1065: }
1066: }
1067:
1068: } // separator(short)
1069:
1070: /**
1071: * The occurrence count for a child in a children content model or
1072: * for the mixed content model group.
1073: *
1074: * @param occurrence The occurrence count for the last element
1075: * or group.
1076: * @param augs Additional information that may include infoset
1077: * augmentations.
1078: * @throws XNIException Thrown by handler to signal an error.
1079: *
1080: * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE
1081: * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE
1082: * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE
1083: */
1084: public void occurrence(short occurrence, Augmentations augs)
1085: throws XNIException {
1086:
1087: if (!fMixed) {
1088: if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE) {
1089: fNodeIndexStack[fDepth] = addContentSpecNode(
1090: XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
1091: fNodeIndexStack[fDepth], -1);
1092: } else if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE) {
1093: fNodeIndexStack[fDepth] = addContentSpecNode(
1094: XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE,
1095: fNodeIndexStack[fDepth], -1);
1096: } else if (occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) {
1097: fNodeIndexStack[fDepth] = addContentSpecNode(
1098: XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE,
1099: fNodeIndexStack[fDepth], -1);
1100: }
1101: }
1102:
1103: } // occurrence(short)
1104:
1105: /**
1106: * The end of a group for mixed or children content models.
1107: *
1108: * @param augs Additional information that may include infoset
1109: * augmentations.
1110: * @throws XNIException Thrown by handler to signal an error.
1111: */
1112: public void endGroup(Augmentations augs) throws XNIException {
1113:
1114: if (!fMixed) {
1115: if (fPrevNodeIndexStack[fDepth] != -1) {
1116: fNodeIndexStack[fDepth] = addContentSpecNode(
1117: fOpStack[fDepth], fPrevNodeIndexStack[fDepth],
1118: fNodeIndexStack[fDepth]);
1119: }
1120: int nodeIndex = fNodeIndexStack[fDepth--];
1121: fNodeIndexStack[fDepth] = nodeIndex;
1122: }
1123:
1124: } // endGroup()
1125:
1126: // no-op methods
1127:
1128: /**
1129: * A content model of ANY.
1130: *
1131: * @param augs Additional information that may include infoset
1132: * augmentations.
1133: * @throws XNIException Thrown by handler to signal an error.
1134: *
1135: * @see #empty
1136: * @see #startGroup
1137: */
1138: public void any(Augmentations augs) throws XNIException {
1139: }
1140:
1141: /**
1142: * A content model of EMPTY.
1143: *
1144: * @param augs Additional information that may include infoset
1145: * augmentations.
1146: * @throws XNIException Thrown by handler to signal an error.
1147: *
1148: * @see #any
1149: * @see #startGroup
1150: */
1151: public void empty(Augmentations augs) throws XNIException {
1152: }
1153:
1154: /**
1155: * The end of a content model.
1156: * @param augs Additional information that may include infoset
1157: * augmentations.
1158: *
1159: * @throws XNIException Thrown by handler to signal an error.
1160: */
1161: public void endContentModel(Augmentations augs) throws XNIException {
1162: }
1163:
1164: //
1165: // Grammar methods
1166: //
1167:
1168: /** Returns true if this grammar is namespace aware. */
1169: public boolean isNamespaceAware() {
1170: return false;
1171: } // isNamespaceAware():boolean
1172:
1173: /** Returns the symbol table. */
1174: public SymbolTable getSymbolTable() {
1175: return fSymbolTable;
1176: } // getSymbolTable():SymbolTable
1177:
1178: /**
1179: * Returns the index of the first element declaration. This index
1180: * is then used to query more information about the element declaration.
1181: *
1182: * @see #getNextElementDeclIndex
1183: * @see #getElementDecl
1184: */
1185: public int getFirstElementDeclIndex() {
1186: return fElementDeclCount >= 0 ? 0 : -1;
1187: } // getFirstElementDeclIndex():int
1188:
1189: /**
1190: * Returns the next index of the element declaration following the
1191: * specified element declaration.
1192: *
1193: * @param elementDeclIndex The element declaration index.
1194: */
1195: public int getNextElementDeclIndex(int elementDeclIndex) {
1196: return elementDeclIndex < fElementDeclCount - 1 ? elementDeclIndex + 1
1197: : -1;
1198: } // getNextElementDeclIndex(int):int
1199:
1200: /**
1201: * getElementDeclIndex
1202: *
1203: * @param elementDeclName
1204: *
1205: * @return index of the elementDeclName in scope
1206: */
1207: public int getElementDeclIndex(String elementDeclName) {
1208: int mapping = fElementIndexMap.get(elementDeclName);
1209: //System.out.println("getElementDeclIndex("+elementDeclName+") -> "+mapping);
1210: return mapping;
1211: } // getElementDeclIndex(String):int
1212:
1213: /** Returns the element decl index.
1214: * @param elementDeclQName qualilfied name of the element
1215: */
1216: public int getElementDeclIndex(QName elementDeclQName) {
1217: return getElementDeclIndex(elementDeclQName.rawname);
1218: } // getElementDeclIndex(QName):int
1219:
1220: /** make separate function for getting contentSpecType of element.
1221: * we can avoid setting of the element values.
1222: */
1223:
1224: public short getContentSpecType(int elementIndex) {
1225: if (elementIndex < 0 || elementIndex >= fElementDeclCount) {
1226: return -1;
1227: }
1228:
1229: int chunk = elementIndex >> CHUNK_SHIFT;
1230: int index = elementIndex & CHUNK_MASK;
1231:
1232: if (fElementDeclType[chunk][index] == -1) {
1233: return -1;
1234: } else {
1235: return (short) (fElementDeclType[chunk][index] & LIST_MASK);
1236: }
1237:
1238: }//getContentSpecType
1239:
1240: /**
1241: * getElementDecl
1242: *
1243: * @param elementDeclIndex
1244: * @param elementDecl The values of this structure are set by this call.
1245: *
1246: * @return True if find the element, False otherwise.
1247: */
1248: public boolean getElementDecl(int elementDeclIndex,
1249: XMLElementDecl elementDecl) {
1250:
1251: if (elementDeclIndex < 0
1252: || elementDeclIndex >= fElementDeclCount) {
1253: return false;
1254: }
1255:
1256: int chunk = elementDeclIndex >> CHUNK_SHIFT;
1257: int index = elementDeclIndex & CHUNK_MASK;
1258:
1259: elementDecl.name.setValues(fElementDeclName[chunk][index]);
1260:
1261: if (fElementDeclType[chunk][index] == -1) {
1262: elementDecl.type = -1;
1263: elementDecl.simpleType.list = false;
1264: } else {
1265: elementDecl.type = (short) (fElementDeclType[chunk][index] & LIST_MASK);
1266: elementDecl.simpleType.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0;
1267: }
1268:
1269: /* Validators are null until we add that code */
1270: if (elementDecl.type == XMLElementDecl.TYPE_CHILDREN
1271: || elementDecl.type == XMLElementDecl.TYPE_MIXED) {
1272: elementDecl.contentModelValidator = getElementContentModelValidator(elementDeclIndex);
1273: }
1274:
1275: elementDecl.simpleType.datatypeValidator = null;
1276: elementDecl.simpleType.defaultType = -1;
1277: elementDecl.simpleType.defaultValue = null;
1278:
1279: return true;
1280:
1281: } // getElementDecl(int,XMLElementDecl):boolean
1282:
1283: QName getElementDeclName(int elementDeclIndex) {
1284: if (elementDeclIndex < 0
1285: || elementDeclIndex >= fElementDeclCount) {
1286: return null;
1287: }
1288: int chunk = elementDeclIndex >> CHUNK_SHIFT;
1289: int index = elementDeclIndex & CHUNK_MASK;
1290: return fElementDeclName[chunk][index];
1291: }
1292:
1293: // REVISIT: Make this getAttributeDeclCount/getAttributeDeclAt. -Ac
1294:
1295: /**
1296: * getFirstAttributeDeclIndex
1297: *
1298: * @param elementDeclIndex
1299: *
1300: * @return index of the first attribute for element declaration elementDeclIndex
1301: */
1302: public int getFirstAttributeDeclIndex(int elementDeclIndex) {
1303: int chunk = elementDeclIndex >> CHUNK_SHIFT;
1304: int index = elementDeclIndex & CHUNK_MASK;
1305:
1306: return fElementDeclFirstAttributeDeclIndex[chunk][index];
1307: } // getFirstAttributeDeclIndex
1308:
1309: /**
1310: * getNextAttributeDeclIndex
1311: *
1312: * @param attributeDeclIndex
1313: *
1314: * @return index of the next attribute of the attribute at attributeDeclIndex
1315: */
1316: public int getNextAttributeDeclIndex(int attributeDeclIndex) {
1317: int chunk = attributeDeclIndex >> CHUNK_SHIFT;
1318: int index = attributeDeclIndex & CHUNK_MASK;
1319:
1320: return fAttributeDeclNextAttributeDeclIndex[chunk][index];
1321: } // getNextAttributeDeclIndex
1322:
1323: /**
1324: * getAttributeDecl
1325: *
1326: * @param attributeDeclIndex
1327: * @param attributeDecl The values of this structure are set by this call.
1328: *
1329: * @return true if getAttributeDecl was able to fill in the value of attributeDecl
1330: */
1331: public boolean getAttributeDecl(int attributeDeclIndex,
1332: XMLAttributeDecl attributeDecl) {
1333: if (attributeDeclIndex < 0
1334: || attributeDeclIndex >= fAttributeDeclCount) {
1335: return false;
1336: }
1337: int chunk = attributeDeclIndex >> CHUNK_SHIFT;
1338: int index = attributeDeclIndex & CHUNK_MASK;
1339:
1340: attributeDecl.name.setValues(fAttributeDeclName[chunk][index]);
1341:
1342: short attributeType;
1343: boolean isList;
1344:
1345: if (fAttributeDeclType[chunk][index] == -1) {
1346:
1347: attributeType = -1;
1348: isList = false;
1349: } else {
1350: attributeType = (short) (fAttributeDeclType[chunk][index] & LIST_MASK);
1351: isList = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0;
1352: }
1353: attributeDecl.simpleType.setValues(attributeType,
1354: fAttributeDeclName[chunk][index].localpart,
1355: fAttributeDeclEnumeration[chunk][index], isList,
1356: fAttributeDeclDefaultType[chunk][index],
1357: fAttributeDeclDefaultValue[chunk][index],
1358: fAttributeDeclNonNormalizedDefaultValue[chunk][index],
1359: fAttributeDeclDatatypeValidator[chunk][index]);
1360: return true;
1361:
1362: } // getAttributeDecl
1363:
1364: /**
1365: * Returns whether the given attribute is of type CDATA or not
1366: *
1367: * @param elName The element name.
1368: * @param atName The attribute name.
1369: *
1370: * @return true if the attribute is of type CDATA
1371: */
1372: public boolean isCDATAAttribute(QName elName, QName atName) {
1373: int elDeclIdx = getElementDeclIndex(elName);
1374: if (getAttributeDecl(elDeclIdx, fAttributeDecl)
1375: && fAttributeDecl.simpleType.type != XMLSimpleType.TYPE_CDATA) {
1376: return false;
1377: }
1378: return true;
1379: }
1380:
1381: /**
1382: * getEntityDeclIndex
1383: *
1384: * @param entityDeclName
1385: *
1386: * @return the index of the EntityDecl
1387: */
1388: public int getEntityDeclIndex(String entityDeclName) {
1389: if (entityDeclName == null) {
1390: return -1;
1391: }
1392:
1393: return fEntityIndexMap.get(entityDeclName);
1394: } // getEntityDeclIndex
1395:
1396: /**
1397: * getEntityDecl
1398: *
1399: * @param entityDeclIndex
1400: * @param entityDecl
1401: *
1402: * @return true if getEntityDecl was able to fill entityDecl with the contents of the entity
1403: * with index entityDeclIndex
1404: */
1405: public boolean getEntityDecl(int entityDeclIndex,
1406: XMLEntityDecl entityDecl) {
1407: if (entityDeclIndex < 0 || entityDeclIndex >= fEntityCount) {
1408: return false;
1409: }
1410: int chunk = entityDeclIndex >> CHUNK_SHIFT;
1411: int index = entityDeclIndex & CHUNK_MASK;
1412:
1413: entityDecl.setValues(fEntityName[chunk][index],
1414: fEntityPublicId[chunk][index],
1415: fEntitySystemId[chunk][index],
1416: fEntityBaseSystemId[chunk][index],
1417: fEntityNotation[chunk][index],
1418: fEntityValue[chunk][index],
1419: fEntityIsPE[chunk][index] == 0 ? false : true,
1420: fEntityInExternal[chunk][index] == 0 ? false : true);
1421:
1422: return true;
1423: } // getEntityDecl
1424:
1425: /**
1426: * getNotationDeclIndex
1427: *
1428: * @param notationDeclName
1429: *
1430: * @return the index if found a notation with the name, otherwise -1.
1431: */
1432: public int getNotationDeclIndex(String notationDeclName) {
1433: if (notationDeclName == null) {
1434: return -1;
1435: }
1436:
1437: return fNotationIndexMap.get(notationDeclName);
1438: } // getNotationDeclIndex
1439:
1440: /**
1441: * getNotationDecl
1442: *
1443: * @param notationDeclIndex
1444: * @param notationDecl
1445: *
1446: * @return return true of getNotationDecl can fill notationDecl with information about
1447: * the notation at notationDeclIndex.
1448: */
1449: public boolean getNotationDecl(int notationDeclIndex,
1450: XMLNotationDecl notationDecl) {
1451: if (notationDeclIndex < 0
1452: || notationDeclIndex >= fNotationCount) {
1453: return false;
1454: }
1455: int chunk = notationDeclIndex >> CHUNK_SHIFT;
1456: int index = notationDeclIndex & CHUNK_MASK;
1457:
1458: notationDecl.setValues(fNotationName[chunk][index],
1459: fNotationPublicId[chunk][index],
1460: fNotationSystemId[chunk][index],
1461: fNotationBaseSystemId[chunk][index]);
1462:
1463: return true;
1464:
1465: } // getNotationDecl
1466:
1467: /**
1468: * getContentSpec
1469: *
1470: * @param contentSpecIndex
1471: * @param contentSpec
1472: *
1473: * @return true if find the requested contentSpec node, false otherwise
1474: */
1475: public boolean getContentSpec(int contentSpecIndex,
1476: XMLContentSpec contentSpec) {
1477: if (contentSpecIndex < 0
1478: || contentSpecIndex >= fContentSpecCount)
1479: return false;
1480:
1481: int chunk = contentSpecIndex >> CHUNK_SHIFT;
1482: int index = contentSpecIndex & CHUNK_MASK;
1483:
1484: contentSpec.type = fContentSpecType[chunk][index];
1485: contentSpec.value = fContentSpecValue[chunk][index];
1486: contentSpec.otherValue = fContentSpecOtherValue[chunk][index];
1487: return true;
1488: }
1489:
1490: /**
1491: * Returns the index to the content spec for the given element
1492: * declaration, or <code>-1</code> if the element declaration
1493: * index was invalid.
1494: */
1495: public int getContentSpecIndex(int elementDeclIndex) {
1496: if (elementDeclIndex < 0
1497: || elementDeclIndex >= fElementDeclCount) {
1498: return -1;
1499: }
1500: final int chunk = elementDeclIndex >> CHUNK_SHIFT;
1501: final int index = elementDeclIndex & CHUNK_MASK;
1502: return fElementDeclContentSpecIndex[chunk][index];
1503: }
1504:
1505: /**
1506: * getContentSpecAsString
1507: *
1508: * @param elementDeclIndex
1509: *
1510: * @return String
1511: */
1512: public String getContentSpecAsString(int elementDeclIndex) {
1513:
1514: if (elementDeclIndex < 0
1515: || elementDeclIndex >= fElementDeclCount) {
1516: return null;
1517: }
1518:
1519: int chunk = elementDeclIndex >> CHUNK_SHIFT;
1520: int index = elementDeclIndex & CHUNK_MASK;
1521:
1522: int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
1523:
1524: // lookup content spec node
1525: XMLContentSpec contentSpec = new XMLContentSpec();
1526:
1527: if (getContentSpec(contentSpecIndex, contentSpec)) {
1528:
1529: // build string
1530: StringBuffer str = new StringBuffer();
1531: int parentContentSpecType = contentSpec.type & 0x0f;
1532: int nextContentSpec;
1533: switch (parentContentSpecType) {
1534: case XMLContentSpec.CONTENTSPECNODE_LEAF: {
1535: str.append('(');
1536: if (contentSpec.value == null
1537: && contentSpec.otherValue == null) {
1538: str.append("#PCDATA");
1539: } else {
1540: str.append(contentSpec.value);
1541: }
1542: str.append(')');
1543: break;
1544: }
1545: case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
1546: getContentSpec(((int[]) contentSpec.value)[0],
1547: contentSpec);
1548: nextContentSpec = contentSpec.type;
1549:
1550: if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1551: str.append('(');
1552: str.append(contentSpec.value);
1553: str.append(')');
1554: } else if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE
1555: || nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
1556: || nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) {
1557: str.append('(');
1558: appendContentSpec(contentSpec, str, true,
1559: parentContentSpecType);
1560: str.append(')');
1561: } else {
1562: appendContentSpec(contentSpec, str, true,
1563: parentContentSpecType);
1564: }
1565: str.append('?');
1566: break;
1567: }
1568: case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
1569: getContentSpec(((int[]) contentSpec.value)[0],
1570: contentSpec);
1571: nextContentSpec = contentSpec.type;
1572:
1573: if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1574: str.append('(');
1575: if (contentSpec.value == null
1576: && contentSpec.otherValue == null) {
1577: str.append("#PCDATA");
1578: } else if (contentSpec.otherValue != null) {
1579: str.append("##any:uri=").append(
1580: contentSpec.otherValue);
1581: } else if (contentSpec.value == null) {
1582: str.append("##any");
1583: } else {
1584: appendContentSpec(contentSpec, str, true,
1585: parentContentSpecType);
1586: }
1587: str.append(')');
1588: } else if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE
1589: || nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
1590: || nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) {
1591: str.append('(');
1592: appendContentSpec(contentSpec, str, true,
1593: parentContentSpecType);
1594: str.append(')');
1595: } else {
1596: appendContentSpec(contentSpec, str, true,
1597: parentContentSpecType);
1598: }
1599: str.append('*');
1600: break;
1601: }
1602: case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
1603: getContentSpec(((int[]) contentSpec.value)[0],
1604: contentSpec);
1605: nextContentSpec = contentSpec.type;
1606:
1607: if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
1608: str.append('(');
1609: if (contentSpec.value == null
1610: && contentSpec.otherValue == null) {
1611: str.append("#PCDATA");
1612: } else if (contentSpec.otherValue != null) {
1613: str.append("##any:uri=").append(
1614: contentSpec.otherValue);
1615: } else if (contentSpec.value == null) {
1616: str.append("##any");
1617: } else {
1618: str.append(contentSpec.value);
1619: }
1620: str.append(')');
1621: } else if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE
1622: || nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
1623: || nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) {
1624: str.append('(');
1625: appendContentSpec(contentSpec, str, true,
1626: parentContentSpecType);
1627: str.append(')');
1628: } else {
1629: appendContentSpec(contentSpec, str, true,
1630: parentContentSpecType);
1631: }
1632: str.append('+');
1633: break;
1634: }
1635: case XMLContentSpec.CONTENTSPECNODE_CHOICE:
1636: case XMLContentSpec.CONTENTSPECNODE_SEQ: {
1637: appendContentSpec(contentSpec, str, true,
1638: parentContentSpecType);
1639: break;
1640: }
1641: case XMLContentSpec.CONTENTSPECNODE_ANY: {
1642: str.append("##any");
1643: if (contentSpec.otherValue != null) {
1644: str.append(":uri=");
1645: str.append(contentSpec.otherValue);
1646: }
1647: break;
1648: }
1649: case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: {
1650: str.append("##other:uri=");
1651: str.append(contentSpec.otherValue);
1652: break;
1653: }
1654: case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: {
1655: str.append("##local");
1656: break;
1657: }
1658: default: {
1659: str.append("???");
1660: }
1661:
1662: } // switch type
1663:
1664: // return string
1665: return str.toString();
1666: }
1667:
1668: // not found
1669: return null;
1670:
1671: } // getContentSpecAsString(int):String
1672:
1673: // debugging
1674:
1675: public void printElements() {
1676: int elementDeclIndex = 0;
1677: XMLElementDecl elementDecl = new XMLElementDecl();
1678: while (getElementDecl(elementDeclIndex++, elementDecl)) {
1679:
1680: System.out.println("element decl: " + elementDecl.name
1681: + ", " + elementDecl.name.rawname);
1682:
1683: // ", "+ elementDecl.contentModelValidator.toString());
1684: }
1685: }
1686:
1687: public void printAttributes(int elementDeclIndex) {
1688: int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex);
1689: System.out.print(elementDeclIndex);
1690: System.out.print(" [");
1691: while (attributeDeclIndex != -1) {
1692: System.out.print(' ');
1693: System.out.print(attributeDeclIndex);
1694: printAttribute(attributeDeclIndex);
1695: attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex);
1696: if (attributeDeclIndex != -1) {
1697: System.out.print(",");
1698: }
1699: }
1700: System.out.println(" ]");
1701: }
1702:
1703: //
1704: // Protected methods
1705: //
1706:
1707: /**
1708: * Adds the content spec to the given element declaration.
1709: */
1710: protected void addContentSpecToElement(XMLElementDecl elementDecl) {
1711: if ((fDepth == 0 || (fDepth == 1 && elementDecl.type == XMLElementDecl.TYPE_MIXED))
1712: && fNodeIndexStack != null) {
1713: if (elementDecl.type == XMLElementDecl.TYPE_MIXED) {
1714: int pcdata = addUniqueLeafNode(null);
1715: if (fNodeIndexStack[0] == -1) {
1716: fNodeIndexStack[0] = pcdata;
1717: } else {
1718: fNodeIndexStack[0] = addContentSpecNode(
1719: XMLContentSpec.CONTENTSPECNODE_CHOICE,
1720: pcdata, fNodeIndexStack[0]);
1721: }
1722: }
1723: setContentSpecIndex(fCurrentElementIndex,
1724: fNodeIndexStack[fDepth]);
1725: }
1726: }
1727:
1728: /**
1729: * getElementContentModelValidator
1730: *
1731: * @param elementDeclIndex
1732: *
1733: * @return its ContentModelValidator if any.
1734: */
1735: protected ContentModelValidator getElementContentModelValidator(
1736: int elementDeclIndex) {
1737:
1738: int chunk = elementDeclIndex >> CHUNK_SHIFT;
1739: int index = elementDeclIndex & CHUNK_MASK;
1740:
1741: ContentModelValidator contentModel = fElementDeclContentModelValidator[chunk][index];
1742:
1743: // If we have one, just return that. Otherwise, gotta create one
1744: if (contentModel != null) {
1745: return contentModel;
1746: }
1747:
1748: int contentType = fElementDeclType[chunk][index];
1749: if (contentType == XMLElementDecl.TYPE_SIMPLE) {
1750: return null;
1751: }
1752:
1753: // Get the type of content this element has
1754: int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
1755:
1756: /***
1757: if ( contentSpecIndex == -1 )
1758: return null;
1759: /***/
1760:
1761: XMLContentSpec contentSpec = new XMLContentSpec();
1762: getContentSpec(contentSpecIndex, contentSpec);
1763:
1764: // And create the content model according to the spec type
1765: if (contentType == XMLElementDecl.TYPE_MIXED) {
1766: //
1767: // Just create a mixel content model object. This type of
1768: // content model is optimized for mixed content validation.
1769: //
1770: ChildrenList children = new ChildrenList();
1771: contentSpecTree(contentSpecIndex, contentSpec, children);
1772: contentModel = new MixedContentModel(children.qname,
1773: children.type, 0, children.length, false);
1774: } else if (contentType == XMLElementDecl.TYPE_CHILDREN) {
1775: // This method will create an optimal model for the complexity
1776: // of the element's defined model. If its simple, it will create
1777: // a SimpleContentModel object. If its a simple list, it will
1778: // create a SimpleListContentModel object. If its complex, it
1779: // will create a DFAContentModel object.
1780: //
1781: contentModel = createChildModel(contentSpecIndex);
1782: } else {
1783: throw new RuntimeException(
1784: "Unknown content type for a element decl "
1785: + "in getElementContentModelValidator() in AbstractDTDGrammar class");
1786: }
1787:
1788: // Add the new model to the content model for this element
1789: fElementDeclContentModelValidator[chunk][index] = contentModel;
1790:
1791: return contentModel;
1792:
1793: } // getElementContentModelValidator(int):ContentModelValidator
1794:
1795: protected int createElementDecl() {
1796: int chunk = fElementDeclCount >> CHUNK_SHIFT;
1797: int index = fElementDeclCount & CHUNK_MASK;
1798: ensureElementDeclCapacity(chunk);
1799: fElementDeclName[chunk][index] = new QName();
1800: fElementDeclType[chunk][index] = -1;
1801: fElementDeclContentModelValidator[chunk][index] = null;
1802: fElementDeclFirstAttributeDeclIndex[chunk][index] = -1;
1803: fElementDeclLastAttributeDeclIndex[chunk][index] = -1;
1804: return fElementDeclCount++;
1805: }
1806:
1807: protected void setElementDecl(int elementDeclIndex,
1808: XMLElementDecl elementDecl) {
1809: if (elementDeclIndex < 0
1810: || elementDeclIndex >= fElementDeclCount) {
1811: return;
1812: }
1813: int chunk = elementDeclIndex >> CHUNK_SHIFT;
1814: int index = elementDeclIndex & CHUNK_MASK;
1815:
1816: fElementDeclName[chunk][index].setValues(elementDecl.name);
1817: fElementDeclType[chunk][index] = elementDecl.type;
1818:
1819: fElementDeclContentModelValidator[chunk][index] = elementDecl.contentModelValidator;
1820:
1821: if (elementDecl.simpleType.list == true) {
1822: fElementDeclType[chunk][index] |= LIST_FLAG;
1823: }
1824:
1825: fElementIndexMap
1826: .put(elementDecl.name.rawname, elementDeclIndex);
1827: }
1828:
1829: protected void putElementNameMapping(QName name, int scope,
1830: int elementDeclIndex) {
1831: }
1832:
1833: protected void setFirstAttributeDeclIndex(int elementDeclIndex,
1834: int newFirstAttrIndex) {
1835:
1836: if (elementDeclIndex < 0
1837: || elementDeclIndex >= fElementDeclCount) {
1838: return;
1839: }
1840:
1841: int chunk = elementDeclIndex >> CHUNK_SHIFT;
1842: int index = elementDeclIndex & CHUNK_MASK;
1843:
1844: fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex;
1845: }
1846:
1847: protected void setContentSpecIndex(int elementDeclIndex,
1848: int contentSpecIndex) {
1849:
1850: if (elementDeclIndex < 0
1851: || elementDeclIndex >= fElementDeclCount) {
1852: return;
1853: }
1854:
1855: int chunk = elementDeclIndex >> CHUNK_SHIFT;
1856: int index = elementDeclIndex & CHUNK_MASK;
1857:
1858: fElementDeclContentSpecIndex[chunk][index] = contentSpecIndex;
1859: }
1860:
1861: protected int createAttributeDecl() {
1862: int chunk = fAttributeDeclCount >> CHUNK_SHIFT;
1863: int index = fAttributeDeclCount & CHUNK_MASK;
1864:
1865: ensureAttributeDeclCapacity(chunk);
1866: fAttributeDeclName[chunk][index] = new QName();
1867: fAttributeDeclType[chunk][index] = -1;
1868: fAttributeDeclDatatypeValidator[chunk][index] = null;
1869: fAttributeDeclEnumeration[chunk][index] = null;
1870: fAttributeDeclDefaultType[chunk][index] = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
1871: fAttributeDeclDefaultValue[chunk][index] = null;
1872: fAttributeDeclNonNormalizedDefaultValue[chunk][index] = null;
1873: fAttributeDeclNextAttributeDeclIndex[chunk][index] = -1;
1874: return fAttributeDeclCount++;
1875: }
1876:
1877: protected void setAttributeDecl(int elementDeclIndex,
1878: int attributeDeclIndex, XMLAttributeDecl attributeDecl) {
1879: int attrChunk = attributeDeclIndex >> CHUNK_SHIFT;
1880: int attrIndex = attributeDeclIndex & CHUNK_MASK;
1881: fAttributeDeclName[attrChunk][attrIndex]
1882: .setValues(attributeDecl.name);
1883: fAttributeDeclType[attrChunk][attrIndex] = attributeDecl.simpleType.type;
1884:
1885: if (attributeDecl.simpleType.list) {
1886: fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG;
1887: }
1888: fAttributeDeclEnumeration[attrChunk][attrIndex] = attributeDecl.simpleType.enumeration;
1889: fAttributeDeclDefaultType[attrChunk][attrIndex] = attributeDecl.simpleType.defaultType;
1890: fAttributeDeclDatatypeValidator[attrChunk][attrIndex] = attributeDecl.simpleType.datatypeValidator;
1891:
1892: fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.defaultValue;
1893: fAttributeDeclNonNormalizedDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.nonNormalizedDefaultValue;
1894:
1895: int elemChunk = elementDeclIndex >> CHUNK_SHIFT;
1896: int elemIndex = elementDeclIndex & CHUNK_MASK;
1897: int index = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex];
1898: while (index != -1) {
1899: if (index == attributeDeclIndex) {
1900: break;
1901: }
1902: attrChunk = index >> CHUNK_SHIFT;
1903: attrIndex = index & CHUNK_MASK;
1904: index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex];
1905: }
1906: if (index == -1) {
1907: if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) {
1908: fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
1909: } else {
1910: index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex];
1911: attrChunk = index >> CHUNK_SHIFT;
1912: attrIndex = index & CHUNK_MASK;
1913: fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex;
1914: }
1915: fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
1916: }
1917: }
1918:
1919: protected int createContentSpec() {
1920: int chunk = fContentSpecCount >> CHUNK_SHIFT;
1921: int index = fContentSpecCount & CHUNK_MASK;
1922:
1923: ensureContentSpecCapacity(chunk);
1924: fContentSpecType[chunk][index] = -1;
1925: fContentSpecValue[chunk][index] = null;
1926: fContentSpecOtherValue[chunk][index] = null;
1927:
1928: return fContentSpecCount++;
1929: }
1930:
1931: protected void setContentSpec(int contentSpecIndex,
1932: XMLContentSpec contentSpec) {
1933: int chunk = contentSpecIndex >> CHUNK_SHIFT;
1934: int index = contentSpecIndex & CHUNK_MASK;
1935:
1936: fContentSpecType[chunk][index] = contentSpec.type;
1937: fContentSpecValue[chunk][index] = contentSpec.value;
1938: fContentSpecOtherValue[chunk][index] = contentSpec.otherValue;
1939: }
1940:
1941: protected int createEntityDecl() {
1942: int chunk = fEntityCount >> CHUNK_SHIFT;
1943: int index = fEntityCount & CHUNK_MASK;
1944:
1945: ensureEntityDeclCapacity(chunk);
1946: fEntityIsPE[chunk][index] = 0;
1947: fEntityInExternal[chunk][index] = 0;
1948:
1949: return fEntityCount++;
1950: }
1951:
1952: protected void setEntityDecl(int entityDeclIndex,
1953: XMLEntityDecl entityDecl) {
1954: int chunk = entityDeclIndex >> CHUNK_SHIFT;
1955: int index = entityDeclIndex & CHUNK_MASK;
1956:
1957: fEntityName[chunk][index] = entityDecl.name;
1958: fEntityValue[chunk][index] = entityDecl.value;
1959: fEntityPublicId[chunk][index] = entityDecl.publicId;
1960: fEntitySystemId[chunk][index] = entityDecl.systemId;
1961: fEntityBaseSystemId[chunk][index] = entityDecl.baseSystemId;
1962: fEntityNotation[chunk][index] = entityDecl.notation;
1963: fEntityIsPE[chunk][index] = entityDecl.isPE ? (byte) 1
1964: : (byte) 0;
1965: fEntityInExternal[chunk][index] = entityDecl.inExternal ? (byte) 1
1966: : (byte) 0;
1967:
1968: fEntityIndexMap.put(entityDecl.name, entityDeclIndex);
1969: }
1970:
1971: protected int createNotationDecl() {
1972: int chunk = fNotationCount >> CHUNK_SHIFT;
1973: ensureNotationDeclCapacity(chunk);
1974: return fNotationCount++;
1975: }
1976:
1977: protected void setNotationDecl(int notationDeclIndex,
1978: XMLNotationDecl notationDecl) {
1979: int chunk = notationDeclIndex >> CHUNK_SHIFT;
1980: int index = notationDeclIndex & CHUNK_MASK;
1981:
1982: fNotationName[chunk][index] = notationDecl.name;
1983: fNotationPublicId[chunk][index] = notationDecl.publicId;
1984: fNotationSystemId[chunk][index] = notationDecl.systemId;
1985: fNotationBaseSystemId[chunk][index] = notationDecl.baseSystemId;
1986:
1987: fNotationIndexMap.put(notationDecl.name, notationDeclIndex);
1988: }
1989:
1990: /**
1991: * Create an XMLContentSpec for a single non-leaf
1992: *
1993: * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
1994: * @param nodeValue handle to an XMLContentSpec
1995: * @return handle to the newly create XMLContentSpec
1996: */
1997: protected int addContentSpecNode(short nodeType, String nodeValue) {
1998:
1999: // create content spec node
2000: int contentSpecIndex = createContentSpec();
2001:
2002: // set content spec node values
2003: fContentSpec.setValues(nodeType, nodeValue, null);
2004: setContentSpec(contentSpecIndex, fContentSpec);
2005:
2006: // return index
2007: return contentSpecIndex;
2008:
2009: } // addContentSpecNode(short,String):int
2010:
2011: /**
2012: * create an XMLContentSpec for a leaf
2013: *
2014: * @param elementName the name (Element) for the node
2015: * @return handle to the newly create XMLContentSpec
2016: */
2017: protected int addUniqueLeafNode(String elementName) {
2018:
2019: // create content spec node
2020: int contentSpecIndex = createContentSpec();
2021:
2022: // set content spec node values
2023: fContentSpec.setValues(XMLContentSpec.CONTENTSPECNODE_LEAF,
2024: elementName, null);
2025: setContentSpec(contentSpecIndex, fContentSpec);
2026:
2027: // return index
2028: return contentSpecIndex;
2029:
2030: } // addUniqueLeafNode(String):int
2031:
2032: /**
2033: * Create an XMLContentSpec for a two child leaf
2034: *
2035: * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
2036: * @param leftNodeIndex handle to an XMLContentSpec
2037: * @param rightNodeIndex handle to an XMLContentSpec
2038: * @return handle to the newly create XMLContentSpec
2039: */
2040: protected int addContentSpecNode(short nodeType, int leftNodeIndex,
2041: int rightNodeIndex) {
2042:
2043: // create content spec node
2044: int contentSpecIndex = createContentSpec();
2045:
2046: // set content spec node values
2047: int[] leftIntArray = new int[1];
2048: int[] rightIntArray = new int[1];
2049:
2050: leftIntArray[0] = leftNodeIndex;
2051: rightIntArray[0] = rightNodeIndex;
2052: fContentSpec.setValues(nodeType, leftIntArray, rightIntArray);
2053: setContentSpec(contentSpecIndex, fContentSpec);
2054:
2055: // return index
2056: return contentSpecIndex;
2057:
2058: } // addContentSpecNode(short,int,int):int
2059:
2060: /** Initialize content model stack. */
2061: protected void initializeContentModelStack() {
2062:
2063: if (fOpStack == null) {
2064: fOpStack = new short[8];
2065: fNodeIndexStack = new int[8];
2066: fPrevNodeIndexStack = new int[8];
2067: } else if (fDepth == fOpStack.length) {
2068: short[] newStack = new short[fDepth * 2];
2069: System.arraycopy(fOpStack, 0, newStack, 0, fDepth);
2070: fOpStack = newStack;
2071: int[] newIntStack = new int[fDepth * 2];
2072: System
2073: .arraycopy(fNodeIndexStack, 0, newIntStack, 0,
2074: fDepth);
2075: fNodeIndexStack = newIntStack;
2076: newIntStack = new int[fDepth * 2];
2077: System.arraycopy(fPrevNodeIndexStack, 0, newIntStack, 0,
2078: fDepth);
2079: fPrevNodeIndexStack = newIntStack;
2080: }
2081: fOpStack[fDepth] = -1;
2082: fNodeIndexStack[fDepth] = -1;
2083: fPrevNodeIndexStack[fDepth] = -1;
2084:
2085: } // initializeContentModelStack()
2086:
2087: boolean isImmutable() {
2088: return fIsImmutable;
2089: }
2090:
2091: //
2092: // Private methods
2093: //
2094:
2095: private void appendContentSpec(XMLContentSpec contentSpec,
2096: StringBuffer str, boolean parens, int parentContentSpecType) {
2097:
2098: int this ContentSpec = contentSpec.type & 0x0f;
2099: switch (this ContentSpec) {
2100: case XMLContentSpec.CONTENTSPECNODE_LEAF: {
2101: if (contentSpec.value == null
2102: && contentSpec.otherValue == null) {
2103: str.append("#PCDATA");
2104: } else if (contentSpec.value == null
2105: && contentSpec.otherValue != null) {
2106: str.append("##any:uri=").append(contentSpec.otherValue);
2107: } else if (contentSpec.value == null) {
2108: str.append("##any");
2109: } else {
2110: str.append(contentSpec.value);
2111: }
2112: break;
2113: }
2114: case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
2115: if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE
2116: || parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
2117: || parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) {
2118: getContentSpec(((int[]) contentSpec.value)[0],
2119: contentSpec);
2120: str.append('(');
2121: appendContentSpec(contentSpec, str, true,
2122: this ContentSpec);
2123: str.append(')');
2124: } else {
2125: getContentSpec(((int[]) contentSpec.value)[0],
2126: contentSpec);
2127: appendContentSpec(contentSpec, str, true,
2128: this ContentSpec);
2129: }
2130: str.append('?');
2131: break;
2132: }
2133: case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
2134: if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE
2135: || parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
2136: || parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) {
2137: getContentSpec(((int[]) contentSpec.value)[0],
2138: contentSpec);
2139: str.append('(');
2140: appendContentSpec(contentSpec, str, true,
2141: this ContentSpec);
2142: str.append(')');
2143: } else {
2144: getContentSpec(((int[]) contentSpec.value)[0],
2145: contentSpec);
2146: appendContentSpec(contentSpec, str, true,
2147: this ContentSpec);
2148: }
2149: str.append('*');
2150: break;
2151: }
2152: case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
2153: if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE
2154: || parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
2155: || parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) {
2156:
2157: str.append('(');
2158: getContentSpec(((int[]) contentSpec.value)[0],
2159: contentSpec);
2160: appendContentSpec(contentSpec, str, true,
2161: this ContentSpec);
2162: str.append(')');
2163: } else {
2164: getContentSpec(((int[]) contentSpec.value)[0],
2165: contentSpec);
2166: appendContentSpec(contentSpec, str, true,
2167: this ContentSpec);
2168: }
2169: str.append('+');
2170: break;
2171: }
2172: case XMLContentSpec.CONTENTSPECNODE_CHOICE:
2173: case XMLContentSpec.CONTENTSPECNODE_SEQ: {
2174: if (parens) {
2175: str.append('(');
2176: }
2177: int type = contentSpec.type;
2178: int otherValue = ((int[]) contentSpec.otherValue)[0];
2179: getContentSpec(((int[]) contentSpec.value)[0], contentSpec);
2180: appendContentSpec(contentSpec, str,
2181: contentSpec.type != type, this ContentSpec);
2182: if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) {
2183: str.append('|');
2184: } else {
2185: str.append(',');
2186: }
2187: getContentSpec(otherValue, contentSpec);
2188: appendContentSpec(contentSpec, str, true, this ContentSpec);
2189: if (parens) {
2190: str.append(')');
2191: }
2192: break;
2193: }
2194: case XMLContentSpec.CONTENTSPECNODE_ANY: {
2195: str.append("##any");
2196: if (contentSpec.otherValue != null) {
2197: str.append(":uri=");
2198: str.append(contentSpec.otherValue);
2199: }
2200: break;
2201: }
2202: case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: {
2203: str.append("##other:uri=");
2204: str.append(contentSpec.otherValue);
2205: break;
2206: }
2207: case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: {
2208: str.append("##local");
2209: break;
2210: }
2211: default: {
2212: str.append("???");
2213: break;
2214: }
2215:
2216: } // switch type
2217:
2218: } // appendContentSpec(XMLContentSpec.Provider,StringPool,XMLContentSpec,StringBuffer,boolean)
2219:
2220: // debugging
2221:
2222: private void printAttribute(int attributeDeclIndex) {
2223:
2224: XMLAttributeDecl attributeDecl = new XMLAttributeDecl();
2225: if (getAttributeDecl(attributeDeclIndex, attributeDecl)) {
2226: System.out.print(" { ");
2227: System.out.print(attributeDecl.name.localpart);
2228: System.out.print(" }");
2229: }
2230:
2231: } // printAttribute(int)
2232:
2233: // content models
2234:
2235: /**
2236: * When the element has a 'CHILDREN' model, this method is called to
2237: * create the content model object. It looks for some special case simple
2238: * models and creates SimpleContentModel objects for those. For the rest
2239: * it creates the standard DFA style model.
2240: */
2241: private synchronized ContentModelValidator createChildModel(
2242: int contentSpecIndex) {
2243:
2244: //
2245: // Get the content spec node for the element we are working on.
2246: // This will tell us what kind of node it is, which tells us what
2247: // kind of model we will try to create.
2248: //
2249: XMLContentSpec contentSpec = new XMLContentSpec();
2250: getContentSpec(contentSpecIndex, contentSpec);
2251:
2252: if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY
2253: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER
2254: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
2255: // let fall through to build a DFAContentModel
2256: }
2257:
2258: else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2259: //
2260: // Check that the left value is not -1, since any content model
2261: // with PCDATA should be MIXED, so we should not have gotten here.
2262: //
2263: if (contentSpec.value == null
2264: && contentSpec.otherValue == null)
2265: throw new RuntimeException(
2266: "ImplementationMessages.VAL_NPCD");
2267:
2268: //
2269: // Its a single leaf, so its an 'a' type of content model, i.e.
2270: // just one instance of one element. That one is definitely a
2271: // simple content model.
2272: //
2273:
2274: fQName.setValues(null, (String) contentSpec.value,
2275: (String) contentSpec.value,
2276: (String) contentSpec.otherValue);
2277: return new SimpleContentModel(contentSpec.type, fQName,
2278: null);
2279: } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
2280: || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
2281: //
2282: // Lets see if both of the children are leafs. If so, then it
2283: // it has to be a simple content model
2284: //
2285: XMLContentSpec contentSpecLeft = new XMLContentSpec();
2286: XMLContentSpec contentSpecRight = new XMLContentSpec();
2287:
2288: getContentSpec(((int[]) contentSpec.value)[0],
2289: contentSpecLeft);
2290: getContentSpec(((int[]) contentSpec.otherValue)[0],
2291: contentSpecRight);
2292:
2293: if ((contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
2294: && (contentSpecRight.type == XMLContentSpec.CONTENTSPECNODE_LEAF)) {
2295: //
2296: // Its a simple choice or sequence, so we can do a simple
2297: // content model for it.
2298: //
2299: fQName.setValues(null, (String) contentSpecLeft.value,
2300: (String) contentSpecLeft.value,
2301: (String) contentSpecLeft.otherValue);
2302: fQName2.setValues(null,
2303: (String) contentSpecRight.value,
2304: (String) contentSpecRight.value,
2305: (String) contentSpecRight.otherValue);
2306: return new SimpleContentModel(contentSpec.type, fQName,
2307: fQName2);
2308: }
2309: } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE)
2310: || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE)
2311: || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE)) {
2312: //
2313: // Its a repetition, so see if its one child is a leaf. If so
2314: // its a repetition of a single element, so we can do a simple
2315: // content model for that.
2316: //
2317: XMLContentSpec contentSpecLeft = new XMLContentSpec();
2318: getContentSpec(((int[]) contentSpec.value)[0],
2319: contentSpecLeft);
2320:
2321: if (contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2322: //
2323: // It is, so we can create a simple content model here that
2324: // will check for this repetition. We pass -1 for the unused
2325: // right node.
2326: //
2327: fQName.setValues(null, (String) contentSpecLeft.value,
2328: (String) contentSpecLeft.value,
2329: (String) contentSpecLeft.otherValue);
2330: return new SimpleContentModel(contentSpec.type, fQName,
2331: null);
2332: }
2333: } else {
2334: throw new RuntimeException("ImplementationMessages.VAL_CST");
2335: }
2336:
2337: //
2338: // Its not a simple content model, so here we have to create a DFA
2339: // for this element. So we create a DFAContentModel object. He
2340: // encapsulates all of the work to create the DFA.
2341: //
2342:
2343: fLeafCount = 0;
2344: //int leafCount = countLeaves(contentSpecIndex);
2345: fLeafCount = 0;
2346: CMNode cmn = buildSyntaxTree(contentSpecIndex, contentSpec);
2347:
2348: // REVISIT: has to be fLeafCount because we convert x+ to x,x*, one more leaf
2349: return new DFAContentModel(cmn, fLeafCount, false);
2350:
2351: } // createChildModel(int):ContentModelValidator
2352:
2353: private final CMNode buildSyntaxTree(int startNode,
2354: XMLContentSpec contentSpec) {
2355:
2356: // We will build a node at this level for the new tree
2357: CMNode nodeRet = null;
2358: getContentSpec(startNode, contentSpec);
2359: if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY) {
2360: //nodeRet = new CMAny(contentSpec.type, -1, fLeafCount++);
2361: nodeRet = new CMAny(contentSpec.type,
2362: (String) contentSpec.otherValue, fLeafCount++);
2363: } else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
2364: nodeRet = new CMAny(contentSpec.type,
2365: (String) contentSpec.otherValue, fLeafCount++);
2366: } else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
2367: nodeRet = new CMAny(contentSpec.type, null, fLeafCount++);
2368: }
2369: //
2370: // If this node is a leaf, then its an easy one. We just add it
2371: // to the tree.
2372: //
2373: else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2374: //
2375: // Create a new leaf node, and pass it the current leaf count,
2376: // which is its DFA state position. Bump the leaf count after
2377: // storing it. This makes the positions zero based since we
2378: // store first and then increment.
2379: //
2380: fQName.setValues(null, (String) contentSpec.value,
2381: (String) contentSpec.value,
2382: (String) contentSpec.otherValue);
2383: nodeRet = new CMLeaf(fQName, fLeafCount++);
2384: } else {
2385: //
2386: // Its not a leaf, so we have to recurse its left and maybe right
2387: // nodes. Save both values before we recurse and trash the node.
2388: final int leftNode = ((int[]) contentSpec.value)[0];
2389: final int rightNode = ((int[]) contentSpec.otherValue)[0];
2390:
2391: if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
2392: || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
2393: //
2394: // Recurse on both children, and return a binary op node
2395: // with the two created sub nodes as its children. The node
2396: // type is the same type as the source.
2397: //
2398:
2399: nodeRet = new CMBinOp(contentSpec.type,
2400: buildSyntaxTree(leftNode, contentSpec),
2401: buildSyntaxTree(rightNode, contentSpec));
2402: } else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) {
2403: nodeRet = new CMUniOp(contentSpec.type,
2404: buildSyntaxTree(leftNode, contentSpec));
2405: } else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
2406: || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE
2407: || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
2408: nodeRet = new CMUniOp(contentSpec.type,
2409: buildSyntaxTree(leftNode, contentSpec));
2410: } else {
2411: throw new RuntimeException(
2412: "ImplementationMessages.VAL_CST");
2413: }
2414: }
2415: // And return our new node for this level
2416: return nodeRet;
2417: }
2418:
2419: /**
2420: * Build a vector of valid QNames from Content Spec
2421: * table.
2422: *
2423: * @param contentSpecIndex
2424: * Content Spec index
2425: * @param vectorQName
2426: * Array of QName
2427: * @exception RuntimeException
2428: */
2429: private void contentSpecTree(int contentSpecIndex,
2430: XMLContentSpec contentSpec, ChildrenList children) {
2431:
2432: // Handle any and leaf nodes
2433: getContentSpec(contentSpecIndex, contentSpec);
2434: if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF
2435: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY
2436: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL
2437: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
2438:
2439: // resize arrays, if needed
2440: if (children.length == children.qname.length) {
2441: QName[] newQName = new QName[children.length * 2];
2442: System.arraycopy(children.qname, 0, newQName, 0,
2443: children.length);
2444: children.qname = newQName;
2445: int[] newType = new int[children.length * 2];
2446: System.arraycopy(children.type, 0, newType, 0,
2447: children.length);
2448: children.type = newType;
2449: }
2450:
2451: // save values and return length
2452: children.qname[children.length] = new QName(null,
2453: (String) contentSpec.value,
2454: (String) contentSpec.value,
2455: (String) contentSpec.otherValue);
2456: children.type[children.length] = contentSpec.type;
2457: children.length++;
2458: return;
2459: }
2460:
2461: //
2462: // Its not a leaf, so we have to recurse its left and maybe right
2463: // nodes. Save both values before we recurse and trash the node.
2464: //
2465: final int leftNode = contentSpec.value != null ? ((int[]) (contentSpec.value))[0]
2466: : -1;
2467: int rightNode = -1;
2468: if (contentSpec.otherValue != null)
2469: rightNode = ((int[]) (contentSpec.otherValue))[0];
2470: else
2471: return;
2472:
2473: if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE
2474: || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
2475: contentSpecTree(leftNode, contentSpec, children);
2476: contentSpecTree(rightNode, contentSpec, children);
2477: return;
2478: }
2479:
2480: if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE
2481: || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
2482: || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
2483: contentSpecTree(leftNode, contentSpec, children);
2484: return;
2485: }
2486:
2487: // error
2488: throw new RuntimeException(
2489: "Invalid content spec type seen in contentSpecTree() method of AbstractDTDGrammar class : "
2490: + contentSpec.type);
2491:
2492: } // contentSpecTree(int,XMLContentSpec,ChildrenList)
2493:
2494: // ensure capacity
2495:
2496: private void ensureElementDeclCapacity(int chunk) {
2497: if (chunk >= fElementDeclName.length) {
2498: fElementDeclIsExternal = resize(fElementDeclIsExternal,
2499: fElementDeclIsExternal.length * 2);
2500:
2501: fElementDeclName = resize(fElementDeclName,
2502: fElementDeclName.length * 2);
2503: fElementDeclType = resize(fElementDeclType,
2504: fElementDeclType.length * 2);
2505: fElementDeclContentModelValidator = resize(
2506: fElementDeclContentModelValidator,
2507: fElementDeclContentModelValidator.length * 2);
2508: fElementDeclContentSpecIndex = resize(
2509: fElementDeclContentSpecIndex,
2510: fElementDeclContentSpecIndex.length * 2);
2511: fElementDeclFirstAttributeDeclIndex = resize(
2512: fElementDeclFirstAttributeDeclIndex,
2513: fElementDeclFirstAttributeDeclIndex.length * 2);
2514: fElementDeclLastAttributeDeclIndex = resize(
2515: fElementDeclLastAttributeDeclIndex,
2516: fElementDeclLastAttributeDeclIndex.length * 2);
2517: } else if (fElementDeclName[chunk] != null) {
2518: return;
2519: }
2520:
2521: fElementDeclIsExternal[chunk] = new int[CHUNK_SIZE];
2522: fElementDeclName[chunk] = new QName[CHUNK_SIZE];
2523: fElementDeclType[chunk] = new short[CHUNK_SIZE];
2524: fElementDeclContentModelValidator[chunk] = new ContentModelValidator[CHUNK_SIZE];
2525: fElementDeclContentSpecIndex[chunk] = new int[CHUNK_SIZE];
2526: fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2527: fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2528: return;
2529: }
2530:
2531: private void ensureAttributeDeclCapacity(int chunk) {
2532:
2533: if (chunk >= fAttributeDeclName.length) {
2534: fAttributeDeclIsExternal = resize(fAttributeDeclIsExternal,
2535: fAttributeDeclIsExternal.length * 2);
2536: fAttributeDeclName = resize(fAttributeDeclName,
2537: fAttributeDeclName.length * 2);
2538: fAttributeDeclType = resize(fAttributeDeclType,
2539: fAttributeDeclType.length * 2);
2540: fAttributeDeclEnumeration = resize(
2541: fAttributeDeclEnumeration,
2542: fAttributeDeclEnumeration.length * 2);
2543: fAttributeDeclDefaultType = resize(
2544: fAttributeDeclDefaultType,
2545: fAttributeDeclDefaultType.length * 2);
2546: fAttributeDeclDatatypeValidator = resize(
2547: fAttributeDeclDatatypeValidator,
2548: fAttributeDeclDatatypeValidator.length * 2);
2549: fAttributeDeclDefaultValue = resize(
2550: fAttributeDeclDefaultValue,
2551: fAttributeDeclDefaultValue.length * 2);
2552: fAttributeDeclNonNormalizedDefaultValue = resize(
2553: fAttributeDeclNonNormalizedDefaultValue,
2554: fAttributeDeclNonNormalizedDefaultValue.length * 2);
2555: fAttributeDeclNextAttributeDeclIndex = resize(
2556: fAttributeDeclNextAttributeDeclIndex,
2557: fAttributeDeclNextAttributeDeclIndex.length * 2);
2558: } else if (fAttributeDeclName[chunk] != null) {
2559: return;
2560: }
2561:
2562: fAttributeDeclIsExternal[chunk] = new int[CHUNK_SIZE];
2563: fAttributeDeclName[chunk] = new QName[CHUNK_SIZE];
2564: fAttributeDeclType[chunk] = new short[CHUNK_SIZE];
2565: fAttributeDeclEnumeration[chunk] = new String[CHUNK_SIZE][];
2566: fAttributeDeclDefaultType[chunk] = new short[CHUNK_SIZE];
2567: fAttributeDeclDatatypeValidator[chunk] = new DatatypeValidator[CHUNK_SIZE];
2568: fAttributeDeclDefaultValue[chunk] = new String[CHUNK_SIZE];
2569: fAttributeDeclNonNormalizedDefaultValue[chunk] = new String[CHUNK_SIZE];
2570: fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
2571: return;
2572: }
2573:
2574: private void ensureEntityDeclCapacity(int chunk) {
2575: if (chunk >= fEntityName.length) {
2576: fEntityName = resize(fEntityName, fEntityName.length * 2);
2577: fEntityValue = resize(fEntityValue, fEntityValue.length * 2);
2578: fEntityPublicId = resize(fEntityPublicId,
2579: fEntityPublicId.length * 2);
2580: fEntitySystemId = resize(fEntitySystemId,
2581: fEntitySystemId.length * 2);
2582: fEntityBaseSystemId = resize(fEntityBaseSystemId,
2583: fEntityBaseSystemId.length * 2);
2584: fEntityNotation = resize(fEntityNotation,
2585: fEntityNotation.length * 2);
2586: fEntityIsPE = resize(fEntityIsPE, fEntityIsPE.length * 2);
2587: fEntityInExternal = resize(fEntityInExternal,
2588: fEntityInExternal.length * 2);
2589: } else if (fEntityName[chunk] != null) {
2590: return;
2591: }
2592:
2593: fEntityName[chunk] = new String[CHUNK_SIZE];
2594: fEntityValue[chunk] = new String[CHUNK_SIZE];
2595: fEntityPublicId[chunk] = new String[CHUNK_SIZE];
2596: fEntitySystemId[chunk] = new String[CHUNK_SIZE];
2597: fEntityBaseSystemId[chunk] = new String[CHUNK_SIZE];
2598: fEntityNotation[chunk] = new String[CHUNK_SIZE];
2599: fEntityIsPE[chunk] = new byte[CHUNK_SIZE];
2600: fEntityInExternal[chunk] = new byte[CHUNK_SIZE];
2601: return;
2602: }
2603:
2604: private void ensureNotationDeclCapacity(int chunk) {
2605: if (chunk >= fNotationName.length) {
2606: fNotationName = resize(fNotationName,
2607: fNotationName.length * 2);
2608: fNotationPublicId = resize(fNotationPublicId,
2609: fNotationPublicId.length * 2);
2610: fNotationSystemId = resize(fNotationSystemId,
2611: fNotationSystemId.length * 2);
2612: fNotationBaseSystemId = resize(fNotationBaseSystemId,
2613: fNotationBaseSystemId.length * 2);
2614: } else if (fNotationName[chunk] != null) {
2615: return;
2616: }
2617:
2618: fNotationName[chunk] = new String[CHUNK_SIZE];
2619: fNotationPublicId[chunk] = new String[CHUNK_SIZE];
2620: fNotationSystemId[chunk] = new String[CHUNK_SIZE];
2621: fNotationBaseSystemId[chunk] = new String[CHUNK_SIZE];
2622: return;
2623: }
2624:
2625: private void ensureContentSpecCapacity(int chunk) {
2626: if (chunk >= fContentSpecType.length) {
2627: fContentSpecType = resize(fContentSpecType,
2628: fContentSpecType.length * 2);
2629: fContentSpecValue = resize(fContentSpecValue,
2630: fContentSpecValue.length * 2);
2631: fContentSpecOtherValue = resize(fContentSpecOtherValue,
2632: fContentSpecOtherValue.length * 2);
2633: } else if (fContentSpecType[chunk] != null) {
2634: return;
2635: }
2636:
2637: fContentSpecType[chunk] = new short[CHUNK_SIZE];
2638: fContentSpecValue[chunk] = new Object[CHUNK_SIZE];
2639: fContentSpecOtherValue[chunk] = new Object[CHUNK_SIZE];
2640: return;
2641: }
2642:
2643: //
2644: // Private static methods
2645: //
2646:
2647: // resize chunks
2648:
2649: private static byte[][] resize(byte array[][], int newsize) {
2650: byte newarray[][] = new byte[newsize][];
2651: System.arraycopy(array, 0, newarray, 0, array.length);
2652: return newarray;
2653: }
2654:
2655: private static short[][] resize(short array[][], int newsize) {
2656: short newarray[][] = new short[newsize][];
2657: System.arraycopy(array, 0, newarray, 0, array.length);
2658: return newarray;
2659: }
2660:
2661: private static int[][] resize(int array[][], int newsize) {
2662: int newarray[][] = new int[newsize][];
2663: System.arraycopy(array, 0, newarray, 0, array.length);
2664: return newarray;
2665: }
2666:
2667: private static DatatypeValidator[][] resize(
2668: DatatypeValidator array[][], int newsize) {
2669: DatatypeValidator newarray[][] = new DatatypeValidator[newsize][];
2670: System.arraycopy(array, 0, newarray, 0, array.length);
2671: return newarray;
2672: }
2673:
2674: private static ContentModelValidator[][] resize(
2675: ContentModelValidator array[][], int newsize) {
2676: ContentModelValidator newarray[][] = new ContentModelValidator[newsize][];
2677: System.arraycopy(array, 0, newarray, 0, array.length);
2678: return newarray;
2679: }
2680:
2681: private static Object[][] resize(Object array[][], int newsize) {
2682: Object newarray[][] = new Object[newsize][];
2683: System.arraycopy(array, 0, newarray, 0, array.length);
2684: return newarray;
2685: }
2686:
2687: private static QName[][] resize(QName array[][], int newsize) {
2688: QName newarray[][] = new QName[newsize][];
2689: System.arraycopy(array, 0, newarray, 0, array.length);
2690: return newarray;
2691: }
2692:
2693: private static String[][] resize(String array[][], int newsize) {
2694: String newarray[][] = new String[newsize][];
2695: System.arraycopy(array, 0, newarray, 0, array.length);
2696: return newarray;
2697: }
2698:
2699: private static String[][][] resize(String array[][][], int newsize) {
2700: String newarray[][][] = new String[newsize][][];
2701: System.arraycopy(array, 0, newarray, 0, array.length);
2702: return newarray;
2703: }
2704:
2705: //
2706: // Classes
2707: //
2708:
2709: /**
2710: * Children list for <code>contentSpecTree</code> method.
2711: *
2712: * @xerces.internal
2713: *
2714: * @author Eric Ye, IBM
2715: */
2716: private static class ChildrenList {
2717:
2718: //
2719: // Data
2720: //
2721:
2722: /** Length. */
2723: public int length = 0;
2724:
2725: // NOTE: The following set of data is mutually exclusive. It is
2726: // written this way because Java doesn't have a native
2727: // union data structure. -Ac
2728:
2729: /** Left and right children names. */
2730: public QName[] qname = new QName[2];
2731:
2732: /** Left and right children types. */
2733: public int[] type = new int[2];
2734:
2735: //
2736: // Constructors
2737: //
2738:
2739: public ChildrenList() {
2740: }
2741:
2742: } // class ChildrenList
2743:
2744: //
2745: // Classes
2746: //
2747:
2748: /**
2749: * A simple Hashtable implementation that takes a tuple (String, String)
2750: * as the key and a int as value.
2751: *
2752: * @xerces.internal
2753: *
2754: * @author Eric Ye, IBM
2755: * @author Andy Clark, IBM
2756: */
2757: protected static final class QNameHashtable {
2758:
2759: //
2760: // Constants
2761: //
2762:
2763: /** Initial bucket size (4). */
2764: private static final int INITIAL_BUCKET_SIZE = 4;
2765:
2766: // NOTE: Changed previous hashtable size from 512 to 101 so
2767: // that we get a better distribution for hashing. -Ac
2768: /** Hashtable size (101). */
2769: private static final int HASHTABLE_SIZE = 101;
2770:
2771: //
2772: // Data
2773: //
2774: private Object[][] fHashTable = new Object[HASHTABLE_SIZE][];
2775:
2776: //
2777: // Public methods
2778: //
2779: /** Associates the given value with the specified key tuple. */
2780: public void put(String key, int value) {
2781:
2782: int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE;
2783: Object[] bucket = fHashTable[hash];
2784:
2785: if (bucket == null) {
2786: bucket = new Object[1 + 2 * INITIAL_BUCKET_SIZE];
2787: bucket[0] = new int[] { 1 };
2788: bucket[1] = key;
2789: bucket[2] = new int[] { value };
2790: fHashTable[hash] = bucket;
2791: } else {
2792: int count = ((int[]) bucket[0])[0];
2793: int offset = 1 + 2 * count;
2794: if (offset == bucket.length) {
2795: int newSize = count + INITIAL_BUCKET_SIZE;
2796: Object[] newBucket = new Object[1 + 2 * newSize];
2797: System.arraycopy(bucket, 0, newBucket, 0, offset);
2798: bucket = newBucket;
2799: fHashTable[hash] = bucket;
2800: }
2801: boolean found = false;
2802: int j = 1;
2803: for (int i = 0; i < count; i++) {
2804: if ((String) bucket[j] == key) {
2805: ((int[]) bucket[j + 1])[0] = value;
2806: found = true;
2807: break;
2808: }
2809: j += 2;
2810: }
2811: if (!found) {
2812: bucket[offset++] = key;
2813: bucket[offset] = new int[] { value };
2814: ((int[]) bucket[0])[0] = ++count;
2815: }
2816:
2817: }
2818: //System.out.println("put("+key+" -> "+value+')');
2819: //System.out.println("get("+key+") -> "+get(key));
2820:
2821: } // put(int,String,String,int)
2822:
2823: /** Returns the value associated with the specified key tuple. */
2824: public int get(String key) {
2825: int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE;
2826: Object[] bucket = fHashTable[hash];
2827:
2828: if (bucket == null) {
2829: return -1;
2830: }
2831: int count = ((int[]) bucket[0])[0];
2832:
2833: int j = 1;
2834: for (int i = 0; i < count; i++) {
2835: if ((String) bucket[j] == key) {
2836: return ((int[]) bucket[j + 1])[0];
2837: }
2838: j += 2;
2839: }
2840: return -1;
2841:
2842: } // get(int,String,String)
2843:
2844: } // class QNameHashtable
2845:
2846: //
2847: // EntityState methods
2848: //
2849: public boolean isEntityDeclared(String name) {
2850: return (getEntityDeclIndex(name) != -1) ? true : false;
2851: }
2852:
2853: public boolean isEntityUnparsed(String name) {
2854: int entityIndex = getEntityDeclIndex(name);
2855: if (entityIndex > -1) {
2856: int chunk = entityIndex >> CHUNK_SHIFT;
2857: int index = entityIndex & CHUNK_MASK;
2858: //for unparsed entity notation!=null
2859: return (fEntityNotation[chunk][index] != null) ? true
2860: : false;
2861: }
2862: return false;
2863: }
2864: } // class DTDGrammar
|