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.xs.traversers;
0019:
0020: import java.util.Enumeration;
0021: import java.util.Hashtable;
0022: import java.util.StringTokenizer;
0023: import java.util.Vector;
0024:
0025: import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
0026: import org.apache.xerces.impl.dv.XSSimpleType;
0027: import org.apache.xerces.impl.xs.SchemaGrammar;
0028: import org.apache.xerces.impl.xs.SchemaNamespaceSupport;
0029: import org.apache.xerces.impl.xs.SchemaSymbols;
0030: import org.apache.xerces.impl.xs.XSAttributeDecl;
0031: import org.apache.xerces.impl.xs.XSGrammarBucket;
0032: import org.apache.xerces.impl.xs.XSWildcardDecl;
0033: import org.apache.xerces.impl.xs.util.XInt;
0034: import org.apache.xerces.impl.xs.util.XIntPool;
0035: import org.apache.xerces.util.DOMUtil;
0036: import org.apache.xerces.util.SymbolTable;
0037: import org.apache.xerces.util.XMLChar;
0038: import org.apache.xerces.util.XMLSymbols;
0039: import org.apache.xerces.xni.QName;
0040: import org.apache.xerces.xs.XSConstants;
0041: import org.w3c.dom.Attr;
0042: import org.w3c.dom.Element;
0043:
0044: /**
0045: * Class <code>XSAttributeCheck</code> is used to check the validity of attributes
0046: * appearing in the schema document. It
0047: * - reports an error for invalid element (invalid namespace, invalid name)
0048: * - reports an error for invalid attribute (invalid namespace, invalid name)
0049: * - reports an error for invalid attribute value
0050: * - return compiled values for attriute values
0051: * - provide default value for missing optional attributes
0052: * - provide default value for incorrect attribute values
0053: *
0054: * But it's the caller's responsibility to check whether a required attribute
0055: * is present.
0056: *
0057: * Things need revisiting:
0058: * - Whether to return non-schema attributes/values
0059: * - Do we need to update NamespaceScope and ErrorReporter when reset()?
0060: * - Should have the datatype validators return compiled value
0061: * - use symbol table instead of many hashtables
0062: *
0063: * @xerces.internal
0064: *
0065: * @author Sandy Gao, IBM
0066: * @version $Id: XSAttributeChecker.java 471890 2006-11-06 22:00:18Z mrglavas $
0067: */
0068:
0069: public class XSAttributeChecker {
0070:
0071: // REVISIT: only local element and attribute are different from others.
0072: // it's possible to have either name or ref. all the others
0073: // are only allowed to have one of name or ref, or neither of them.
0074: // we'd better move such checking to the traverser.
0075: private static final String ELEMENT_N = "element_n";
0076: private static final String ELEMENT_R = "element_r";
0077: private static final String ATTRIBUTE_N = "attribute_n";
0078: private static final String ATTRIBUTE_R = "attribute_r";
0079:
0080: private static int ATTIDX_COUNT = 0;
0081: public static final int ATTIDX_ABSTRACT = ATTIDX_COUNT++;
0082: public static final int ATTIDX_AFORMDEFAULT = ATTIDX_COUNT++;
0083: public static final int ATTIDX_BASE = ATTIDX_COUNT++;
0084: public static final int ATTIDX_BLOCK = ATTIDX_COUNT++;
0085: public static final int ATTIDX_BLOCKDEFAULT = ATTIDX_COUNT++;
0086: public static final int ATTIDX_DEFAULT = ATTIDX_COUNT++;
0087: public static final int ATTIDX_EFORMDEFAULT = ATTIDX_COUNT++;
0088: public static final int ATTIDX_FINAL = ATTIDX_COUNT++;
0089: public static final int ATTIDX_FINALDEFAULT = ATTIDX_COUNT++;
0090: public static final int ATTIDX_FIXED = ATTIDX_COUNT++;
0091: public static final int ATTIDX_FORM = ATTIDX_COUNT++;
0092: public static final int ATTIDX_ID = ATTIDX_COUNT++;
0093: public static final int ATTIDX_ITEMTYPE = ATTIDX_COUNT++;
0094: public static final int ATTIDX_MAXOCCURS = ATTIDX_COUNT++;
0095: public static final int ATTIDX_MEMBERTYPES = ATTIDX_COUNT++;
0096: public static final int ATTIDX_MINOCCURS = ATTIDX_COUNT++;
0097: public static final int ATTIDX_MIXED = ATTIDX_COUNT++;
0098: public static final int ATTIDX_NAME = ATTIDX_COUNT++;
0099: public static final int ATTIDX_NAMESPACE = ATTIDX_COUNT++;
0100: public static final int ATTIDX_NAMESPACE_LIST = ATTIDX_COUNT++;
0101: public static final int ATTIDX_NILLABLE = ATTIDX_COUNT++;
0102: public static final int ATTIDX_NONSCHEMA = ATTIDX_COUNT++;
0103: public static final int ATTIDX_PROCESSCONTENTS = ATTIDX_COUNT++;
0104: public static final int ATTIDX_PUBLIC = ATTIDX_COUNT++;
0105: public static final int ATTIDX_REF = ATTIDX_COUNT++;
0106: public static final int ATTIDX_REFER = ATTIDX_COUNT++;
0107: public static final int ATTIDX_SCHEMALOCATION = ATTIDX_COUNT++;
0108: public static final int ATTIDX_SOURCE = ATTIDX_COUNT++;
0109: public static final int ATTIDX_SUBSGROUP = ATTIDX_COUNT++;
0110: public static final int ATTIDX_SYSTEM = ATTIDX_COUNT++;
0111: public static final int ATTIDX_TARGETNAMESPACE = ATTIDX_COUNT++;
0112: public static final int ATTIDX_TYPE = ATTIDX_COUNT++;
0113: public static final int ATTIDX_USE = ATTIDX_COUNT++;
0114: public static final int ATTIDX_VALUE = ATTIDX_COUNT++;
0115: public static final int ATTIDX_ENUMNSDECLS = ATTIDX_COUNT++;
0116: public static final int ATTIDX_VERSION = ATTIDX_COUNT++;
0117: public static final int ATTIDX_XML_LANG = ATTIDX_COUNT++;
0118: public static final int ATTIDX_XPATH = ATTIDX_COUNT++;
0119: public static final int ATTIDX_FROMDEFAULT = ATTIDX_COUNT++;
0120: //public static final int ATTIDX_OTHERVALUES = ATTIDX_COUNT++;
0121: public static final int ATTIDX_ISRETURNED = ATTIDX_COUNT++;
0122:
0123: private static final XIntPool fXIntPool = new XIntPool();
0124: // constants to return
0125: private static final XInt INT_QUALIFIED = fXIntPool
0126: .getXInt(SchemaSymbols.FORM_QUALIFIED);
0127: private static final XInt INT_UNQUALIFIED = fXIntPool
0128: .getXInt(SchemaSymbols.FORM_UNQUALIFIED);
0129: private static final XInt INT_EMPTY_SET = fXIntPool
0130: .getXInt(XSConstants.DERIVATION_NONE);
0131: private static final XInt INT_ANY_STRICT = fXIntPool
0132: .getXInt(XSWildcardDecl.PC_STRICT);
0133: private static final XInt INT_ANY_LAX = fXIntPool
0134: .getXInt(XSWildcardDecl.PC_LAX);
0135: private static final XInt INT_ANY_SKIP = fXIntPool
0136: .getXInt(XSWildcardDecl.PC_SKIP);
0137: private static final XInt INT_ANY_ANY = fXIntPool
0138: .getXInt(XSWildcardDecl.NSCONSTRAINT_ANY);
0139: private static final XInt INT_ANY_LIST = fXIntPool
0140: .getXInt(XSWildcardDecl.NSCONSTRAINT_LIST);
0141: private static final XInt INT_ANY_NOT = fXIntPool
0142: .getXInt(XSWildcardDecl.NSCONSTRAINT_NOT);
0143: private static final XInt INT_USE_OPTIONAL = fXIntPool
0144: .getXInt(SchemaSymbols.USE_OPTIONAL);
0145: private static final XInt INT_USE_REQUIRED = fXIntPool
0146: .getXInt(SchemaSymbols.USE_REQUIRED);
0147: private static final XInt INT_USE_PROHIBITED = fXIntPool
0148: .getXInt(SchemaSymbols.USE_PROHIBITED);
0149: private static final XInt INT_WS_PRESERVE = fXIntPool
0150: .getXInt(XSSimpleType.WS_PRESERVE);
0151: private static final XInt INT_WS_REPLACE = fXIntPool
0152: .getXInt(XSSimpleType.WS_REPLACE);
0153: private static final XInt INT_WS_COLLAPSE = fXIntPool
0154: .getXInt(XSSimpleType.WS_COLLAPSE);
0155: private static final XInt INT_UNBOUNDED = fXIntPool
0156: .getXInt(SchemaSymbols.OCCURRENCE_UNBOUNDED);
0157:
0158: // used to store the map from element name to attribute list
0159: // for 14 global elements
0160: private static final Hashtable fEleAttrsMapG = new Hashtable(29);
0161: // for 39 local elememnts
0162: private static final Hashtable fEleAttrsMapL = new Hashtable(79);
0163:
0164: // used to initialize fEleAttrsMap
0165: // step 1: all possible data types
0166: // DT_??? >= 0 : validate using a validator, which is initialized staticly
0167: // DT_??? < 0 : validate directly, which is done in "validate()"
0168:
0169: protected static final int DT_ANYURI = 0;
0170: protected static final int DT_ID = 1;
0171: protected static final int DT_QNAME = 2;
0172: protected static final int DT_STRING = 3;
0173: protected static final int DT_TOKEN = 4;
0174: protected static final int DT_NCNAME = 5;
0175: protected static final int DT_XPATH = 6;
0176: protected static final int DT_XPATH1 = 7;
0177: protected static final int DT_LANGUAGE = 8;
0178:
0179: // used to store extra datatype validators
0180: protected static final int DT_COUNT = DT_LANGUAGE + 1;
0181: private static final XSSimpleType[] fExtraDVs = new XSSimpleType[DT_COUNT];
0182: static {
0183: // step 5: register all datatype validators for new types
0184: SchemaGrammar grammar = SchemaGrammar.SG_SchemaNS;
0185: // anyURI
0186: fExtraDVs[DT_ANYURI] = (XSSimpleType) grammar
0187: .getGlobalTypeDecl(SchemaSymbols.ATTVAL_ANYURI);
0188: // ID
0189: fExtraDVs[DT_ID] = (XSSimpleType) grammar
0190: .getGlobalTypeDecl(SchemaSymbols.ATTVAL_ID);
0191: // QName
0192: fExtraDVs[DT_QNAME] = (XSSimpleType) grammar
0193: .getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME);
0194: // string
0195: fExtraDVs[DT_STRING] = (XSSimpleType) grammar
0196: .getGlobalTypeDecl(SchemaSymbols.ATTVAL_STRING);
0197: // token
0198: fExtraDVs[DT_TOKEN] = (XSSimpleType) grammar
0199: .getGlobalTypeDecl(SchemaSymbols.ATTVAL_TOKEN);
0200: // NCName
0201: fExtraDVs[DT_NCNAME] = (XSSimpleType) grammar
0202: .getGlobalTypeDecl(SchemaSymbols.ATTVAL_NCNAME);
0203: // xpath = a subset of XPath expression
0204: fExtraDVs[DT_XPATH] = fExtraDVs[DT_STRING];
0205: // xpath = a subset of XPath expression
0206: fExtraDVs[DT_XPATH] = fExtraDVs[DT_STRING];
0207: // language
0208: fExtraDVs[DT_LANGUAGE] = (XSSimpleType) grammar
0209: .getGlobalTypeDecl(SchemaSymbols.ATTVAL_LANGUAGE);
0210: }
0211:
0212: protected static final int DT_BLOCK = -1;
0213: protected static final int DT_BLOCK1 = -2;
0214: protected static final int DT_FINAL = -3;
0215: protected static final int DT_FINAL1 = -4;
0216: protected static final int DT_FINAL2 = -5;
0217: protected static final int DT_FORM = -6;
0218: protected static final int DT_MAXOCCURS = -7;
0219: protected static final int DT_MAXOCCURS1 = -8;
0220: protected static final int DT_MEMBERTYPES = -9;
0221: protected static final int DT_MINOCCURS1 = -10;
0222: protected static final int DT_NAMESPACE = -11;
0223: protected static final int DT_PROCESSCONTENTS = -12;
0224: protected static final int DT_USE = -13;
0225: protected static final int DT_WHITESPACE = -14;
0226: protected static final int DT_BOOLEAN = -15;
0227: protected static final int DT_NONNEGINT = -16;
0228: protected static final int DT_POSINT = -17;
0229:
0230: static {
0231: // step 2: all possible attributes for all elements
0232: int attCount = 0;
0233: int ATT_ABSTRACT_D = attCount++;
0234: int ATT_ATTRIBUTE_FD_D = attCount++;
0235: int ATT_BASE_R = attCount++;
0236: int ATT_BASE_N = attCount++;
0237: int ATT_BLOCK_N = attCount++;
0238: int ATT_BLOCK1_N = attCount++;
0239: int ATT_BLOCK_D_D = attCount++;
0240: int ATT_DEFAULT_N = attCount++;
0241: int ATT_ELEMENT_FD_D = attCount++;
0242: int ATT_FINAL_N = attCount++;
0243: int ATT_FINAL1_N = attCount++;
0244: int ATT_FINAL_D_D = attCount++;
0245: int ATT_FIXED_N = attCount++;
0246: int ATT_FIXED_D = attCount++;
0247: int ATT_FORM_N = attCount++;
0248: int ATT_ID_N = attCount++;
0249: int ATT_ITEMTYPE_N = attCount++;
0250: int ATT_MAXOCCURS_D = attCount++;
0251: int ATT_MAXOCCURS1_D = attCount++;
0252: int ATT_MEMBER_T_N = attCount++;
0253: int ATT_MINOCCURS_D = attCount++;
0254: int ATT_MINOCCURS1_D = attCount++;
0255: int ATT_MIXED_D = attCount++;
0256: int ATT_MIXED_N = attCount++;
0257: int ATT_NAME_R = attCount++;
0258: int ATT_NAMESPACE_D = attCount++;
0259: int ATT_NAMESPACE_N = attCount++;
0260: int ATT_NILLABLE_D = attCount++;
0261: int ATT_PROCESS_C_D = attCount++;
0262: int ATT_PUBLIC_R = attCount++;
0263: int ATT_REF_R = attCount++;
0264: int ATT_REFER_R = attCount++;
0265: int ATT_SCHEMA_L_R = attCount++;
0266: int ATT_SCHEMA_L_N = attCount++;
0267: int ATT_SOURCE_N = attCount++;
0268: int ATT_SUBSTITUTION_G_N = attCount++;
0269: int ATT_SYSTEM_N = attCount++;
0270: int ATT_TARGET_N_N = attCount++;
0271: int ATT_TYPE_N = attCount++;
0272: int ATT_USE_D = attCount++;
0273: int ATT_VALUE_NNI_N = attCount++;
0274: int ATT_VALUE_PI_N = attCount++;
0275: int ATT_VALUE_STR_N = attCount++;
0276: int ATT_VALUE_WS_N = attCount++;
0277: int ATT_VERSION_N = attCount++;
0278: int ATT_XML_LANG = attCount++;
0279: int ATT_XPATH_R = attCount++;
0280: int ATT_XPATH1_R = attCount++;
0281:
0282: // step 3: store all these attributes in an array
0283: OneAttr[] allAttrs = new OneAttr[attCount];
0284: allAttrs[ATT_ABSTRACT_D] = new OneAttr(
0285: SchemaSymbols.ATT_ABSTRACT, DT_BOOLEAN,
0286: ATTIDX_ABSTRACT, Boolean.FALSE);
0287: allAttrs[ATT_ATTRIBUTE_FD_D] = new OneAttr(
0288: SchemaSymbols.ATT_ATTRIBUTEFORMDEFAULT, DT_FORM,
0289: ATTIDX_AFORMDEFAULT, INT_UNQUALIFIED);
0290: allAttrs[ATT_BASE_R] = new OneAttr(SchemaSymbols.ATT_BASE,
0291: DT_QNAME, ATTIDX_BASE, null);
0292: allAttrs[ATT_BASE_N] = new OneAttr(SchemaSymbols.ATT_BASE,
0293: DT_QNAME, ATTIDX_BASE, null);
0294: allAttrs[ATT_BLOCK_N] = new OneAttr(SchemaSymbols.ATT_BLOCK,
0295: DT_BLOCK, ATTIDX_BLOCK, null);
0296: allAttrs[ATT_BLOCK1_N] = new OneAttr(SchemaSymbols.ATT_BLOCK,
0297: DT_BLOCK1, ATTIDX_BLOCK, null);
0298: allAttrs[ATT_BLOCK_D_D] = new OneAttr(
0299: SchemaSymbols.ATT_BLOCKDEFAULT, DT_BLOCK,
0300: ATTIDX_BLOCKDEFAULT, INT_EMPTY_SET);
0301: allAttrs[ATT_DEFAULT_N] = new OneAttr(
0302: SchemaSymbols.ATT_DEFAULT, DT_STRING, ATTIDX_DEFAULT,
0303: null);
0304: allAttrs[ATT_ELEMENT_FD_D] = new OneAttr(
0305: SchemaSymbols.ATT_ELEMENTFORMDEFAULT, DT_FORM,
0306: ATTIDX_EFORMDEFAULT, INT_UNQUALIFIED);
0307: allAttrs[ATT_FINAL_N] = new OneAttr(SchemaSymbols.ATT_FINAL,
0308: DT_FINAL, ATTIDX_FINAL, null);
0309: allAttrs[ATT_FINAL1_N] = new OneAttr(SchemaSymbols.ATT_FINAL,
0310: DT_FINAL1, ATTIDX_FINAL, null);
0311: allAttrs[ATT_FINAL_D_D] = new OneAttr(
0312: SchemaSymbols.ATT_FINALDEFAULT, DT_FINAL2,
0313: ATTIDX_FINALDEFAULT, INT_EMPTY_SET);
0314: allAttrs[ATT_FIXED_N] = new OneAttr(SchemaSymbols.ATT_FIXED,
0315: DT_STRING, ATTIDX_FIXED, null);
0316: allAttrs[ATT_FIXED_D] = new OneAttr(SchemaSymbols.ATT_FIXED,
0317: DT_BOOLEAN, ATTIDX_FIXED, Boolean.FALSE);
0318: allAttrs[ATT_FORM_N] = new OneAttr(SchemaSymbols.ATT_FORM,
0319: DT_FORM, ATTIDX_FORM, null);
0320: allAttrs[ATT_ID_N] = new OneAttr(SchemaSymbols.ATT_ID, DT_ID,
0321: ATTIDX_ID, null);
0322: allAttrs[ATT_ITEMTYPE_N] = new OneAttr(
0323: SchemaSymbols.ATT_ITEMTYPE, DT_QNAME, ATTIDX_ITEMTYPE,
0324: null);
0325: allAttrs[ATT_MAXOCCURS_D] = new OneAttr(
0326: SchemaSymbols.ATT_MAXOCCURS, DT_MAXOCCURS,
0327: ATTIDX_MAXOCCURS, fXIntPool.getXInt(1));
0328: allAttrs[ATT_MAXOCCURS1_D] = new OneAttr(
0329: SchemaSymbols.ATT_MAXOCCURS, DT_MAXOCCURS1,
0330: ATTIDX_MAXOCCURS, fXIntPool.getXInt(1));
0331: allAttrs[ATT_MEMBER_T_N] = new OneAttr(
0332: SchemaSymbols.ATT_MEMBERTYPES, DT_MEMBERTYPES,
0333: ATTIDX_MEMBERTYPES, null);
0334: allAttrs[ATT_MINOCCURS_D] = new OneAttr(
0335: SchemaSymbols.ATT_MINOCCURS, DT_NONNEGINT,
0336: ATTIDX_MINOCCURS, fXIntPool.getXInt(1));
0337: allAttrs[ATT_MINOCCURS1_D] = new OneAttr(
0338: SchemaSymbols.ATT_MINOCCURS, DT_MINOCCURS1,
0339: ATTIDX_MINOCCURS, fXIntPool.getXInt(1));
0340: allAttrs[ATT_MIXED_D] = new OneAttr(SchemaSymbols.ATT_MIXED,
0341: DT_BOOLEAN, ATTIDX_MIXED, Boolean.FALSE);
0342: allAttrs[ATT_MIXED_N] = new OneAttr(SchemaSymbols.ATT_MIXED,
0343: DT_BOOLEAN, ATTIDX_MIXED, null);
0344: allAttrs[ATT_NAME_R] = new OneAttr(SchemaSymbols.ATT_NAME,
0345: DT_NCNAME, ATTIDX_NAME, null);
0346: allAttrs[ATT_NAMESPACE_D] = new OneAttr(
0347: SchemaSymbols.ATT_NAMESPACE, DT_NAMESPACE,
0348: ATTIDX_NAMESPACE, INT_ANY_ANY);
0349: allAttrs[ATT_NAMESPACE_N] = new OneAttr(
0350: SchemaSymbols.ATT_NAMESPACE, DT_ANYURI,
0351: ATTIDX_NAMESPACE, null);
0352: allAttrs[ATT_NILLABLE_D] = new OneAttr(
0353: SchemaSymbols.ATT_NILLABLE, DT_BOOLEAN,
0354: ATTIDX_NILLABLE, Boolean.FALSE);
0355: allAttrs[ATT_PROCESS_C_D] = new OneAttr(
0356: SchemaSymbols.ATT_PROCESSCONTENTS, DT_PROCESSCONTENTS,
0357: ATTIDX_PROCESSCONTENTS, INT_ANY_STRICT);
0358: allAttrs[ATT_PUBLIC_R] = new OneAttr(SchemaSymbols.ATT_PUBLIC,
0359: DT_TOKEN, ATTIDX_PUBLIC, null);
0360: allAttrs[ATT_REF_R] = new OneAttr(SchemaSymbols.ATT_REF,
0361: DT_QNAME, ATTIDX_REF, null);
0362: allAttrs[ATT_REFER_R] = new OneAttr(SchemaSymbols.ATT_REFER,
0363: DT_QNAME, ATTIDX_REFER, null);
0364: allAttrs[ATT_SCHEMA_L_R] = new OneAttr(
0365: SchemaSymbols.ATT_SCHEMALOCATION, DT_ANYURI,
0366: ATTIDX_SCHEMALOCATION, null);
0367: allAttrs[ATT_SCHEMA_L_N] = new OneAttr(
0368: SchemaSymbols.ATT_SCHEMALOCATION, DT_ANYURI,
0369: ATTIDX_SCHEMALOCATION, null);
0370: allAttrs[ATT_SOURCE_N] = new OneAttr(SchemaSymbols.ATT_SOURCE,
0371: DT_ANYURI, ATTIDX_SOURCE, null);
0372: allAttrs[ATT_SUBSTITUTION_G_N] = new OneAttr(
0373: SchemaSymbols.ATT_SUBSTITUTIONGROUP, DT_QNAME,
0374: ATTIDX_SUBSGROUP, null);
0375: allAttrs[ATT_SYSTEM_N] = new OneAttr(SchemaSymbols.ATT_SYSTEM,
0376: DT_ANYURI, ATTIDX_SYSTEM, null);
0377: allAttrs[ATT_TARGET_N_N] = new OneAttr(
0378: SchemaSymbols.ATT_TARGETNAMESPACE, DT_ANYURI,
0379: ATTIDX_TARGETNAMESPACE, null);
0380: allAttrs[ATT_TYPE_N] = new OneAttr(SchemaSymbols.ATT_TYPE,
0381: DT_QNAME, ATTIDX_TYPE, null);
0382: allAttrs[ATT_USE_D] = new OneAttr(SchemaSymbols.ATT_USE,
0383: DT_USE, ATTIDX_USE, INT_USE_OPTIONAL);
0384: allAttrs[ATT_VALUE_NNI_N] = new OneAttr(
0385: SchemaSymbols.ATT_VALUE, DT_NONNEGINT, ATTIDX_VALUE,
0386: null);
0387: allAttrs[ATT_VALUE_PI_N] = new OneAttr(SchemaSymbols.ATT_VALUE,
0388: DT_POSINT, ATTIDX_VALUE, null);
0389: allAttrs[ATT_VALUE_STR_N] = new OneAttr(
0390: SchemaSymbols.ATT_VALUE, DT_STRING, ATTIDX_VALUE, null);
0391: allAttrs[ATT_VALUE_WS_N] = new OneAttr(SchemaSymbols.ATT_VALUE,
0392: DT_WHITESPACE, ATTIDX_VALUE, null);
0393: allAttrs[ATT_VERSION_N] = new OneAttr(
0394: SchemaSymbols.ATT_VERSION, DT_TOKEN, ATTIDX_VERSION,
0395: null);
0396: allAttrs[ATT_XML_LANG] = new OneAttr(
0397: SchemaSymbols.ATT_XML_LANG, DT_LANGUAGE,
0398: ATTIDX_XML_LANG, null);
0399: allAttrs[ATT_XPATH_R] = new OneAttr(SchemaSymbols.ATT_XPATH,
0400: DT_XPATH, ATTIDX_XPATH, null);
0401: allAttrs[ATT_XPATH1_R] = new OneAttr(SchemaSymbols.ATT_XPATH,
0402: DT_XPATH1, ATTIDX_XPATH, null);
0403:
0404: // step 4: for each element, make a list of possible attributes
0405: Container attrList;
0406:
0407: // for element "attribute" - global
0408: attrList = Container.getContainer(5);
0409: // default = string
0410: attrList
0411: .put(SchemaSymbols.ATT_DEFAULT, allAttrs[ATT_DEFAULT_N]);
0412: // fixed = string
0413: attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_N]);
0414: // id = ID
0415: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0416: // name = NCName
0417: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0418: // type = QName
0419: attrList.put(SchemaSymbols.ATT_TYPE, allAttrs[ATT_TYPE_N]);
0420: fEleAttrsMapG.put(SchemaSymbols.ELT_ATTRIBUTE, attrList);
0421:
0422: // for element "attribute" - local name
0423: attrList = Container.getContainer(7);
0424: // default = string
0425: attrList
0426: .put(SchemaSymbols.ATT_DEFAULT, allAttrs[ATT_DEFAULT_N]);
0427: // fixed = string
0428: attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_N]);
0429: // form = (qualified | unqualified)
0430: attrList.put(SchemaSymbols.ATT_FORM, allAttrs[ATT_FORM_N]);
0431: // id = ID
0432: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0433: // name = NCName
0434: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0435: // type = QName
0436: attrList.put(SchemaSymbols.ATT_TYPE, allAttrs[ATT_TYPE_N]);
0437: // use = (optional | prohibited | required) : optional
0438: attrList.put(SchemaSymbols.ATT_USE, allAttrs[ATT_USE_D]);
0439: fEleAttrsMapL.put(ATTRIBUTE_N, attrList);
0440:
0441: // for element "attribute" - local ref
0442: attrList = Container.getContainer(5);
0443: // default = string
0444: attrList
0445: .put(SchemaSymbols.ATT_DEFAULT, allAttrs[ATT_DEFAULT_N]);
0446: // fixed = string
0447: attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_N]);
0448: // id = ID
0449: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0450: // ref = QName
0451: attrList.put(SchemaSymbols.ATT_REF, allAttrs[ATT_REF_R]);
0452: // use = (optional | prohibited | required) : optional
0453: attrList.put(SchemaSymbols.ATT_USE, allAttrs[ATT_USE_D]);
0454: fEleAttrsMapL.put(ATTRIBUTE_R, attrList);
0455:
0456: // for element "element" - global
0457: attrList = Container.getContainer(10);
0458: // abstract = boolean : false
0459: attrList.put(SchemaSymbols.ATT_ABSTRACT,
0460: allAttrs[ATT_ABSTRACT_D]);
0461: // block = (#all | List of (extension | restriction | substitution))
0462: attrList.put(SchemaSymbols.ATT_BLOCK, allAttrs[ATT_BLOCK_N]);
0463: // default = string
0464: attrList
0465: .put(SchemaSymbols.ATT_DEFAULT, allAttrs[ATT_DEFAULT_N]);
0466: // final = (#all | List of (extension | restriction))
0467: attrList.put(SchemaSymbols.ATT_FINAL, allAttrs[ATT_FINAL_N]);
0468: // fixed = string
0469: attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_N]);
0470: // id = ID
0471: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0472: // name = NCName
0473: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0474: // nillable = boolean : false
0475: attrList.put(SchemaSymbols.ATT_NILLABLE,
0476: allAttrs[ATT_NILLABLE_D]);
0477: // substitutionGroup = QName
0478: attrList.put(SchemaSymbols.ATT_SUBSTITUTIONGROUP,
0479: allAttrs[ATT_SUBSTITUTION_G_N]);
0480: // type = QName
0481: attrList.put(SchemaSymbols.ATT_TYPE, allAttrs[ATT_TYPE_N]);
0482: fEleAttrsMapG.put(SchemaSymbols.ELT_ELEMENT, attrList);
0483:
0484: // for element "element" - local name
0485: attrList = Container.getContainer(10);
0486: // block = (#all | List of (extension | restriction | substitution))
0487: attrList.put(SchemaSymbols.ATT_BLOCK, allAttrs[ATT_BLOCK_N]);
0488: // default = string
0489: attrList
0490: .put(SchemaSymbols.ATT_DEFAULT, allAttrs[ATT_DEFAULT_N]);
0491: // fixed = string
0492: attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_N]);
0493: // form = (qualified | unqualified)
0494: attrList.put(SchemaSymbols.ATT_FORM, allAttrs[ATT_FORM_N]);
0495: // id = ID
0496: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0497: // maxOccurs = (nonNegativeInteger | unbounded) : 1
0498: attrList.put(SchemaSymbols.ATT_MAXOCCURS,
0499: allAttrs[ATT_MAXOCCURS_D]);
0500: // minOccurs = nonNegativeInteger : 1
0501: attrList.put(SchemaSymbols.ATT_MINOCCURS,
0502: allAttrs[ATT_MINOCCURS_D]);
0503: // name = NCName
0504: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0505: // nillable = boolean : false
0506: attrList.put(SchemaSymbols.ATT_NILLABLE,
0507: allAttrs[ATT_NILLABLE_D]);
0508: // type = QName
0509: attrList.put(SchemaSymbols.ATT_TYPE, allAttrs[ATT_TYPE_N]);
0510: fEleAttrsMapL.put(ELEMENT_N, attrList);
0511:
0512: // for element "element" - local ref
0513: attrList = Container.getContainer(4);
0514: // id = ID
0515: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0516: // maxOccurs = (nonNegativeInteger | unbounded) : 1
0517: attrList.put(SchemaSymbols.ATT_MAXOCCURS,
0518: allAttrs[ATT_MAXOCCURS_D]);
0519: // minOccurs = nonNegativeInteger : 1
0520: attrList.put(SchemaSymbols.ATT_MINOCCURS,
0521: allAttrs[ATT_MINOCCURS_D]);
0522: // ref = QName
0523: attrList.put(SchemaSymbols.ATT_REF, allAttrs[ATT_REF_R]);
0524: fEleAttrsMapL.put(ELEMENT_R, attrList);
0525:
0526: // for element "complexType" - global
0527: attrList = Container.getContainer(6);
0528: // abstract = boolean : false
0529: attrList.put(SchemaSymbols.ATT_ABSTRACT,
0530: allAttrs[ATT_ABSTRACT_D]);
0531: // block = (#all | List of (extension | restriction))
0532: attrList.put(SchemaSymbols.ATT_BLOCK, allAttrs[ATT_BLOCK1_N]);
0533: // final = (#all | List of (extension | restriction))
0534: attrList.put(SchemaSymbols.ATT_FINAL, allAttrs[ATT_FINAL_N]);
0535: // id = ID
0536: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0537: // mixed = boolean : false
0538: attrList.put(SchemaSymbols.ATT_MIXED, allAttrs[ATT_MIXED_D]);
0539: // name = NCName
0540: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0541: fEleAttrsMapG.put(SchemaSymbols.ELT_COMPLEXTYPE, attrList);
0542:
0543: // for element "notation" - global
0544: attrList = Container.getContainer(4);
0545: // id = ID
0546: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0547: // name = NCName
0548: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0549: // public = A public identifier, per ISO 8879
0550: attrList.put(SchemaSymbols.ATT_PUBLIC, allAttrs[ATT_PUBLIC_R]);
0551: // system = anyURI
0552: attrList.put(SchemaSymbols.ATT_SYSTEM, allAttrs[ATT_SYSTEM_N]);
0553: fEleAttrsMapG.put(SchemaSymbols.ELT_NOTATION, attrList);
0554:
0555: // for element "complexType" - local
0556: attrList = Container.getContainer(2);
0557: // id = ID
0558: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0559: // mixed = boolean : false
0560: attrList.put(SchemaSymbols.ATT_MIXED, allAttrs[ATT_MIXED_D]);
0561: fEleAttrsMapL.put(SchemaSymbols.ELT_COMPLEXTYPE, attrList);
0562:
0563: // for element "simpleContent" - local
0564: attrList = Container.getContainer(1);
0565: // id = ID
0566: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0567: fEleAttrsMapL.put(SchemaSymbols.ELT_SIMPLECONTENT, attrList);
0568:
0569: // for element "restriction" - local
0570: attrList = Container.getContainer(2);
0571: // base = QName
0572: attrList.put(SchemaSymbols.ATT_BASE, allAttrs[ATT_BASE_N]);
0573: // id = ID
0574: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0575: fEleAttrsMapL.put(SchemaSymbols.ELT_RESTRICTION, attrList);
0576:
0577: // for element "extension" - local
0578: attrList = Container.getContainer(2);
0579: // base = QName
0580: attrList.put(SchemaSymbols.ATT_BASE, allAttrs[ATT_BASE_R]);
0581: // id = ID
0582: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0583: fEleAttrsMapL.put(SchemaSymbols.ELT_EXTENSION, attrList);
0584:
0585: // for element "attributeGroup" - local ref
0586: attrList = Container.getContainer(2);
0587: // id = ID
0588: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0589: // ref = QName
0590: attrList.put(SchemaSymbols.ATT_REF, allAttrs[ATT_REF_R]);
0591: fEleAttrsMapL.put(SchemaSymbols.ELT_ATTRIBUTEGROUP, attrList);
0592:
0593: // for element "anyAttribute" - local
0594: attrList = Container.getContainer(3);
0595: // id = ID
0596: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0597: // namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) ) : ##any
0598: attrList.put(SchemaSymbols.ATT_NAMESPACE,
0599: allAttrs[ATT_NAMESPACE_D]);
0600: // processContents = (lax | skip | strict) : strict
0601: attrList.put(SchemaSymbols.ATT_PROCESSCONTENTS,
0602: allAttrs[ATT_PROCESS_C_D]);
0603: fEleAttrsMapL.put(SchemaSymbols.ELT_ANYATTRIBUTE, attrList);
0604:
0605: // for element "complexContent" - local
0606: attrList = Container.getContainer(2);
0607: // id = ID
0608: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0609: // mixed = boolean
0610: attrList.put(SchemaSymbols.ATT_MIXED, allAttrs[ATT_MIXED_N]);
0611: fEleAttrsMapL.put(SchemaSymbols.ELT_COMPLEXCONTENT, attrList);
0612:
0613: // for element "attributeGroup" - global
0614: attrList = Container.getContainer(2);
0615: // id = ID
0616: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0617: // name = NCName
0618: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0619: fEleAttrsMapG.put(SchemaSymbols.ELT_ATTRIBUTEGROUP, attrList);
0620:
0621: // for element "group" - global
0622: attrList = Container.getContainer(2);
0623: // id = ID
0624: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0625: // name = NCName
0626: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0627: fEleAttrsMapG.put(SchemaSymbols.ELT_GROUP, attrList);
0628:
0629: // for element "group" - local ref
0630: attrList = Container.getContainer(4);
0631: // id = ID
0632: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0633: // maxOccurs = (nonNegativeInteger | unbounded) : 1
0634: attrList.put(SchemaSymbols.ATT_MAXOCCURS,
0635: allAttrs[ATT_MAXOCCURS_D]);
0636: // minOccurs = nonNegativeInteger : 1
0637: attrList.put(SchemaSymbols.ATT_MINOCCURS,
0638: allAttrs[ATT_MINOCCURS_D]);
0639: // ref = QName
0640: attrList.put(SchemaSymbols.ATT_REF, allAttrs[ATT_REF_R]);
0641: fEleAttrsMapL.put(SchemaSymbols.ELT_GROUP, attrList);
0642:
0643: // for element "all" - local
0644: attrList = Container.getContainer(3);
0645: // id = ID
0646: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0647: // maxOccurs = 1 : 1
0648: attrList.put(SchemaSymbols.ATT_MAXOCCURS,
0649: allAttrs[ATT_MAXOCCURS1_D]);
0650: // minOccurs = (0 | 1) : 1
0651: attrList.put(SchemaSymbols.ATT_MINOCCURS,
0652: allAttrs[ATT_MINOCCURS1_D]);
0653: fEleAttrsMapL.put(SchemaSymbols.ELT_ALL, attrList);
0654:
0655: // for element "choice" - local
0656: attrList = Container.getContainer(3);
0657: // id = ID
0658: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0659: // maxOccurs = (nonNegativeInteger | unbounded) : 1
0660: attrList.put(SchemaSymbols.ATT_MAXOCCURS,
0661: allAttrs[ATT_MAXOCCURS_D]);
0662: // minOccurs = nonNegativeInteger : 1
0663: attrList.put(SchemaSymbols.ATT_MINOCCURS,
0664: allAttrs[ATT_MINOCCURS_D]);
0665: fEleAttrsMapL.put(SchemaSymbols.ELT_CHOICE, attrList);
0666: // for element "sequence" - local
0667: fEleAttrsMapL.put(SchemaSymbols.ELT_SEQUENCE, attrList);
0668:
0669: // for element "any" - local
0670: attrList = Container.getContainer(5);
0671: // id = ID
0672: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0673: // maxOccurs = (nonNegativeInteger | unbounded) : 1
0674: attrList.put(SchemaSymbols.ATT_MAXOCCURS,
0675: allAttrs[ATT_MAXOCCURS_D]);
0676: // minOccurs = nonNegativeInteger : 1
0677: attrList.put(SchemaSymbols.ATT_MINOCCURS,
0678: allAttrs[ATT_MINOCCURS_D]);
0679: // namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) ) : ##any
0680: attrList.put(SchemaSymbols.ATT_NAMESPACE,
0681: allAttrs[ATT_NAMESPACE_D]);
0682: // processContents = (lax | skip | strict) : strict
0683: attrList.put(SchemaSymbols.ATT_PROCESSCONTENTS,
0684: allAttrs[ATT_PROCESS_C_D]);
0685: fEleAttrsMapL.put(SchemaSymbols.ELT_ANY, attrList);
0686:
0687: // for element "unique" - local
0688: attrList = Container.getContainer(2);
0689: // id = ID
0690: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0691: // name = NCName
0692: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0693: fEleAttrsMapL.put(SchemaSymbols.ELT_UNIQUE, attrList);
0694: // for element "key" - local
0695: fEleAttrsMapL.put(SchemaSymbols.ELT_KEY, attrList);
0696:
0697: // for element "keyref" - local
0698: attrList = Container.getContainer(3);
0699: // id = ID
0700: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0701: // name = NCName
0702: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0703: // refer = QName
0704: attrList.put(SchemaSymbols.ATT_REFER, allAttrs[ATT_REFER_R]);
0705: fEleAttrsMapL.put(SchemaSymbols.ELT_KEYREF, attrList);
0706:
0707: // for element "selector" - local
0708: attrList = Container.getContainer(2);
0709: // id = ID
0710: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0711: // xpath = a subset of XPath expression
0712: attrList.put(SchemaSymbols.ATT_XPATH, allAttrs[ATT_XPATH_R]);
0713: fEleAttrsMapL.put(SchemaSymbols.ELT_SELECTOR, attrList);
0714:
0715: // for element "field" - local
0716: attrList = Container.getContainer(2);
0717: // id = ID
0718: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0719: // xpath = a subset of XPath expression
0720: attrList.put(SchemaSymbols.ATT_XPATH, allAttrs[ATT_XPATH1_R]);
0721: fEleAttrsMapL.put(SchemaSymbols.ELT_FIELD, attrList);
0722:
0723: // for element "annotation" - global
0724: attrList = Container.getContainer(1);
0725: // id = ID
0726: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0727: fEleAttrsMapG.put(SchemaSymbols.ELT_ANNOTATION, attrList);
0728: // for element "annotation" - local
0729: fEleAttrsMapL.put(SchemaSymbols.ELT_ANNOTATION, attrList);
0730:
0731: // for element "appinfo" - local
0732: attrList = Container.getContainer(1);
0733: // source = anyURI
0734: attrList.put(SchemaSymbols.ATT_SOURCE, allAttrs[ATT_SOURCE_N]);
0735: fEleAttrsMapG.put(SchemaSymbols.ELT_APPINFO, attrList);
0736: fEleAttrsMapL.put(SchemaSymbols.ELT_APPINFO, attrList);
0737:
0738: // for element "documentation" - local
0739: attrList = Container.getContainer(2);
0740: // source = anyURI
0741: attrList.put(SchemaSymbols.ATT_SOURCE, allAttrs[ATT_SOURCE_N]);
0742: // xml:lang = language
0743: attrList
0744: .put(SchemaSymbols.ATT_XML_LANG, allAttrs[ATT_XML_LANG]);
0745: fEleAttrsMapG.put(SchemaSymbols.ELT_DOCUMENTATION, attrList);
0746: fEleAttrsMapL.put(SchemaSymbols.ELT_DOCUMENTATION, attrList);
0747:
0748: // for element "simpleType" - global
0749: attrList = Container.getContainer(3);
0750: // final = (#all | List of (list | union | restriction))
0751: attrList.put(SchemaSymbols.ATT_FINAL, allAttrs[ATT_FINAL1_N]);
0752: // id = ID
0753: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0754: // name = NCName
0755: attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]);
0756: fEleAttrsMapG.put(SchemaSymbols.ELT_SIMPLETYPE, attrList);
0757:
0758: // for element "simpleType" - local
0759: attrList = Container.getContainer(2);
0760: // final = (#all | List of (list | union | restriction))
0761: attrList.put(SchemaSymbols.ATT_FINAL, allAttrs[ATT_FINAL1_N]);
0762: // id = ID
0763: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0764: fEleAttrsMapL.put(SchemaSymbols.ELT_SIMPLETYPE, attrList);
0765:
0766: // for element "restriction" - local
0767: // already registered for complexType
0768:
0769: // for element "list" - local
0770: attrList = Container.getContainer(2);
0771: // id = ID
0772: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0773: // itemType = QName
0774: attrList.put(SchemaSymbols.ATT_ITEMTYPE,
0775: allAttrs[ATT_ITEMTYPE_N]);
0776: fEleAttrsMapL.put(SchemaSymbols.ELT_LIST, attrList);
0777:
0778: // for element "union" - local
0779: attrList = Container.getContainer(2);
0780: // id = ID
0781: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0782: // memberTypes = List of QName
0783: attrList.put(SchemaSymbols.ATT_MEMBERTYPES,
0784: allAttrs[ATT_MEMBER_T_N]);
0785: fEleAttrsMapL.put(SchemaSymbols.ELT_UNION, attrList);
0786:
0787: // for element "schema" - global
0788: attrList = Container.getContainer(8);
0789: // attributeFormDefault = (qualified | unqualified) : unqualified
0790: attrList.put(SchemaSymbols.ATT_ATTRIBUTEFORMDEFAULT,
0791: allAttrs[ATT_ATTRIBUTE_FD_D]);
0792: // blockDefault = (#all | List of (extension | restriction | substitution)) : ''
0793: attrList.put(SchemaSymbols.ATT_BLOCKDEFAULT,
0794: allAttrs[ATT_BLOCK_D_D]);
0795: // elementFormDefault = (qualified | unqualified) : unqualified
0796: attrList.put(SchemaSymbols.ATT_ELEMENTFORMDEFAULT,
0797: allAttrs[ATT_ELEMENT_FD_D]);
0798: // finalDefault = (#all | List of (extension | restriction | list | union)) : ''
0799: attrList.put(SchemaSymbols.ATT_FINALDEFAULT,
0800: allAttrs[ATT_FINAL_D_D]);
0801: // id = ID
0802: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0803: // targetNamespace = anyURI
0804: attrList.put(SchemaSymbols.ATT_TARGETNAMESPACE,
0805: allAttrs[ATT_TARGET_N_N]);
0806: // version = token
0807: attrList
0808: .put(SchemaSymbols.ATT_VERSION, allAttrs[ATT_VERSION_N]);
0809: // xml:lang = language
0810: attrList
0811: .put(SchemaSymbols.ATT_XML_LANG, allAttrs[ATT_XML_LANG]);
0812: fEleAttrsMapG.put(SchemaSymbols.ELT_SCHEMA, attrList);
0813:
0814: // for element "include" - global
0815: attrList = Container.getContainer(2);
0816: // id = ID
0817: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0818: // schemaLocation = anyURI
0819: attrList.put(SchemaSymbols.ATT_SCHEMALOCATION,
0820: allAttrs[ATT_SCHEMA_L_R]);
0821: fEleAttrsMapG.put(SchemaSymbols.ELT_INCLUDE, attrList);
0822: // for element "redefine" - global
0823: fEleAttrsMapG.put(SchemaSymbols.ELT_REDEFINE, attrList);
0824:
0825: // for element "import" - global
0826: attrList = Container.getContainer(3);
0827: // id = ID
0828: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0829: // namespace = anyURI
0830: attrList.put(SchemaSymbols.ATT_NAMESPACE,
0831: allAttrs[ATT_NAMESPACE_N]);
0832: // schemaLocation = anyURI
0833: attrList.put(SchemaSymbols.ATT_SCHEMALOCATION,
0834: allAttrs[ATT_SCHEMA_L_N]);
0835: fEleAttrsMapG.put(SchemaSymbols.ELT_IMPORT, attrList);
0836:
0837: // for element "length" - local
0838: attrList = Container.getContainer(3);
0839: // id = ID
0840: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0841: // value = nonNegativeInteger
0842: attrList
0843: .put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_NNI_N]);
0844: // fixed = boolean : false
0845: attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_D]);
0846: fEleAttrsMapL.put(SchemaSymbols.ELT_LENGTH, attrList);
0847: // for element "minLength" - local
0848: fEleAttrsMapL.put(SchemaSymbols.ELT_MINLENGTH, attrList);
0849: // for element "maxLength" - local
0850: fEleAttrsMapL.put(SchemaSymbols.ELT_MAXLENGTH, attrList);
0851: // for element "fractionDigits" - local
0852: fEleAttrsMapL.put(SchemaSymbols.ELT_FRACTIONDIGITS, attrList);
0853:
0854: // for element "totalDigits" - local
0855: attrList = Container.getContainer(3);
0856: // id = ID
0857: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0858: // value = positiveInteger
0859: attrList.put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_PI_N]);
0860: // fixed = boolean : false
0861: attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_D]);
0862: fEleAttrsMapL.put(SchemaSymbols.ELT_TOTALDIGITS, attrList);
0863:
0864: // for element "pattern" - local
0865: attrList = Container.getContainer(2);
0866: // id = ID
0867: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0868: // value = string
0869: attrList
0870: .put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_STR_N]);
0871: fEleAttrsMapL.put(SchemaSymbols.ELT_PATTERN, attrList);
0872:
0873: // for element "enumeration" - local
0874: attrList = Container.getContainer(2);
0875: // id = ID
0876: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0877: // value = anySimpleType
0878: attrList
0879: .put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_STR_N]);
0880: fEleAttrsMapL.put(SchemaSymbols.ELT_ENUMERATION, attrList);
0881:
0882: // for element "whiteSpace" - local
0883: attrList = Container.getContainer(3);
0884: // id = ID
0885: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0886: // value = preserve | replace | collapse
0887: attrList.put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_WS_N]);
0888: // fixed = boolean : false
0889: attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_D]);
0890: fEleAttrsMapL.put(SchemaSymbols.ELT_WHITESPACE, attrList);
0891:
0892: // for element "maxInclusive" - local
0893: attrList = Container.getContainer(3);
0894: // id = ID
0895: attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]);
0896: // value = anySimpleType
0897: attrList
0898: .put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_STR_N]);
0899: // fixed = boolean : false
0900: attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_D]);
0901: fEleAttrsMapL.put(SchemaSymbols.ELT_MAXINCLUSIVE, attrList);
0902: // for element "maxExclusive" - local
0903: fEleAttrsMapL.put(SchemaSymbols.ELT_MAXEXCLUSIVE, attrList);
0904: // for element "minInclusive" - local
0905: fEleAttrsMapL.put(SchemaSymbols.ELT_MININCLUSIVE, attrList);
0906: // for element "minExclusive" - local
0907: fEleAttrsMapL.put(SchemaSymbols.ELT_MINEXCLUSIVE, attrList);
0908: }
0909:
0910: // used to resolver namespace prefixes
0911: protected XSDHandler fSchemaHandler = null;
0912:
0913: // used to store symbols.
0914: protected SymbolTable fSymbolTable = null;
0915:
0916: // used to store the mapping from processed element to attributes
0917: protected Hashtable fNonSchemaAttrs = new Hashtable();
0918:
0919: // temprory vector, used to hold the namespace list
0920: protected Vector fNamespaceList = new Vector();
0921:
0922: // whether this attribute appeared in the current element
0923: protected boolean[] fSeen = new boolean[ATTIDX_COUNT];
0924: private static boolean[] fSeenTemp = new boolean[ATTIDX_COUNT];
0925:
0926: // constructor. Sets fErrorReproter and get datatype validators
0927: public XSAttributeChecker(XSDHandler schemaHandler) {
0928: fSchemaHandler = schemaHandler;
0929: }
0930:
0931: public void reset(SymbolTable symbolTable) {
0932: fSymbolTable = symbolTable;
0933: fNonSchemaAttrs.clear();
0934: }
0935:
0936: /**
0937: * Check whether the specified element conforms to the attributes restriction
0938: * an array of attribute values is returned. the caller must call
0939: * <code>returnAttrArray</code> to return that array.
0940: *
0941: * @param element which element to check
0942: * @param isGlobal whether a child of <schema> or <redefine>
0943: * @param schemaDoc the document where the element lives in
0944: * @return an array containing attribute values
0945: */
0946: public Object[] checkAttributes(Element element, boolean isGlobal,
0947: XSDocumentInfo schemaDoc) {
0948: return checkAttributes(element, isGlobal, schemaDoc, false);
0949: }
0950:
0951: /**
0952: * Check whether the specified element conforms to the attributes restriction
0953: * an array of attribute values is returned. the caller must call
0954: * <code>returnAttrArray</code> to return that array. This method also takes
0955: * an extra parameter: if the element is "enumeration", whether to make a
0956: * copy of the namespace context, so that the value can be resolved as a
0957: * QName later.
0958: *
0959: * @param element which element to check
0960: * @param isGlobal whether a child of <schema> or <redefine>
0961: * @param schemaDoc the document where the element lives in
0962: * @param enumAsQName whether to tread enumeration value as QName
0963: * @return an array containing attribute values
0964: */
0965: public Object[] checkAttributes(Element element, boolean isGlobal,
0966: XSDocumentInfo schemaDoc, boolean enumAsQName) {
0967: if (element == null)
0968: return null;
0969:
0970: // get all attributes
0971: Attr[] attrs = DOMUtil.getAttrs(element);
0972:
0973: // update NamespaceSupport
0974: resolveNamespace(element, attrs, schemaDoc.fNamespaceSupport);
0975:
0976: String uri = DOMUtil.getNamespaceURI(element);
0977: String elName = DOMUtil.getLocalName(element);
0978:
0979: if (!SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(uri)) {
0980: reportSchemaError("s4s-elt-schema-ns",
0981: new Object[] { elName }, element);
0982: }
0983:
0984: Hashtable eleAttrsMap = fEleAttrsMapG;
0985: String lookupName = elName;
0986:
0987: // REVISIT: only local element and attribute are different from others.
0988: // it's possible to have either name or ref. all the others
0989: // are only allowed to have one of name or ref, or neither of them.
0990: // we'd better move such checking to the traverser.
0991: if (!isGlobal) {
0992: eleAttrsMap = fEleAttrsMapL;
0993: if (elName.equals(SchemaSymbols.ELT_ELEMENT)) {
0994: if (DOMUtil.getAttr(element, SchemaSymbols.ATT_REF) != null)
0995: lookupName = ELEMENT_R;
0996: else
0997: lookupName = ELEMENT_N;
0998: } else if (elName.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
0999: if (DOMUtil.getAttr(element, SchemaSymbols.ATT_REF) != null)
1000: lookupName = ATTRIBUTE_R;
1001: else
1002: lookupName = ATTRIBUTE_N;
1003: }
1004: }
1005:
1006: // get desired attribute list of this element
1007: Container attrList = (Container) eleAttrsMap.get(lookupName);
1008: if (attrList == null) {
1009: // should never gets here.
1010: // when this method is called, the call already knows that
1011: // the element can appear.
1012: reportSchemaError("s4s-elt-invalid",
1013: new Object[] { elName }, element);
1014: return null;
1015: }
1016:
1017: //Hashtable attrValues = new Hashtable();
1018: Object[] attrValues = getAvailableArray();
1019: //Hashtable otherValues = new Hashtable();
1020: long fromDefault = 0;
1021:
1022: // clear the "seen" flag.
1023: System.arraycopy(fSeenTemp, 0, fSeen, 0, ATTIDX_COUNT);
1024:
1025: // traverse all attributes
1026: int length = attrs.length;
1027: Attr sattr = null;
1028: for (int i = 0; i < length; i++) {
1029: sattr = attrs[i];
1030: // get the attribute name/value
1031: //String attrName = DOMUtil.getLocalName(sattr);
1032: String attrName = sattr.getName();
1033: String attrURI = DOMUtil.getNamespaceURI(sattr);
1034: String attrVal = DOMUtil.getValue(sattr);
1035:
1036: if (attrName.startsWith("xml")) {
1037: String attrPrefix = DOMUtil.getPrefix(sattr);
1038: // we don't want to add namespace declarations to the non-schema attributes
1039: if ("xmlns".equals(attrPrefix)
1040: || "xmlns".equals(attrName)) {
1041: continue;
1042: }
1043: // Both <schema> and <documentation> may have an xml:lang attribute.
1044: // Set the URI for this attribute to null so that we process it
1045: // like any other schema attribute.
1046: else if (SchemaSymbols.ATT_XML_LANG.equals(attrName)
1047: && (SchemaSymbols.ELT_SCHEMA.equals(elName) || SchemaSymbols.ELT_DOCUMENTATION
1048: .equals(elName))) {
1049: attrURI = null;
1050: }
1051: }
1052:
1053: // for attributes with namespace prefix
1054: //
1055: if (attrURI != null && attrURI.length() != 0) {
1056: // attributes with schema namespace are not allowed
1057: // and not allowed on "document" and "appInfo"
1058: if (attrURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) {
1059: reportSchemaError("s4s-att-not-allowed",
1060: new Object[] { elName, attrName }, element);
1061: } else {
1062: if (attrValues[ATTIDX_NONSCHEMA] == null) {
1063: // these are usually small
1064: attrValues[ATTIDX_NONSCHEMA] = new Vector(4, 2);
1065: }
1066: ((Vector) attrValues[ATTIDX_NONSCHEMA])
1067: .addElement(attrName);
1068: ((Vector) attrValues[ATTIDX_NONSCHEMA])
1069: .addElement(attrVal);
1070: // for attributes from other namespace
1071: // store them in a list, and TRY to validate them after
1072: // schema traversal (because it's "lax")
1073: //otherValues.put(attrName, attrVal);
1074: // REVISIT: actually use this some day...
1075: // String attrRName = attrURI + "," + attrName;
1076: // Vector values = (Vector)fNonSchemaAttrs.get(attrRName);
1077: // if (values == null) {
1078: // values = new Vector();
1079: // values.addElement(attrName);
1080: // values.addElement(elName);
1081: // values.addElement(attrVal);
1082: // fNonSchemaAttrs.put(attrRName, values);
1083: // }
1084: // else {
1085: // values.addElement(elName);
1086: // values.addElement(attrVal);
1087: // }
1088: }
1089: continue;
1090: }
1091:
1092: // check whether this attribute is allowed
1093: OneAttr oneAttr = attrList.get(attrName);
1094: if (oneAttr == null) {
1095: reportSchemaError("s4s-att-not-allowed", new Object[] {
1096: elName, attrName }, element);
1097: continue;
1098: }
1099:
1100: // we've seen this attribute
1101: fSeen[oneAttr.valueIndex] = true;
1102:
1103: // check the value against the datatype
1104: try {
1105: // no checking on string needs to be done here.
1106: // no checking on xpath needs to be done here.
1107: // xpath values are validated in xpath parser
1108: if (oneAttr.dvIndex >= 0) {
1109: if (oneAttr.dvIndex != DT_STRING
1110: && oneAttr.dvIndex != DT_XPATH
1111: && oneAttr.dvIndex != DT_XPATH1) {
1112: XSSimpleType dv = fExtraDVs[oneAttr.dvIndex];
1113: Object avalue = dv.validate(attrVal,
1114: schemaDoc.fValidationContext, null);
1115: // kludge to handle chameleon includes/redefines...
1116: if (oneAttr.dvIndex == DT_QNAME) {
1117: QName qname = (QName) avalue;
1118: if (qname.prefix == XMLSymbols.EMPTY_STRING
1119: && qname.uri == null
1120: && schemaDoc.fIsChameleonSchema)
1121: qname.uri = schemaDoc.fTargetNamespace;
1122: }
1123: attrValues[oneAttr.valueIndex] = avalue;
1124: } else {
1125: attrValues[oneAttr.valueIndex] = attrVal;
1126: }
1127: } else {
1128: attrValues[oneAttr.valueIndex] = validate(
1129: attrValues, attrName, attrVal,
1130: oneAttr.dvIndex, schemaDoc);
1131: }
1132: } catch (InvalidDatatypeValueException ide) {
1133: reportSchemaError("s4s-att-invalid-value",
1134: new Object[] { elName, attrName,
1135: ide.getMessage() }, element);
1136: if (oneAttr.dfltValue != null)
1137: //attrValues.put(attrName, oneAttr.dfltValue);
1138: attrValues[oneAttr.valueIndex] = oneAttr.dfltValue;
1139: }
1140:
1141: // For "enumeration", and type is possible to be a QName, we need
1142: // to return namespace context for later QName resolution.
1143: if (elName.equals(SchemaSymbols.ELT_ENUMERATION)
1144: && enumAsQName) {
1145: attrValues[ATTIDX_ENUMNSDECLS] = new SchemaNamespaceSupport(
1146: schemaDoc.fNamespaceSupport);
1147: }
1148: }
1149:
1150: // apply default values
1151: OneAttr[] reqAttrs = attrList.values;
1152: for (int i = 0; i < reqAttrs.length; i++) {
1153: OneAttr oneAttr = reqAttrs[i];
1154:
1155: // if the attribute didn't apprear, and
1156: // if the attribute is optional with default value, apply it
1157: if (oneAttr.dfltValue != null && !fSeen[oneAttr.valueIndex]) {
1158: //attrValues.put(oneAttr.name, oneAttr.dfltValue);
1159: attrValues[oneAttr.valueIndex] = oneAttr.dfltValue;
1160: fromDefault |= (1 << oneAttr.valueIndex);
1161: }
1162: }
1163:
1164: attrValues[ATTIDX_FROMDEFAULT] = new Long(fromDefault);
1165: //attrValues[ATTIDX_OTHERVALUES] = otherValues;
1166:
1167: // Check that minOccurs isn't greater than maxOccurs.
1168: // p-props-correct 2.1
1169: if (attrValues[ATTIDX_MAXOCCURS] != null) {
1170: int min = ((XInt) attrValues[ATTIDX_MINOCCURS]).intValue();
1171: int max = ((XInt) attrValues[ATTIDX_MAXOCCURS]).intValue();
1172: if (max != SchemaSymbols.OCCURRENCE_UNBOUNDED) {
1173: if (min > max) {
1174: reportSchemaError("p-props-correct.2.1",
1175: new Object[] { elName,
1176: attrValues[ATTIDX_MINOCCURS],
1177: attrValues[ATTIDX_MAXOCCURS] },
1178: element);
1179: attrValues[ATTIDX_MINOCCURS] = attrValues[ATTIDX_MAXOCCURS];
1180: }
1181: }
1182: }
1183:
1184: return attrValues;
1185: }
1186:
1187: private Object validate(Object[] attrValues, String attr,
1188: String ivalue, int dvIndex, XSDocumentInfo schemaDoc)
1189: throws InvalidDatatypeValueException {
1190: if (ivalue == null)
1191: return null;
1192:
1193: // To validate these types, we don't actually need to normalize the
1194: // strings. We only need to remove the whitespace from both ends.
1195: // In some special cases (list types), StringTokenizer can correctly
1196: // process the un-normalized whitespace.
1197:
1198: String value = XMLChar.trim(ivalue);
1199: Object retValue = null;
1200: Vector memberType;
1201: int choice;
1202:
1203: switch (dvIndex) {
1204: case DT_BOOLEAN:
1205: if (value.equals(SchemaSymbols.ATTVAL_FALSE)
1206: || value.equals(SchemaSymbols.ATTVAL_FALSE_0)) {
1207: retValue = Boolean.FALSE;
1208: } else if (value.equals(SchemaSymbols.ATTVAL_TRUE)
1209: || value.equals(SchemaSymbols.ATTVAL_TRUE_1)) {
1210: retValue = Boolean.TRUE;
1211: } else {
1212: throw new InvalidDatatypeValueException(
1213: "cvc-datatype-valid.1.2.1", new Object[] {
1214: value, "boolean" });
1215: }
1216: break;
1217: case DT_NONNEGINT:
1218: try {
1219: if (value.length() > 0 && value.charAt(0) == '+')
1220: value = value.substring(1);
1221: retValue = fXIntPool.getXInt(Integer.parseInt(value));
1222: } catch (NumberFormatException e) {
1223: throw new InvalidDatatypeValueException(
1224: "cvc-datatype-valid.1.2.1", new Object[] {
1225: value, "nonNegativeInteger" });
1226: }
1227: if (((XInt) retValue).intValue() < 0)
1228: throw new InvalidDatatypeValueException(
1229: "cvc-datatype-valid.1.2.1", new Object[] {
1230: value, "nonNegativeInteger" });
1231: break;
1232: case DT_POSINT:
1233: try {
1234: if (value.length() > 0 && value.charAt(0) == '+')
1235: value = value.substring(1);
1236: retValue = fXIntPool.getXInt(Integer.parseInt(value));
1237: } catch (NumberFormatException e) {
1238: throw new InvalidDatatypeValueException(
1239: "cvc-datatype-valid.1.2.1", new Object[] {
1240: value, "positiveInteger" });
1241: }
1242: if (((XInt) retValue).intValue() <= 0)
1243: throw new InvalidDatatypeValueException(
1244: "cvc-datatype-valid.1.2.1", new Object[] {
1245: value, "positiveInteger" });
1246: break;
1247: case DT_BLOCK:
1248: // block = (#all | List of (extension | restriction | substitution))
1249: choice = 0;
1250: if (value.equals(SchemaSymbols.ATTVAL_POUNDALL)) {
1251: choice = XSConstants.DERIVATION_SUBSTITUTION
1252: | XSConstants.DERIVATION_EXTENSION
1253: | XSConstants.DERIVATION_RESTRICTION
1254: | XSConstants.DERIVATION_LIST
1255: | XSConstants.DERIVATION_UNION;
1256: } else {
1257: StringTokenizer t = new StringTokenizer(value,
1258: " \n\t\r");
1259: while (t.hasMoreTokens()) {
1260: String token = t.nextToken();
1261:
1262: if (token.equals(SchemaSymbols.ATTVAL_EXTENSION)) {
1263: choice |= XSConstants.DERIVATION_EXTENSION;
1264: } else if (token
1265: .equals(SchemaSymbols.ATTVAL_RESTRICTION)) {
1266: choice |= XSConstants.DERIVATION_RESTRICTION;
1267: } else if (token
1268: .equals(SchemaSymbols.ATTVAL_SUBSTITUTION)) {
1269: choice |= XSConstants.DERIVATION_SUBSTITUTION;
1270: } else {
1271: throw new InvalidDatatypeValueException(
1272: "cvc-datatype-valid.1.2.3",
1273: new Object[] { value,
1274: "(#all | List of (extension | restriction | substitution))" });
1275: }
1276: }
1277: }
1278: retValue = fXIntPool.getXInt(choice);
1279: break;
1280: case DT_BLOCK1:
1281: case DT_FINAL:
1282: // block = (#all | List of (extension | restriction))
1283: // final = (#all | List of (extension | restriction))
1284: choice = 0;
1285: if (value.equals(SchemaSymbols.ATTVAL_POUNDALL)) {
1286: //choice = SchemaSymbols.EXTENSION|SchemaSymbols.RESTRICTION;
1287: // REVISIT: if #all, then make the result the combination of
1288: // everything: substitution/externsion/restriction/list/union.
1289: // would this be a problem?
1290: // the reason doing so is that when final/blockFinal on <schema>
1291: // is #all, it's not always the same as the conbination of those
1292: // values allowed by final/blockFinal.
1293: // for example, finalDefault="#all" is not always the same as
1294: // finalDefault="extension restriction".
1295: // if finalDefault="#all", final on any simple type would be
1296: // "extension restriction list union".
1297: choice = XSConstants.DERIVATION_SUBSTITUTION
1298: | XSConstants.DERIVATION_EXTENSION
1299: | XSConstants.DERIVATION_RESTRICTION
1300: | XSConstants.DERIVATION_LIST
1301: | XSConstants.DERIVATION_UNION;
1302: } else {
1303: StringTokenizer t = new StringTokenizer(value,
1304: " \n\t\r");
1305: while (t.hasMoreTokens()) {
1306: String token = t.nextToken();
1307:
1308: if (token.equals(SchemaSymbols.ATTVAL_EXTENSION)) {
1309: choice |= XSConstants.DERIVATION_EXTENSION;
1310: } else if (token
1311: .equals(SchemaSymbols.ATTVAL_RESTRICTION)) {
1312: choice |= XSConstants.DERIVATION_RESTRICTION;
1313: } else {
1314: throw new InvalidDatatypeValueException(
1315: "cvc-datatype-valid.1.2.3",
1316: new Object[] { value,
1317: "(#all | List of (extension | restriction))" });
1318: }
1319: }
1320: }
1321: retValue = fXIntPool.getXInt(choice);
1322: break;
1323: case DT_FINAL1:
1324: // final = (#all | List of (list | union | restriction))
1325: choice = 0;
1326: if (value.equals(SchemaSymbols.ATTVAL_POUNDALL)) {
1327: //choice = SchemaSymbols.RESTRICTION|SchemaSymbols.LIST|
1328: // SchemaSymbols.UNION;
1329: // REVISIT: if #all, then make the result the combination of
1330: // everything: substitution/externsion/restriction/list/union.
1331: // would this be a problem?
1332: // same reason as above DT_BLOCK1/DT_FINAL
1333: choice = XSConstants.DERIVATION_SUBSTITUTION
1334: | XSConstants.DERIVATION_EXTENSION
1335: | XSConstants.DERIVATION_RESTRICTION
1336: | XSConstants.DERIVATION_LIST
1337: | XSConstants.DERIVATION_UNION;
1338: } else {
1339: StringTokenizer t = new StringTokenizer(value,
1340: " \n\t\r");
1341: while (t.hasMoreTokens()) {
1342: String token = t.nextToken();
1343:
1344: if (token.equals(SchemaSymbols.ATTVAL_LIST)) {
1345: choice |= XSConstants.DERIVATION_LIST;
1346: } else if (token.equals(SchemaSymbols.ATTVAL_UNION)) {
1347: choice |= XSConstants.DERIVATION_UNION;
1348: } else if (token
1349: .equals(SchemaSymbols.ATTVAL_RESTRICTION)) {
1350: choice |= XSConstants.DERIVATION_RESTRICTION;
1351: } else {
1352: throw new InvalidDatatypeValueException(
1353: "cvc-datatype-valid.1.2.3",
1354: new Object[] { value,
1355: "(#all | List of (list | union | restriction))" });
1356: }
1357: }
1358: }
1359: retValue = fXIntPool.getXInt(choice);
1360: break;
1361: case DT_FINAL2:
1362: // finalDefault = (#all | List of (extension | restriction | list | union))
1363: choice = 0;
1364: if (value.equals(SchemaSymbols.ATTVAL_POUNDALL)) {
1365: //choice = SchemaSymbols.RESTRICTION|SchemaSymbols.LIST|
1366: // SchemaSymbols.UNION;
1367: // REVISIT: if #all, then make the result the combination of
1368: // everything: substitution/externsion/restriction/list/union.
1369: // would this be a problem?
1370: // same reason as above DT_BLOCK1/DT_FINAL
1371: choice = XSConstants.DERIVATION_SUBSTITUTION
1372: | XSConstants.DERIVATION_EXTENSION
1373: | XSConstants.DERIVATION_RESTRICTION
1374: | XSConstants.DERIVATION_LIST
1375: | XSConstants.DERIVATION_UNION;
1376: } else {
1377: StringTokenizer t = new StringTokenizer(value,
1378: " \n\t\r");
1379: while (t.hasMoreTokens()) {
1380: String token = t.nextToken();
1381:
1382: if (token.equals(SchemaSymbols.ATTVAL_EXTENSION)) {
1383: choice |= XSConstants.DERIVATION_EXTENSION;
1384: } else if (token
1385: .equals(SchemaSymbols.ATTVAL_RESTRICTION)) {
1386: choice |= XSConstants.DERIVATION_RESTRICTION;
1387: } else if (token.equals(SchemaSymbols.ATTVAL_LIST)) {
1388: choice |= XSConstants.DERIVATION_LIST;
1389: } else if (token.equals(SchemaSymbols.ATTVAL_UNION)) {
1390: choice |= XSConstants.DERIVATION_UNION;
1391: } else {
1392: throw new InvalidDatatypeValueException(
1393: "cvc-datatype-valid.1.2.3",
1394: new Object[] { value,
1395: "(#all | List of (extension | restriction | list | union))" });
1396: }
1397: }
1398: }
1399: retValue = fXIntPool.getXInt(choice);
1400: break;
1401: case DT_FORM:
1402: // form = (qualified | unqualified)
1403: if (value.equals(SchemaSymbols.ATTVAL_QUALIFIED))
1404: retValue = INT_QUALIFIED;
1405: else if (value.equals(SchemaSymbols.ATTVAL_UNQUALIFIED))
1406: retValue = INT_UNQUALIFIED;
1407: else
1408: throw new InvalidDatatypeValueException(
1409: "cvc-enumeration-valid", new Object[] { value,
1410: "(qualified | unqualified)" });
1411: break;
1412: case DT_MAXOCCURS:
1413: // maxOccurs = (nonNegativeInteger | unbounded)
1414: if (value.equals(SchemaSymbols.ATTVAL_UNBOUNDED)) {
1415: retValue = INT_UNBOUNDED;
1416: } else {
1417: try {
1418: retValue = validate(attrValues, attr, value,
1419: DT_NONNEGINT, schemaDoc);
1420: } catch (NumberFormatException e) {
1421: throw new InvalidDatatypeValueException(
1422: "cvc-datatype-valid.1.2.3",
1423: new Object[] { value,
1424: "(nonNegativeInteger | unbounded)" });
1425: }
1426: }
1427: break;
1428: case DT_MAXOCCURS1:
1429: // maxOccurs = 1
1430: if (value.equals("1"))
1431: retValue = fXIntPool.getXInt(1);
1432: else
1433: throw new InvalidDatatypeValueException(
1434: "cvc-enumeration-valid", new Object[] { value,
1435: "(1)" });
1436: break;
1437: case DT_MEMBERTYPES:
1438: // memberTypes = List of QName
1439: memberType = new Vector();
1440: try {
1441: StringTokenizer t = new StringTokenizer(value,
1442: " \n\t\r");
1443: while (t.hasMoreTokens()) {
1444: String token = t.nextToken();
1445: QName qname = (QName) fExtraDVs[DT_QNAME].validate(
1446: token, schemaDoc.fValidationContext, null);
1447: // kludge to handle chameleon includes/redefines...
1448: if (qname.prefix == XMLSymbols.EMPTY_STRING
1449: && qname.uri == null
1450: && schemaDoc.fIsChameleonSchema)
1451: qname.uri = schemaDoc.fTargetNamespace;
1452: memberType.addElement(qname);
1453: }
1454: retValue = memberType;
1455: } catch (InvalidDatatypeValueException ide) {
1456: throw new InvalidDatatypeValueException(
1457: "cvc-datatype-valid.1.2.2", new Object[] {
1458: value, "(List of QName)" });
1459: }
1460: break;
1461: case DT_MINOCCURS1:
1462: // minOccurs = (0 | 1)
1463: if (value.equals("0"))
1464: retValue = fXIntPool.getXInt(0);
1465: else if (value.equals("1"))
1466: retValue = fXIntPool.getXInt(1);
1467: else
1468: throw new InvalidDatatypeValueException(
1469: "cvc-enumeration-valid", new Object[] { value,
1470: "(0 | 1)" });
1471: break;
1472: case DT_NAMESPACE:
1473: // namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )
1474: if (value.equals(SchemaSymbols.ATTVAL_TWOPOUNDANY)) {
1475: // ##any
1476: retValue = INT_ANY_ANY;
1477: } else if (value.equals(SchemaSymbols.ATTVAL_TWOPOUNDOTHER)) {
1478: // ##other
1479: retValue = INT_ANY_NOT;
1480: String[] list = new String[2];
1481: list[0] = schemaDoc.fTargetNamespace;
1482: list[1] = null;
1483: attrValues[ATTIDX_NAMESPACE_LIST] = list;
1484: } else {
1485: // list
1486: retValue = INT_ANY_LIST;
1487:
1488: fNamespaceList.removeAllElements();
1489:
1490: // tokenize
1491: StringTokenizer tokens = new StringTokenizer(value,
1492: " \n\t\r");
1493: String token;
1494: String tempNamespace;
1495: try {
1496: while (tokens.hasMoreTokens()) {
1497: token = tokens.nextToken();
1498: if (token
1499: .equals(SchemaSymbols.ATTVAL_TWOPOUNDLOCAL)) {
1500: tempNamespace = null;
1501: } else if (token
1502: .equals(SchemaSymbols.ATTVAL_TWOPOUNDTARGETNS)) {
1503: tempNamespace = schemaDoc.fTargetNamespace;
1504: } else {
1505: // we have found namespace URI here
1506: // need to add it to the symbol table
1507: fExtraDVs[DT_ANYURI].validate(token,
1508: schemaDoc.fValidationContext, null);
1509: tempNamespace = fSymbolTable
1510: .addSymbol(token);
1511: }
1512:
1513: //check for duplicate namespaces in the list
1514: if (!fNamespaceList.contains(tempNamespace)) {
1515: fNamespaceList.addElement(tempNamespace);
1516: }
1517: }
1518: } catch (InvalidDatatypeValueException ide) {
1519: throw new InvalidDatatypeValueException(
1520: "cvc-datatype-valid.1.2.3",
1521: new Object[] { value,
1522: "((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )" });
1523: }
1524:
1525: // convert the vector to an array
1526: int num = fNamespaceList.size();
1527: String[] list = new String[num];
1528: fNamespaceList.copyInto(list);
1529: attrValues[ATTIDX_NAMESPACE_LIST] = list;
1530: }
1531: break;
1532: case DT_PROCESSCONTENTS:
1533: // processContents = (lax | skip | strict)
1534: if (value.equals(SchemaSymbols.ATTVAL_STRICT))
1535: retValue = INT_ANY_STRICT;
1536: else if (value.equals(SchemaSymbols.ATTVAL_LAX))
1537: retValue = INT_ANY_LAX;
1538: else if (value.equals(SchemaSymbols.ATTVAL_SKIP))
1539: retValue = INT_ANY_SKIP;
1540: else
1541: throw new InvalidDatatypeValueException(
1542: "cvc-enumeration-valid", new Object[] { value,
1543: "(lax | skip | strict)" });
1544: break;
1545: case DT_USE:
1546: // use = (optional | prohibited | required)
1547: if (value.equals(SchemaSymbols.ATTVAL_OPTIONAL))
1548: retValue = INT_USE_OPTIONAL;
1549: else if (value.equals(SchemaSymbols.ATTVAL_REQUIRED))
1550: retValue = INT_USE_REQUIRED;
1551: else if (value.equals(SchemaSymbols.ATTVAL_PROHIBITED))
1552: retValue = INT_USE_PROHIBITED;
1553: else
1554: throw new InvalidDatatypeValueException(
1555: "cvc-enumeration-valid", new Object[] { value,
1556: "(optional | prohibited | required)" });
1557: break;
1558: case DT_WHITESPACE:
1559: // value = preserve | replace | collapse
1560: if (value.equals(SchemaSymbols.ATTVAL_PRESERVE))
1561: retValue = INT_WS_PRESERVE;
1562: else if (value.equals(SchemaSymbols.ATTVAL_REPLACE))
1563: retValue = INT_WS_REPLACE;
1564: else if (value.equals(SchemaSymbols.ATTVAL_COLLAPSE))
1565: retValue = INT_WS_COLLAPSE;
1566: else
1567: throw new InvalidDatatypeValueException(
1568: "cvc-enumeration-valid", new Object[] { value,
1569: "(preserve | replace | collapse)" });
1570: break;
1571: }
1572:
1573: return retValue;
1574: }
1575:
1576: void reportSchemaError(String key, Object[] args, Element ele) {
1577: fSchemaHandler.reportSchemaError(key, args, ele);
1578: }
1579:
1580: // validate attriubtes from non-schema namespaces
1581: // REVISIT: why we store the attributes in this way? why not just a list
1582: // of structure {element node, attr name/qname, attr value)?
1583: // REVISIT: pass the proper element node to reportSchemaError
1584: public void checkNonSchemaAttributes(XSGrammarBucket grammarBucket) {
1585: // for all attributes
1586: Enumeration keys = fNonSchemaAttrs.keys();
1587: XSAttributeDecl attrDecl;
1588: while (keys.hasMoreElements()) {
1589: // get name, uri, localpart
1590: String attrRName = (String) keys.nextElement();
1591: String attrURI = attrRName.substring(0, attrRName
1592: .indexOf(','));
1593: String attrLocal = attrRName.substring(attrRName
1594: .indexOf(',') + 1);
1595: // find associated grammar
1596: SchemaGrammar sGrammar = grammarBucket.getGrammar(attrURI);
1597: if (sGrammar == null)
1598: continue;
1599: // and get the datatype validator, if there is one
1600: attrDecl = sGrammar.getGlobalAttributeDecl(attrLocal);
1601: if (attrDecl == null)
1602: continue;
1603: XSSimpleType dv = (XSSimpleType) attrDecl
1604: .getTypeDefinition();
1605: if (dv == null)
1606: continue;
1607:
1608: // get all values appeared with this attribute name
1609: Vector values = (Vector) fNonSchemaAttrs.get(attrRName);
1610: String elName;
1611: String attrName = (String) values.elementAt(0);
1612: // for each of the values
1613: int count = values.size();
1614: for (int i = 1; i < count; i += 2) {
1615: elName = (String) values.elementAt(i);
1616: try {
1617: // and validate it using the XSSimpleType
1618: // REVISIT: what would be the proper validation context?
1619: // guess we need to save that in the vectors too.
1620: dv.validate((String) values.elementAt(i + 1), null,
1621: null);
1622: } catch (InvalidDatatypeValueException ide) {
1623: reportSchemaError("s4s-att-invalid-value",
1624: new Object[] { elName, attrName,
1625: ide.getMessage() }, null);
1626: }
1627: }
1628: }
1629: }
1630:
1631: // normalize the string according to the whiteSpace facet
1632: public static String normalize(String content, short ws) {
1633: int len = content == null ? 0 : content.length();
1634: if (len == 0 || ws == XSSimpleType.WS_PRESERVE)
1635: return content;
1636:
1637: StringBuffer sb = new StringBuffer();
1638: if (ws == XSSimpleType.WS_REPLACE) {
1639: char ch;
1640: // when it's replace, just replace #x9, #xa, #xd by #x20
1641: for (int i = 0; i < len; i++) {
1642: ch = content.charAt(i);
1643: if (ch != 0x9 && ch != 0xa && ch != 0xd)
1644: sb.append(ch);
1645: else
1646: sb.append((char) 0x20);
1647: }
1648: } else {
1649: char ch;
1650: int i;
1651: boolean isLeading = true;
1652: // when it's collapse
1653: for (i = 0; i < len; i++) {
1654: ch = content.charAt(i);
1655: // append real characters, so we passed leading ws
1656: if (ch != 0x9 && ch != 0xa && ch != 0xd && ch != 0x20) {
1657: sb.append(ch);
1658: isLeading = false;
1659: } else {
1660: // for whitespaces, we skip all following ws
1661: for (; i < len - 1; i++) {
1662: ch = content.charAt(i + 1);
1663: if (ch != 0x9 && ch != 0xa && ch != 0xd
1664: && ch != 0x20)
1665: break;
1666: }
1667: // if it's not a leading or tailing ws, then append a space
1668: if (i < len - 1 && !isLeading)
1669: sb.append((char) 0x20);
1670: }
1671: }
1672: }
1673:
1674: return sb.toString();
1675: }
1676:
1677: // the following part implements an attribute-value-array pool.
1678: // when checkAttribute is called, it calls getAvailableArray to get
1679: // an array from the pool; when the caller is done with the array,
1680: // it calls returnAttrArray to return that array to the pool.
1681:
1682: // initial size of the array pool. 10 is big enough
1683: static final int INIT_POOL_SIZE = 10;
1684: // the incremental size of the array pool
1685: static final int INC_POOL_SIZE = 10;
1686: // the array pool
1687: Object[][] fArrayPool = new Object[INIT_POOL_SIZE][ATTIDX_COUNT];
1688: // used to clear the returned array
1689: // I think System.arrayCopy is more efficient than setting 35 fields to null
1690: private static Object[] fTempArray = new Object[ATTIDX_COUNT];
1691: // current position of the array pool (# of arrays not returned)
1692: int fPoolPos = 0;
1693:
1694: // get the next available array
1695: protected Object[] getAvailableArray() {
1696: // if no array left in the pool, increase the pool size
1697: if (fArrayPool.length == fPoolPos) {
1698: // increase size
1699: fArrayPool = new Object[fPoolPos + INC_POOL_SIZE][];
1700: // initialize each *new* array
1701: for (int i = fPoolPos; i < fArrayPool.length; i++)
1702: fArrayPool[i] = new Object[ATTIDX_COUNT];
1703: }
1704: // get the next available one
1705: Object[] retArray = fArrayPool[fPoolPos];
1706: // clear it from the pool. this is for GC: if a caller forget to
1707: // return the array, we want that array to be GCed.
1708: fArrayPool[fPoolPos++] = null;
1709: // to make sure that one array is not returned twice, we use
1710: // the last entry to indicate whether an array is already returned
1711: // now set it to false.
1712: System.arraycopy(fTempArray, 0, retArray, 0, ATTIDX_COUNT - 1);
1713: retArray[ATTIDX_ISRETURNED] = Boolean.FALSE;
1714:
1715: return retArray;
1716: }
1717:
1718: // return an array back to the pool
1719: public void returnAttrArray(Object[] attrArray,
1720: XSDocumentInfo schemaDoc) {
1721: // pop the namespace context
1722: if (schemaDoc != null)
1723: schemaDoc.fNamespaceSupport.popContext();
1724:
1725: // if 1. the pool is full; 2. the array is null;
1726: // 3. the array is of wrong size; 4. the array is already returned
1727: // then we can't accept this array to be returned
1728: if (fPoolPos == 0
1729: || attrArray == null
1730: || attrArray.length != ATTIDX_COUNT
1731: || ((Boolean) attrArray[ATTIDX_ISRETURNED])
1732: .booleanValue()) {
1733: return;
1734: }
1735:
1736: // mark this array as returned
1737: attrArray[ATTIDX_ISRETURNED] = Boolean.TRUE;
1738: // better clear nonschema vector
1739: if (attrArray[ATTIDX_NONSCHEMA] != null)
1740: ((Vector) attrArray[ATTIDX_NONSCHEMA]).clear();
1741: // and put it into the pool
1742: fArrayPool[--fPoolPos] = attrArray;
1743: }
1744:
1745: public void resolveNamespace(Element element, Attr[] attrs,
1746: SchemaNamespaceSupport nsSupport) {
1747: // push the namespace context
1748: nsSupport.pushContext();
1749:
1750: // search for new namespace bindings
1751: int length = attrs.length;
1752: Attr sattr = null;
1753: String rawname, prefix, uri;
1754: for (int i = 0; i < length; i++) {
1755: sattr = attrs[i];
1756: rawname = DOMUtil.getName(sattr);
1757: prefix = null;
1758: if (rawname.equals(XMLSymbols.PREFIX_XMLNS))
1759: prefix = XMLSymbols.EMPTY_STRING;
1760: else if (rawname.startsWith("xmlns:"))
1761: prefix = fSymbolTable.addSymbol(DOMUtil
1762: .getLocalName(sattr));
1763: if (prefix != null) {
1764: uri = fSymbolTable.addSymbol(DOMUtil.getValue(sattr));
1765: nsSupport.declarePrefix(prefix, uri.length() != 0 ? uri
1766: : null);
1767: }
1768: }
1769: }
1770: }
1771:
1772: class OneAttr {
1773: // name of the attribute
1774: public String name;
1775: // index of the datatype validator
1776: public int dvIndex;
1777: // whether it's optional, and has default value
1778: public int valueIndex;
1779: // the default value of this attribute
1780: public Object dfltValue;
1781:
1782: public OneAttr(String name, int dvIndex, int valueIndex,
1783: Object dfltValue) {
1784: this .name = name;
1785: this .dvIndex = dvIndex;
1786: this .valueIndex = valueIndex;
1787: this .dfltValue = dfltValue;
1788: }
1789: }
1790:
1791: abstract class Container {
1792: static final int THRESHOLD = 5;
1793:
1794: static Container getContainer(int size) {
1795: if (size > THRESHOLD)
1796: return new LargeContainer(size);
1797: else
1798: return new SmallContainer(size);
1799: }
1800:
1801: abstract void put(String key, OneAttr value);
1802:
1803: abstract OneAttr get(String key);
1804:
1805: OneAttr[] values;
1806: int pos = 0;
1807: }
1808:
1809: class SmallContainer extends Container {
1810: String[] keys;
1811:
1812: SmallContainer(int size) {
1813: keys = new String[size];
1814: values = new OneAttr[size];
1815: }
1816:
1817: void put(String key, OneAttr value) {
1818: keys[pos] = key;
1819: values[pos++] = value;
1820: }
1821:
1822: OneAttr get(String key) {
1823: for (int i = 0; i < pos; i++) {
1824: if (keys[i].equals(key)) {
1825: return values[i];
1826: }
1827: }
1828: return null;
1829: }
1830: }
1831:
1832: class LargeContainer extends Container {
1833: Hashtable items;
1834:
1835: LargeContainer(int size) {
1836: items = new Hashtable(size * 2 + 1);
1837: values = new OneAttr[size];
1838: }
1839:
1840: void put(String key, OneAttr value) {
1841: items.put(key, value);
1842: values[pos++] = value;
1843: }
1844:
1845: OneAttr get(String key) {
1846: OneAttr ret = (OneAttr) items.get(key);
1847: return ret;
1848: }
1849: }
|