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