0001: /*
0002: * The Apache Software License, Version 1.1
0003: *
0004: *
0005: * Copyright (c) 2000 The Apache Software Foundation. All rights
0006: * reserved.
0007: *
0008: * Redistribution and use in source and binary forms, with or without
0009: * modification, are permitted provided that the following conditions
0010: * are met:
0011: *
0012: * 1. Redistributions of source code must retain the above copyright
0013: * notice, this list of conditions and the following disclaimer.
0014: *
0015: * 2. Redistributions in binary form must reproduce the above copyright
0016: * notice, this list of conditions and the following disclaimer in
0017: * the documentation and/or other materials provided with the
0018: * distribution.
0019: *
0020: * 3. The end-user documentation included with the redistribution,
0021: * if any, must include the following acknowledgment:
0022: * "This product includes software developed by the
0023: * Apache Software Foundation (http://www.apache.org/)."
0024: * Alternately, this acknowledgment may appear in the software itself,
0025: * if and wherever such third-party acknowledgments normally appear.
0026: *
0027: * 4. The names "Xerces" and "Apache Software Foundation" must
0028: * not be used to endorse or promote products derived from this
0029: * software without prior written permission. For written
0030: * permission, please contact apache@apache.org.
0031: *
0032: * 5. Products derived from this software may not be called "Apache",
0033: * nor may "Apache" appear in their name, without prior written
0034: * permission of the Apache Software Foundation.
0035: *
0036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0039: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0040: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0047: * SUCH DAMAGE.
0048: * ====================================================================
0049: *
0050: * This software consists of voluntary contributions made by many
0051: * individuals on behalf of the Apache Software Foundation and was
0052: * originally based on software copyright (c) 1999, International
0053: * Business Machines, Inc., http://www.apache.org. For more
0054: * information on the Apache Software Foundation, please see
0055: * <http://www.apache.org/>.
0056: */
0057:
0058: package org.apache.xerces.validators.common;
0059:
0060: import org.apache.xerces.framework.XMLContentSpec;
0061: import org.apache.xerces.utils.Hash2intTable;
0062: import org.apache.xerces.utils.QName;
0063: import org.apache.xerces.utils.StringPool;
0064: import org.apache.xerces.validators.datatype.DatatypeValidator;
0065: import org.apache.xerces.validators.common.XMLContentModel;
0066: import org.apache.xerces.validators.common.CMException;
0067: import org.apache.xerces.validators.schema.identity.IdentityConstraint;
0068: import org.apache.xerces.utils.ImplementationMessages;
0069: import org.w3c.dom.Document;
0070: import java.util.Vector;
0071: import org.apache.xerces.validators.schema.SubstitutionGroupComparator;
0072:
0073: /**
0074: * @version $Id: Grammar.java,v 1.30 2001/08/10 13:18:09 sandygao Exp $
0075: */
0076: public class Grammar implements XMLContentSpec.Provider {
0077:
0078: //
0079: // Constants
0080: //
0081:
0082: /** Signifies top level scope (-1). */
0083: public static final int TOP_LEVEL_SCOPE = -1;
0084:
0085: private static final int CHUNK_SHIFT = 8; // 2^8 = 256
0086: private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
0087: private static final int CHUNK_MASK = CHUNK_SIZE - 1;
0088: private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k
0089:
0090: private static final int LIST_FLAG = 0x8000;
0091: private static final int LIST_MASK = ~LIST_FLAG;
0092:
0093: //
0094: // Data
0095: //
0096:
0097: // basic information
0098:
0099: private int fTargetNamespace;
0100:
0101: private Document fGrammarDocument;
0102:
0103: // element decl tables
0104:
0105: private int fElementDeclCount = 0;
0106: private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
0107: private int fElementDeclType[][] = new int[INITIAL_CHUNK_COUNT][];
0108: private DatatypeValidator fElementDeclDatatypeValidator[][] = new DatatypeValidator[INITIAL_CHUNK_COUNT][];
0109: private int fElementDeclContentSpecIndex[][] = new int[INITIAL_CHUNK_COUNT][];
0110: private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
0111: private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
0112: private Vector fElementDeclUnique[][] = new Vector[INITIAL_CHUNK_COUNT][];
0113: private Vector fElementDeclKey[][] = new Vector[INITIAL_CHUNK_COUNT][];
0114: private Vector fElementDeclKeyRef[][] = new Vector[INITIAL_CHUNK_COUNT][];
0115:
0116: // content spec tables
0117:
0118: private int fContentSpecCount = 0;
0119: private int fContentSpecType[][] = new int[INITIAL_CHUNK_COUNT][];
0120: private int fContentSpecValue[][] = new int[INITIAL_CHUNK_COUNT][];
0121: private int fContentSpecOtherValue[][] = new int[INITIAL_CHUNK_COUNT][];
0122: private XMLContentModel fContentSpecValidator[][] = new XMLContentModel[INITIAL_CHUNK_COUNT][];
0123:
0124: // attribute decl tables
0125:
0126: private int fAttributeDeclCount = 0;
0127: private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
0128: private int fAttributeDeclType[][] = new int[INITIAL_CHUNK_COUNT][];
0129: private int fAttributeDeclEnumeration[][] = new int[INITIAL_CHUNK_COUNT][];
0130: private int fAttributeDeclDefaultType[][] = new int[INITIAL_CHUNK_COUNT][];
0131: private DatatypeValidator fAttributeDeclDatatypeValidator[][] = new DatatypeValidator[INITIAL_CHUNK_COUNT][];
0132: private String fAttributeDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
0133: private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
0134:
0135: // scope mapping tables
0136:
0137: private Hash2intTable fElementNameAndScopeToElementDeclIndexMapping = new Hash2intTable();
0138:
0139: // temp vars
0140:
0141: private QName fQName1 = new QName();
0142: private QName fQName2 = new QName();
0143:
0144: //
0145: // Public methods
0146: //
0147:
0148: public Document getGrammarDocument() {
0149: return fGrammarDocument;
0150: }
0151:
0152: public int getElementDeclIndex(int localpartIndex, int scopeIndex) {
0153: if (localpartIndex > -1 && scopeIndex > -2) {
0154: return fElementNameAndScopeToElementDeclIndexMapping
0155: .get(StringPool.EMPTY_STRING, localpartIndex,
0156: scopeIndex);
0157: }
0158: return -1;
0159: }
0160:
0161: public int getElementDeclIndex(int uriIndex, int localpartIndex,
0162: int scopeIndex) {
0163: if (localpartIndex > -1 && scopeIndex > -2) {
0164: return fElementNameAndScopeToElementDeclIndexMapping.get(
0165: uriIndex, localpartIndex, scopeIndex);
0166: }
0167: return -1;
0168: }
0169:
0170: public int getElementDeclIndex(QName element, int scopeIndex) {
0171: if (element.localpart > -1 && scopeIndex > -2) {
0172: return fElementNameAndScopeToElementDeclIndexMapping.get(
0173: element.uri, element.localpart, scopeIndex);
0174: }
0175: return -1;
0176: }
0177:
0178: public boolean getElementDecl(int elementDeclIndex,
0179: XMLElementDecl elementDecl) {
0180: if (elementDeclIndex < 0
0181: || elementDeclIndex >= fElementDeclCount) {
0182: return false;
0183: }
0184:
0185: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0186: int index = elementDeclIndex & CHUNK_MASK;
0187:
0188: elementDecl.name.setValues(fElementDeclName[chunk][index]);
0189: if (fElementDeclType[chunk][index] == -1) {
0190: elementDecl.type = -1;
0191: elementDecl.list = false;
0192: } else {
0193: elementDecl.type = fElementDeclType[chunk][index]
0194: & LIST_MASK;
0195: elementDecl.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0;
0196: }
0197: elementDecl.datatypeValidator = fElementDeclDatatypeValidator[chunk][index];
0198: elementDecl.contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
0199:
0200: // copy identity constraints
0201: elementDecl.unique.removeAllElements();
0202: int ucount = fElementDeclUnique[chunk][index] != null ? fElementDeclUnique[chunk][index]
0203: .size()
0204: : 0;
0205: for (int i = 0; i < ucount; i++) {
0206: elementDecl.unique
0207: .addElement(fElementDeclUnique[chunk][index]
0208: .elementAt(i));
0209: }
0210: elementDecl.key.removeAllElements();
0211: int kcount = fElementDeclKey[chunk][index] != null ? fElementDeclKey[chunk][index]
0212: .size()
0213: : 0;
0214: for (int i = 0; i < kcount; i++) {
0215: elementDecl.key.addElement(fElementDeclKey[chunk][index]
0216: .elementAt(i));
0217: }
0218: elementDecl.keyRef.removeAllElements();
0219: int krcount = fElementDeclKeyRef[chunk][index] != null ? fElementDeclKeyRef[chunk][index]
0220: .size()
0221: : 0;
0222: for (int i = 0; i < krcount; i++) {
0223: elementDecl.keyRef
0224: .addElement(fElementDeclKeyRef[chunk][index]
0225: .elementAt(i));
0226: }
0227:
0228: return true;
0229: }
0230:
0231: public int getFirstAttributeDeclIndex(int elementDeclIndex) {
0232: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0233: int index = elementDeclIndex & CHUNK_MASK;
0234:
0235: return fElementDeclFirstAttributeDeclIndex[chunk][index];
0236: }
0237:
0238: public int getNextAttributeDeclIndex(int attributeDeclIndex) {
0239: int chunk = attributeDeclIndex >> CHUNK_SHIFT;
0240: int index = attributeDeclIndex & CHUNK_MASK;
0241:
0242: return fAttributeDeclNextAttributeDeclIndex[chunk][index];
0243: }
0244:
0245: public boolean getContentSpec(int contentSpecIndex,
0246: XMLContentSpec contentSpec) {
0247: if (contentSpecIndex < 0
0248: || contentSpecIndex >= fContentSpecCount)
0249: return false;
0250:
0251: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0252: int index = contentSpecIndex & CHUNK_MASK;
0253:
0254: contentSpec.type = fContentSpecType[chunk][index];
0255: contentSpec.value = fContentSpecValue[chunk][index];
0256: contentSpec.otherValue = fContentSpecOtherValue[chunk][index];
0257: return true;
0258: }
0259:
0260: protected void clearContentModel(int contentSpecIndex) {
0261: if (contentSpecIndex < 0
0262: || contentSpecIndex >= fContentSpecCount)
0263: return;
0264:
0265: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0266: int index = contentSpecIndex & CHUNK_MASK;
0267:
0268: fContentSpecValidator[chunk][index] = null;
0269: }
0270:
0271: protected boolean existContentModel(int contentSpecIndex) {
0272: if (contentSpecIndex < 0
0273: || contentSpecIndex >= fContentSpecCount)
0274: return false;
0275:
0276: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0277: int index = contentSpecIndex & CHUNK_MASK;
0278:
0279: return (fContentSpecValidator[chunk][index] != null);
0280: }
0281:
0282: public XMLContentModel getElementContentModel(int elementDeclIndex,
0283: SubstitutionGroupComparator comparator) throws Exception {
0284:
0285: if (elementDeclIndex < 0
0286: || elementDeclIndex >= fElementDeclCount)
0287: return null;
0288:
0289: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0290: int index = elementDeclIndex & CHUNK_MASK;
0291:
0292: int contentType = fElementDeclType[chunk][index];
0293:
0294: return getContentModel(
0295: fElementDeclContentSpecIndex[chunk][index],
0296: contentType, comparator);
0297: }
0298:
0299: public XMLContentModel getContentModel(int contentSpecIndex,
0300: int contentType, SubstitutionGroupComparator comparator)
0301: throws Exception {
0302: if (contentSpecIndex < 0
0303: || contentSpecIndex >= fContentSpecCount)
0304: return null;
0305:
0306: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0307: int index = contentSpecIndex & CHUNK_MASK;
0308:
0309: XMLContentModel contentModel = fContentSpecValidator[chunk][index];
0310:
0311: // If we have one, just return that. Otherwise, gotta create one
0312: if (contentModel != null)
0313: return contentModel;
0314:
0315: if (contentType == XMLElementDecl.TYPE_SIMPLE) {
0316: return null;
0317: }
0318:
0319: // Get the type of content this element has
0320: int expendedIndex = convertContentSpecTree(contentSpecIndex);
0321:
0322: XMLContentSpec contentSpec = new XMLContentSpec();
0323: getContentSpec(expendedIndex, contentSpec);
0324:
0325: // And create the content model according to the spec type
0326:
0327: if (contentType == XMLElementDecl.TYPE_MIXED_SIMPLE) {
0328: //
0329: // just create a mixed content model object. This type of
0330: // content model is optimized for simple mixed content validation.
0331: //
0332:
0333: Vector vQName = new Vector();
0334: ChildrenList children = new ChildrenList();
0335: contentSpecTree(expendedIndex, contentSpec, children);
0336: contentModel = new MixedContentModel(children.qname,
0337: children.type, 0, children.length, false, isDTD());
0338: } else if (contentType == XMLElementDecl.TYPE_MIXED_COMPLEX) {
0339: //
0340: // For Schema, we need a more complex model. Create a child model as
0341: // per the element-only case, unless there are actually no children in
0342: // the model. If that's the case, we can use the Mixed Content Model for
0343: // DTDs.
0344: contentModel = createChildModel(expendedIndex, true);
0345: }
0346:
0347: else if (contentType == XMLElementDecl.TYPE_CHILDREN) {
0348: // This method will create an optimal model for the complexity
0349: // of the element's defined model. If it's simple, it will create
0350: // a SimpleContentModel object. If it's a simple list, it will
0351: // create a SimpleListContentModel object. If it's complex, it
0352: // will create a DFAContentModel object.
0353: //
0354: contentModel = createChildModel(expendedIndex, false);
0355: } else {
0356: throw new CMException(ImplementationMessages.VAL_CST);
0357: }
0358:
0359: // Add the new model to the content model for this element
0360:
0361: fContentSpecValidator[chunk][index] = contentModel;
0362:
0363: //build it ..... in XMLValidator
0364: if (contentModel != null)
0365: contentModel.setSubstitutionGroupComparator(comparator);
0366:
0367: return contentModel;
0368: }
0369:
0370: public boolean getAttributeDecl(int attributeDeclIndex,
0371: XMLAttributeDecl attributeDecl) {
0372: if (attributeDeclIndex < 0
0373: || attributeDeclIndex >= fAttributeDeclCount) {
0374: return false;
0375: }
0376: int chunk = attributeDeclIndex >> CHUNK_SHIFT;
0377: int index = attributeDeclIndex & CHUNK_MASK;
0378:
0379: attributeDecl.name.setValues(fAttributeDeclName[chunk][index]);
0380:
0381: if (fAttributeDeclType[chunk][index] == -1) {
0382:
0383: attributeDecl.type = -1;
0384: attributeDecl.list = false;
0385: } else {
0386: attributeDecl.type = fAttributeDeclType[chunk][index]
0387: & LIST_MASK;
0388: attributeDecl.list = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0;
0389: }
0390: attributeDecl.datatypeValidator = fAttributeDeclDatatypeValidator[chunk][index];
0391: attributeDecl.enumeration = fAttributeDeclEnumeration[chunk][index];
0392: attributeDecl.defaultType = fAttributeDeclDefaultType[chunk][index];
0393: attributeDecl.defaultValue = fAttributeDeclDefaultValue[chunk][index];
0394: return true;
0395: }
0396:
0397: //
0398: // Protected methods
0399: //
0400:
0401: protected void setGrammarDocument(Document grammarDocument) {
0402: fGrammarDocument = grammarDocument;
0403: }
0404:
0405: // SchemaGrammar overrides this and does a conversion
0406: protected int convertContentSpecTree(int index) {
0407: return index;
0408: }
0409:
0410: protected int createElementDecl() {
0411:
0412: int chunk = fElementDeclCount >> CHUNK_SHIFT;
0413: int index = fElementDeclCount & CHUNK_MASK;
0414: ensureElementDeclCapacity(chunk);
0415: fElementDeclName[chunk][index] = new QName();
0416: fElementDeclType[chunk][index] = -1;
0417: fElementDeclDatatypeValidator[chunk][index] = null;
0418: fElementDeclContentSpecIndex[chunk][index] = -1;
0419: fElementDeclFirstAttributeDeclIndex[chunk][index] = -1;
0420: fElementDeclLastAttributeDeclIndex[chunk][index] = -1;
0421: return fElementDeclCount++;
0422: }
0423:
0424: protected void setElementDecl(int elementDeclIndex,
0425: XMLElementDecl elementDecl) {
0426:
0427: if (elementDeclIndex < 0
0428: || elementDeclIndex >= fElementDeclCount) {
0429: return;
0430: }
0431: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0432: int index = elementDeclIndex & CHUNK_MASK;
0433:
0434: fElementDeclName[chunk][index].setValues(elementDecl.name);
0435: fElementDeclType[chunk][index] = elementDecl.type;
0436: if (elementDecl.list) {
0437: fElementDeclType[chunk][index] |= LIST_FLAG;
0438: }
0439: fElementDeclDatatypeValidator[chunk][index] = elementDecl.datatypeValidator;
0440: fElementDeclContentSpecIndex[chunk][index] = elementDecl.contentSpecIndex;
0441:
0442: // copy identity constraints
0443: int ucount = elementDecl.unique.size();
0444: if (ucount > 0) {
0445: if (fElementDeclUnique[chunk][index] == null) {
0446: fElementDeclUnique[chunk][index] = (Vector) elementDecl.unique
0447: .clone();
0448: } else {
0449: fElementDeclUnique[chunk][index].removeAllElements();
0450: for (int i = 0; i < ucount; i++) {
0451: fElementDeclUnique[chunk][index]
0452: .addElement(elementDecl.unique.elementAt(i));
0453: }
0454: }
0455: }
0456: int kcount = elementDecl.key.size();
0457: if (kcount > 0) {
0458: if (fElementDeclKey[chunk][index] == null) {
0459: fElementDeclKey[chunk][index] = (Vector) elementDecl.key
0460: .clone();
0461: } else {
0462: fElementDeclKey[chunk][index].removeAllElements();
0463: for (int i = 0; i < kcount; i++) {
0464: fElementDeclKey[chunk][index]
0465: .addElement(elementDecl.key.elementAt(i));
0466: }
0467: }
0468: }
0469: int krcount = elementDecl.keyRef.size();
0470: if (krcount > 0) {
0471: if (fElementDeclKeyRef[chunk][index] == null) {
0472: fElementDeclKeyRef[chunk][index] = (Vector) elementDecl.keyRef
0473: .clone();
0474: } else {
0475: fElementDeclKeyRef[chunk][index].removeAllElements();
0476: for (int i = 0; i < krcount; i++) {
0477: fElementDeclKeyRef[chunk][index]
0478: .addElement(elementDecl.keyRef.elementAt(i));
0479: }
0480: }
0481: }
0482:
0483: // add the mapping information to the
0484: putElementNameMapping(elementDecl.name,
0485: elementDecl.enclosingScope, elementDeclIndex);
0486: }
0487:
0488: protected void putElementNameMapping(QName name, int scope,
0489: int elementDeclIndex) {
0490: fElementNameAndScopeToElementDeclIndexMapping.put(name.uri,
0491: name.localpart, scope, elementDeclIndex);
0492: }
0493:
0494: protected void setFirstAttributeDeclIndex(int elementDeclIndex,
0495: int newFirstAttrIndex) {
0496:
0497: if (elementDeclIndex < 0
0498: || elementDeclIndex >= fElementDeclCount) {
0499: return;
0500: }
0501:
0502: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0503: int index = elementDeclIndex & CHUNK_MASK;
0504:
0505: fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex;
0506: if (fElementDeclLastAttributeDeclIndex[chunk][index] == -1)
0507: fElementDeclLastAttributeDeclIndex[chunk][index] = newFirstAttrIndex;
0508: }
0509:
0510: protected int createContentSpec() {
0511: int chunk = fContentSpecCount >> CHUNK_SHIFT;
0512: int index = fContentSpecCount & CHUNK_MASK;
0513:
0514: ensureContentSpecCapacity(chunk);
0515: fContentSpecType[chunk][index] = -1;
0516: fContentSpecValue[chunk][index] = -1;
0517: fContentSpecOtherValue[chunk][index] = -1;
0518: fContentSpecValidator[chunk][index] = null;
0519:
0520: return fContentSpecCount++;
0521: }
0522:
0523: protected void setContentSpec(int contentSpecIndex,
0524: XMLContentSpec contentSpec) {
0525: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0526: int index = contentSpecIndex & CHUNK_MASK;
0527:
0528: fContentSpecType[chunk][index] = contentSpec.type;
0529: fContentSpecValue[chunk][index] = contentSpec.value;
0530: fContentSpecOtherValue[chunk][index] = contentSpec.otherValue;
0531: }
0532:
0533: protected int createAttributeDecl() {
0534: int chunk = fAttributeDeclCount >> CHUNK_SHIFT;
0535: int index = fAttributeDeclCount & CHUNK_MASK;
0536:
0537: ensureAttributeDeclCapacity(chunk);
0538: fAttributeDeclName[chunk][index] = new QName();
0539: fAttributeDeclType[chunk][index] = -1;
0540: fAttributeDeclDatatypeValidator[chunk][index] = null;
0541: fAttributeDeclEnumeration[chunk][index] = -1;
0542: fAttributeDeclDefaultType[chunk][index] = XMLAttributeDecl.DEFAULT_TYPE_IMPLIED;
0543: fAttributeDeclDefaultValue[chunk][index] = null;
0544: fAttributeDeclNextAttributeDeclIndex[chunk][index] = -1;
0545: return fAttributeDeclCount++;
0546: }
0547:
0548: protected void setAttributeDecl(int elementDeclIndex,
0549: int attributeDeclIndex, XMLAttributeDecl attributeDecl) {
0550:
0551: int attrChunk = attributeDeclIndex >> CHUNK_SHIFT;
0552: int attrIndex = attributeDeclIndex & CHUNK_MASK;
0553:
0554: fAttributeDeclName[attrChunk][attrIndex]
0555: .setValues(attributeDecl.name);
0556:
0557: fAttributeDeclType[attrChunk][attrIndex] = attributeDecl.type;
0558: if (attributeDecl.list) {
0559: fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG;
0560: }
0561: fAttributeDeclEnumeration[attrChunk][attrIndex] = attributeDecl.enumeration;
0562: fAttributeDeclDefaultType[attrChunk][attrIndex] = attributeDecl.defaultType;
0563: fAttributeDeclDatatypeValidator[attrChunk][attrIndex] = attributeDecl.datatypeValidator;
0564: fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.defaultValue;
0565:
0566: int elemChunk = elementDeclIndex >> CHUNK_SHIFT;
0567: int elemIndex = elementDeclIndex & CHUNK_MASK;
0568: int index = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex];
0569: while (index != -1) {
0570: if (index == attributeDeclIndex) {
0571: break;
0572: }
0573: attrChunk = index >> CHUNK_SHIFT;
0574: attrIndex = index & CHUNK_MASK;
0575: index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex];
0576: }
0577: if (index == -1) {
0578: if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) {
0579: fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
0580: } else {
0581: index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex];
0582: attrChunk = index >> CHUNK_SHIFT;
0583: attrIndex = index & CHUNK_MASK;
0584: fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex;
0585: }
0586: fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
0587: }
0588:
0589: }
0590:
0591: protected boolean isDTD() {
0592: return false;
0593: }
0594:
0595: // debugging
0596:
0597: public void printElements(org.apache.xerces.utils.StringPool pool) {
0598: int elementDeclIndex = 0;
0599: XMLElementDecl elementDecl = new XMLElementDecl();
0600: while (getElementDecl(elementDeclIndex++, elementDecl)) {
0601: System.out.println("element decl: "
0602: + elementDecl.name
0603: + ", "
0604: + pool.toString(elementDecl.name.rawname)
0605: + ", "
0606: + XMLContentSpec.toString(this , pool,
0607: elementDecl.contentSpecIndex));
0608: }
0609: }
0610:
0611: public void printAttributes(int elementDeclIndex) {
0612: int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex);
0613: System.out.print(elementDeclIndex);
0614: System.out.print(" [");
0615: while (attributeDeclIndex != -1) {
0616: System.out.print(' ');
0617: System.out.print(attributeDeclIndex);
0618: printAttribute(attributeDeclIndex);
0619: attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex);
0620: if (attributeDeclIndex != -1) {
0621: System.out.print(",");
0622: }
0623: }
0624: System.out.println(" ]");
0625: }
0626:
0627: //
0628: // Private methods
0629: //
0630:
0631: // debugging
0632:
0633: private void printAttribute(int attributeDeclIndex) {
0634: XMLAttributeDecl attributeDecl = new XMLAttributeDecl();
0635: if (getAttributeDecl(attributeDeclIndex, attributeDecl)) {
0636: System.out.print(" { ");
0637: System.out.print(attributeDecl.name.localpart);
0638: System.out.print(" }");
0639: }
0640: }
0641:
0642: // content models
0643:
0644: //
0645: // When the element has a 'CHILDREN' model, this method is called to
0646: // create the content model object. It looks for some special case simple
0647: // models and creates SimpleContentModel objects for those. For the rest
0648: // it creates the standard DFA style model.
0649: //
0650: private final XMLContentModel createChildModel(
0651: int contentSpecIndex, boolean isMixed) throws CMException {
0652: //
0653: // Get the content spec node for the element we are working on.
0654: // This will tell us what kind of node it is, which tells us what
0655: // kind of model we will try to create.
0656: //
0657: XMLContentSpec contentSpec = new XMLContentSpec();
0658:
0659: getContentSpec(contentSpecIndex, contentSpec);
0660:
0661: if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY
0662: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER
0663: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_NS) {
0664: // let fall through to build a DFAContentModel
0665: } else if (isMixed) {
0666: if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ALL) {
0667: // All the nodes under an ALL must be additional ALL nodes and
0668: // ELEMENTs (or ELEMENTs under ZERO_OR_ONE nodes.)
0669: // We collapse the ELEMENTs into a single vector.
0670: AllContentModel allContent = new AllContentModel(false,
0671: true);
0672: gatherAllLeaves(contentSpecIndex, contentSpec,
0673: allContent);
0674:
0675: return allContent;
0676: } else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) {
0677: int zeroOrOneChildIndex = contentSpec.value;
0678: getContentSpec(zeroOrOneChildIndex, contentSpec);
0679:
0680: // An ALL node can appear under a ZERO_OR_ONE node.
0681: if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ALL) {
0682: AllContentModel allContent = new AllContentModel(
0683: true, true);
0684: gatherAllLeaves(zeroOrOneChildIndex, contentSpec,
0685: allContent);
0686:
0687: return new AllContentModel(true);
0688: }
0689: }
0690: // otherwise, let fall through to build a DFAContentModel
0691: }
0692:
0693: else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
0694: //
0695: // Check that the left value is not -1, since any content model
0696: // with PCDATA should be MIXED, so we should not have gotten here.
0697: //
0698: if (contentSpec.value == -1 && contentSpec.otherValue == -1)
0699: throw new CMException(ImplementationMessages.VAL_NPCD);
0700:
0701: //
0702: // It's a single leaf, so it's an 'a' type of content model, i.e.
0703: // just one instance of one element. That one is definitely a
0704: // simple content model.
0705: //
0706:
0707: fQName1.setValues(-1, contentSpec.value, contentSpec.value,
0708: contentSpec.otherValue);
0709: return new SimpleContentModel(fQName1, null,
0710: contentSpec.type, isDTD());
0711: } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
0712: || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
0713: //
0714: // Lets see if both of the children are leafs. If so, then
0715: // it has to be a simple content model
0716: //
0717: XMLContentSpec contentSpecLeft = new XMLContentSpec();
0718: XMLContentSpec contentSpecRight = new XMLContentSpec();
0719:
0720: getContentSpec(contentSpec.value, contentSpecLeft);
0721: getContentSpec(contentSpec.otherValue, contentSpecRight);
0722:
0723: if ((contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
0724: && (contentSpecRight.type == XMLContentSpec.CONTENTSPECNODE_LEAF)) {
0725: //
0726: // It's a simple choice or sequence, so we can do a simple
0727: // content model for it.
0728: //
0729: fQName1.setValues(-1, contentSpecLeft.value,
0730: contentSpecLeft.value,
0731: contentSpecLeft.otherValue);
0732: fQName2.setValues(-1, contentSpecRight.value,
0733: contentSpecRight.value,
0734: contentSpecRight.otherValue);
0735: return new SimpleContentModel(fQName1, fQName2,
0736: contentSpec.type, isDTD());
0737: }
0738: } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE)
0739: || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE)
0740: || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE)) {
0741: //
0742: // It's a repetition, so see if its one child is a leaf. If so
0743: // it's a repetition of a single element, so we can do a simple
0744: // content model for that.
0745: //
0746: XMLContentSpec contentSpecLeft = new XMLContentSpec();
0747: getContentSpec(contentSpec.value, contentSpecLeft);
0748:
0749: if (contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
0750: //
0751: // It is, so we can create a simple content model here that
0752: // will check for this repetition. We pass -1 for the unused
0753: // right node.
0754: //
0755: fQName1.setValues(-1, contentSpecLeft.value,
0756: contentSpecLeft.value,
0757: contentSpecLeft.otherValue);
0758: return new SimpleContentModel(fQName1, null,
0759: contentSpec.type, isDTD());
0760: } else if (contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_ALL) {
0761: // An ALL can be optional. We must use the special
0762: // AllContentModel for such an animal. Indicate the
0763: // entire content is optional on the constructor.
0764: AllContentModel allContent = new AllContentModel(true);
0765:
0766: // All of the nodes under an ALL must be additional ALL nodes
0767: // and ELEMENTs (or ELEMENTs under ZERO_OR_ONE nodes.)
0768: // We collapse the ELEMENTs into a single vector.
0769: gatherAllLeaves(contentSpec.value, contentSpecLeft,
0770: allContent);
0771:
0772: return allContent;
0773: }
0774: } else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ALL) {
0775: // All of the nodes under an ALL must be additional ALL nodes and
0776: // ELEMENTs (or ELEMENTs under ZERO_OR_ONE nodes.)
0777: // We collapse the ELEMENTs into a single vector.
0778: AllContentModel allContent = new AllContentModel(false);
0779: gatherAllLeaves(contentSpecIndex, contentSpec, allContent);
0780:
0781: return allContent;
0782: } else {
0783: throw new CMException(ImplementationMessages.VAL_CST);
0784: }
0785:
0786: //
0787: // It's not a simple content model, so here we have to create a DFA
0788: // for this element. So we create a DFAContentModel object. He
0789: // encapsulates all of the work to create the DFA.
0790: //
0791:
0792: //int leafCount = countLeaves(contentSpecIndex);
0793: fLeafCount = 0;
0794: CMNode cmn = buildSyntaxTree(contentSpecIndex, contentSpec);
0795:
0796: // REVISIT: has to be fLeafCount because we convert x+ to x,x*, one more leaf
0797: return new DFAContentModel(cmn, fLeafCount, isDTD(), isMixed);
0798: }
0799:
0800: private void printSyntaxTree(CMNode cmn) {
0801: System.out.println("CMNode : " + cmn.type());
0802:
0803: if (cmn.type() == XMLContentSpec.CONTENTSPECNODE_LEAF) {
0804: System.out.println(" Leaf: "
0805: + ((CMLeaf) cmn).getElement());
0806: return;
0807: }
0808: if (cmn instanceof CMBinOp) {
0809: printSyntaxTree(((CMBinOp) cmn).getLeft());
0810: printSyntaxTree(((CMBinOp) cmn).getRight());
0811: }
0812: if (cmn instanceof CMUniOp) {
0813: printSyntaxTree(((CMUniOp) cmn).getChild());
0814: }
0815:
0816: }
0817:
0818: private int countLeaves(int contentSpecIndex) {
0819: return countLeaves(contentSpecIndex, new XMLContentSpec());
0820: }
0821:
0822: private int countLeaves(int contentSpecIndex,
0823: XMLContentSpec contentSpec) {
0824:
0825: if (contentSpecIndex == -1) {
0826: return 0;
0827: }
0828: /****
0829: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0830: int index = contentSpecIndex & CHUNK_MASK;
0831: int type = fContentSpecType[chunk][index];
0832: if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
0833: return 1;
0834: }
0835: int value = fContentSpecValue[chunk][index];
0836: int otherValue = fContentSpecOtherValue[chunk][index];
0837: return countLeaves(value) + countLeaves(otherValue);
0838: /***/
0839: getContentSpec(contentSpecIndex, contentSpec);
0840: if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
0841: return 1;
0842: }
0843: int value = contentSpec.value;
0844: int otherValue = contentSpec.otherValue;
0845: return countLeaves(value, contentSpec)
0846: + countLeaves(otherValue, contentSpec);
0847: /***/
0848: }
0849:
0850: private int fLeafCount = 0;
0851: private int fEpsilonIndex = -1;
0852:
0853: private final CMNode buildSyntaxTree(int startNode,
0854: XMLContentSpec contentSpec) throws CMException {
0855: // We will build a node at this level for the new tree
0856: CMNode nodeRet = null;
0857: getContentSpec(startNode, contentSpec);
0858: if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY
0859: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER
0860: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_NS) {
0861: nodeRet = new CMAny(contentSpec.type,
0862: contentSpec.otherValue, fLeafCount++);
0863: }
0864: //
0865: // If this node is a leaf, then it's an easy one. We just add it
0866: // to the tree.
0867: //
0868: else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
0869: //
0870: // Create a new leaf node, and pass it the current leaf count,
0871: // which is its DFA state position. Bump the leaf count after
0872: // storing it. This makes the positions zero based since we
0873: // store first and then increment.
0874: //
0875: fQName1.setValues(-1, contentSpec.value, contentSpec.value,
0876: contentSpec.otherValue);
0877: nodeRet = new CMLeaf(fQName1, fLeafCount++);
0878: } else {
0879: //
0880: // It's not a leaf, so we have to recurse its left and maybe right
0881: // nodes. Save both values before we recurse and trash the node.
0882: //
0883: final int leftNode = contentSpec.value;
0884: final int rightNode = contentSpec.otherValue;
0885:
0886: if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
0887: || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
0888: //
0889: // Recurse on both children, and return a binary op node
0890: // with the two created sub nodes as its children. The node
0891: // type is the same type as the source.
0892: //
0893:
0894: nodeRet = new CMBinOp(contentSpec.type,
0895: buildSyntaxTree(leftNode, contentSpec),
0896: buildSyntaxTree(rightNode, contentSpec));
0897:
0898: /* MODIFIED (Jan, 2001) */
0899:
0900: } else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
0901: || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE
0902: || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
0903: nodeRet = new CMUniOp(contentSpec.type,
0904: buildSyntaxTree(leftNode, contentSpec));
0905: }
0906:
0907: /* MODIFIED (Jan, 2001) */
0908:
0909: else {
0910: throw new CMException(ImplementationMessages.VAL_CST);
0911: }
0912: }
0913: // And return our new node for this level
0914: return nodeRet;
0915: }
0916:
0917: /**
0918: * Recursively build an AllContentModel based on a content spec tree
0919: * rooted at an ALL node.
0920: *
0921: * @param contentSpecIndex
0922: * A content spec tree containing only ALL, LEAF and
0923: * ZERO_OR_ONE nodes. Any ZERO_OR_ONE nodes must be parents
0924: * of LEAF nodes.
0925: * @param contentSpec
0926: * A temporary XMLContentSpec object used to record info.
0927: * about the current node in the tree. Used as a scratch
0928: * pad by each recursive invocation of this method.
0929: * @param allContent
0930: * The AllContentModel that's being built for this tree
0931: * @exception CMException
0932: */
0933: private final void gatherAllLeaves(int contentSpecIndex,
0934: XMLContentSpec contentSpec, AllContentModel allContent)
0935: throws CMException {
0936:
0937: if (contentSpecIndex <= -1)
0938: return;
0939:
0940: getContentSpec(contentSpecIndex, contentSpec);
0941:
0942: int value = contentSpec.value;
0943: int otherValue = contentSpec.otherValue;
0944: int type = contentSpec.type;
0945:
0946: if (type == XMLContentSpec.CONTENTSPECNODE_ALL) {
0947: // At an all node, visit left and right subtrees
0948: gatherAllLeaves(value, contentSpec, allContent);
0949: gatherAllLeaves(otherValue, contentSpec, allContent);
0950: } else if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
0951: // At leaf, add the element to list of elements permitted in the all
0952: allContent.addElement(new QName(-1, value, value,
0953: otherValue), false);
0954: } else if (type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) {
0955: // At ZERO_OR_ONE node, subtree must be an element
0956: // that was specified with minOccurs=0, maxOccurs=1
0957: getContentSpec(value, contentSpec);
0958:
0959: value = contentSpec.value;
0960: otherValue = contentSpec.otherValue;
0961: type = contentSpec.type;
0962:
0963: if (type != XMLContentSpec.CONTENTSPECNODE_LEAF)
0964: throw new CMException(ImplementationMessages.VAL_CST);
0965:
0966: // Add the optional element to list of elements permitted in the all
0967: allContent.addElement(new QName(-1, value, value,
0968: otherValue), true);
0969: } else {
0970: throw new CMException(ImplementationMessages.VAL_CST);
0971: }
0972: }
0973:
0974: /**
0975: * Build a vector of valid QNames from Content Spec
0976: * table.
0977: *
0978: * @param contentSpecIndex
0979: * Content Spec index
0980: * @param vectorQName
0981: * Array of QName
0982: * @exception CMException
0983: */
0984: private void contentSpecTree(int contentSpecIndex,
0985: XMLContentSpec contentSpec, ChildrenList children)
0986: throws CMException {
0987:
0988: // Handle any and leaf nodes
0989: getContentSpec(contentSpecIndex, contentSpec);
0990: if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF
0991: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY
0992: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_NS
0993: || (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
0994:
0995: // resize arrays, if needed
0996: if (children.length == children.qname.length) {
0997: QName[] newQName = new QName[children.length * 2];
0998: System.arraycopy(children.qname, 0, newQName, 0,
0999: children.length);
1000: children.qname = newQName;
1001: int[] newType = new int[children.length * 2];
1002: System.arraycopy(children.type, 0, newType, 0,
1003: children.length);
1004: children.type = newType;
1005: }
1006:
1007: // save values and return length
1008: children.qname[children.length] = new QName(-1,
1009: contentSpec.value, contentSpec.value,
1010: contentSpec.otherValue);
1011: children.type[children.length] = contentSpec.type;
1012: children.length++;
1013: return;
1014: }
1015:
1016: //
1017: // It's not a leaf, so we have to recurse its left and maybe right
1018: // nodes. Save both values before we recurse and trash the node.
1019: //
1020: final int leftNode = contentSpec.value;
1021: final int rightNode = contentSpec.otherValue;
1022:
1023: if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE
1024: || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
1025: contentSpecTree(leftNode, contentSpec, children);
1026: contentSpecTree(rightNode, contentSpec, children);
1027: return;
1028: }
1029:
1030: if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE
1031: || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
1032: || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
1033: contentSpecTree(leftNode, contentSpec, children);
1034: return;
1035: }
1036:
1037: // error
1038: throw new CMException(ImplementationMessages.VAL_CST);
1039: }
1040:
1041: // ensure capacity
1042:
1043: private void ensureElementDeclCapacity(int chunk) {
1044: if (chunk >= fElementDeclName.length) {
1045: fElementDeclName = resize(fElementDeclName,
1046: fElementDeclName.length * 2);
1047: fElementDeclType = resize(fElementDeclType,
1048: fElementDeclType.length * 2);
1049: fElementDeclDatatypeValidator = resize(
1050: fElementDeclDatatypeValidator,
1051: fElementDeclDatatypeValidator.length * 2);
1052: fElementDeclContentSpecIndex = resize(
1053: fElementDeclContentSpecIndex,
1054: fElementDeclContentSpecIndex.length * 2);
1055: fElementDeclFirstAttributeDeclIndex = resize(
1056: fElementDeclFirstAttributeDeclIndex,
1057: fElementDeclFirstAttributeDeclIndex.length * 2);
1058: fElementDeclLastAttributeDeclIndex = resize(
1059: fElementDeclLastAttributeDeclIndex,
1060: fElementDeclLastAttributeDeclIndex.length * 2);
1061: fElementDeclUnique = resize(fElementDeclUnique,
1062: fElementDeclUnique.length * 2);
1063: fElementDeclKey = resize(fElementDeclKey,
1064: fElementDeclKey.length * 2);
1065: fElementDeclKeyRef = resize(fElementDeclKeyRef,
1066: fElementDeclKeyRef.length * 2);
1067: } else if (fElementDeclName[chunk] != null) {
1068: return;
1069: }
1070: fElementDeclName[chunk] = new QName[CHUNK_SIZE];
1071: fElementDeclType[chunk] = new int[CHUNK_SIZE];
1072: fElementDeclDatatypeValidator[chunk] = new DatatypeValidator[CHUNK_SIZE];
1073: fElementDeclContentSpecIndex[chunk] = new int[CHUNK_SIZE];
1074: fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
1075: fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
1076: fElementDeclUnique[chunk] = new Vector[CHUNK_SIZE];
1077: fElementDeclKey[chunk] = new Vector[CHUNK_SIZE];
1078: fElementDeclKeyRef[chunk] = new Vector[CHUNK_SIZE];
1079: }
1080:
1081: private void ensureContentSpecCapacity(int chunk) {
1082: if (chunk >= fContentSpecType.length) {
1083: fContentSpecType = resize(fContentSpecType,
1084: fContentSpecType.length * 2);
1085: fContentSpecValue = resize(fContentSpecValue,
1086: fContentSpecValue.length * 2);
1087: fContentSpecOtherValue = resize(fContentSpecOtherValue,
1088: fContentSpecOtherValue.length * 2);
1089: fContentSpecValidator = resize(fContentSpecValidator,
1090: fContentSpecValidator.length * 2);
1091: } else if (fContentSpecType[chunk] != null) {
1092: return;
1093: }
1094: fContentSpecType[chunk] = new int[CHUNK_SIZE];
1095: fContentSpecValue[chunk] = new int[CHUNK_SIZE];
1096: fContentSpecOtherValue[chunk] = new int[CHUNK_SIZE];
1097: fContentSpecValidator[chunk] = new XMLContentModel[CHUNK_SIZE];
1098: }
1099:
1100: private void ensureAttributeDeclCapacity(int chunk) {
1101: if (chunk >= fAttributeDeclName.length) {
1102: fAttributeDeclName = resize(fAttributeDeclName,
1103: fAttributeDeclName.length * 2);
1104: fAttributeDeclType = resize(fAttributeDeclType,
1105: fAttributeDeclType.length * 2);
1106: fAttributeDeclEnumeration = resize(
1107: fAttributeDeclEnumeration,
1108: fAttributeDeclEnumeration.length * 2);
1109: fAttributeDeclDefaultType = resize(
1110: fAttributeDeclDefaultType,
1111: fAttributeDeclDefaultType.length * 2);
1112: fAttributeDeclDatatypeValidator = resize(
1113: fAttributeDeclDatatypeValidator,
1114: fAttributeDeclDatatypeValidator.length * 2);
1115: fAttributeDeclDefaultValue = resize(
1116: fAttributeDeclDefaultValue,
1117: fAttributeDeclDefaultValue.length * 2);
1118: fAttributeDeclNextAttributeDeclIndex = resize(
1119: fAttributeDeclNextAttributeDeclIndex,
1120: fAttributeDeclNextAttributeDeclIndex.length * 2);
1121: } else if (fAttributeDeclName[chunk] != null) {
1122: return;
1123: }
1124: fAttributeDeclName[chunk] = new QName[CHUNK_SIZE];
1125: fAttributeDeclType[chunk] = new int[CHUNK_SIZE];
1126: fAttributeDeclEnumeration[chunk] = new int[CHUNK_SIZE];
1127: fAttributeDeclDefaultType[chunk] = new int[CHUNK_SIZE];
1128: fAttributeDeclDatatypeValidator[chunk] = new DatatypeValidator[CHUNK_SIZE];
1129: fAttributeDeclDefaultValue[chunk] = new String[CHUNK_SIZE];
1130: fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
1131: }
1132:
1133: // resize initial chunk
1134:
1135: private int[][] resize(int array[][], int newsize) {
1136: int newarray[][] = new int[newsize][];
1137: System.arraycopy(array, 0, newarray, 0, array.length);
1138: return newarray;
1139: }
1140:
1141: private DatatypeValidator[][] resize(DatatypeValidator array[][],
1142: int newsize) {
1143: DatatypeValidator newarray[][] = new DatatypeValidator[newsize][];
1144: System.arraycopy(array, 0, newarray, 0, array.length);
1145: return newarray;
1146: }
1147:
1148: private XMLContentModel[][] resize(XMLContentModel array[][],
1149: int newsize) {
1150: XMLContentModel newarray[][] = new XMLContentModel[newsize][];
1151: System.arraycopy(array, 0, newarray, 0, array.length);
1152: return newarray;
1153: }
1154:
1155: private QName[][] resize(QName array[][], int newsize) {
1156: QName newarray[][] = new QName[newsize][];
1157: System.arraycopy(array, 0, newarray, 0, array.length);
1158: return newarray;
1159: }
1160:
1161: private String[][] resize(String array[][], int newsize) {
1162: String newarray[][] = new String[newsize][];
1163: System.arraycopy(array, 0, newarray, 0, array.length);
1164: return newarray;
1165: }
1166:
1167: private Vector[][] resize(Vector array[][], int newsize) {
1168: Vector newarray[][] = new Vector[newsize][];
1169: System.arraycopy(array, 0, newarray, 0, array.length);
1170: return newarray;
1171: }
1172:
1173: //
1174: // Classes
1175: //
1176:
1177: /**
1178: * Children list for <code>contentSpecTree</code> method.
1179: */
1180: static class ChildrenList {
1181: public int length = 0;
1182: public QName[] qname = new QName[2];
1183: public int[] type = new int[2];
1184: }
1185:
1186: } // class Grammar
|