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: /*
0059: * @author Eric Ye
0060: *
0061: * @see
0062: * @version $Id: SchemaGrammar.java,v 1.40 2001/06/30 21:14:22 lmartin Exp $
0063: */
0064: package org.apache.xerces.validators.schema;
0065:
0066: import org.apache.xerces.framework.XMLContentSpec;
0067: import org.apache.xerces.validators.common.CMException;
0068: import org.apache.xerces.utils.NamespacesScope;
0069: import org.apache.xerces.utils.QName;
0070: import org.apache.xerces.framework.XMLContentSpec;
0071: import org.apache.xerces.validators.datatype.DatatypeValidator;
0072: import org.apache.xerces.validators.datatype.DatatypeValidatorFactoryImpl;
0073: import org.apache.xerces.validators.common.XMLAttributeDecl;
0074: import org.apache.xerces.validators.common.XMLContentModel;
0075: import org.apache.xerces.validators.common.XMLElementDecl;
0076: import org.apache.xerces.validators.common.Grammar;
0077: import org.apache.xerces.validators.common.GrammarResolver;
0078: import org.apache.xerces.utils.StringPool;
0079: import org.w3c.dom.Document;
0080: import org.w3c.dom.Element;
0081:
0082: import java.util.Hashtable;
0083: import java.util.Vector;
0084:
0085: public class SchemaGrammar extends Grammar {
0086:
0087: // Constants
0088: //
0089:
0090: private static final int CHUNK_SHIFT = 8; // 2^8 = 256
0091: private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
0092: private static final int CHUNK_MASK = CHUNK_SIZE - 1;
0093: private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k
0094:
0095: //Temp objects for decls structs.
0096: private XMLContentSpec fTempContentSpecNode = new XMLContentSpec();
0097: private XMLElementDecl fTempElementDecl = new XMLElementDecl();
0098: private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl();
0099:
0100: //
0101: // Data
0102: //
0103:
0104: // basic information
0105:
0106: // private int fTargetNamespace;
0107:
0108: // private Element fGrammarDocument;
0109:
0110: // element decl tables that used only by Schemas
0111: // these arrays are indexed by elementdeclindex.
0112:
0113: private int fScopeDefinedByElement[][] = new int[INITIAL_CHUNK_COUNT][];
0114: private String fFromAnotherSchemaURI[][] = new String[INITIAL_CHUNK_COUNT][];
0115: private TraverseSchema.ComplexTypeInfo fComplexTypeInfo[][] = new TraverseSchema.ComplexTypeInfo[INITIAL_CHUNK_COUNT][];
0116: private int fElementDeclDefaultType[][] = new int[INITIAL_CHUNK_COUNT][];
0117: private String fElementDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
0118: private String fElementDeclSubGroupAffFullName[][] = new String[INITIAL_CHUNK_COUNT][];
0119: private Vector fElementDeclSubGroupQNames[][] = new Vector[INITIAL_CHUNK_COUNT][];
0120: private Vector fElementDeclAllSubGroupQNamesBlock[][] = new Vector[INITIAL_CHUNK_COUNT][];
0121: private Vector fElementDeclAllSubGroupQNames[][] = new Vector[INITIAL_CHUNK_COUNT][];
0122: private int fElementDeclBlockSet[][] = new int[INITIAL_CHUNK_COUNT][];
0123: private int fElementDeclFinalSet[][] = new int[INITIAL_CHUNK_COUNT][];
0124: private int fElementDeclMiscFlags[][] = new int[INITIAL_CHUNK_COUNT][];
0125:
0126: // additional content spec tables
0127: // used if deferContentSpecExansion is enabled
0128: private int fContentSpecMinOccurs[][] = new int[INITIAL_CHUNK_COUNT][];
0129: private int fContentSpecMaxOccurs[][] = new int[INITIAL_CHUNK_COUNT][];
0130:
0131: //ComplexType and SimpleTypeRegistries
0132: private Hashtable fComplexTypeRegistry = null;
0133: private Hashtable fAttributeDeclRegistry = null;
0134: private DatatypeValidatorFactoryImpl fDatatypeRegistry = null;
0135:
0136: Hashtable topLevelGroupDecls = new Hashtable();
0137: Hashtable topLevelNotationDecls = new Hashtable();
0138: Hashtable topLevelAttrDecls = new Hashtable();
0139: Hashtable topLevelAttrGrpDecls = new Hashtable();
0140: Hashtable topLevelElemDecls = new Hashtable();
0141: Hashtable topLevelTypeDecls = new Hashtable();
0142:
0143: private NamespacesScope fNamespacesScope = null;
0144: private String fTargetNamespaceURI = "";
0145:
0146: // Set if we defer min/max expansion for content trees. This is required if we
0147: // are doing particle derivation checking for schema.
0148: private boolean deferContentSpecExpansion = false;
0149:
0150: // Set if we check Unique Particle Attribution
0151: // This one onle takes effect when deferContentSpecExpansion is set
0152: private boolean checkUniqueParticleAttribution = false;
0153: private boolean checkingUPA = false;
0154: // store the original uri
0155: private int fContentSpecOrgUri[][] = new int[INITIAL_CHUNK_COUNT][];
0156:
0157: //
0158: // Public methods
0159: //
0160:
0161: public NamespacesScope getNamespacesScope() {
0162: return fNamespacesScope;
0163: }
0164:
0165: public boolean getDeferContentSpecExpansion() {
0166: return deferContentSpecExpansion;
0167: }
0168:
0169: public boolean getCheckUniqueParticleAttribution() {
0170: return checkUniqueParticleAttribution;
0171: }
0172:
0173: public String getTargetNamespaceURI() {
0174: return fTargetNamespaceURI;
0175: }
0176:
0177: public Hashtable getAttributeDeclRegistry() {
0178: return fAttributeDeclRegistry;
0179: }
0180:
0181: public Hashtable getComplexTypeRegistry() {
0182: return fComplexTypeRegistry;
0183: }
0184:
0185: public DatatypeValidatorFactoryImpl getDatatypeRegistry() {
0186: return fDatatypeRegistry;
0187: }
0188:
0189: public int getElementDefinedScope(int elementDeclIndex) {
0190:
0191: if (elementDeclIndex < -1) {
0192: return -1;
0193: }
0194: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0195: int index = elementDeclIndex & CHUNK_MASK;
0196: return fScopeDefinedByElement[chunk][index];
0197:
0198: }
0199:
0200: public int getElementDefaultTYpe(int elementDeclIndex) {
0201:
0202: if (elementDeclIndex < -1) {
0203: return -1;
0204: }
0205: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0206: int index = elementDeclIndex & CHUNK_MASK;
0207: return fElementDeclDefaultType[chunk][index];
0208:
0209: }
0210:
0211: public int getElementDeclBlockSet(int elementDeclIndex) {
0212:
0213: if (elementDeclIndex < -1) {
0214: return -1;
0215: }
0216: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0217: int index = elementDeclIndex & CHUNK_MASK;
0218: return fElementDeclBlockSet[chunk][index];
0219: }
0220:
0221: public int getElementDeclFinalSet(int elementDeclIndex) {
0222:
0223: if (elementDeclIndex < -1) {
0224: return -1;
0225: }
0226: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0227: int index = elementDeclIndex & CHUNK_MASK;
0228: return fElementDeclFinalSet[chunk][index];
0229: }
0230:
0231: public int getElementDeclMiscFlags(int elementDeclIndex) {
0232:
0233: if (elementDeclIndex < -1) {
0234: return -1;
0235: }
0236: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0237: int index = elementDeclIndex & CHUNK_MASK;
0238: return fElementDeclMiscFlags[chunk][index];
0239: }
0240:
0241: public String getElementFromAnotherSchemaURI(int elementDeclIndex) {
0242:
0243: if (elementDeclIndex < 0) {
0244: return null;
0245: }
0246: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0247: int index = elementDeclIndex & CHUNK_MASK;
0248: return fFromAnotherSchemaURI[chunk][index];
0249:
0250: }
0251:
0252: public String getElementDefaultValue(int elementDeclIndex) {
0253:
0254: if (elementDeclIndex < 0) {
0255: return null;
0256: }
0257: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0258: int index = elementDeclIndex & CHUNK_MASK;
0259: return fElementDeclDefaultValue[chunk][index];
0260:
0261: }
0262:
0263: public String getElementDeclSubstitutionGroupAffFullName(
0264: int elementDeclIndex) {
0265:
0266: if (elementDeclIndex < 0) {
0267: return null;
0268: }
0269: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0270: int index = elementDeclIndex & CHUNK_MASK;
0271: return fElementDeclSubGroupAffFullName[chunk][index];
0272:
0273: }
0274:
0275: // get a list of element qnames that substitute the current element directly
0276: private Vector getElementDeclSubstitutionGroupQNames(
0277: int elementDeclIndex) {
0278:
0279: if (elementDeclIndex < 0) {
0280: return null;
0281: }
0282: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0283: int index = elementDeclIndex & CHUNK_MASK;
0284: return fElementDeclSubGroupQNames[chunk][index];
0285:
0286: }
0287:
0288: // get a list of element qnames that substitute the current element directly
0289: // or indirectly
0290: // and get the derivation methods / block set along the derivation chain
0291: // but we haven't checked "blockset" yet, because it's possible that
0292: // A substitute B, B substitute C, with types (AT, BT, CT)
0293: // but the derivation method from AT to BT is block by B's blockset
0294: // then A can't substitute B, but it's still possible that A substitute C.
0295: private Vector getElementDeclAllSubstitutionGroupQNamesBlock(
0296: int elementDeclIndex, GrammarResolver grammarResolver,
0297: StringPool stringPool) {
0298: if (elementDeclIndex < 0) {
0299: return null;
0300: }
0301: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0302: int index = elementDeclIndex & CHUNK_MASK;
0303: if (fElementDeclAllSubGroupQNamesBlock[chunk][index] != null)
0304: return fElementDeclAllSubGroupQNamesBlock[chunk][index];
0305:
0306: Vector groups = new Vector();
0307: fElementDeclAllSubGroupQNamesBlock[chunk][index] = groups;
0308:
0309: // get the type info for the current element
0310: TraverseSchema.ComplexTypeInfo typeInfo = getElementComplexTypeInfo(elementDeclIndex);
0311:
0312: // for all elements that can substitute directly
0313: Vector substitutionGroupQNames = getElementDeclSubstitutionGroupQNames(elementDeclIndex);
0314: int size = substitutionGroupQNames == null ? 0
0315: : substitutionGroupQNames.size();
0316: for (int i = 0; i < size; i++) {
0317: OneSubGroup oneGroup = (OneSubGroup) substitutionGroupQNames
0318: .elementAt(i);
0319: SchemaGrammar sGrammar = oneGroup.grammar;
0320: int subElementIndex = oneGroup.eleIndex;
0321:
0322: // derivation method
0323: // and prohibited derivation method
0324: int devMethod = 0, pDevMethod = 0;
0325:
0326: TraverseSchema.ComplexTypeInfo subTypeInfo = sGrammar
0327: .getElementComplexTypeInfo(subElementIndex);
0328: if (subTypeInfo == null) {
0329: // for simple type, we compare the datatypeValidators
0330: XMLElementDecl tmpElementDecl = new XMLElementDecl();
0331: sGrammar
0332: .getElementDecl(subElementIndex, tmpElementDecl);
0333: DatatypeValidator subElementDV = tmpElementDecl.datatypeValidator;
0334: getElementDecl(elementDeclIndex, tmpElementDecl);
0335: DatatypeValidator elementDV = tmpElementDecl.datatypeValidator;
0336: if (subElementDV != null && subElementDV != elementDV)
0337: devMethod = SchemaSymbols.RESTRICTION;
0338: } else {
0339: // store the devMethod of the deriving type,
0340: // and pDevMethod of the derived type
0341: if (subTypeInfo != typeInfo) {
0342: devMethod = subTypeInfo.derivedBy;
0343: if (typeInfo != null)
0344: pDevMethod = typeInfo.blockSet;
0345: subTypeInfo = subTypeInfo.baseComplexTypeInfo;
0346: }
0347: for (; subTypeInfo != null && subTypeInfo != typeInfo; subTypeInfo = subTypeInfo.baseComplexTypeInfo) {
0348: devMethod |= subTypeInfo.derivedBy;
0349: pDevMethod |= subTypeInfo.blockSet;
0350: }
0351: }
0352:
0353: // put this element into the list
0354: SubGroupBlockQName oneName = new SubGroupBlockQName();
0355: oneName.name = oneGroup;
0356: oneName.method = devMethod;
0357: oneName.pmethod = pDevMethod;
0358: groups.addElement(oneName);
0359:
0360: // recursively get all elements that can substitute this element
0361: Vector subSubGroup = sGrammar
0362: .getElementDeclAllSubstitutionGroupQNamesBlock(
0363: subElementIndex, grammarResolver,
0364: stringPool);
0365: int bsize = subSubGroup == null ? 0 : subSubGroup.size();
0366: for (int j = 0; j < bsize; j++) {
0367: // and add them to the list too
0368: SubGroupBlockQName name = (SubGroupBlockQName) subSubGroup
0369: .elementAt(j);
0370: oneName = new SubGroupBlockQName();
0371: oneName.name = name.name;
0372: // note that we need to append the dev/pdev method
0373: oneName.method = name.method | devMethod;
0374: oneName.pmethod = name.pmethod | pDevMethod;
0375: groups.addElement(oneName);
0376: }
0377: }
0378:
0379: return groups;
0380: }
0381:
0382: // all elements that can substitute the given one
0383: // returns a list (Vector) of SchemaGrammar.OneSubGroup: qname+grammar+elementIndex
0384: // be sure to call this method ONLY AFTER (not during) schema traversal!!!
0385: public Vector getElementDeclAllSubstitutionGroupQNames(
0386: int elementDeclIndex, GrammarResolver grammarResolver,
0387: StringPool stringPool) {
0388:
0389: if (elementDeclIndex < 0) {
0390: return null;
0391: }
0392: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0393: int index = elementDeclIndex & CHUNK_MASK;
0394: if (fElementDeclAllSubGroupQNames[chunk][index] != null)
0395: return fElementDeclAllSubGroupQNames[chunk][index];
0396:
0397: Vector groups = new Vector();
0398: fElementDeclAllSubGroupQNames[chunk][index] = groups;
0399:
0400: // get the blockset of the current element
0401: int blockSet = getElementDeclBlockSet(elementDeclIndex);
0402: // 1 The blocking constraint does not contain substitution.
0403: if ((blockSet & SchemaSymbols.SUBSTITUTION) != 0)
0404: return groups;
0405:
0406: // 2 There is a chain of {substitution group affiliation}s from D to C, that is, either D's {substitution group affiliation} is C, or D's {substitution group affiliation}'s {substitution group affiliation} is C, or . . .
0407: // get all substitution candidates without checking blockset
0408: Vector substitutionGroupQNamesBlock = getElementDeclAllSubstitutionGroupQNamesBlock(
0409: elementDeclIndex, grammarResolver, stringPool);
0410: // now check it
0411: // 3 The set of all {derivation method}s involved in the derivation of D's {type definition} from C's {type definition} does not intersect with the union of the blocking constraint, C's {prohibited substitutions} (if C is complex, otherwise the empty set) and the {prohibited substitutions} (respectively the empty set) of any intermediate {type definition}s in the derivation of D's {type definition} from C's {type definition}.
0412: for (int i = 0; i < substitutionGroupQNamesBlock.size(); i++) {
0413: SubGroupBlockQName oneName = (SubGroupBlockQName) substitutionGroupQNamesBlock
0414: .elementAt(i);
0415: if (((blockSet | oneName.pmethod) & oneName.method) == 0)
0416: groups.addElement(oneName.name);
0417: }
0418:
0419: return groups;
0420: }
0421:
0422: public TraverseSchema.ComplexTypeInfo getElementComplexTypeInfo(
0423: int elementDeclIndex) {
0424:
0425: if (elementDeclIndex < -1) {
0426: return null;
0427: }
0428: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0429: int index = elementDeclIndex & CHUNK_MASK;
0430: return fComplexTypeInfo[chunk][index];
0431: }
0432:
0433: // Protected methods
0434: //
0435:
0436: protected int convertContentSpecTree(int contentSpecIndex) {
0437:
0438: // We may want to consider trying to combine this with buildSyntaxTree at some
0439: // point (if possible)
0440:
0441: if ((!deferContentSpecExpansion) || (contentSpecIndex < 0)) {
0442: return contentSpecIndex;
0443: }
0444:
0445: getContentSpec(contentSpecIndex, fTempContentSpecNode);
0446:
0447: int minOccurs = getContentSpecMinOccurs(contentSpecIndex);
0448: int maxOccurs = getContentSpecMaxOccurs(contentSpecIndex);
0449:
0450: if (((fTempContentSpecNode.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY)
0451: || ((fTempContentSpecNode.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER)
0452: || ((fTempContentSpecNode.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_NS)
0453: || (fTempContentSpecNode.type == XMLContentSpec.CONTENTSPECNODE_LEAF)) {
0454:
0455: // When checking Unique Particle Attribution, rename leaf elements
0456: if (checkingUPA) {
0457: contentSpecIndex = addContentSpecNode(
0458: fTempContentSpecNode.type,
0459: fTempContentSpecNode.value,
0460: fTempContentSpecNode.otherValue, false);
0461: setContentSpecOrgUri(contentSpecIndex,
0462: fTempContentSpecNode.otherValue);
0463: getContentSpec(contentSpecIndex, fTempContentSpecNode);
0464: fTempContentSpecNode.otherValue = contentSpecIndex;
0465: setContentSpec(contentSpecIndex, fTempContentSpecNode);
0466: }
0467:
0468: return expandContentModel(contentSpecIndex, minOccurs,
0469: maxOccurs);
0470: } else if (fTempContentSpecNode.type == XMLContentSpec.CONTENTSPECNODE_CHOICE
0471: || fTempContentSpecNode.type == XMLContentSpec.CONTENTSPECNODE_ALL
0472: || fTempContentSpecNode.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
0473:
0474: int left = fTempContentSpecNode.value;
0475: int right = fTempContentSpecNode.otherValue;
0476: int type = fTempContentSpecNode.type;
0477:
0478: left = convertContentSpecTree(left);
0479:
0480: if (right == -2)
0481: return expandContentModel(left, minOccurs, maxOccurs);
0482:
0483: right = convertContentSpecTree(right);
0484:
0485: // When checking Unique Particle Attribution, we always create new
0486: // new node to store different name for different groups
0487: if (checkingUPA) {
0488: contentSpecIndex = addContentSpecNode(type, left,
0489: right, false);
0490: } else {
0491: fTempContentSpecNode.type = type;
0492: fTempContentSpecNode.value = left;
0493: fTempContentSpecNode.otherValue = right;
0494: setContentSpec(contentSpecIndex, fTempContentSpecNode);
0495: }
0496:
0497: return expandContentModel(contentSpecIndex, minOccurs,
0498: maxOccurs);
0499: } else {
0500: // When checking Unique Particle Attribution, we have to rename
0501: // uri even on zero_or_one, zero_or_more and one_or_more
0502: if (checkingUPA) {
0503: return addContentSpecNode(
0504: fTempContentSpecNode.type,
0505: convertContentSpecTree(fTempContentSpecNode.value),
0506: convertContentSpecTree(fTempContentSpecNode.otherValue),
0507: false);
0508: } else {
0509: return contentSpecIndex;
0510: }
0511: }
0512: }
0513:
0514: // Unique Particle Attribution
0515: // overrides same method from Grammar, to do UPA checking
0516: public XMLContentModel getContentModel(int contentSpecIndex,
0517: int contentType, SubstitutionGroupComparator comparator)
0518: throws Exception {
0519: // if the content model is already there, no UPA checking is necessary
0520: if (existContentModel(contentSpecIndex))
0521: return super .getContentModel(contentSpecIndex, contentType,
0522: comparator);
0523:
0524: // if it's not there, we create a new one, do UPA checking,
0525: // then throw it away. because UPA checking might result in NFA,
0526: // but we need DFA for further checking
0527: if (checkUniqueParticleAttribution) {
0528: checkingUPA = true;
0529: XMLContentModel contentModel = super .getContentModel(
0530: contentSpecIndex, contentType, comparator);
0531: checkingUPA = false;
0532:
0533: if (contentModel != null) {
0534: contentModel.checkUniqueParticleAttribution(this );
0535: clearContentModel(contentSpecIndex);
0536: }
0537: }
0538:
0539: return super .getContentModel(contentSpecIndex, contentType,
0540: comparator);
0541: }
0542:
0543: // Unique Particle Attribution
0544: // set/get the original uri for a specific index
0545: public void setContentSpecOrgUri(int contentSpecIndex, int orgUri) {
0546: if (contentSpecIndex > -1) {
0547: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0548: int index = contentSpecIndex & CHUNK_MASK;
0549: ensureContentSpecCapacity(chunk);
0550: fContentSpecOrgUri[chunk][index] = orgUri;
0551: }
0552: }
0553:
0554: public int getContentSpecOrgUri(int contentSpecIndex) {
0555: if (contentSpecIndex > -1) {
0556: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0557: int index = contentSpecIndex & CHUNK_MASK;
0558: return fContentSpecOrgUri[chunk][index];
0559: } else {
0560: return -1;
0561: }
0562: }
0563:
0564: public void setDeferContentSpecExpansion() {
0565: deferContentSpecExpansion = true;
0566: }
0567:
0568: public void setCheckUniqueParticleAttribution() {
0569: deferContentSpecExpansion = true;
0570: checkUniqueParticleAttribution = true;
0571: }
0572:
0573: protected void setAttributeDeclRegistry(Hashtable attrReg) {
0574: fAttributeDeclRegistry = attrReg;
0575: }
0576:
0577: protected void setComplexTypeRegistry(Hashtable cTypeReg) {
0578: fComplexTypeRegistry = cTypeReg;
0579: }
0580:
0581: protected void setDatatypeRegistry(
0582: DatatypeValidatorFactoryImpl dTypeReg) {
0583: fDatatypeRegistry = dTypeReg;
0584: }
0585:
0586: protected void setNamespacesScope(NamespacesScope nsScope) {
0587: fNamespacesScope = nsScope;
0588: }
0589:
0590: protected void setTargetNamespaceURI(String targetNSUri) {
0591: fTargetNamespaceURI = targetNSUri;
0592: }
0593:
0594: protected int createElementDecl() {
0595: return super .createElementDecl();
0596: }
0597:
0598: protected void setElementDecl(int elementDeclIndex,
0599: XMLElementDecl elementDecl) {
0600: super .setElementDecl(elementDeclIndex, elementDecl);
0601: }
0602:
0603: //public int addAttributeDeclByHead(int attributeDeclIndex, int attributeListHead) {
0604: // return super.addAttributeDeclByHead(attributeDeclIndex, attributeListHead);
0605: //}
0606:
0607: protected int createContentSpec() {
0608: return super .createContentSpec();
0609: }
0610:
0611: protected void setContentSpec(int contentSpecIndex,
0612: XMLContentSpec contentSpec) {
0613: super .setContentSpec(contentSpecIndex, contentSpec);
0614: }
0615:
0616: protected int createAttributeDecl() {
0617: return super .createAttributeDecl();
0618: }
0619:
0620: protected void setAttributeDecl(int elementDeclIndex,
0621: int attributeDeclIndex, XMLAttributeDecl attributeDecl) {
0622: super .setAttributeDecl(elementDeclIndex, attributeDeclIndex,
0623: attributeDecl);
0624: }
0625:
0626: protected void setElementDefinedScope(int elementDeclIndex,
0627: int scopeDefined) {
0628: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0629: int index = elementDeclIndex & CHUNK_MASK;
0630: ensureElementDeclCapacity(chunk);
0631: if (elementDeclIndex > -1) {
0632: fScopeDefinedByElement[chunk][index] = scopeDefined;
0633: }
0634: }
0635:
0636: protected void setElementFromAnotherSchemaURI(int elementDeclIndex,
0637: String anotherSchemaURI) {
0638: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0639: int index = elementDeclIndex & CHUNK_MASK;
0640: ensureElementDeclCapacity(chunk);
0641: if (elementDeclIndex > -1) {
0642: fFromAnotherSchemaURI[chunk][index] = anotherSchemaURI;
0643: }
0644: }
0645:
0646: protected void setElementComplexTypeInfo(int elementDeclIndex,
0647: TraverseSchema.ComplexTypeInfo typeInfo) {
0648: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0649: int index = elementDeclIndex & CHUNK_MASK;
0650: ensureElementDeclCapacity(chunk);
0651: if (elementDeclIndex > -1) {
0652: fComplexTypeInfo[chunk][index] = typeInfo;
0653: }
0654: }
0655:
0656: protected void setElementDefault(int elementDeclIndex,
0657: String defaultValue) {
0658: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0659: int index = elementDeclIndex & CHUNK_MASK;
0660: ensureElementDeclCapacity(chunk);
0661: if (elementDeclIndex > -1) {
0662: fElementDeclDefaultValue[chunk][index] = defaultValue;
0663: }
0664: }
0665:
0666: protected void setElementDeclBlockSet(int elementDeclIndex,
0667: int blockSet) {
0668: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0669: int index = elementDeclIndex & CHUNK_MASK;
0670: ensureElementDeclCapacity(chunk);
0671: if (elementDeclIndex > -1) {
0672: fElementDeclBlockSet[chunk][index] = blockSet;
0673: }
0674: }
0675:
0676: protected void setElementDeclFinalSet(int elementDeclIndex,
0677: int finalSet) {
0678: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0679: int index = elementDeclIndex & CHUNK_MASK;
0680: ensureElementDeclCapacity(chunk);
0681: if (elementDeclIndex > -1) {
0682: fElementDeclFinalSet[chunk][index] = finalSet;
0683: }
0684: }
0685:
0686: protected void setElementDeclMiscFlags(int elementDeclIndex,
0687: int miscFlags) {
0688: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0689: int index = elementDeclIndex & CHUNK_MASK;
0690: ensureElementDeclCapacity(chunk);
0691: if (elementDeclIndex > -1) {
0692: fElementDeclMiscFlags[chunk][index] = miscFlags;
0693: }
0694: }
0695:
0696: protected void setElementDeclSubstitutionGroupAffFullName(
0697: int elementDeclIndex, String substitutionGroupFullName) {
0698: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0699: int index = elementDeclIndex & CHUNK_MASK;
0700: ensureElementDeclCapacity(chunk);
0701: if (elementDeclIndex > -1) {
0702: fElementDeclSubGroupAffFullName[chunk][index] = substitutionGroupFullName;
0703: }
0704: }
0705:
0706: protected void addElementDeclOneSubstitutionGroupQName(
0707: int elementDeclIndex, QName name, SchemaGrammar grammar,
0708: int eleIndex) {
0709: int chunk = elementDeclIndex >> CHUNK_SHIFT;
0710: int index = elementDeclIndex & CHUNK_MASK;
0711: ensureElementDeclCapacity(chunk);
0712: if (elementDeclIndex > -1) {
0713: if (fElementDeclSubGroupQNames[chunk][index] == null)
0714: fElementDeclSubGroupQNames[chunk][index] = new Vector();
0715: OneSubGroup oneGroup = new OneSubGroup();
0716: oneGroup.name = name;
0717: oneGroup.grammar = grammar;
0718: oneGroup.eleIndex = eleIndex;
0719: fElementDeclSubGroupQNames[chunk][index]
0720: .addElement(oneGroup);
0721: }
0722: }
0723:
0724: protected void setContentSpecMinOccurs(int contentSpecIndex,
0725: int minOccurs) {
0726: if (contentSpecIndex > -1) {
0727: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0728: int index = contentSpecIndex & CHUNK_MASK;
0729: ensureContentSpecCapacity(chunk);
0730: fContentSpecMinOccurs[chunk][index] = minOccurs;
0731: }
0732: }
0733:
0734: protected int getContentSpecMinOccurs(int contentSpecIndex) {
0735: if (contentSpecIndex > -1) {
0736: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0737: int index = contentSpecIndex & CHUNK_MASK;
0738: return fContentSpecMinOccurs[chunk][index];
0739: } else {
0740: return -1;
0741: }
0742: }
0743:
0744: protected int getContentSpecMaxOccurs(int contentSpecIndex) {
0745: if (contentSpecIndex > -1) {
0746: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0747: int index = contentSpecIndex & CHUNK_MASK;
0748: return fContentSpecMaxOccurs[chunk][index];
0749: } else {
0750: return -1;
0751: }
0752: }
0753:
0754: protected void setContentSpecMaxOccurs(int contentSpecIndex,
0755: int maxOccurs) {
0756: if (contentSpecIndex > -1) {
0757: int chunk = contentSpecIndex >> CHUNK_SHIFT;
0758: int index = contentSpecIndex & CHUNK_MASK;
0759: ensureContentSpecCapacity(chunk);
0760: fContentSpecMaxOccurs[chunk][index] = maxOccurs;
0761: }
0762: }
0763:
0764: //add methods for TraverseSchema
0765: /**
0766: *@return elementDecl Index,
0767: */
0768:
0769: protected int addElementDecl(QName eltQName, int enclosingScope,
0770: int scopeDefined, int contentSpecType,
0771: int contentSpecIndex, int attrListHead, DatatypeValidator dv) {
0772: int elementDeclIndex = getElementDeclIndex(eltQName,
0773: enclosingScope);
0774: if (elementDeclIndex == -1) {
0775: if (enclosingScope < -1 || scopeDefined < -1) {
0776: //TO DO: report error here;
0777: }
0778: fTempElementDecl.name.setValues(eltQName);
0779: fTempElementDecl.enclosingScope = enclosingScope;
0780: fTempElementDecl.type = contentSpecType;
0781: fTempElementDecl.contentSpecIndex = contentSpecIndex;
0782: fTempElementDecl.datatypeValidator = dv;
0783: //fTempElementDecl.firstAttributeDeclIndex = attrListHead;
0784: elementDeclIndex = createElementDecl();
0785: setElementDecl(elementDeclIndex, fTempElementDecl);
0786: setFirstAttributeDeclIndex(elementDeclIndex, attrListHead);
0787: //note, this is the scope defined by the element, not its enclosing scope
0788: setElementDefinedScope(elementDeclIndex, scopeDefined);
0789: }
0790:
0791: //debugging
0792: /*****
0793: XMLElementDecl fTempElementDecl = new XMLElementDecl();
0794: getElementDecl(elementDeclIndex, fTempElementDecl);
0795: System.out.println("elementDeclIndex in addElementDecl : " + elementDeclIndex
0796: + " \n and itsName : '"
0797: + (fTempElementDecl.name.localpart)
0798: +"' \n its ContentType:" + (fTempElementDecl.type)
0799: +"\n its ContentSpecIndex : " + fTempElementDecl.contentSpecIndex +"\n");
0800: /*****/
0801: return elementDeclIndex;
0802:
0803: }
0804:
0805: // Create a new elementdecl at a new scope, based on an existing decl
0806: protected int cloneElementDecl(int eltNdx, int enclosingScope,
0807: int scopeDefined) {
0808:
0809: getElementDecl(eltNdx, fTempElementDecl);
0810: TraverseSchema.ComplexTypeInfo typeInfo = getElementComplexTypeInfo(eltNdx);
0811: int blockSet = getElementDeclBlockSet(eltNdx);
0812: int finalSet = getElementDeclFinalSet(eltNdx);
0813: int elementMiscFlags = getElementDeclMiscFlags(eltNdx);
0814: String defaultStr = getElementDefaultValue(eltNdx);
0815: String subGroupName = getElementDeclSubstitutionGroupAffFullName(eltNdx);
0816: int attrListHead = getFirstAttributeDeclIndex(eltNdx);
0817: String anotherSchema = getElementFromAnotherSchemaURI(eltNdx);
0818:
0819: fTempElementDecl.enclosingScope = enclosingScope;
0820: int newElt = addElementDecl(fTempElementDecl.name,
0821: enclosingScope, scopeDefined, fTempElementDecl.type,
0822: fTempElementDecl.contentSpecIndex, attrListHead,
0823: fTempElementDecl.datatypeValidator);
0824:
0825: setElementComplexTypeInfo(newElt, typeInfo);
0826: setElementDeclBlockSet(newElt, blockSet);
0827: setElementDeclFinalSet(newElt, finalSet);
0828: setElementDeclMiscFlags(newElt, elementMiscFlags);
0829: setElementDefault(newElt, defaultStr);
0830: setElementFromAnotherSchemaURI(newElt, anotherSchema);
0831: return newElt;
0832:
0833: }
0834:
0835: /**
0836: *@return the new attribute List Head
0837: */
0838: protected void addAttDef(int templateElementIndex, QName attQName,
0839: int attType, int enumeration, int attDefaultType,
0840: String attDefaultValue, DatatypeValidator dv, boolean isList) {
0841: int attrDeclIndex = createAttributeDecl();
0842: fTempAttributeDecl.name.setValues(attQName);
0843: fTempAttributeDecl.datatypeValidator = dv;
0844: fTempAttributeDecl.type = attType;
0845: fTempAttributeDecl.defaultType = attDefaultType;
0846: fTempAttributeDecl.defaultValue = attDefaultValue;
0847: fTempAttributeDecl.list = isList;
0848: fTempAttributeDecl.enumeration = enumeration;
0849:
0850: super .setAttributeDecl(templateElementIndex, attrDeclIndex,
0851: fTempAttributeDecl);
0852: }
0853:
0854: public int getAttributeDeclIndex(int elementIndex, QName attribute) {
0855: if (elementIndex == -1) {
0856: return -1;
0857: }
0858: int attDefIndex = getFirstAttributeDeclIndex(elementIndex);
0859: return findAttributeDecl(attDefIndex, attribute);
0860:
0861: } // getAttributeDeclIndex (int,QName)
0862:
0863: public int findAttributeDecl(int attListHead, QName attribute) {
0864:
0865: int attDefIndex = attListHead;
0866: while (attDefIndex != -1) {
0867: getAttributeDecl(attDefIndex, fTempAttributeDecl);
0868: if (fTempAttributeDecl.name.localpart == attribute.localpart
0869: && fTempAttributeDecl.name.uri == attribute.uri) {
0870: return attDefIndex;
0871: }
0872: attDefIndex = getNextAttributeDeclIndex(attDefIndex);
0873: }
0874: return -1;
0875: }
0876:
0877: /**
0878: set the attribute decl index
0879: */
0880: protected void setFirstAttributeDeclIndex(int eltNdx,
0881: int attListHead) {
0882: super .setFirstAttributeDeclIndex(eltNdx, attListHead);
0883: }
0884:
0885: /**
0886: *@return the new contentSpec Index
0887: */
0888: protected int addContentSpecNode(int contentSpecType, int value,
0889: int otherValue, boolean mustBeUnique) {
0890: fTempContentSpecNode.type = contentSpecType;
0891: fTempContentSpecNode.value = value;
0892: fTempContentSpecNode.otherValue = otherValue;
0893:
0894: int contentSpecIndex = createContentSpec();
0895: setContentSpec(contentSpecIndex, fTempContentSpecNode);
0896: setContentSpecMinOccurs(contentSpecIndex, 1);
0897: setContentSpecMaxOccurs(contentSpecIndex, 1);
0898: return contentSpecIndex;
0899: }
0900:
0901: protected int expandContentModel(int index, int minOccurs,
0902: int maxOccurs) {
0903:
0904: int leafIndex = index;
0905:
0906: if (minOccurs == 1 && maxOccurs == 1) {
0907:
0908: } else if (minOccurs == 0 && maxOccurs == 1) {
0909: //zero or one
0910: index = addContentSpecNode(
0911: XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, index,
0912: -1, false);
0913: } else if (minOccurs == 0
0914: && maxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED) {
0915: //zero or more
0916: index = addContentSpecNode(
0917: XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, index,
0918: -1, false);
0919: } else if (minOccurs == 1
0920: && maxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED) {
0921: //one or more
0922: index = addContentSpecNode(
0923: XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, index,
0924: -1, false);
0925: } else if (maxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED) {
0926: if (minOccurs < 2) {
0927: //REVISIT
0928: }
0929:
0930: // => a,a,..,a+
0931: index = addContentSpecNode(
0932: XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, index,
0933: -1, false);
0934:
0935: for (int i = 0; i < (minOccurs - 1); i++) {
0936: index = addContentSpecNode(
0937: XMLContentSpec.CONTENTSPECNODE_SEQ, leafIndex,
0938: index, false);
0939: }
0940:
0941: } else {
0942: // {n,m} => a,a,a,...(a),(a),...
0943:
0944: if (minOccurs == 0) {
0945: int optional = addContentSpecNode(
0946: XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
0947: leafIndex, -1, false);
0948: index = optional;
0949: for (int i = 0; i < (maxOccurs - minOccurs - 1); i++) {
0950: index = addContentSpecNode(
0951: XMLContentSpec.CONTENTSPECNODE_SEQ, index,
0952: optional, false);
0953: }
0954: } else {
0955: for (int i = 0; i < (minOccurs - 1); i++) {
0956: index = addContentSpecNode(
0957: XMLContentSpec.CONTENTSPECNODE_SEQ, index,
0958: leafIndex, false);
0959: }
0960:
0961: int optional = addContentSpecNode(
0962: XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE,
0963: leafIndex, -1, false);
0964: for (int i = 0; i < (maxOccurs - minOccurs); i++) {
0965: index = addContentSpecNode(
0966: XMLContentSpec.CONTENTSPECNODE_SEQ, index,
0967: optional, false);
0968: }
0969: }
0970: }
0971:
0972: return index;
0973: }
0974:
0975: //
0976: // Private methods
0977: //
0978:
0979: // ensure capacity
0980:
0981: private boolean ensureContentSpecCapacity(int chunk) {
0982: try {
0983: return fContentSpecMinOccurs[chunk][0] == 0;
0984: } catch (ArrayIndexOutOfBoundsException ex) {
0985: fContentSpecMinOccurs = resize(fContentSpecMinOccurs,
0986: fContentSpecMinOccurs.length * 2);
0987: fContentSpecMaxOccurs = resize(fContentSpecMaxOccurs,
0988: fContentSpecMaxOccurs.length * 2);
0989: fContentSpecOrgUri = resize(fContentSpecOrgUri,
0990: fContentSpecOrgUri.length * 2);
0991: } catch (NullPointerException ex) {
0992: // ignore
0993: }
0994: fContentSpecMinOccurs[chunk] = new int[CHUNK_SIZE];
0995: fContentSpecMaxOccurs[chunk] = new int[CHUNK_SIZE];
0996: fContentSpecOrgUri[chunk] = new int[CHUNK_SIZE];
0997: return true;
0998: }
0999:
1000: private boolean ensureElementDeclCapacity(int chunk) {
1001: try {
1002: return fScopeDefinedByElement[chunk][0] == -2;
1003: } catch (ArrayIndexOutOfBoundsException ex) {
1004: fScopeDefinedByElement = resize(fScopeDefinedByElement,
1005: fScopeDefinedByElement.length * 2);
1006: fFromAnotherSchemaURI = resize(fFromAnotherSchemaURI,
1007: fFromAnotherSchemaURI.length * 2);
1008: fComplexTypeInfo = resize(fComplexTypeInfo,
1009: fComplexTypeInfo.length * 2);
1010: fElementDeclDefaultType = resize(fElementDeclDefaultType,
1011: fElementDeclDefaultType.length * 2);
1012: fElementDeclDefaultValue = resize(fElementDeclDefaultValue,
1013: fElementDeclDefaultValue.length * 2);
1014: fElementDeclBlockSet = resize(fElementDeclBlockSet,
1015: fElementDeclBlockSet.length * 2);
1016: fElementDeclFinalSet = resize(fElementDeclFinalSet,
1017: fElementDeclFinalSet.length * 2);
1018: fElementDeclMiscFlags = resize(fElementDeclMiscFlags,
1019: fElementDeclMiscFlags.length * 2);
1020: fElementDeclSubGroupAffFullName = resize(
1021: fElementDeclSubGroupAffFullName,
1022: fElementDeclSubGroupAffFullName.length * 2);
1023: fElementDeclSubGroupQNames = resize(
1024: fElementDeclSubGroupQNames,
1025: fElementDeclSubGroupQNames.length * 2);
1026: fElementDeclAllSubGroupQNames = resize(
1027: fElementDeclAllSubGroupQNames,
1028: fElementDeclAllSubGroupQNames.length * 2);
1029: fElementDeclAllSubGroupQNamesBlock = resize(
1030: fElementDeclAllSubGroupQNamesBlock,
1031: fElementDeclAllSubGroupQNamesBlock.length * 2);
1032: } catch (NullPointerException ex) {
1033: // ignore
1034: }
1035: fScopeDefinedByElement[chunk] = new int[CHUNK_SIZE];
1036: for (int i = 0; i < CHUNK_SIZE; i++) {
1037: fScopeDefinedByElement[chunk][i] = -2; //-1, 0 are all valid scope value.
1038: }
1039: fFromAnotherSchemaURI[chunk] = new String[CHUNK_SIZE];
1040: fComplexTypeInfo[chunk] = new TraverseSchema.ComplexTypeInfo[CHUNK_SIZE];
1041: fElementDeclDefaultType[chunk] = new int[CHUNK_SIZE];
1042: fElementDeclDefaultValue[chunk] = new String[CHUNK_SIZE];
1043: fElementDeclSubGroupAffFullName[chunk] = new String[CHUNK_SIZE];
1044: fElementDeclSubGroupQNames[chunk] = new Vector[CHUNK_SIZE];
1045: fElementDeclAllSubGroupQNames[chunk] = new Vector[CHUNK_SIZE];
1046: fElementDeclAllSubGroupQNamesBlock[chunk] = new Vector[CHUNK_SIZE];
1047: fElementDeclBlockSet[chunk] = new int[CHUNK_SIZE]; // initialized to 0
1048: fElementDeclFinalSet[chunk] = new int[CHUNK_SIZE]; // initialized to 0
1049: fElementDeclMiscFlags[chunk] = new int[CHUNK_SIZE]; // initialized to 0
1050: return true;
1051: }
1052:
1053: // resize initial chunk
1054:
1055: private int[][] resize(int array[][], int newsize) {
1056: int newarray[][] = new int[newsize][];
1057: System.arraycopy(array, 0, newarray, 0, array.length);
1058: return newarray;
1059: }
1060:
1061: private String[][] resize(String array[][], int newsize) {
1062: String newarray[][] = new String[newsize][];
1063: System.arraycopy(array, 0, newarray, 0, array.length);
1064: return newarray;
1065: }
1066:
1067: private TraverseSchema.ComplexTypeInfo[][] resize(
1068: TraverseSchema.ComplexTypeInfo array[][], int newsize) {
1069: TraverseSchema.ComplexTypeInfo newarray[][] = new TraverseSchema.ComplexTypeInfo[newsize][];
1070: System.arraycopy(array, 0, newarray, 0, array.length);
1071: return newarray;
1072: }
1073:
1074: private Vector[][] resize(Vector array[][], int newsize) {
1075: Vector newarray[][] = new Vector[newsize][];
1076: System.arraycopy(array, 0, newarray, 0, array.length);
1077: return newarray;
1078: }
1079:
1080: // make it public, so that other classes can access both qname and
1081: // grammar+index pair
1082: public class OneSubGroup {
1083: public QName name;
1084: SchemaGrammar grammar;
1085: int eleIndex;
1086: }
1087:
1088: // OneSubGroup + derivation/prohibited derivation method
1089: private class SubGroupBlockQName {
1090: public OneSubGroup name;
1091: public int method;
1092: public int pmethod;
1093: } // class IgnoreWhitespaceParser
1094: } // class SchemaGrammar
|