1 /* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xerces.internal.impl.xs.traversers; 22 23 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException; 24 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; 25 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar; 26 import com.sun.org.apache.xerces.internal.impl.xs.SchemaNamespaceSupport; 27 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols; 28 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeDecl; 29 import com.sun.org.apache.xerces.internal.impl.xs.XSGrammarBucket; 30 import com.sun.org.apache.xerces.internal.impl.xs.XSWildcardDecl; 31 import com.sun.org.apache.xerces.internal.impl.xs.util.XInt; 32 import com.sun.org.apache.xerces.internal.impl.xs.util.XIntPool; 33 import com.sun.org.apache.xerces.internal.util.DOMUtil; 34 import com.sun.org.apache.xerces.internal.util.SymbolTable; 35 import com.sun.org.apache.xerces.internal.util.XMLChar; 36 import com.sun.org.apache.xerces.internal.util.XMLSymbols; 37 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; 38 import com.sun.org.apache.xerces.internal.xni.QName; 39 import com.sun.org.apache.xerces.internal.xs.XSConstants; 40 import java.util.HashMap; 41 import java.util.Iterator; 42 import java.util.Map; 43 import java.util.StringTokenizer; 44 import java.util.Vector; 45 import org.w3c.dom.Attr; 46 import org.w3c.dom.Element; 47 48 /** 49 * Class <code>XSAttributeCheck</code> is used to check the validity of attributes 50 * appearing in the schema document. It 51 * - reports an error for invalid element (invalid namespace, invalid name) 52 * - reports an error for invalid attribute (invalid namespace, invalid name) 53 * - reports an error for invalid attribute value 54 * - return compiled values for attriute values 55 * - provide default value for missing optional attributes 56 * - provide default value for incorrect attribute values 57 * 58 * But it's the caller's responsibility to check whether a required attribute 59 * is present. 60 * 61 * Things need revisiting: 62 * - Whether to return non-schema attributes/values 63 * - Do we need to update NamespaceScope and ErrorReporter when reset()? 64 * - Should have the datatype validators return compiled value 65 * - use symbol table instead of many maps 66 * 67 * @xerces.internal 68 * 69 * @author Sandy Gao, IBM 70 */ 71 72 public class XSAttributeChecker { 73 74 // REVISIT: only local element and attribute are different from others. 75 // it's possible to have either name or ref. all the others 76 // are only allowed to have one of name or ref, or neither of them. 77 // we'd better move such checking to the traverser. 78 private static final String ELEMENT_N = "element_n"; 79 private static final String ELEMENT_R = "element_r"; 80 private static final String ATTRIBUTE_N = "attribute_n"; 81 private static final String ATTRIBUTE_R = "attribute_r"; 82 83 private static int ATTIDX_COUNT = 0; 84 public static final int ATTIDX_ABSTRACT = ATTIDX_COUNT++; 85 public static final int ATTIDX_AFORMDEFAULT = ATTIDX_COUNT++; 86 public static final int ATTIDX_BASE = ATTIDX_COUNT++; 87 public static final int ATTIDX_BLOCK = ATTIDX_COUNT++; 88 public static final int ATTIDX_BLOCKDEFAULT = ATTIDX_COUNT++; 89 public static final int ATTIDX_DEFAULT = ATTIDX_COUNT++; 90 public static final int ATTIDX_EFORMDEFAULT = ATTIDX_COUNT++; 91 public static final int ATTIDX_FINAL = ATTIDX_COUNT++; 92 public static final int ATTIDX_FINALDEFAULT = ATTIDX_COUNT++; 93 public static final int ATTIDX_FIXED = ATTIDX_COUNT++; 94 public static final int ATTIDX_FORM = ATTIDX_COUNT++; 95 public static final int ATTIDX_ID = ATTIDX_COUNT++; 96 public static final int ATTIDX_ITEMTYPE = ATTIDX_COUNT++; 97 public static final int ATTIDX_MAXOCCURS = ATTIDX_COUNT++; 98 public static final int ATTIDX_MEMBERTYPES = ATTIDX_COUNT++; 99 public static final int ATTIDX_MINOCCURS = ATTIDX_COUNT++; 100 public static final int ATTIDX_MIXED = ATTIDX_COUNT++; 101 public static final int ATTIDX_NAME = ATTIDX_COUNT++; 102 public static final int ATTIDX_NAMESPACE = ATTIDX_COUNT++; 103 public static final int ATTIDX_NAMESPACE_LIST = ATTIDX_COUNT++; 104 public static final int ATTIDX_NILLABLE = ATTIDX_COUNT++; 105 public static final int ATTIDX_NONSCHEMA = ATTIDX_COUNT++; 106 public static final int ATTIDX_PROCESSCONTENTS = ATTIDX_COUNT++; 107 public static final int ATTIDX_PUBLIC = ATTIDX_COUNT++; 108 public static final int ATTIDX_REF = ATTIDX_COUNT++; 109 public static final int ATTIDX_REFER = ATTIDX_COUNT++; 110 public static final int ATTIDX_SCHEMALOCATION = ATTIDX_COUNT++; 111 public static final int ATTIDX_SOURCE = ATTIDX_COUNT++; 112 public static final int ATTIDX_SUBSGROUP = ATTIDX_COUNT++; 113 public static final int ATTIDX_SYSTEM = ATTIDX_COUNT++; 114 public static final int ATTIDX_TARGETNAMESPACE = ATTIDX_COUNT++; 115 public static final int ATTIDX_TYPE = ATTIDX_COUNT++; 116 public static final int ATTIDX_USE = ATTIDX_COUNT++; 117 public static final int ATTIDX_VALUE = ATTIDX_COUNT++; 118 public static final int ATTIDX_ENUMNSDECLS = ATTIDX_COUNT++; 119 public static final int ATTIDX_VERSION = ATTIDX_COUNT++; 120 public static final int ATTIDX_XML_LANG = ATTIDX_COUNT++; 121 public static final int ATTIDX_XPATH = ATTIDX_COUNT++; 122 public static final int ATTIDX_FROMDEFAULT = ATTIDX_COUNT++; 123 //public static final int ATTIDX_OTHERVALUES = ATTIDX_COUNT++; 124 public static final int ATTIDX_ISRETURNED = ATTIDX_COUNT++; 125 126 private static final XIntPool fXIntPool = new XIntPool(); 127 // constants to return 128 private static final XInt INT_QUALIFIED = fXIntPool.getXInt(SchemaSymbols.FORM_QUALIFIED); 129 private static final XInt INT_UNQUALIFIED = fXIntPool.getXInt(SchemaSymbols.FORM_UNQUALIFIED); 130 private static final XInt INT_EMPTY_SET = fXIntPool.getXInt(XSConstants.DERIVATION_NONE); 131 private static final XInt INT_ANY_STRICT = fXIntPool.getXInt(XSWildcardDecl.PC_STRICT); 132 private static final XInt INT_ANY_LAX = fXIntPool.getXInt(XSWildcardDecl.PC_LAX); 133 private static final XInt INT_ANY_SKIP = fXIntPool.getXInt(XSWildcardDecl.PC_SKIP); 134 private static final XInt INT_ANY_ANY = fXIntPool.getXInt(XSWildcardDecl.NSCONSTRAINT_ANY); 135 private static final XInt INT_ANY_LIST = fXIntPool.getXInt(XSWildcardDecl.NSCONSTRAINT_LIST); 136 private static final XInt INT_ANY_NOT = fXIntPool.getXInt(XSWildcardDecl.NSCONSTRAINT_NOT); 137 private static final XInt INT_USE_OPTIONAL = fXIntPool.getXInt(SchemaSymbols.USE_OPTIONAL); 138 private static final XInt INT_USE_REQUIRED = fXIntPool.getXInt(SchemaSymbols.USE_REQUIRED); 139 private static final XInt INT_USE_PROHIBITED = fXIntPool.getXInt(SchemaSymbols.USE_PROHIBITED); 140 private static final XInt INT_WS_PRESERVE = fXIntPool.getXInt(XSSimpleType.WS_PRESERVE); 141 private static final XInt INT_WS_REPLACE = fXIntPool.getXInt(XSSimpleType.WS_REPLACE); 142 private static final XInt INT_WS_COLLAPSE = fXIntPool.getXInt(XSSimpleType.WS_COLLAPSE); 143 private static final XInt INT_UNBOUNDED = fXIntPool.getXInt(SchemaSymbols.OCCURRENCE_UNBOUNDED); 144 145 // used to store the map from element name to attribute list 146 // for 14 global elements 147 private static final Map fEleAttrsMapG = new HashMap(29); 148 // for 39 local elememnts 149 private static final Map fEleAttrsMapL = new HashMap(79); 150 151 // used to initialize fEleAttrsMap 152 // step 1: all possible data types 153 // DT_??? >= 0 : validate using a validator, which is initialized staticly 154 // DT_??? < 0 : validate directly, which is done in "validate()" 155 156 protected static final int DT_ANYURI = 0; 157 protected static final int DT_ID = 1; 158 protected static final int DT_QNAME = 2; 159 protected static final int DT_STRING = 3; 160 protected static final int DT_TOKEN = 4; 161 protected static final int DT_NCNAME = 5; 162 protected static final int DT_XPATH = 6; 163 protected static final int DT_XPATH1 = 7; 164 protected static final int DT_LANGUAGE = 8; 165 166 // used to store extra datatype validators 167 protected static final int DT_COUNT = DT_LANGUAGE + 1; 168 private static final XSSimpleType[] fExtraDVs = new XSSimpleType[DT_COUNT]; 169 static { 170 // step 5: register all datatype validators for new types 171 SchemaGrammar grammar = SchemaGrammar.SG_SchemaNS; 172 // anyURI 173 fExtraDVs[DT_ANYURI] = (XSSimpleType)grammar.getGlobalTypeDecl(SchemaSymbols.ATTVAL_ANYURI); 174 // ID 175 fExtraDVs[DT_ID] = (XSSimpleType)grammar.getGlobalTypeDecl(SchemaSymbols.ATTVAL_ID); 176 // QName 177 fExtraDVs[DT_QNAME] = (XSSimpleType)grammar.getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME); 178 // string 179 fExtraDVs[DT_STRING] = (XSSimpleType)grammar.getGlobalTypeDecl(SchemaSymbols.ATTVAL_STRING); 180 // token 181 fExtraDVs[DT_TOKEN] = (XSSimpleType)grammar.getGlobalTypeDecl(SchemaSymbols.ATTVAL_TOKEN); 182 // NCName 183 fExtraDVs[DT_NCNAME] = (XSSimpleType)grammar.getGlobalTypeDecl(SchemaSymbols.ATTVAL_NCNAME); 184 // xpath = a subset of XPath expression 185 fExtraDVs[DT_XPATH] = fExtraDVs[DT_STRING]; 186 // xpath = a subset of XPath expression 187 fExtraDVs[DT_XPATH] = fExtraDVs[DT_STRING]; 188 // language 189 fExtraDVs[DT_LANGUAGE] = (XSSimpleType)grammar.getGlobalTypeDecl(SchemaSymbols.ATTVAL_LANGUAGE); 190 } 191 192 protected static final int DT_BLOCK = -1; 193 protected static final int DT_BLOCK1 = -2; 194 protected static final int DT_FINAL = -3; 195 protected static final int DT_FINAL1 = -4; 196 protected static final int DT_FINAL2 = -5; 197 protected static final int DT_FORM = -6; 198 protected static final int DT_MAXOCCURS = -7; 199 protected static final int DT_MAXOCCURS1 = -8; 200 protected static final int DT_MEMBERTYPES = -9; 201 protected static final int DT_MINOCCURS1 = -10; 202 protected static final int DT_NAMESPACE = -11; 203 protected static final int DT_PROCESSCONTENTS = -12; 204 protected static final int DT_USE = -13; 205 protected static final int DT_WHITESPACE = -14; 206 protected static final int DT_BOOLEAN = -15; 207 protected static final int DT_NONNEGINT = -16; 208 protected static final int DT_POSINT = -17; 209 210 static { 211 // step 2: all possible attributes for all elements 212 int attCount = 0; 213 int ATT_ABSTRACT_D = attCount++; 214 int ATT_ATTRIBUTE_FD_D = attCount++; 215 int ATT_BASE_R = attCount++; 216 int ATT_BASE_N = attCount++; 217 int ATT_BLOCK_N = attCount++; 218 int ATT_BLOCK1_N = attCount++; 219 int ATT_BLOCK_D_D = attCount++; 220 int ATT_DEFAULT_N = attCount++; 221 int ATT_ELEMENT_FD_D = attCount++; 222 int ATT_FINAL_N = attCount++; 223 int ATT_FINAL1_N = attCount++; 224 int ATT_FINAL_D_D = attCount++; 225 int ATT_FIXED_N = attCount++; 226 int ATT_FIXED_D = attCount++; 227 int ATT_FORM_N = attCount++; 228 int ATT_ID_N = attCount++; 229 int ATT_ITEMTYPE_N = attCount++; 230 int ATT_MAXOCCURS_D = attCount++; 231 int ATT_MAXOCCURS1_D = attCount++; 232 int ATT_MEMBER_T_N = attCount++; 233 int ATT_MINOCCURS_D = attCount++; 234 int ATT_MINOCCURS1_D = attCount++; 235 int ATT_MIXED_D = attCount++; 236 int ATT_MIXED_N = attCount++; 237 int ATT_NAME_R = attCount++; 238 int ATT_NAMESPACE_D = attCount++; 239 int ATT_NAMESPACE_N = attCount++; 240 int ATT_NILLABLE_D = attCount++; 241 int ATT_PROCESS_C_D = attCount++; 242 int ATT_PUBLIC_R = attCount++; 243 int ATT_REF_R = attCount++; 244 int ATT_REFER_R = attCount++; 245 int ATT_SCHEMA_L_R = attCount++; 246 int ATT_SCHEMA_L_N = attCount++; 247 int ATT_SOURCE_N = attCount++; 248 int ATT_SUBSTITUTION_G_N = attCount++; 249 int ATT_SYSTEM_N = attCount++; 250 int ATT_TARGET_N_N = attCount++; 251 int ATT_TYPE_N = attCount++; 252 int ATT_USE_D = attCount++; 253 int ATT_VALUE_NNI_N = attCount++; 254 int ATT_VALUE_PI_N = attCount++; 255 int ATT_VALUE_STR_N = attCount++; 256 int ATT_VALUE_WS_N = attCount++; 257 int ATT_VERSION_N = attCount++; 258 int ATT_XML_LANG = attCount++; 259 int ATT_XPATH_R = attCount++; 260 int ATT_XPATH1_R = attCount++; 261 262 // step 3: store all these attributes in an array 263 OneAttr[] allAttrs = new OneAttr[attCount]; 264 allAttrs[ATT_ABSTRACT_D] = new OneAttr(SchemaSymbols.ATT_ABSTRACT, 265 DT_BOOLEAN, 266 ATTIDX_ABSTRACT, 267 Boolean.FALSE); 268 allAttrs[ATT_ATTRIBUTE_FD_D] = new OneAttr(SchemaSymbols.ATT_ATTRIBUTEFORMDEFAULT, 269 DT_FORM, 270 ATTIDX_AFORMDEFAULT, 271 INT_UNQUALIFIED); 272 allAttrs[ATT_BASE_R] = new OneAttr(SchemaSymbols.ATT_BASE, 273 DT_QNAME, 274 ATTIDX_BASE, 275 null); 276 allAttrs[ATT_BASE_N] = new OneAttr(SchemaSymbols.ATT_BASE, 277 DT_QNAME, 278 ATTIDX_BASE, 279 null); 280 allAttrs[ATT_BLOCK_N] = new OneAttr(SchemaSymbols.ATT_BLOCK, 281 DT_BLOCK, 282 ATTIDX_BLOCK, 283 null); 284 allAttrs[ATT_BLOCK1_N] = new OneAttr(SchemaSymbols.ATT_BLOCK, 285 DT_BLOCK1, 286 ATTIDX_BLOCK, 287 null); 288 allAttrs[ATT_BLOCK_D_D] = new OneAttr(SchemaSymbols.ATT_BLOCKDEFAULT, 289 DT_BLOCK, 290 ATTIDX_BLOCKDEFAULT, 291 INT_EMPTY_SET); 292 allAttrs[ATT_DEFAULT_N] = new OneAttr(SchemaSymbols.ATT_DEFAULT, 293 DT_STRING, 294 ATTIDX_DEFAULT, 295 null); 296 allAttrs[ATT_ELEMENT_FD_D] = new OneAttr(SchemaSymbols.ATT_ELEMENTFORMDEFAULT, 297 DT_FORM, 298 ATTIDX_EFORMDEFAULT, 299 INT_UNQUALIFIED); 300 allAttrs[ATT_FINAL_N] = new OneAttr(SchemaSymbols.ATT_FINAL, 301 DT_FINAL, 302 ATTIDX_FINAL, 303 null); 304 allAttrs[ATT_FINAL1_N] = new OneAttr(SchemaSymbols.ATT_FINAL, 305 DT_FINAL1, 306 ATTIDX_FINAL, 307 null); 308 allAttrs[ATT_FINAL_D_D] = new OneAttr(SchemaSymbols.ATT_FINALDEFAULT, 309 DT_FINAL2, 310 ATTIDX_FINALDEFAULT, 311 INT_EMPTY_SET); 312 allAttrs[ATT_FIXED_N] = new OneAttr(SchemaSymbols.ATT_FIXED, 313 DT_STRING, 314 ATTIDX_FIXED, 315 null); 316 allAttrs[ATT_FIXED_D] = new OneAttr(SchemaSymbols.ATT_FIXED, 317 DT_BOOLEAN, 318 ATTIDX_FIXED, 319 Boolean.FALSE); 320 allAttrs[ATT_FORM_N] = new OneAttr(SchemaSymbols.ATT_FORM, 321 DT_FORM, 322 ATTIDX_FORM, 323 null); 324 allAttrs[ATT_ID_N] = new OneAttr(SchemaSymbols.ATT_ID, 325 DT_ID, 326 ATTIDX_ID, 327 null); 328 allAttrs[ATT_ITEMTYPE_N] = new OneAttr(SchemaSymbols.ATT_ITEMTYPE, 329 DT_QNAME, 330 ATTIDX_ITEMTYPE, 331 null); 332 allAttrs[ATT_MAXOCCURS_D] = new OneAttr(SchemaSymbols.ATT_MAXOCCURS, 333 DT_MAXOCCURS, 334 ATTIDX_MAXOCCURS, 335 fXIntPool.getXInt(1)); 336 allAttrs[ATT_MAXOCCURS1_D] = new OneAttr(SchemaSymbols.ATT_MAXOCCURS, 337 DT_MAXOCCURS1, 338 ATTIDX_MAXOCCURS, 339 fXIntPool.getXInt(1)); 340 allAttrs[ATT_MEMBER_T_N] = new OneAttr(SchemaSymbols.ATT_MEMBERTYPES, 341 DT_MEMBERTYPES, 342 ATTIDX_MEMBERTYPES, 343 null); 344 allAttrs[ATT_MINOCCURS_D] = new OneAttr(SchemaSymbols.ATT_MINOCCURS, 345 DT_NONNEGINT, 346 ATTIDX_MINOCCURS, 347 fXIntPool.getXInt(1)); 348 allAttrs[ATT_MINOCCURS1_D] = new OneAttr(SchemaSymbols.ATT_MINOCCURS, 349 DT_MINOCCURS1, 350 ATTIDX_MINOCCURS, 351 fXIntPool.getXInt(1)); 352 allAttrs[ATT_MIXED_D] = new OneAttr(SchemaSymbols.ATT_MIXED, 353 DT_BOOLEAN, 354 ATTIDX_MIXED, 355 Boolean.FALSE); 356 allAttrs[ATT_MIXED_N] = new OneAttr(SchemaSymbols.ATT_MIXED, 357 DT_BOOLEAN, 358 ATTIDX_MIXED, 359 null); 360 allAttrs[ATT_NAME_R] = new OneAttr(SchemaSymbols.ATT_NAME, 361 DT_NCNAME, 362 ATTIDX_NAME, 363 null); 364 allAttrs[ATT_NAMESPACE_D] = new OneAttr(SchemaSymbols.ATT_NAMESPACE, 365 DT_NAMESPACE, 366 ATTIDX_NAMESPACE, 367 INT_ANY_ANY); 368 allAttrs[ATT_NAMESPACE_N] = new OneAttr(SchemaSymbols.ATT_NAMESPACE, 369 DT_ANYURI, 370 ATTIDX_NAMESPACE, 371 null); 372 allAttrs[ATT_NILLABLE_D] = new OneAttr(SchemaSymbols.ATT_NILLABLE, 373 DT_BOOLEAN, 374 ATTIDX_NILLABLE, 375 Boolean.FALSE); 376 allAttrs[ATT_PROCESS_C_D] = new OneAttr(SchemaSymbols.ATT_PROCESSCONTENTS, 377 DT_PROCESSCONTENTS, 378 ATTIDX_PROCESSCONTENTS, 379 INT_ANY_STRICT); 380 allAttrs[ATT_PUBLIC_R] = new OneAttr(SchemaSymbols.ATT_PUBLIC, 381 DT_TOKEN, 382 ATTIDX_PUBLIC, 383 null); 384 allAttrs[ATT_REF_R] = new OneAttr(SchemaSymbols.ATT_REF, 385 DT_QNAME, 386 ATTIDX_REF, 387 null); 388 allAttrs[ATT_REFER_R] = new OneAttr(SchemaSymbols.ATT_REFER, 389 DT_QNAME, 390 ATTIDX_REFER, 391 null); 392 allAttrs[ATT_SCHEMA_L_R] = new OneAttr(SchemaSymbols.ATT_SCHEMALOCATION, 393 DT_ANYURI, 394 ATTIDX_SCHEMALOCATION, 395 null); 396 allAttrs[ATT_SCHEMA_L_N] = new OneAttr(SchemaSymbols.ATT_SCHEMALOCATION, 397 DT_ANYURI, 398 ATTIDX_SCHEMALOCATION, 399 null); 400 allAttrs[ATT_SOURCE_N] = new OneAttr(SchemaSymbols.ATT_SOURCE, 401 DT_ANYURI, 402 ATTIDX_SOURCE, 403 null); 404 allAttrs[ATT_SUBSTITUTION_G_N] = new OneAttr(SchemaSymbols.ATT_SUBSTITUTIONGROUP, 405 DT_QNAME, 406 ATTIDX_SUBSGROUP, 407 null); 408 allAttrs[ATT_SYSTEM_N] = new OneAttr(SchemaSymbols.ATT_SYSTEM, 409 DT_ANYURI, 410 ATTIDX_SYSTEM, 411 null); 412 allAttrs[ATT_TARGET_N_N] = new OneAttr(SchemaSymbols.ATT_TARGETNAMESPACE, 413 DT_ANYURI, 414 ATTIDX_TARGETNAMESPACE, 415 null); 416 allAttrs[ATT_TYPE_N] = new OneAttr(SchemaSymbols.ATT_TYPE, 417 DT_QNAME, 418 ATTIDX_TYPE, 419 null); 420 allAttrs[ATT_USE_D] = new OneAttr(SchemaSymbols.ATT_USE, 421 DT_USE, 422 ATTIDX_USE, 423 INT_USE_OPTIONAL); 424 allAttrs[ATT_VALUE_NNI_N] = new OneAttr(SchemaSymbols.ATT_VALUE, 425 DT_NONNEGINT, 426 ATTIDX_VALUE, 427 null); 428 allAttrs[ATT_VALUE_PI_N] = new OneAttr(SchemaSymbols.ATT_VALUE, 429 DT_POSINT, 430 ATTIDX_VALUE, 431 null); 432 allAttrs[ATT_VALUE_STR_N] = new OneAttr(SchemaSymbols.ATT_VALUE, 433 DT_STRING, 434 ATTIDX_VALUE, 435 null); 436 allAttrs[ATT_VALUE_WS_N] = new OneAttr(SchemaSymbols.ATT_VALUE, 437 DT_WHITESPACE, 438 ATTIDX_VALUE, 439 null); 440 allAttrs[ATT_VERSION_N] = new OneAttr(SchemaSymbols.ATT_VERSION, 441 DT_TOKEN, 442 ATTIDX_VERSION, 443 null); 444 allAttrs[ATT_XML_LANG] = new OneAttr(SchemaSymbols.ATT_XML_LANG, 445 DT_LANGUAGE, 446 ATTIDX_XML_LANG, 447 null); 448 allAttrs[ATT_XPATH_R] = new OneAttr(SchemaSymbols.ATT_XPATH, 449 DT_XPATH, 450 ATTIDX_XPATH, 451 null); 452 allAttrs[ATT_XPATH1_R] = new OneAttr(SchemaSymbols.ATT_XPATH, 453 DT_XPATH1, 454 ATTIDX_XPATH, 455 null); 456 457 // step 4: for each element, make a list of possible attributes 458 Container attrList; 459 460 // for element "attribute" - global 461 attrList = Container.getContainer(5); 462 // default = string 463 attrList.put(SchemaSymbols.ATT_DEFAULT, allAttrs[ATT_DEFAULT_N]); 464 // fixed = string 465 attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_N]); 466 // id = ID 467 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 468 // name = NCName 469 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 470 // type = QName 471 attrList.put(SchemaSymbols.ATT_TYPE, allAttrs[ATT_TYPE_N]); 472 fEleAttrsMapG.put(SchemaSymbols.ELT_ATTRIBUTE, attrList); 473 474 // for element "attribute" - local name 475 attrList = Container.getContainer(7); 476 // default = string 477 attrList.put(SchemaSymbols.ATT_DEFAULT, allAttrs[ATT_DEFAULT_N]); 478 // fixed = string 479 attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_N]); 480 // form = (qualified | unqualified) 481 attrList.put(SchemaSymbols.ATT_FORM, allAttrs[ATT_FORM_N]); 482 // id = ID 483 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 484 // name = NCName 485 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 486 // type = QName 487 attrList.put(SchemaSymbols.ATT_TYPE, allAttrs[ATT_TYPE_N]); 488 // use = (optional | prohibited | required) : optional 489 attrList.put(SchemaSymbols.ATT_USE, allAttrs[ATT_USE_D]); 490 fEleAttrsMapL.put(ATTRIBUTE_N, attrList); 491 492 // for element "attribute" - local ref 493 attrList = Container.getContainer(5); 494 // default = string 495 attrList.put(SchemaSymbols.ATT_DEFAULT, allAttrs[ATT_DEFAULT_N]); 496 // fixed = string 497 attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_N]); 498 // id = ID 499 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 500 // ref = QName 501 attrList.put(SchemaSymbols.ATT_REF, allAttrs[ATT_REF_R]); 502 // use = (optional | prohibited | required) : optional 503 attrList.put(SchemaSymbols.ATT_USE, allAttrs[ATT_USE_D]); 504 fEleAttrsMapL.put(ATTRIBUTE_R, attrList); 505 506 // for element "element" - global 507 attrList = Container.getContainer(10); 508 // abstract = boolean : false 509 attrList.put(SchemaSymbols.ATT_ABSTRACT, allAttrs[ATT_ABSTRACT_D]); 510 // block = (#all | List of (extension | restriction | substitution)) 511 attrList.put(SchemaSymbols.ATT_BLOCK, allAttrs[ATT_BLOCK_N]); 512 // default = string 513 attrList.put(SchemaSymbols.ATT_DEFAULT, allAttrs[ATT_DEFAULT_N]); 514 // final = (#all | List of (extension | restriction)) 515 attrList.put(SchemaSymbols.ATT_FINAL, allAttrs[ATT_FINAL_N]); 516 // fixed = string 517 attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_N]); 518 // id = ID 519 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 520 // name = NCName 521 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 522 // nillable = boolean : false 523 attrList.put(SchemaSymbols.ATT_NILLABLE, allAttrs[ATT_NILLABLE_D]); 524 // substitutionGroup = QName 525 attrList.put(SchemaSymbols.ATT_SUBSTITUTIONGROUP, allAttrs[ATT_SUBSTITUTION_G_N]); 526 // type = QName 527 attrList.put(SchemaSymbols.ATT_TYPE, allAttrs[ATT_TYPE_N]); 528 fEleAttrsMapG.put(SchemaSymbols.ELT_ELEMENT, attrList); 529 530 // for element "element" - local name 531 attrList = Container.getContainer(10); 532 // block = (#all | List of (extension | restriction | substitution)) 533 attrList.put(SchemaSymbols.ATT_BLOCK, allAttrs[ATT_BLOCK_N]); 534 // default = string 535 attrList.put(SchemaSymbols.ATT_DEFAULT, allAttrs[ATT_DEFAULT_N]); 536 // fixed = string 537 attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_N]); 538 // form = (qualified | unqualified) 539 attrList.put(SchemaSymbols.ATT_FORM, allAttrs[ATT_FORM_N]); 540 // id = ID 541 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 542 // maxOccurs = (nonNegativeInteger | unbounded) : 1 543 attrList.put(SchemaSymbols.ATT_MAXOCCURS, allAttrs[ATT_MAXOCCURS_D]); 544 // minOccurs = nonNegativeInteger : 1 545 attrList.put(SchemaSymbols.ATT_MINOCCURS, allAttrs[ATT_MINOCCURS_D]); 546 // name = NCName 547 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 548 // nillable = boolean : false 549 attrList.put(SchemaSymbols.ATT_NILLABLE, allAttrs[ATT_NILLABLE_D]); 550 // type = QName 551 attrList.put(SchemaSymbols.ATT_TYPE, allAttrs[ATT_TYPE_N]); 552 fEleAttrsMapL.put(ELEMENT_N, attrList); 553 554 // for element "element" - local ref 555 attrList = Container.getContainer(4); 556 // id = ID 557 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 558 // maxOccurs = (nonNegativeInteger | unbounded) : 1 559 attrList.put(SchemaSymbols.ATT_MAXOCCURS, allAttrs[ATT_MAXOCCURS_D]); 560 // minOccurs = nonNegativeInteger : 1 561 attrList.put(SchemaSymbols.ATT_MINOCCURS, allAttrs[ATT_MINOCCURS_D]); 562 // ref = QName 563 attrList.put(SchemaSymbols.ATT_REF, allAttrs[ATT_REF_R]); 564 fEleAttrsMapL.put(ELEMENT_R, attrList); 565 566 // for element "complexType" - global 567 attrList = Container.getContainer(6); 568 // abstract = boolean : false 569 attrList.put(SchemaSymbols.ATT_ABSTRACT, allAttrs[ATT_ABSTRACT_D]); 570 // block = (#all | List of (extension | restriction)) 571 attrList.put(SchemaSymbols.ATT_BLOCK, allAttrs[ATT_BLOCK1_N]); 572 // final = (#all | List of (extension | restriction)) 573 attrList.put(SchemaSymbols.ATT_FINAL, allAttrs[ATT_FINAL_N]); 574 // id = ID 575 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 576 // mixed = boolean : false 577 attrList.put(SchemaSymbols.ATT_MIXED, allAttrs[ATT_MIXED_D]); 578 // name = NCName 579 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 580 fEleAttrsMapG.put(SchemaSymbols.ELT_COMPLEXTYPE, attrList); 581 582 // for element "notation" - global 583 attrList = Container.getContainer(4); 584 // id = ID 585 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 586 // name = NCName 587 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 588 // public = A public identifier, per ISO 8879 589 attrList.put(SchemaSymbols.ATT_PUBLIC, allAttrs[ATT_PUBLIC_R]); 590 // system = anyURI 591 attrList.put(SchemaSymbols.ATT_SYSTEM, allAttrs[ATT_SYSTEM_N]); 592 fEleAttrsMapG.put(SchemaSymbols.ELT_NOTATION, attrList); 593 594 595 // for element "complexType" - local 596 attrList = Container.getContainer(2); 597 // id = ID 598 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 599 // mixed = boolean : false 600 attrList.put(SchemaSymbols.ATT_MIXED, allAttrs[ATT_MIXED_D]); 601 fEleAttrsMapL.put(SchemaSymbols.ELT_COMPLEXTYPE, attrList); 602 603 // for element "simpleContent" - local 604 attrList = Container.getContainer(1); 605 // id = ID 606 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 607 fEleAttrsMapL.put(SchemaSymbols.ELT_SIMPLECONTENT, attrList); 608 609 // for element "restriction" - local 610 attrList = Container.getContainer(2); 611 // base = QName 612 attrList.put(SchemaSymbols.ATT_BASE, allAttrs[ATT_BASE_N]); 613 // id = ID 614 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 615 fEleAttrsMapL.put(SchemaSymbols.ELT_RESTRICTION, attrList); 616 617 // for element "extension" - local 618 attrList = Container.getContainer(2); 619 // base = QName 620 attrList.put(SchemaSymbols.ATT_BASE, allAttrs[ATT_BASE_R]); 621 // id = ID 622 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 623 fEleAttrsMapL.put(SchemaSymbols.ELT_EXTENSION, attrList); 624 625 // for element "attributeGroup" - local ref 626 attrList = Container.getContainer(2); 627 // id = ID 628 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 629 // ref = QName 630 attrList.put(SchemaSymbols.ATT_REF, allAttrs[ATT_REF_R]); 631 fEleAttrsMapL.put(SchemaSymbols.ELT_ATTRIBUTEGROUP, attrList); 632 633 // for element "anyAttribute" - local 634 attrList = Container.getContainer(3); 635 // id = ID 636 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 637 // namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) ) : ##any 638 attrList.put(SchemaSymbols.ATT_NAMESPACE, allAttrs[ATT_NAMESPACE_D]); 639 // processContents = (lax | skip | strict) : strict 640 attrList.put(SchemaSymbols.ATT_PROCESSCONTENTS, allAttrs[ATT_PROCESS_C_D]); 641 fEleAttrsMapL.put(SchemaSymbols.ELT_ANYATTRIBUTE, attrList); 642 643 // for element "complexContent" - local 644 attrList = Container.getContainer(2); 645 // id = ID 646 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 647 // mixed = boolean 648 attrList.put(SchemaSymbols.ATT_MIXED, allAttrs[ATT_MIXED_N]); 649 fEleAttrsMapL.put(SchemaSymbols.ELT_COMPLEXCONTENT, attrList); 650 651 // for element "attributeGroup" - global 652 attrList = Container.getContainer(2); 653 // id = ID 654 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 655 // name = NCName 656 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 657 fEleAttrsMapG.put(SchemaSymbols.ELT_ATTRIBUTEGROUP, attrList); 658 659 // for element "group" - global 660 attrList = Container.getContainer(2); 661 // id = ID 662 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 663 // name = NCName 664 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 665 fEleAttrsMapG.put(SchemaSymbols.ELT_GROUP, attrList); 666 667 // for element "group" - local ref 668 attrList = Container.getContainer(4); 669 // id = ID 670 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 671 // maxOccurs = (nonNegativeInteger | unbounded) : 1 672 attrList.put(SchemaSymbols.ATT_MAXOCCURS, allAttrs[ATT_MAXOCCURS_D]); 673 // minOccurs = nonNegativeInteger : 1 674 attrList.put(SchemaSymbols.ATT_MINOCCURS, allAttrs[ATT_MINOCCURS_D]); 675 // ref = QName 676 attrList.put(SchemaSymbols.ATT_REF, allAttrs[ATT_REF_R]); 677 fEleAttrsMapL.put(SchemaSymbols.ELT_GROUP, attrList); 678 679 // for element "all" - local 680 attrList = Container.getContainer(3); 681 // id = ID 682 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 683 // maxOccurs = 1 : 1 684 attrList.put(SchemaSymbols.ATT_MAXOCCURS, allAttrs[ATT_MAXOCCURS1_D]); 685 // minOccurs = (0 | 1) : 1 686 attrList.put(SchemaSymbols.ATT_MINOCCURS, allAttrs[ATT_MINOCCURS1_D]); 687 fEleAttrsMapL.put(SchemaSymbols.ELT_ALL, attrList); 688 689 // for element "choice" - local 690 attrList = Container.getContainer(3); 691 // id = ID 692 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 693 // maxOccurs = (nonNegativeInteger | unbounded) : 1 694 attrList.put(SchemaSymbols.ATT_MAXOCCURS, allAttrs[ATT_MAXOCCURS_D]); 695 // minOccurs = nonNegativeInteger : 1 696 attrList.put(SchemaSymbols.ATT_MINOCCURS, allAttrs[ATT_MINOCCURS_D]); 697 fEleAttrsMapL.put(SchemaSymbols.ELT_CHOICE, attrList); 698 // for element "sequence" - local 699 fEleAttrsMapL.put(SchemaSymbols.ELT_SEQUENCE, attrList); 700 701 // for element "any" - local 702 attrList = Container.getContainer(5); 703 // id = ID 704 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 705 // maxOccurs = (nonNegativeInteger | unbounded) : 1 706 attrList.put(SchemaSymbols.ATT_MAXOCCURS, allAttrs[ATT_MAXOCCURS_D]); 707 // minOccurs = nonNegativeInteger : 1 708 attrList.put(SchemaSymbols.ATT_MINOCCURS, allAttrs[ATT_MINOCCURS_D]); 709 // namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) ) : ##any 710 attrList.put(SchemaSymbols.ATT_NAMESPACE, allAttrs[ATT_NAMESPACE_D]); 711 // processContents = (lax | skip | strict) : strict 712 attrList.put(SchemaSymbols.ATT_PROCESSCONTENTS, allAttrs[ATT_PROCESS_C_D]); 713 fEleAttrsMapL.put(SchemaSymbols.ELT_ANY, attrList); 714 715 // for element "unique" - local 716 attrList = Container.getContainer(2); 717 // id = ID 718 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 719 // name = NCName 720 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 721 fEleAttrsMapL.put(SchemaSymbols.ELT_UNIQUE, attrList); 722 // for element "key" - local 723 fEleAttrsMapL.put(SchemaSymbols.ELT_KEY, attrList); 724 725 // for element "keyref" - local 726 attrList = Container.getContainer(3); 727 // id = ID 728 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 729 // name = NCName 730 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 731 // refer = QName 732 attrList.put(SchemaSymbols.ATT_REFER, allAttrs[ATT_REFER_R]); 733 fEleAttrsMapL.put(SchemaSymbols.ELT_KEYREF, attrList); 734 735 // for element "selector" - local 736 attrList = Container.getContainer(2); 737 // id = ID 738 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 739 // xpath = a subset of XPath expression 740 attrList.put(SchemaSymbols.ATT_XPATH, allAttrs[ATT_XPATH_R]); 741 fEleAttrsMapL.put(SchemaSymbols.ELT_SELECTOR, attrList); 742 743 // for element "field" - local 744 attrList = Container.getContainer(2); 745 // id = ID 746 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 747 // xpath = a subset of XPath expression 748 attrList.put(SchemaSymbols.ATT_XPATH, allAttrs[ATT_XPATH1_R]); 749 fEleAttrsMapL.put(SchemaSymbols.ELT_FIELD, attrList); 750 751 // for element "annotation" - global 752 attrList = Container.getContainer(1); 753 // id = ID 754 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 755 fEleAttrsMapG.put(SchemaSymbols.ELT_ANNOTATION, attrList); 756 // for element "annotation" - local 757 fEleAttrsMapL.put(SchemaSymbols.ELT_ANNOTATION, attrList); 758 759 // for element "appinfo" - local 760 attrList = Container.getContainer(1); 761 // source = anyURI 762 attrList.put(SchemaSymbols.ATT_SOURCE, allAttrs[ATT_SOURCE_N]); 763 fEleAttrsMapG.put(SchemaSymbols.ELT_APPINFO, attrList); 764 fEleAttrsMapL.put(SchemaSymbols.ELT_APPINFO, attrList); 765 766 // for element "documentation" - local 767 attrList = Container.getContainer(2); 768 // source = anyURI 769 attrList.put(SchemaSymbols.ATT_SOURCE, allAttrs[ATT_SOURCE_N]); 770 // xml:lang = language 771 attrList.put(SchemaSymbols.ATT_XML_LANG, allAttrs[ATT_XML_LANG]); 772 fEleAttrsMapG.put(SchemaSymbols.ELT_DOCUMENTATION, attrList); 773 fEleAttrsMapL.put(SchemaSymbols.ELT_DOCUMENTATION, attrList); 774 775 // for element "simpleType" - global 776 attrList = Container.getContainer(3); 777 // final = (#all | List of (list | union | restriction)) 778 attrList.put(SchemaSymbols.ATT_FINAL, allAttrs[ATT_FINAL1_N]); 779 // id = ID 780 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 781 // name = NCName 782 attrList.put(SchemaSymbols.ATT_NAME, allAttrs[ATT_NAME_R]); 783 fEleAttrsMapG.put(SchemaSymbols.ELT_SIMPLETYPE, attrList); 784 785 // for element "simpleType" - local 786 attrList = Container.getContainer(2); 787 // final = (#all | List of (list | union | restriction)) 788 attrList.put(SchemaSymbols.ATT_FINAL, allAttrs[ATT_FINAL1_N]); 789 // id = ID 790 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 791 fEleAttrsMapL.put(SchemaSymbols.ELT_SIMPLETYPE, attrList); 792 793 // for element "restriction" - local 794 // already registered for complexType 795 796 // for element "list" - local 797 attrList = Container.getContainer(2); 798 // id = ID 799 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 800 // itemType = QName 801 attrList.put(SchemaSymbols.ATT_ITEMTYPE, allAttrs[ATT_ITEMTYPE_N]); 802 fEleAttrsMapL.put(SchemaSymbols.ELT_LIST, attrList); 803 804 // for element "union" - local 805 attrList = Container.getContainer(2); 806 // id = ID 807 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 808 // memberTypes = List of QName 809 attrList.put(SchemaSymbols.ATT_MEMBERTYPES, allAttrs[ATT_MEMBER_T_N]); 810 fEleAttrsMapL.put(SchemaSymbols.ELT_UNION, attrList); 811 812 // for element "schema" - global 813 attrList = Container.getContainer(8); 814 // attributeFormDefault = (qualified | unqualified) : unqualified 815 attrList.put(SchemaSymbols.ATT_ATTRIBUTEFORMDEFAULT, allAttrs[ATT_ATTRIBUTE_FD_D]); 816 // blockDefault = (#all | List of (extension | restriction | substitution)) : '' 817 attrList.put(SchemaSymbols.ATT_BLOCKDEFAULT, allAttrs[ATT_BLOCK_D_D]); 818 // elementFormDefault = (qualified | unqualified) : unqualified 819 attrList.put(SchemaSymbols.ATT_ELEMENTFORMDEFAULT, allAttrs[ATT_ELEMENT_FD_D]); 820 // finalDefault = (#all | List of (extension | restriction | list | union)) : '' 821 attrList.put(SchemaSymbols.ATT_FINALDEFAULT, allAttrs[ATT_FINAL_D_D]); 822 // id = ID 823 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 824 // targetNamespace = anyURI 825 attrList.put(SchemaSymbols.ATT_TARGETNAMESPACE, allAttrs[ATT_TARGET_N_N]); 826 // version = token 827 attrList.put(SchemaSymbols.ATT_VERSION, allAttrs[ATT_VERSION_N]); 828 // xml:lang = language 829 attrList.put(SchemaSymbols.ATT_XML_LANG, allAttrs[ATT_XML_LANG]); 830 fEleAttrsMapG.put(SchemaSymbols.ELT_SCHEMA, attrList); 831 832 // for element "include" - global 833 attrList = Container.getContainer(2); 834 // id = ID 835 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 836 // schemaLocation = anyURI 837 attrList.put(SchemaSymbols.ATT_SCHEMALOCATION, allAttrs[ATT_SCHEMA_L_R]); 838 fEleAttrsMapG.put(SchemaSymbols.ELT_INCLUDE, attrList); 839 // for element "redefine" - global 840 fEleAttrsMapG.put(SchemaSymbols.ELT_REDEFINE, attrList); 841 842 // for element "import" - global 843 attrList = Container.getContainer(3); 844 // id = ID 845 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 846 // namespace = anyURI 847 attrList.put(SchemaSymbols.ATT_NAMESPACE, allAttrs[ATT_NAMESPACE_N]); 848 // schemaLocation = anyURI 849 attrList.put(SchemaSymbols.ATT_SCHEMALOCATION, allAttrs[ATT_SCHEMA_L_N]); 850 fEleAttrsMapG.put(SchemaSymbols.ELT_IMPORT, attrList); 851 852 // for element "length" - local 853 attrList = Container.getContainer(3); 854 // id = ID 855 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 856 // value = nonNegativeInteger 857 attrList.put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_NNI_N]); 858 // fixed = boolean : false 859 attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_D]); 860 fEleAttrsMapL.put(SchemaSymbols.ELT_LENGTH, attrList); 861 // for element "minLength" - local 862 fEleAttrsMapL.put(SchemaSymbols.ELT_MINLENGTH, attrList); 863 // for element "maxLength" - local 864 fEleAttrsMapL.put(SchemaSymbols.ELT_MAXLENGTH, attrList); 865 // for element "fractionDigits" - local 866 fEleAttrsMapL.put(SchemaSymbols.ELT_FRACTIONDIGITS, attrList); 867 868 // for element "totalDigits" - local 869 attrList = Container.getContainer(3); 870 // id = ID 871 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 872 // value = positiveInteger 873 attrList.put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_PI_N]); 874 // fixed = boolean : false 875 attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_D]); 876 fEleAttrsMapL.put(SchemaSymbols.ELT_TOTALDIGITS, attrList); 877 878 // for element "pattern" - local 879 attrList = Container.getContainer(2); 880 // id = ID 881 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 882 // value = string 883 attrList.put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_STR_N]); 884 fEleAttrsMapL.put(SchemaSymbols.ELT_PATTERN, attrList); 885 886 // for element "enumeration" - local 887 attrList = Container.getContainer(2); 888 // id = ID 889 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 890 // value = anySimpleType 891 attrList.put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_STR_N]); 892 fEleAttrsMapL.put(SchemaSymbols.ELT_ENUMERATION, attrList); 893 894 // for element "whiteSpace" - local 895 attrList = Container.getContainer(3); 896 // id = ID 897 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 898 // value = preserve | replace | collapse 899 attrList.put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_WS_N]); 900 // fixed = boolean : false 901 attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_D]); 902 fEleAttrsMapL.put(SchemaSymbols.ELT_WHITESPACE, attrList); 903 904 // for element "maxInclusive" - local 905 attrList = Container.getContainer(3); 906 // id = ID 907 attrList.put(SchemaSymbols.ATT_ID, allAttrs[ATT_ID_N]); 908 // value = anySimpleType 909 attrList.put(SchemaSymbols.ATT_VALUE, allAttrs[ATT_VALUE_STR_N]); 910 // fixed = boolean : false 911 attrList.put(SchemaSymbols.ATT_FIXED, allAttrs[ATT_FIXED_D]); 912 fEleAttrsMapL.put(SchemaSymbols.ELT_MAXINCLUSIVE, attrList); 913 // for element "maxExclusive" - local 914 fEleAttrsMapL.put(SchemaSymbols.ELT_MAXEXCLUSIVE, attrList); 915 // for element "minInclusive" - local 916 fEleAttrsMapL.put(SchemaSymbols.ELT_MININCLUSIVE, attrList); 917 // for element "minExclusive" - local 918 fEleAttrsMapL.put(SchemaSymbols.ELT_MINEXCLUSIVE, attrList); 919 } 920 921 // used to resolver namespace prefixes 922 protected XSDHandler fSchemaHandler = null; 923 924 // used to store symbols. 925 protected SymbolTable fSymbolTable = null; 926 927 // used to store the mapping from processed element to attributes 928 protected Map fNonSchemaAttrs = new HashMap(); 929 930 // temprory vector, used to hold the namespace list 931 protected Vector fNamespaceList = new Vector(); 932 933 // whether this attribute appeared in the current element 934 protected boolean[] fSeen = new boolean[ATTIDX_COUNT]; 935 private static boolean[] fSeenTemp = new boolean[ATTIDX_COUNT]; 936 937 // constructor. Sets fErrorReproter and get datatype validators 938 public XSAttributeChecker(XSDHandler schemaHandler) { 939 fSchemaHandler = schemaHandler; 940 } 941 942 public void reset(SymbolTable symbolTable) { 943 fSymbolTable = symbolTable; 944 fNonSchemaAttrs.clear(); 945 } 946 947 /** 948 * Check whether the specified element conforms to the attributes restriction 949 * an array of attribute values is returned. the caller must call 950 * <code>returnAttrArray</code> to return that array. 951 * 952 * @param element which element to check 953 * @param isGlobal whether a child of <schema> or <redefine> 954 * @param schemaDoc the document where the element lives in 955 * @return an array containing attribute values 956 */ 957 public Object[] checkAttributes(Element element, boolean isGlobal, 958 XSDocumentInfo schemaDoc) { 959 return checkAttributes(element, isGlobal, schemaDoc, false); 960 } 961 962 /** 963 * Check whether the specified element conforms to the attributes restriction 964 * an array of attribute values is returned. the caller must call 965 * <code>returnAttrArray</code> to return that array. This method also takes 966 * an extra parameter: if the element is "enumeration", whether to make a 967 * copy of the namespace context, so that the value can be resolved as a 968 * QName later. 969 * 970 * @param element which element to check 971 * @param isGlobal whether a child of <schema> or <redefine> 972 * @param schemaDoc the document where the element lives in 973 * @param enumAsQName whether to tread enumeration value as QName 974 * @return an array containing attribute values 975 */ 976 public Object[] checkAttributes(Element element, boolean isGlobal, 977 XSDocumentInfo schemaDoc, boolean enumAsQName) { 978 if (element == null) 979 return null; 980 981 // get all attributes 982 Attr[] attrs = DOMUtil.getAttrs(element); 983 984 // update NamespaceSupport 985 resolveNamespace(element, attrs, schemaDoc.fNamespaceSupport); 986 987 String uri = DOMUtil.getNamespaceURI(element); 988 String elName = DOMUtil.getLocalName(element); 989 990 if (!SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(uri)) { 991 reportSchemaError("s4s-elt-schema-ns", new Object[] {elName}, element); 992 } 993 994 Map eleAttrsMap = fEleAttrsMapG; 995 String lookupName = elName; 996 997 // REVISIT: only local element and attribute are different from others. 998 // it's possible to have either name or ref. all the others 999 // are only allowed to have one of name or ref, or neither of them. 1000 // we'd better move such checking to the traverser. 1001 if (!isGlobal) { 1002 eleAttrsMap = fEleAttrsMapL; 1003 if (elName.equals(SchemaSymbols.ELT_ELEMENT)) { 1004 if (DOMUtil.getAttr(element, SchemaSymbols.ATT_REF) != null) 1005 lookupName = ELEMENT_R; 1006 else 1007 lookupName = ELEMENT_N; 1008 } else if (elName.equals(SchemaSymbols.ELT_ATTRIBUTE)) { 1009 if (DOMUtil.getAttr(element, SchemaSymbols.ATT_REF) != null) 1010 lookupName = ATTRIBUTE_R; 1011 else 1012 lookupName = ATTRIBUTE_N; 1013 } 1014 } 1015 1016 // get desired attribute list of this element 1017 Container attrList = (Container)eleAttrsMap.get(lookupName); 1018 if (attrList == null) { 1019 // should never gets here. 1020 // when this method is called, the call already knows that 1021 // the element can appear. 1022 reportSchemaError ("s4s-elt-invalid", new Object[] {elName}, element); 1023 return null; 1024 } 1025 1026 Object[] attrValues = getAvailableArray(); 1027 long fromDefault = 0; 1028 1029 // clear the "seen" flag. 1030 System.arraycopy(fSeenTemp, 0, fSeen, 0, ATTIDX_COUNT); 1031 1032 // traverse all attributes 1033 int length = attrs.length; 1034 Attr sattr = null; 1035 for (int i = 0; i < length; i++) { 1036 sattr = attrs[i]; 1037 // get the attribute name/value 1038 //String attrName = DOMUtil.getLocalName(sattr); 1039 String attrName = sattr.getName(); 1040 String attrURI = DOMUtil.getNamespaceURI(sattr); 1041 String attrVal = DOMUtil.getValue(sattr); 1042 1043 if (attrName.startsWith("xml")) { 1044 String attrPrefix = DOMUtil.getPrefix(sattr); 1045 // we don't want to add namespace declarations to the non-schema attributes 1046 if ("xmlns".equals(attrPrefix) || "xmlns".equals(attrName)) { 1047 continue; 1048 } 1049 // Both <schema> and <documentation> may have an xml:lang attribute. 1050 // Set the URI for this attribute to null so that we process it 1051 // like any other schema attribute. 1052 else if (SchemaSymbols.ATT_XML_LANG.equals(attrName) && 1053 (SchemaSymbols.ELT_SCHEMA.equals(elName) || 1054 SchemaSymbols.ELT_DOCUMENTATION.equals(elName))) { 1055 attrURI = null; 1056 } 1057 } 1058 1059 // for attributes with namespace prefix 1060 // 1061 if (attrURI != null && attrURI.length() != 0) { 1062 // attributes with schema namespace are not allowed 1063 // and not allowed on "document" and "appInfo" 1064 if (attrURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) { 1065 reportSchemaError ("s4s-att-not-allowed", new Object[] {elName, attrName}, element); 1066 } 1067 else { 1068 if(attrValues[ATTIDX_NONSCHEMA] == null) { 1069 // these are usually small 1070 attrValues[ATTIDX_NONSCHEMA] = new Vector(4,2); 1071 } 1072 ((Vector)attrValues[ATTIDX_NONSCHEMA]).addElement(attrName); 1073 ((Vector)attrValues[ATTIDX_NONSCHEMA]).addElement(attrVal); 1074 // for attributes from other namespace 1075 // store them in a list, and TRY to validate them after 1076 // schema traversal (because it's "lax") 1077 //otherValues.put(attrName, attrVal); 1078 // REVISIT: actually use this some day... 1079 // String attrRName = attrURI + "," + attrName; 1080 // Vector values = (Vector)fNonSchemaAttrs.get(attrRName); 1081 // if (values == null) { 1082 // values = new Vector(); 1083 // values.addElement(attrName); 1084 // values.addElement(elName); 1085 // values.addElement(attrVal); 1086 // fNonSchemaAttrs.put(attrRName, values); 1087 // } 1088 // else { 1089 // values.addElement(elName); 1090 // values.addElement(attrVal); 1091 // } 1092 } 1093 continue; 1094 } 1095 1096 // check whether this attribute is allowed 1097 OneAttr oneAttr = attrList.get(attrName); 1098 if (oneAttr == null) { 1099 reportSchemaError ("s4s-att-not-allowed", 1100 new Object[] {elName, attrName}, 1101 element); 1102 continue; 1103 } 1104 1105 // we've seen this attribute 1106 fSeen[oneAttr.valueIndex] = true; 1107 1108 // check the value against the datatype 1109 try { 1110 // no checking on string needs to be done here. 1111 // no checking on xpath needs to be done here. 1112 // xpath values are validated in xpath parser 1113 if (oneAttr.dvIndex >= 0) { 1114 if (oneAttr.dvIndex != DT_STRING && 1115 oneAttr.dvIndex != DT_XPATH && 1116 oneAttr.dvIndex != DT_XPATH1) { 1117 XSSimpleType dv = fExtraDVs[oneAttr.dvIndex]; 1118 Object avalue = dv.validate(attrVal, schemaDoc.fValidationContext, null); 1119 // kludge to handle chameleon includes/redefines... 1120 if (oneAttr.dvIndex == DT_QNAME) { 1121 QName qname = (QName)avalue; 1122 if(qname.prefix == XMLSymbols.EMPTY_STRING && qname.uri == null && schemaDoc.fIsChameleonSchema) 1123 qname.uri = schemaDoc.fTargetNamespace; 1124 } 1125 attrValues[oneAttr.valueIndex] = avalue; 1126 } else { 1127 attrValues[oneAttr.valueIndex] = attrVal; 1128 } 1129 } 1130 else { 1131 attrValues[oneAttr.valueIndex] = validate(attrValues, attrName, attrVal, oneAttr.dvIndex, schemaDoc); 1132 } 1133 } catch (InvalidDatatypeValueException ide) { 1134 reportSchemaError ("s4s-att-invalid-value", 1135 new Object[] {elName, attrName, ide.getMessage()}, 1136 element); 1137 if (oneAttr.dfltValue != null) 1138 //attrValues.put(attrName, oneAttr.dfltValue); 1139 attrValues[oneAttr.valueIndex] = oneAttr.dfltValue; 1140 } 1141 1142 // For "enumeration", and type is possible to be a QName, we need 1143 // to return namespace context for later QName resolution. 1144 if (elName.equals(SchemaSymbols.ELT_ENUMERATION) && enumAsQName) { 1145 attrValues[ATTIDX_ENUMNSDECLS] = new SchemaNamespaceSupport(schemaDoc.fNamespaceSupport); 1146 } 1147 } 1148 1149 // apply default values 1150 OneAttr[] reqAttrs = attrList.values; 1151 for (int i = 0; i < reqAttrs.length; i++) { 1152 OneAttr oneAttr = reqAttrs[i]; 1153 1154 // if the attribute didn't apprear, and 1155 // if the attribute is optional with default value, apply it 1156 if (oneAttr.dfltValue != null && !fSeen[oneAttr.valueIndex]) { 1157 //attrValues.put(oneAttr.name, oneAttr.dfltValue); 1158 attrValues[oneAttr.valueIndex] = oneAttr.dfltValue; 1159 fromDefault |= (1<<oneAttr.valueIndex); 1160 } 1161 } 1162 1163 attrValues[ATTIDX_FROMDEFAULT] = new Long(fromDefault); 1164 //attrValues[ATTIDX_OTHERVALUES] = otherValues; 1165 1166 // Check that minOccurs isn't greater than maxOccurs. 1167 // p-props-correct 2.1 1168 if (attrValues[ATTIDX_MAXOCCURS] != null) { 1169 int min = ((XInt)attrValues[ATTIDX_MINOCCURS]).intValue(); 1170 int max = ((XInt)attrValues[ATTIDX_MAXOCCURS]).intValue(); 1171 if (max != SchemaSymbols.OCCURRENCE_UNBOUNDED) { 1172 1173 // maxOccurLimit is only check in secure mode 1174 if (fSchemaHandler.fSecurityManager != null) { 1175 String localName = element.getLocalName(); 1176 1177 // The maxOccurs restriction no longer applies to elements 1178 // and wildcards in a sequence in which they are the only 1179 // particle. These are now validated using a constant 1180 // space algorithm. The restriction still applies to all 1181 // other cases. 1182 1183 // Determine if constant-space algorithm can be applied 1184 final boolean optimize = 1185 (localName.equals("element") || localName.equals("any")) && 1186 (element.getNextSibling() == null) && 1187 (element.getPreviousSibling() == null) && 1188 (element.getParentNode().getLocalName().equals("sequence")); 1189 1190 if (!optimize) { 1191 //Revisit :: IMO this is not right place to check 1192 // maxOccurNodeLimit. 1193 int maxOccurNodeLimit = fSchemaHandler.fSecurityManager.getLimit(XMLSecurityManager.Limit.MAX_OCCUR_NODE_LIMIT); 1194 if (max > maxOccurNodeLimit && !fSchemaHandler.fSecurityManager.isNoLimit(maxOccurNodeLimit)) { 1195 reportSchemaFatalError("MaxOccurLimit", new Object[] {new Integer(maxOccurNodeLimit)}, element); 1196 1197 // reset max values in case processing continues on error 1198 attrValues[ATTIDX_MAXOCCURS] = fXIntPool.getXInt(maxOccurNodeLimit); 1199 //new Integer(maxOccurNodeLimit); 1200 max = maxOccurNodeLimit; 1201 } 1202 } 1203 } 1204 1205 if (min > max) { 1206 reportSchemaError ("p-props-correct.2.1", 1207 new Object[] {elName, attrValues[ATTIDX_MINOCCURS], attrValues[ATTIDX_MAXOCCURS]}, 1208 element); 1209 attrValues[ATTIDX_MINOCCURS] = attrValues[ATTIDX_MAXOCCURS]; 1210 } 1211 } 1212 } 1213 1214 return attrValues; 1215 } 1216 1217 private Object validate(Object[] attrValues, String attr, String ivalue, int dvIndex, 1218 XSDocumentInfo schemaDoc) throws InvalidDatatypeValueException { 1219 if (ivalue == null) 1220 return null; 1221 1222 // To validate these types, we don't actually need to normalize the 1223 // strings. We only need to remove the whitespace from both ends. 1224 // In some special cases (list types), StringTokenizer can correctly 1225 // process the un-normalized whitespace. 1226 1227 String value = XMLChar.trim(ivalue); 1228 Object retValue = null; 1229 Vector memberType; 1230 int choice; 1231 1232 switch (dvIndex) { 1233 case DT_BOOLEAN: 1234 if (value.equals(SchemaSymbols.ATTVAL_FALSE) || 1235 value.equals(SchemaSymbols.ATTVAL_FALSE_0)) { 1236 retValue = Boolean.FALSE; 1237 } else if (value.equals(SchemaSymbols.ATTVAL_TRUE) || 1238 value.equals(SchemaSymbols.ATTVAL_TRUE_1)) { 1239 retValue = Boolean.TRUE; 1240 } else { 1241 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{value, "boolean"}); 1242 } 1243 break; 1244 case DT_NONNEGINT: 1245 try { 1246 if (value.length() > 0 && value.charAt(0) == '+') 1247 value = value.substring(1); 1248 retValue = fXIntPool.getXInt(Integer.parseInt(value)); 1249 } catch (NumberFormatException e) { 1250 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{value, "nonNegativeInteger"}); 1251 } 1252 if (((XInt)retValue).intValue() < 0) 1253 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{value, "nonNegativeInteger"}); 1254 break; 1255 case DT_POSINT: 1256 try { 1257 if (value.length() > 0 && value.charAt(0) == '+') 1258 value = value.substring(1); 1259 retValue = fXIntPool.getXInt(Integer.parseInt(value)); 1260 } catch (NumberFormatException e) { 1261 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{value, "positiveInteger"}); 1262 } 1263 if (((XInt)retValue).intValue() <= 0) 1264 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{value, "positiveInteger"}); 1265 break; 1266 case DT_BLOCK: 1267 // block = (#all | List of (extension | restriction | substitution)) 1268 choice = 0; 1269 if (value.equals (SchemaSymbols.ATTVAL_POUNDALL)) { 1270 choice = XSConstants.DERIVATION_SUBSTITUTION|XSConstants.DERIVATION_EXTENSION| 1271 XSConstants.DERIVATION_RESTRICTION; 1272 } 1273 else { 1274 StringTokenizer t = new StringTokenizer(value, " \n\t\r"); 1275 while (t.hasMoreTokens()) { 1276 String token = t.nextToken (); 1277 1278 if (token.equals (SchemaSymbols.ATTVAL_EXTENSION)) { 1279 choice |= XSConstants.DERIVATION_EXTENSION; 1280 } 1281 else if (token.equals (SchemaSymbols.ATTVAL_RESTRICTION)) { 1282 choice |= XSConstants.DERIVATION_RESTRICTION; 1283 } 1284 else if (token.equals (SchemaSymbols.ATTVAL_SUBSTITUTION)) { 1285 choice |= XSConstants.DERIVATION_SUBSTITUTION; 1286 } 1287 else { 1288 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "(#all | List of (extension | restriction | substitution))"}); 1289 } 1290 } 1291 } 1292 retValue = fXIntPool.getXInt(choice); 1293 break; 1294 case DT_BLOCK1: 1295 case DT_FINAL: 1296 // block = (#all | List of (extension | restriction)) 1297 // final = (#all | List of (extension | restriction)) 1298 choice = 0; 1299 if (value.equals (SchemaSymbols.ATTVAL_POUNDALL)) { 1300 //choice = SchemaSymbols.EXTENSION|SchemaSymbols.RESTRICTION; 1301 // REVISIT: if #all, then make the result the combination of 1302 // everything: substitution/externsion/restriction/list/union. 1303 // would this be a problem? 1304 // the reason doing so is that when final/blockFinal on <schema> 1305 // is #all, it's not always the same as the conbination of those 1306 // values allowed by final/blockFinal. 1307 // for example, finalDefault="#all" is not always the same as 1308 // finalDefault="extension restriction". 1309 // if finalDefault="#all", final on any simple type would be 1310 // "extension restriction list union". 1311 choice = XSConstants.DERIVATION_SUBSTITUTION|XSConstants.DERIVATION_EXTENSION| 1312 XSConstants.DERIVATION_RESTRICTION|XSConstants.DERIVATION_LIST| 1313 XSConstants.DERIVATION_UNION; 1314 } 1315 else { 1316 StringTokenizer t = new StringTokenizer(value, " \n\t\r"); 1317 while (t.hasMoreTokens()) { 1318 String token = t.nextToken (); 1319 1320 if (token.equals (SchemaSymbols.ATTVAL_EXTENSION)) { 1321 choice |= XSConstants.DERIVATION_EXTENSION; 1322 } 1323 else if (token.equals (SchemaSymbols.ATTVAL_RESTRICTION)) { 1324 choice |= XSConstants.DERIVATION_RESTRICTION; 1325 } 1326 else { 1327 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "(#all | List of (extension | restriction))"}); 1328 } 1329 } 1330 } 1331 retValue = fXIntPool.getXInt(choice); 1332 break; 1333 case DT_FINAL1: 1334 // final = (#all | List of (list | union | restriction)) 1335 choice = 0; 1336 if (value.equals (SchemaSymbols.ATTVAL_POUNDALL)) { 1337 //choice = SchemaSymbols.RESTRICTION|SchemaSymbols.LIST| 1338 // SchemaSymbols.UNION; 1339 // REVISIT: if #all, then make the result the combination of 1340 // everything: substitution/externsion/restriction/list/union. 1341 // would this be a problem? 1342 // same reason as above DT_BLOCK1/DT_FINAL 1343 choice = XSConstants.DERIVATION_SUBSTITUTION|XSConstants.DERIVATION_EXTENSION| 1344 XSConstants.DERIVATION_RESTRICTION|XSConstants.DERIVATION_LIST| 1345 XSConstants.DERIVATION_UNION; 1346 } 1347 else { 1348 StringTokenizer t = new StringTokenizer(value, " \n\t\r"); 1349 while (t.hasMoreTokens()) { 1350 String token = t.nextToken (); 1351 1352 if (token.equals (SchemaSymbols.ATTVAL_LIST)) { 1353 choice |= XSConstants.DERIVATION_LIST; 1354 } 1355 else if (token.equals (SchemaSymbols.ATTVAL_UNION)) { 1356 choice |= XSConstants.DERIVATION_UNION; 1357 } 1358 else if (token.equals (SchemaSymbols.ATTVAL_RESTRICTION)) { 1359 choice |= XSConstants.DERIVATION_RESTRICTION; 1360 } 1361 else { 1362 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "(#all | List of (list | union | restriction))"}); 1363 } 1364 } 1365 } 1366 retValue = fXIntPool.getXInt(choice); 1367 break; 1368 case DT_FINAL2: 1369 // finalDefault = (#all | List of (extension | restriction | list | union)) 1370 choice = 0; 1371 if (value.equals (SchemaSymbols.ATTVAL_POUNDALL)) { 1372 //choice = SchemaSymbols.RESTRICTION|SchemaSymbols.LIST| 1373 // SchemaSymbols.UNION; 1374 // REVISIT: if #all, then make the result the combination of 1375 // everything: substitution/externsion/restriction/list/union. 1376 // would this be a problem? 1377 // same reason as above DT_BLOCK1/DT_FINAL 1378 choice = XSConstants.DERIVATION_SUBSTITUTION|XSConstants.DERIVATION_EXTENSION| 1379 XSConstants.DERIVATION_RESTRICTION|XSConstants.DERIVATION_LIST| 1380 XSConstants.DERIVATION_UNION; 1381 } 1382 else { 1383 StringTokenizer t = new StringTokenizer(value, " \n\t\r"); 1384 while (t.hasMoreTokens()) { 1385 String token = t.nextToken (); 1386 1387 if (token.equals (SchemaSymbols.ATTVAL_EXTENSION)) { 1388 choice |= XSConstants.DERIVATION_EXTENSION; 1389 } 1390 else if (token.equals (SchemaSymbols.ATTVAL_RESTRICTION)) { 1391 choice |= XSConstants.DERIVATION_RESTRICTION; 1392 } 1393 else if (token.equals (SchemaSymbols.ATTVAL_LIST)) { 1394 choice |= XSConstants.DERIVATION_LIST; 1395 } 1396 else if (token.equals (SchemaSymbols.ATTVAL_UNION)) { 1397 choice |= XSConstants.DERIVATION_UNION; 1398 } 1399 else { 1400 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "(#all | List of (extension | restriction | list | union))"}); 1401 } 1402 } 1403 } 1404 retValue = fXIntPool.getXInt(choice); 1405 break; 1406 case DT_FORM: 1407 // form = (qualified | unqualified) 1408 if (value.equals (SchemaSymbols.ATTVAL_QUALIFIED)) 1409 retValue = INT_QUALIFIED; 1410 else if (value.equals (SchemaSymbols.ATTVAL_UNQUALIFIED)) 1411 retValue = INT_UNQUALIFIED; 1412 else 1413 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1414 new Object[]{value, "(qualified | unqualified)"}); 1415 break; 1416 case DT_MAXOCCURS: 1417 // maxOccurs = (nonNegativeInteger | unbounded) 1418 if (value.equals(SchemaSymbols.ATTVAL_UNBOUNDED)) { 1419 retValue = INT_UNBOUNDED; 1420 } else { 1421 try { 1422 retValue = validate(attrValues, attr, value, DT_NONNEGINT, schemaDoc); 1423 } catch (NumberFormatException e) { 1424 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "(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("cvc-enumeration-valid", 1434 new Object[]{value, "(1)"}); 1435 break; 1436 case DT_MEMBERTYPES: 1437 // memberTypes = List of QName 1438 memberType = new Vector(); 1439 try { 1440 StringTokenizer t = new StringTokenizer(value, " \n\t\r"); 1441 while (t.hasMoreTokens()) { 1442 String token = t.nextToken (); 1443 QName qname = (QName)fExtraDVs[DT_QNAME].validate(token, schemaDoc.fValidationContext, null); 1444 // kludge to handle chameleon includes/redefines... 1445 if(qname.prefix == XMLSymbols.EMPTY_STRING && qname.uri == null && schemaDoc.fIsChameleonSchema) 1446 qname.uri = schemaDoc.fTargetNamespace; 1447 memberType.addElement(qname); 1448 } 1449 retValue = memberType; 1450 } 1451 catch (InvalidDatatypeValueException ide) { 1452 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.2", new Object[]{value, "(List of QName)"}); 1453 } 1454 break; 1455 case DT_MINOCCURS1: 1456 // minOccurs = (0 | 1) 1457 if (value.equals("0")) 1458 retValue = fXIntPool.getXInt(0); 1459 else if (value.equals("1")) 1460 retValue = fXIntPool.getXInt(1); 1461 else 1462 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1463 new Object[]{value, "(0 | 1)"}); 1464 break; 1465 case DT_NAMESPACE: 1466 // namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) ) 1467 if (value.equals(SchemaSymbols.ATTVAL_TWOPOUNDANY)) { 1468 // ##any 1469 retValue = INT_ANY_ANY; 1470 } else if (value.equals(SchemaSymbols.ATTVAL_TWOPOUNDOTHER)) { 1471 // ##other 1472 retValue = INT_ANY_NOT; 1473 String[] list = new String[2]; 1474 list[0] = schemaDoc.fTargetNamespace; 1475 list[1] = null; 1476 attrValues[ATTIDX_NAMESPACE_LIST] = list; 1477 } else { 1478 // list 1479 retValue = INT_ANY_LIST; 1480 1481 fNamespaceList.removeAllElements(); 1482 1483 // tokenize 1484 StringTokenizer tokens = new StringTokenizer(value, " \n\t\r"); 1485 String token; 1486 String tempNamespace; 1487 try { 1488 while (tokens.hasMoreTokens()) { 1489 token = tokens.nextToken(); 1490 if (token.equals(SchemaSymbols.ATTVAL_TWOPOUNDLOCAL)) { 1491 tempNamespace = null; 1492 } else if (token.equals(SchemaSymbols.ATTVAL_TWOPOUNDTARGETNS)) { 1493 tempNamespace = schemaDoc.fTargetNamespace; 1494 } else { 1495 // we have found namespace URI here 1496 // need to add it to the symbol table 1497 fExtraDVs[DT_ANYURI].validate(token, schemaDoc.fValidationContext, null); 1498 tempNamespace = fSymbolTable.addSymbol(token); 1499 } 1500 1501 //check for duplicate namespaces in the list 1502 if (!fNamespaceList.contains(tempNamespace)) { 1503 fNamespaceList.addElement(tempNamespace); 1504 } 1505 } 1506 } catch (InvalidDatatypeValueException ide) { 1507 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )"}); 1508 } 1509 1510 // convert the vector to an array 1511 int num = fNamespaceList.size(); 1512 String[] list = new String[num]; 1513 fNamespaceList.copyInto(list); 1514 attrValues[ATTIDX_NAMESPACE_LIST] = list; 1515 } 1516 break; 1517 case DT_PROCESSCONTENTS: 1518 // processContents = (lax | skip | strict) 1519 if (value.equals (SchemaSymbols.ATTVAL_STRICT)) 1520 retValue = INT_ANY_STRICT; 1521 else if (value.equals (SchemaSymbols.ATTVAL_LAX)) 1522 retValue = INT_ANY_LAX; 1523 else if (value.equals (SchemaSymbols.ATTVAL_SKIP)) 1524 retValue = INT_ANY_SKIP; 1525 else 1526 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1527 new Object[]{value, "(lax | skip | strict)"}); 1528 break; 1529 case DT_USE: 1530 // use = (optional | prohibited | required) 1531 if (value.equals (SchemaSymbols.ATTVAL_OPTIONAL)) 1532 retValue = INT_USE_OPTIONAL; 1533 else if (value.equals (SchemaSymbols.ATTVAL_REQUIRED)) 1534 retValue = INT_USE_REQUIRED; 1535 else if (value.equals (SchemaSymbols.ATTVAL_PROHIBITED)) 1536 retValue = INT_USE_PROHIBITED; 1537 else 1538 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1539 new Object[]{value, "(optional | prohibited | required)"}); 1540 break; 1541 case DT_WHITESPACE: 1542 // value = preserve | replace | collapse 1543 if (value.equals (SchemaSymbols.ATTVAL_PRESERVE)) 1544 retValue = INT_WS_PRESERVE; 1545 else if (value.equals (SchemaSymbols.ATTVAL_REPLACE)) 1546 retValue = INT_WS_REPLACE; 1547 else if (value.equals (SchemaSymbols.ATTVAL_COLLAPSE)) 1548 retValue = INT_WS_COLLAPSE; 1549 else 1550 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1551 new Object[]{value, "(preserve | replace | collapse)"}); 1552 break; 1553 } 1554 1555 return retValue; 1556 } 1557 1558 void reportSchemaFatalError (String key, Object[] args, Element ele) { 1559 fSchemaHandler.reportSchemaFatalError(key, args, ele); 1560 } 1561 1562 void reportSchemaError (String key, Object[] args, Element ele) { 1563 fSchemaHandler.reportSchemaError(key, args, ele); 1564 } 1565 1566 // validate attriubtes from non-schema namespaces 1567 // REVISIT: why we store the attributes in this way? why not just a list 1568 // of structure {element node, attr name/qname, attr value)? 1569 // REVISIT: pass the proper element node to reportSchemaError 1570 public void checkNonSchemaAttributes(XSGrammarBucket grammarBucket) { 1571 // for all attributes 1572 Iterator entries = fNonSchemaAttrs.entrySet().iterator(); 1573 XSAttributeDecl attrDecl; 1574 while (entries.hasNext()) { 1575 Map.Entry entry = (Map.Entry) entries.next(); 1576 // get name, uri, localpart 1577 String attrRName = (String) entry.getKey(); 1578 String attrURI = attrRName.substring(0,attrRName.indexOf(',')); 1579 String attrLocal = attrRName.substring(attrRName.indexOf(',')+1); 1580 // find associated grammar 1581 SchemaGrammar sGrammar = grammarBucket.getGrammar(attrURI); 1582 if (sGrammar == null) { 1583 continue; 1584 } 1585 // and get the datatype validator, if there is one 1586 attrDecl = sGrammar.getGlobalAttributeDecl(attrLocal); 1587 if (attrDecl == null) { 1588 continue; 1589 } 1590 XSSimpleType dv = (XSSimpleType)attrDecl.getTypeDefinition(); 1591 if (dv == null) { 1592 continue; 1593 } 1594 1595 // get all values appeared with this attribute name 1596 Vector values = (Vector) entry.getValue(); 1597 String elName; 1598 String attrName = (String)values.elementAt(0); 1599 // for each of the values 1600 int count = values.size(); 1601 for (int i = 1; i < count; i += 2) { 1602 elName = (String)values.elementAt(i); 1603 try { 1604 // and validate it using the XSSimpleType 1605 // REVISIT: what would be the proper validation context? 1606 // guess we need to save that in the vectors too. 1607 dv.validate((String)values.elementAt(i+1), null, null); 1608 } catch(InvalidDatatypeValueException ide) { 1609 reportSchemaError ("s4s-att-invalid-value", 1610 new Object[] {elName, attrName, ide.getMessage()}, 1611 null); 1612 } 1613 } 1614 } 1615 } 1616 1617 // normalize the string according to the whiteSpace facet 1618 public static String normalize(String content, short ws) { 1619 int len = content == null ? 0 : content.length(); 1620 if (len == 0 || ws == XSSimpleType.WS_PRESERVE) 1621 return content; 1622 1623 StringBuffer sb = new StringBuffer(); 1624 if (ws == XSSimpleType.WS_REPLACE) { 1625 char ch; 1626 // when it's replace, just replace #x9, #xa, #xd by #x20 1627 for (int i = 0; i < len; i++) { 1628 ch = content.charAt(i); 1629 if (ch != 0x9 && ch != 0xa && ch != 0xd) 1630 sb.append(ch); 1631 else 1632 sb.append((char)0x20); 1633 } 1634 } else { 1635 char ch; 1636 int i; 1637 boolean isLeading = true; 1638 // when it's collapse 1639 for (i = 0; i < len; i++) { 1640 ch = content.charAt(i); 1641 // append real characters, so we passed leading ws 1642 if (ch != 0x9 && ch != 0xa && ch != 0xd && ch != 0x20) { 1643 sb.append(ch); 1644 isLeading = false; 1645 } 1646 else { 1647 // for whitespaces, we skip all following ws 1648 for (; i < len-1; i++) { 1649 ch = content.charAt(i+1); 1650 if (ch != 0x9 && ch != 0xa && ch != 0xd && ch != 0x20) 1651 break; 1652 } 1653 // if it's not a leading or tailing ws, then append a space 1654 if (i < len - 1 && !isLeading) 1655 sb.append((char)0x20); 1656 } 1657 } 1658 } 1659 1660 return sb.toString(); 1661 } 1662 1663 // the following part implements an attribute-value-array pool. 1664 // when checkAttribute is called, it calls getAvailableArray to get 1665 // an array from the pool; when the caller is done with the array, 1666 // it calls returnAttrArray to return that array to the pool. 1667 1668 // initial size of the array pool. 10 is big enough 1669 static final int INIT_POOL_SIZE = 10; 1670 // the incremental size of the array pool 1671 static final int INC_POOL_SIZE = 10; 1672 // the array pool 1673 Object[][] fArrayPool = new Object[INIT_POOL_SIZE][ATTIDX_COUNT]; 1674 // used to clear the returned array 1675 // I think System.arrayCopy is more efficient than setting 35 fields to null 1676 private static Object[] fTempArray = new Object[ATTIDX_COUNT]; 1677 // current position of the array pool (# of arrays not returned) 1678 int fPoolPos = 0; 1679 1680 // get the next available array 1681 protected Object[] getAvailableArray() { 1682 // if no array left in the pool, increase the pool size 1683 if (fArrayPool.length == fPoolPos) { 1684 // increase size 1685 fArrayPool = new Object[fPoolPos+INC_POOL_SIZE][]; 1686 // initialize each *new* array 1687 for (int i = fPoolPos; i < fArrayPool.length; i++) 1688 fArrayPool[i] = new Object[ATTIDX_COUNT]; 1689 } 1690 // get the next available one 1691 Object[] retArray = fArrayPool[fPoolPos]; 1692 // clear it from the pool. this is for GC: if a caller forget to 1693 // return the array, we want that array to be GCed. 1694 fArrayPool[fPoolPos++] = null; 1695 // to make sure that one array is not returned twice, we use 1696 // the last entry to indicate whether an array is already returned 1697 // now set it to false. 1698 System.arraycopy(fTempArray, 0, retArray, 0, ATTIDX_COUNT-1); 1699 retArray[ATTIDX_ISRETURNED] = Boolean.FALSE; 1700 1701 return retArray; 1702 } 1703 1704 // return an array back to the pool 1705 public void returnAttrArray(Object[] attrArray, XSDocumentInfo schemaDoc) { 1706 // pop the namespace context 1707 if (schemaDoc != null) 1708 schemaDoc.fNamespaceSupport.popContext(); 1709 1710 // if 1. the pool is full; 2. the array is null; 1711 // 3. the array is of wrong size; 4. the array is already returned 1712 // then we can't accept this array to be returned 1713 if (fPoolPos == 0 || 1714 attrArray == null || 1715 attrArray.length != ATTIDX_COUNT || 1716 ((Boolean)attrArray[ATTIDX_ISRETURNED]).booleanValue()) { 1717 return; 1718 } 1719 1720 // mark this array as returned 1721 attrArray[ATTIDX_ISRETURNED] = Boolean.TRUE; 1722 // better clear nonschema vector 1723 if(attrArray[ATTIDX_NONSCHEMA] != null) 1724 ((Vector)attrArray[ATTIDX_NONSCHEMA]).clear(); 1725 // and put it into the pool 1726 fArrayPool[--fPoolPos] = attrArray; 1727 } 1728 1729 public void resolveNamespace(Element element, Attr[] attrs, 1730 SchemaNamespaceSupport nsSupport) { 1731 // push the namespace context 1732 nsSupport.pushContext(); 1733 1734 // search for new namespace bindings 1735 int length = attrs.length; 1736 Attr sattr = null; 1737 String rawname, prefix, uri; 1738 for (int i = 0; i < length; i++) { 1739 sattr = attrs[i]; 1740 rawname = DOMUtil.getName(sattr); 1741 prefix = null; 1742 if (rawname.equals(XMLSymbols.PREFIX_XMLNS)) 1743 prefix = XMLSymbols.EMPTY_STRING; 1744 else if (rawname.startsWith("xmlns:")) 1745 prefix = fSymbolTable.addSymbol(DOMUtil.getLocalName(sattr)); 1746 if (prefix != null) { 1747 uri = fSymbolTable.addSymbol(DOMUtil.getValue(sattr)); 1748 nsSupport.declarePrefix(prefix, uri.length()!=0 ? uri : null); 1749 } 1750 } 1751 } 1752 } 1753 1754 class OneAttr { 1755 // name of the attribute 1756 public String name; 1757 // index of the datatype validator 1758 public int dvIndex; 1759 // whether it's optional, and has default value 1760 public int valueIndex; 1761 // the default value of this attribute 1762 public Object dfltValue; 1763 1764 public OneAttr(String name, int dvIndex, int valueIndex, Object dfltValue) { 1765 this.name = name; 1766 this.dvIndex = dvIndex; 1767 this.valueIndex = valueIndex; 1768 this.dfltValue = dfltValue; 1769 } 1770 } 1771 1772 abstract class Container { 1773 static final int THRESHOLD = 5; 1774 static Container getContainer(int size) { 1775 if (size > THRESHOLD) 1776 return new LargeContainer(size); 1777 else 1778 return new SmallContainer(size); 1779 } 1780 abstract void put(String key, OneAttr value); 1781 abstract OneAttr get(String key); 1782 1783 OneAttr[] values; 1784 int pos = 0; 1785 } 1786 1787 class SmallContainer extends Container { 1788 String[] keys; 1789 SmallContainer(int size) { 1790 keys = new String[size]; 1791 values = new OneAttr[size]; 1792 } 1793 void put(String key, OneAttr value) { 1794 keys[pos] = key; 1795 values[pos++] = value; 1796 } 1797 OneAttr get(String key) { 1798 for (int i = 0; i < pos; i++) { 1799 if (keys[i].equals(key)) { 1800 return values[i]; 1801 } 1802 } 1803 return null; 1804 } 1805 } 1806 1807 class LargeContainer extends Container { 1808 Map items; 1809 LargeContainer(int size) { 1810 items = new HashMap(size*2+1); 1811 values = new OneAttr[size]; 1812 } 1813 void put(String key, OneAttr value) { 1814 items.put(key, value); 1815 values[pos++] = value; 1816 } 1817 OneAttr get(String key) { 1818 OneAttr ret = (OneAttr)items.get(key); 1819 return ret; 1820 } 1821 }