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 * @version $Id: XSAttributeChecker.java,v 1.12 2010-11-01 04:40:02 joehw Exp $ 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 fEleAttrsMapG = new HashMap(29); 149 // for 39 local elememnts 150 private static final Map 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 fNonSchemaAttrs = new HashMap(); 930 931 // temprory vector, used to hold the namespace list 932 protected Vector fNamespaceList = new Vector(); 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 public Object[] checkAttributes(Element element, boolean isGlobal, 978 XSDocumentInfo schemaDoc, boolean enumAsQName) { 979 if (element == null) 980 return null; 981 982 // get all attributes 983 Attr[] attrs = DOMUtil.getAttrs(element); 984 985 // update NamespaceSupport 986 resolveNamespace(element, attrs, schemaDoc.fNamespaceSupport); 987 988 String uri = DOMUtil.getNamespaceURI(element); 989 String elName = DOMUtil.getLocalName(element); 990 991 if (!SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(uri)) { 992 reportSchemaError("s4s-elt-schema-ns", new Object[] {elName}, element); 993 } 994 995 Map eleAttrsMap = fEleAttrsMapG; 996 String lookupName = elName; 997 998 // REVISIT: only local element and attribute are different from others. 999 // it's possible to have either name or ref. all the others 1000 // are only allowed to have one of name or ref, or neither of them. 1001 // we'd better move such checking to the traverser. 1002 if (!isGlobal) { 1003 eleAttrsMap = fEleAttrsMapL; 1004 if (elName.equals(SchemaSymbols.ELT_ELEMENT)) { 1005 if (DOMUtil.getAttr(element, SchemaSymbols.ATT_REF) != null) 1006 lookupName = ELEMENT_R; 1007 else 1008 lookupName = ELEMENT_N; 1009 } else if (elName.equals(SchemaSymbols.ELT_ATTRIBUTE)) { 1010 if (DOMUtil.getAttr(element, SchemaSymbols.ATT_REF) != null) 1011 lookupName = ATTRIBUTE_R; 1012 else 1013 lookupName = ATTRIBUTE_N; 1014 } 1015 } 1016 1017 // get desired attribute list of this element 1018 Container attrList = (Container)eleAttrsMap.get(lookupName); 1019 if (attrList == null) { 1020 // should never gets here. 1021 // when this method is called, the call already knows that 1022 // the element can appear. 1023 reportSchemaError ("s4s-elt-invalid", new Object[] {elName}, element); 1024 return null; 1025 } 1026 1027 Object[] attrValues = getAvailableArray(); 1028 long fromDefault = 0; 1029 1030 // clear the "seen" flag. 1031 System.arraycopy(fSeenTemp, 0, fSeen, 0, ATTIDX_COUNT); 1032 1033 // traverse all attributes 1034 int length = attrs.length; 1035 Attr sattr = null; 1036 for (int i = 0; i < length; i++) { 1037 sattr = attrs[i]; 1038 // get the attribute name/value 1039 //String attrName = DOMUtil.getLocalName(sattr); 1040 String attrName = sattr.getName(); 1041 String attrURI = DOMUtil.getNamespaceURI(sattr); 1042 String attrVal = DOMUtil.getValue(sattr); 1043 1044 if (attrName.startsWith("xml")) { 1045 String attrPrefix = DOMUtil.getPrefix(sattr); 1046 // we don't want to add namespace declarations to the non-schema attributes 1047 if ("xmlns".equals(attrPrefix) || "xmlns".equals(attrName)) { 1048 continue; 1049 } 1050 // Both <schema> and <documentation> may have an xml:lang attribute. 1051 // Set the URI for this attribute to null so that we process it 1052 // like any other schema attribute. 1053 else if (SchemaSymbols.ATT_XML_LANG.equals(attrName) && 1054 (SchemaSymbols.ELT_SCHEMA.equals(elName) || 1055 SchemaSymbols.ELT_DOCUMENTATION.equals(elName))) { 1056 attrURI = null; 1057 } 1058 } 1059 1060 // for attributes with namespace prefix 1061 // 1062 if (attrURI != null && attrURI.length() != 0) { 1063 // attributes with schema namespace are not allowed 1064 // and not allowed on "document" and "appInfo" 1065 if (attrURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) { 1066 reportSchemaError ("s4s-att-not-allowed", new Object[] {elName, attrName}, element); 1067 } 1068 else { 1069 if(attrValues[ATTIDX_NONSCHEMA] == null) { 1070 // these are usually small 1071 attrValues[ATTIDX_NONSCHEMA] = new Vector(4,2); 1072 } 1073 ((Vector)attrValues[ATTIDX_NONSCHEMA]).addElement(attrName); 1074 ((Vector)attrValues[ATTIDX_NONSCHEMA]).addElement(attrVal); 1075 // for attributes from other namespace 1076 // store them in a list, and TRY to validate them after 1077 // schema traversal (because it's "lax") 1078 //otherValues.put(attrName, attrVal); 1079 // REVISIT: actually use this some day... 1080 // String attrRName = attrURI + "," + attrName; 1081 // Vector values = (Vector)fNonSchemaAttrs.get(attrRName); 1082 // if (values == null) { 1083 // values = new Vector(); 1084 // values.addElement(attrName); 1085 // values.addElement(elName); 1086 // values.addElement(attrVal); 1087 // fNonSchemaAttrs.put(attrRName, values); 1088 // } 1089 // else { 1090 // values.addElement(elName); 1091 // values.addElement(attrVal); 1092 // } 1093 } 1094 continue; 1095 } 1096 1097 // check whether this attribute is allowed 1098 OneAttr oneAttr = attrList.get(attrName); 1099 if (oneAttr == null) { 1100 reportSchemaError ("s4s-att-not-allowed", 1101 new Object[] {elName, attrName}, 1102 element); 1103 continue; 1104 } 1105 1106 // we've seen this attribute 1107 fSeen[oneAttr.valueIndex] = true; 1108 1109 // check the value against the datatype 1110 try { 1111 // no checking on string needs to be done here. 1112 // no checking on xpath needs to be done here. 1113 // xpath values are validated in xpath parser 1114 if (oneAttr.dvIndex >= 0) { 1115 if (oneAttr.dvIndex != DT_STRING && 1116 oneAttr.dvIndex != DT_XPATH && 1117 oneAttr.dvIndex != DT_XPATH1) { 1118 XSSimpleType dv = fExtraDVs[oneAttr.dvIndex]; 1119 Object avalue = dv.validate(attrVal, schemaDoc.fValidationContext, null); 1120 // kludge to handle chameleon includes/redefines... 1121 if (oneAttr.dvIndex == DT_QNAME) { 1122 QName qname = (QName)avalue; 1123 if(qname.prefix == XMLSymbols.EMPTY_STRING && qname.uri == null && schemaDoc.fIsChameleonSchema) 1124 qname.uri = schemaDoc.fTargetNamespace; 1125 } 1126 attrValues[oneAttr.valueIndex] = avalue; 1127 } else { 1128 attrValues[oneAttr.valueIndex] = attrVal; 1129 } 1130 } 1131 else { 1132 attrValues[oneAttr.valueIndex] = validate(attrValues, attrName, attrVal, oneAttr.dvIndex, schemaDoc); 1133 } 1134 } catch (InvalidDatatypeValueException ide) { 1135 reportSchemaError ("s4s-att-invalid-value", 1136 new Object[] {elName, attrName, ide.getMessage()}, 1137 element); 1138 if (oneAttr.dfltValue != null) 1139 //attrValues.put(attrName, oneAttr.dfltValue); 1140 attrValues[oneAttr.valueIndex] = oneAttr.dfltValue; 1141 } 1142 1143 // For "enumeration", and type is possible to be a QName, we need 1144 // to return namespace context for later QName resolution. 1145 if (elName.equals(SchemaSymbols.ELT_ENUMERATION) && enumAsQName) { 1146 attrValues[ATTIDX_ENUMNSDECLS] = new SchemaNamespaceSupport(schemaDoc.fNamespaceSupport); 1147 } 1148 } 1149 1150 // apply default values 1151 OneAttr[] reqAttrs = attrList.values; 1152 for (int i = 0; i < reqAttrs.length; i++) { 1153 OneAttr oneAttr = reqAttrs[i]; 1154 1155 // if the attribute didn't apprear, and 1156 // if the attribute is optional with default value, apply it 1157 if (oneAttr.dfltValue != null && !fSeen[oneAttr.valueIndex]) { 1158 //attrValues.put(oneAttr.name, oneAttr.dfltValue); 1159 attrValues[oneAttr.valueIndex] = oneAttr.dfltValue; 1160 fromDefault |= (1<<oneAttr.valueIndex); 1161 } 1162 } 1163 1164 attrValues[ATTIDX_FROMDEFAULT] = new Long(fromDefault); 1165 //attrValues[ATTIDX_OTHERVALUES] = otherValues; 1166 1167 // Check that minOccurs isn't greater than maxOccurs. 1168 // p-props-correct 2.1 1169 if (attrValues[ATTIDX_MAXOCCURS] != null) { 1170 int min = ((XInt)attrValues[ATTIDX_MINOCCURS]).intValue(); 1171 int max = ((XInt)attrValues[ATTIDX_MAXOCCURS]).intValue(); 1172 if (max != SchemaSymbols.OCCURRENCE_UNBOUNDED) { 1173 1174 // maxOccurLimit is only check in secure mode 1175 if (fSchemaHandler.fSecurityManager != null) { 1176 String localName = element.getLocalName(); 1177 1178 // The maxOccurs restriction no longer applies to elements 1179 // and wildcards in a sequence in which they are the only 1180 // particle. These are now validated using a constant 1181 // space algorithm. The restriction still applies to all 1182 // other cases. 1183 1184 // Determine if constant-space algorithm can be applied 1185 final boolean optimize = 1186 (localName.equals("element") || localName.equals("any")) && 1187 (element.getNextSibling() == null) && 1188 (element.getPreviousSibling() == null) && 1189 (element.getParentNode().getLocalName().equals("sequence")); 1190 1191 if (!optimize) { 1192 //Revisit :: IMO this is not right place to check 1193 // maxOccurNodeLimit. 1194 int maxOccurNodeLimit = fSchemaHandler.fSecurityManager.getLimit(XMLSecurityManager.Limit.MAX_OCCUR_NODE_LIMIT); 1195 if (max > maxOccurNodeLimit && !fSchemaHandler.fSecurityManager.isNoLimit(maxOccurNodeLimit)) { 1196 reportSchemaFatalError("MaxOccurLimit", new Object[] {new Integer(maxOccurNodeLimit)}, element); 1197 1198 // reset max values in case processing continues on error 1199 attrValues[ATTIDX_MAXOCCURS] = fXIntPool.getXInt(maxOccurNodeLimit); 1200 //new Integer(maxOccurNodeLimit); 1201 max = maxOccurNodeLimit; 1202 } 1203 } 1204 } 1205 1206 if (min > max) { 1207 reportSchemaError ("p-props-correct.2.1", 1208 new Object[] {elName, attrValues[ATTIDX_MINOCCURS], attrValues[ATTIDX_MAXOCCURS]}, 1209 element); 1210 attrValues[ATTIDX_MINOCCURS] = attrValues[ATTIDX_MAXOCCURS]; 1211 } 1212 } 1213 } 1214 1215 return attrValues; 1216 } 1217 1218 private Object validate(Object[] attrValues, String attr, String ivalue, int dvIndex, 1219 XSDocumentInfo schemaDoc) throws InvalidDatatypeValueException { 1220 if (ivalue == null) 1221 return null; 1222 1223 // To validate these types, we don't actually need to normalize the 1224 // strings. We only need to remove the whitespace from both ends. 1225 // In some special cases (list types), StringTokenizer can correctly 1226 // process the un-normalized whitespace. 1227 1228 String value = XMLChar.trim(ivalue); 1229 Object retValue = null; 1230 Vector memberType; 1231 int choice; 1232 1233 switch (dvIndex) { 1234 case DT_BOOLEAN: 1235 if (value.equals(SchemaSymbols.ATTVAL_FALSE) || 1236 value.equals(SchemaSymbols.ATTVAL_FALSE_0)) { 1237 retValue = Boolean.FALSE; 1238 } else if (value.equals(SchemaSymbols.ATTVAL_TRUE) || 1239 value.equals(SchemaSymbols.ATTVAL_TRUE_1)) { 1240 retValue = Boolean.TRUE; 1241 } else { 1242 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{value, "boolean"}); 1243 } 1244 break; 1245 case DT_NONNEGINT: 1246 try { 1247 if (value.length() > 0 && value.charAt(0) == '+') 1248 value = value.substring(1); 1249 retValue = fXIntPool.getXInt(Integer.parseInt(value)); 1250 } catch (NumberFormatException e) { 1251 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{value, "nonNegativeInteger"}); 1252 } 1253 if (((XInt)retValue).intValue() < 0) 1254 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{value, "nonNegativeInteger"}); 1255 break; 1256 case DT_POSINT: 1257 try { 1258 if (value.length() > 0 && value.charAt(0) == '+') 1259 value = value.substring(1); 1260 retValue = fXIntPool.getXInt(Integer.parseInt(value)); 1261 } catch (NumberFormatException e) { 1262 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{value, "positiveInteger"}); 1263 } 1264 if (((XInt)retValue).intValue() <= 0) 1265 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{value, "positiveInteger"}); 1266 break; 1267 case DT_BLOCK: 1268 // block = (#all | List of (extension | restriction | substitution)) 1269 choice = 0; 1270 if (value.equals (SchemaSymbols.ATTVAL_POUNDALL)) { 1271 choice = XSConstants.DERIVATION_SUBSTITUTION|XSConstants.DERIVATION_EXTENSION| 1272 XSConstants.DERIVATION_RESTRICTION; 1273 } 1274 else { 1275 StringTokenizer t = new StringTokenizer(value, " \n\t\r"); 1276 while (t.hasMoreTokens()) { 1277 String token = t.nextToken (); 1278 1279 if (token.equals (SchemaSymbols.ATTVAL_EXTENSION)) { 1280 choice |= XSConstants.DERIVATION_EXTENSION; 1281 } 1282 else if (token.equals (SchemaSymbols.ATTVAL_RESTRICTION)) { 1283 choice |= XSConstants.DERIVATION_RESTRICTION; 1284 } 1285 else if (token.equals (SchemaSymbols.ATTVAL_SUBSTITUTION)) { 1286 choice |= XSConstants.DERIVATION_SUBSTITUTION; 1287 } 1288 else { 1289 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "(#all | List of (extension | restriction | substitution))"}); 1290 } 1291 } 1292 } 1293 retValue = fXIntPool.getXInt(choice); 1294 break; 1295 case DT_BLOCK1: 1296 case DT_FINAL: 1297 // block = (#all | List of (extension | restriction)) 1298 // final = (#all | List of (extension | restriction)) 1299 choice = 0; 1300 if (value.equals (SchemaSymbols.ATTVAL_POUNDALL)) { 1301 //choice = SchemaSymbols.EXTENSION|SchemaSymbols.RESTRICTION; 1302 // REVISIT: if #all, then make the result the combination of 1303 // everything: substitution/externsion/restriction/list/union. 1304 // would this be a problem? 1305 // the reason doing so is that when final/blockFinal on <schema> 1306 // is #all, it's not always the same as the conbination of those 1307 // values allowed by final/blockFinal. 1308 // for example, finalDefault="#all" is not always the same as 1309 // finalDefault="extension restriction". 1310 // if finalDefault="#all", final on any simple type would be 1311 // "extension restriction list union". 1312 choice = XSConstants.DERIVATION_SUBSTITUTION|XSConstants.DERIVATION_EXTENSION| 1313 XSConstants.DERIVATION_RESTRICTION|XSConstants.DERIVATION_LIST| 1314 XSConstants.DERIVATION_UNION; 1315 } 1316 else { 1317 StringTokenizer t = new StringTokenizer(value, " \n\t\r"); 1318 while (t.hasMoreTokens()) { 1319 String token = t.nextToken (); 1320 1321 if (token.equals (SchemaSymbols.ATTVAL_EXTENSION)) { 1322 choice |= XSConstants.DERIVATION_EXTENSION; 1323 } 1324 else if (token.equals (SchemaSymbols.ATTVAL_RESTRICTION)) { 1325 choice |= XSConstants.DERIVATION_RESTRICTION; 1326 } 1327 else { 1328 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "(#all | List of (extension | restriction))"}); 1329 } 1330 } 1331 } 1332 retValue = fXIntPool.getXInt(choice); 1333 break; 1334 case DT_FINAL1: 1335 // final = (#all | List of (list | union | restriction)) 1336 choice = 0; 1337 if (value.equals (SchemaSymbols.ATTVAL_POUNDALL)) { 1338 //choice = SchemaSymbols.RESTRICTION|SchemaSymbols.LIST| 1339 // SchemaSymbols.UNION; 1340 // REVISIT: if #all, then make the result the combination of 1341 // everything: substitution/externsion/restriction/list/union. 1342 // would this be a problem? 1343 // same reason as above DT_BLOCK1/DT_FINAL 1344 choice = XSConstants.DERIVATION_SUBSTITUTION|XSConstants.DERIVATION_EXTENSION| 1345 XSConstants.DERIVATION_RESTRICTION|XSConstants.DERIVATION_LIST| 1346 XSConstants.DERIVATION_UNION; 1347 } 1348 else { 1349 StringTokenizer t = new StringTokenizer(value, " \n\t\r"); 1350 while (t.hasMoreTokens()) { 1351 String token = t.nextToken (); 1352 1353 if (token.equals (SchemaSymbols.ATTVAL_LIST)) { 1354 choice |= XSConstants.DERIVATION_LIST; 1355 } 1356 else if (token.equals (SchemaSymbols.ATTVAL_UNION)) { 1357 choice |= XSConstants.DERIVATION_UNION; 1358 } 1359 else if (token.equals (SchemaSymbols.ATTVAL_RESTRICTION)) { 1360 choice |= XSConstants.DERIVATION_RESTRICTION; 1361 } 1362 else { 1363 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "(#all | List of (list | union | restriction))"}); 1364 } 1365 } 1366 } 1367 retValue = fXIntPool.getXInt(choice); 1368 break; 1369 case DT_FINAL2: 1370 // finalDefault = (#all | List of (extension | restriction | list | union)) 1371 choice = 0; 1372 if (value.equals (SchemaSymbols.ATTVAL_POUNDALL)) { 1373 //choice = SchemaSymbols.RESTRICTION|SchemaSymbols.LIST| 1374 // SchemaSymbols.UNION; 1375 // REVISIT: if #all, then make the result the combination of 1376 // everything: substitution/externsion/restriction/list/union. 1377 // would this be a problem? 1378 // same reason as above DT_BLOCK1/DT_FINAL 1379 choice = XSConstants.DERIVATION_SUBSTITUTION|XSConstants.DERIVATION_EXTENSION| 1380 XSConstants.DERIVATION_RESTRICTION|XSConstants.DERIVATION_LIST| 1381 XSConstants.DERIVATION_UNION; 1382 } 1383 else { 1384 StringTokenizer t = new StringTokenizer(value, " \n\t\r"); 1385 while (t.hasMoreTokens()) { 1386 String token = t.nextToken (); 1387 1388 if (token.equals (SchemaSymbols.ATTVAL_EXTENSION)) { 1389 choice |= XSConstants.DERIVATION_EXTENSION; 1390 } 1391 else if (token.equals (SchemaSymbols.ATTVAL_RESTRICTION)) { 1392 choice |= XSConstants.DERIVATION_RESTRICTION; 1393 } 1394 else if (token.equals (SchemaSymbols.ATTVAL_LIST)) { 1395 choice |= XSConstants.DERIVATION_LIST; 1396 } 1397 else if (token.equals (SchemaSymbols.ATTVAL_UNION)) { 1398 choice |= XSConstants.DERIVATION_UNION; 1399 } 1400 else { 1401 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "(#all | List of (extension | restriction | list | union))"}); 1402 } 1403 } 1404 } 1405 retValue = fXIntPool.getXInt(choice); 1406 break; 1407 case DT_FORM: 1408 // form = (qualified | unqualified) 1409 if (value.equals (SchemaSymbols.ATTVAL_QUALIFIED)) 1410 retValue = INT_QUALIFIED; 1411 else if (value.equals (SchemaSymbols.ATTVAL_UNQUALIFIED)) 1412 retValue = INT_UNQUALIFIED; 1413 else 1414 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1415 new Object[]{value, "(qualified | unqualified)"}); 1416 break; 1417 case DT_MAXOCCURS: 1418 // maxOccurs = (nonNegativeInteger | unbounded) 1419 if (value.equals(SchemaSymbols.ATTVAL_UNBOUNDED)) { 1420 retValue = INT_UNBOUNDED; 1421 } else { 1422 try { 1423 retValue = validate(attrValues, attr, value, DT_NONNEGINT, schemaDoc); 1424 } catch (NumberFormatException e) { 1425 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "(nonNegativeInteger | unbounded)"}); 1426 } 1427 } 1428 break; 1429 case DT_MAXOCCURS1: 1430 // maxOccurs = 1 1431 if (value.equals("1")) 1432 retValue = fXIntPool.getXInt(1); 1433 else 1434 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1435 new Object[]{value, "(1)"}); 1436 break; 1437 case DT_MEMBERTYPES: 1438 // memberTypes = List of QName 1439 memberType = new Vector(); 1440 try { 1441 StringTokenizer t = new StringTokenizer(value, " \n\t\r"); 1442 while (t.hasMoreTokens()) { 1443 String token = t.nextToken (); 1444 QName qname = (QName)fExtraDVs[DT_QNAME].validate(token, schemaDoc.fValidationContext, null); 1445 // kludge to handle chameleon includes/redefines... 1446 if(qname.prefix == XMLSymbols.EMPTY_STRING && qname.uri == null && schemaDoc.fIsChameleonSchema) 1447 qname.uri = schemaDoc.fTargetNamespace; 1448 memberType.addElement(qname); 1449 } 1450 retValue = memberType; 1451 } 1452 catch (InvalidDatatypeValueException ide) { 1453 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.2", new Object[]{value, "(List of QName)"}); 1454 } 1455 break; 1456 case DT_MINOCCURS1: 1457 // minOccurs = (0 | 1) 1458 if (value.equals("0")) 1459 retValue = fXIntPool.getXInt(0); 1460 else if (value.equals("1")) 1461 retValue = fXIntPool.getXInt(1); 1462 else 1463 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1464 new Object[]{value, "(0 | 1)"}); 1465 break; 1466 case DT_NAMESPACE: 1467 // namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) ) 1468 if (value.equals(SchemaSymbols.ATTVAL_TWOPOUNDANY)) { 1469 // ##any 1470 retValue = INT_ANY_ANY; 1471 } else if (value.equals(SchemaSymbols.ATTVAL_TWOPOUNDOTHER)) { 1472 // ##other 1473 retValue = INT_ANY_NOT; 1474 String[] list = new String[2]; 1475 list[0] = schemaDoc.fTargetNamespace; 1476 list[1] = null; 1477 attrValues[ATTIDX_NAMESPACE_LIST] = list; 1478 } else { 1479 // list 1480 retValue = INT_ANY_LIST; 1481 1482 fNamespaceList.removeAllElements(); 1483 1484 // tokenize 1485 StringTokenizer tokens = new StringTokenizer(value, " \n\t\r"); 1486 String token; 1487 String tempNamespace; 1488 try { 1489 while (tokens.hasMoreTokens()) { 1490 token = tokens.nextToken(); 1491 if (token.equals(SchemaSymbols.ATTVAL_TWOPOUNDLOCAL)) { 1492 tempNamespace = null; 1493 } else if (token.equals(SchemaSymbols.ATTVAL_TWOPOUNDTARGETNS)) { 1494 tempNamespace = schemaDoc.fTargetNamespace; 1495 } else { 1496 // we have found namespace URI here 1497 // need to add it to the symbol table 1498 fExtraDVs[DT_ANYURI].validate(token, schemaDoc.fValidationContext, null); 1499 tempNamespace = fSymbolTable.addSymbol(token); 1500 } 1501 1502 //check for duplicate namespaces in the list 1503 if (!fNamespaceList.contains(tempNamespace)) { 1504 fNamespaceList.addElement(tempNamespace); 1505 } 1506 } 1507 } catch (InvalidDatatypeValueException ide) { 1508 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3", new Object[]{value, "((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )"}); 1509 } 1510 1511 // convert the vector to an array 1512 int num = fNamespaceList.size(); 1513 String[] list = new String[num]; 1514 fNamespaceList.copyInto(list); 1515 attrValues[ATTIDX_NAMESPACE_LIST] = list; 1516 } 1517 break; 1518 case DT_PROCESSCONTENTS: 1519 // processContents = (lax | skip | strict) 1520 if (value.equals (SchemaSymbols.ATTVAL_STRICT)) 1521 retValue = INT_ANY_STRICT; 1522 else if (value.equals (SchemaSymbols.ATTVAL_LAX)) 1523 retValue = INT_ANY_LAX; 1524 else if (value.equals (SchemaSymbols.ATTVAL_SKIP)) 1525 retValue = INT_ANY_SKIP; 1526 else 1527 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1528 new Object[]{value, "(lax | skip | strict)"}); 1529 break; 1530 case DT_USE: 1531 // use = (optional | prohibited | required) 1532 if (value.equals (SchemaSymbols.ATTVAL_OPTIONAL)) 1533 retValue = INT_USE_OPTIONAL; 1534 else if (value.equals (SchemaSymbols.ATTVAL_REQUIRED)) 1535 retValue = INT_USE_REQUIRED; 1536 else if (value.equals (SchemaSymbols.ATTVAL_PROHIBITED)) 1537 retValue = INT_USE_PROHIBITED; 1538 else 1539 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1540 new Object[]{value, "(optional | prohibited | required)"}); 1541 break; 1542 case DT_WHITESPACE: 1543 // value = preserve | replace | collapse 1544 if (value.equals (SchemaSymbols.ATTVAL_PRESERVE)) 1545 retValue = INT_WS_PRESERVE; 1546 else if (value.equals (SchemaSymbols.ATTVAL_REPLACE)) 1547 retValue = INT_WS_REPLACE; 1548 else if (value.equals (SchemaSymbols.ATTVAL_COLLAPSE)) 1549 retValue = INT_WS_COLLAPSE; 1550 else 1551 throw new InvalidDatatypeValueException("cvc-enumeration-valid", 1552 new Object[]{value, "(preserve | replace | collapse)"}); 1553 break; 1554 } 1555 1556 return retValue; 1557 } 1558 1559 void reportSchemaFatalError (String key, Object[] args, Element ele) { 1560 fSchemaHandler.reportSchemaFatalError(key, args, ele); 1561 } 1562 1563 void reportSchemaError (String key, Object[] args, Element ele) { 1564 fSchemaHandler.reportSchemaError(key, args, ele); 1565 } 1566 1567 // validate attriubtes from non-schema namespaces 1568 // REVISIT: why we store the attributes in this way? why not just a list 1569 // of structure {element node, attr name/qname, attr value)? 1570 // REVISIT: pass the proper element node to reportSchemaError 1571 public void checkNonSchemaAttributes(XSGrammarBucket grammarBucket) { 1572 // for all attributes 1573 Iterator entries = fNonSchemaAttrs.entrySet().iterator(); 1574 XSAttributeDecl attrDecl; 1575 while (entries.hasNext()) { 1576 Map.Entry entry = (Map.Entry) entries.next(); 1577 // get name, uri, localpart 1578 String attrRName = (String) entry.getKey(); 1579 String attrURI = attrRName.substring(0,attrRName.indexOf(',')); 1580 String attrLocal = attrRName.substring(attrRName.indexOf(',')+1); 1581 // find associated grammar 1582 SchemaGrammar sGrammar = grammarBucket.getGrammar(attrURI); 1583 if (sGrammar == null) { 1584 continue; 1585 } 1586 // and get the datatype validator, if there is one 1587 attrDecl = sGrammar.getGlobalAttributeDecl(attrLocal); 1588 if (attrDecl == null) { 1589 continue; 1590 } 1591 XSSimpleType dv = (XSSimpleType)attrDecl.getTypeDefinition(); 1592 if (dv == null) { 1593 continue; 1594 } 1595 1596 // get all values appeared with this attribute name 1597 Vector values = (Vector) entry.getValue(); 1598 String elName; 1599 String attrName = (String)values.elementAt(0); 1600 // for each of the values 1601 int count = values.size(); 1602 for (int i = 1; i < count; i += 2) { 1603 elName = (String)values.elementAt(i); 1604 try { 1605 // and validate it using the XSSimpleType 1606 // REVISIT: what would be the proper validation context? 1607 // guess we need to save that in the vectors too. 1608 dv.validate((String)values.elementAt(i+1), null, null); 1609 } catch(InvalidDatatypeValueException ide) { 1610 reportSchemaError ("s4s-att-invalid-value", 1611 new Object[] {elName, attrName, ide.getMessage()}, 1612 null); 1613 } 1614 } 1615 } 1616 } 1617 1618 // normalize the string according to the whiteSpace facet 1619 public static String normalize(String content, short ws) { 1620 int len = content == null ? 0 : content.length(); 1621 if (len == 0 || ws == XSSimpleType.WS_PRESERVE) 1622 return content; 1623 1624 StringBuffer sb = new StringBuffer(); 1625 if (ws == XSSimpleType.WS_REPLACE) { 1626 char ch; 1627 // when it's replace, just replace #x9, #xa, #xd by #x20 1628 for (int i = 0; i < len; i++) { 1629 ch = content.charAt(i); 1630 if (ch != 0x9 && ch != 0xa && ch != 0xd) 1631 sb.append(ch); 1632 else 1633 sb.append((char)0x20); 1634 } 1635 } else { 1636 char ch; 1637 int i; 1638 boolean isLeading = true; 1639 // when it's collapse 1640 for (i = 0; i < len; i++) { 1641 ch = content.charAt(i); 1642 // append real characters, so we passed leading ws 1643 if (ch != 0x9 && ch != 0xa && ch != 0xd && ch != 0x20) { 1644 sb.append(ch); 1645 isLeading = false; 1646 } 1647 else { 1648 // for whitespaces, we skip all following ws 1649 for (; i < len-1; i++) { 1650 ch = content.charAt(i+1); 1651 if (ch != 0x9 && ch != 0xa && ch != 0xd && ch != 0x20) 1652 break; 1653 } 1654 // if it's not a leading or tailing ws, then append a space 1655 if (i < len - 1 && !isLeading) 1656 sb.append((char)0x20); 1657 } 1658 } 1659 } 1660 1661 return sb.toString(); 1662 } 1663 1664 // the following part implements an attribute-value-array pool. 1665 // when checkAttribute is called, it calls getAvailableArray to get 1666 // an array from the pool; when the caller is done with the array, 1667 // it calls returnAttrArray to return that array to the pool. 1668 1669 // initial size of the array pool. 10 is big enough 1670 static final int INIT_POOL_SIZE = 10; 1671 // the incremental size of the array pool 1672 static final int INC_POOL_SIZE = 10; 1673 // the array pool 1674 Object[][] fArrayPool = new Object[INIT_POOL_SIZE][ATTIDX_COUNT]; 1675 // used to clear the returned array 1676 // I think System.arrayCopy is more efficient than setting 35 fields to null 1677 private static Object[] fTempArray = new Object[ATTIDX_COUNT]; 1678 // current position of the array pool (# of arrays not returned) 1679 int fPoolPos = 0; 1680 1681 // get the next available array 1682 protected Object[] getAvailableArray() { 1683 // if no array left in the pool, increase the pool size 1684 if (fArrayPool.length == fPoolPos) { 1685 // increase size 1686 fArrayPool = new Object[fPoolPos+INC_POOL_SIZE][]; 1687 // initialize each *new* array 1688 for (int i = fPoolPos; i < fArrayPool.length; i++) 1689 fArrayPool[i] = new Object[ATTIDX_COUNT]; 1690 } 1691 // get the next available one 1692 Object[] retArray = fArrayPool[fPoolPos]; 1693 // clear it from the pool. this is for GC: if a caller forget to 1694 // return the array, we want that array to be GCed. 1695 fArrayPool[fPoolPos++] = null; 1696 // to make sure that one array is not returned twice, we use 1697 // the last entry to indicate whether an array is already returned 1698 // now set it to false. 1699 System.arraycopy(fTempArray, 0, retArray, 0, ATTIDX_COUNT-1); 1700 retArray[ATTIDX_ISRETURNED] = Boolean.FALSE; 1701 1702 return retArray; 1703 } 1704 1705 // return an array back to the pool 1706 public void returnAttrArray(Object[] attrArray, XSDocumentInfo schemaDoc) { 1707 // pop the namespace context 1708 if (schemaDoc != null) 1709 schemaDoc.fNamespaceSupport.popContext(); 1710 1711 // if 1. the pool is full; 2. the array is null; 1712 // 3. the array is of wrong size; 4. the array is already returned 1713 // then we can't accept this array to be returned 1714 if (fPoolPos == 0 || 1715 attrArray == null || 1716 attrArray.length != ATTIDX_COUNT || 1717 ((Boolean)attrArray[ATTIDX_ISRETURNED]).booleanValue()) { 1718 return; 1719 } 1720 1721 // mark this array as returned 1722 attrArray[ATTIDX_ISRETURNED] = Boolean.TRUE; 1723 // better clear nonschema vector 1724 if(attrArray[ATTIDX_NONSCHEMA] != null) 1725 ((Vector)attrArray[ATTIDX_NONSCHEMA]).clear(); 1726 // and put it into the pool 1727 fArrayPool[--fPoolPos] = attrArray; 1728 } 1729 1730 public void resolveNamespace(Element element, Attr[] attrs, 1731 SchemaNamespaceSupport nsSupport) { 1732 // push the namespace context 1733 nsSupport.pushContext(); 1734 1735 // search for new namespace bindings 1736 int length = attrs.length; 1737 Attr sattr = null; 1738 String rawname, prefix, uri; 1739 for (int i = 0; i < length; i++) { 1740 sattr = attrs[i]; 1741 rawname = DOMUtil.getName(sattr); 1742 prefix = null; 1743 if (rawname.equals(XMLSymbols.PREFIX_XMLNS)) 1744 prefix = XMLSymbols.EMPTY_STRING; 1745 else if (rawname.startsWith("xmlns:")) 1746 prefix = fSymbolTable.addSymbol(DOMUtil.getLocalName(sattr)); 1747 if (prefix != null) { 1748 uri = fSymbolTable.addSymbol(DOMUtil.getValue(sattr)); 1749 nsSupport.declarePrefix(prefix, uri.length()!=0 ? uri : null); 1750 } 1751 } 1752 } 1753 } 1754 1755 class OneAttr { 1756 // name of the attribute 1757 public String name; 1758 // index of the datatype validator 1759 public int dvIndex; 1760 // whether it's optional, and has default value 1761 public int valueIndex; 1762 // the default value of this attribute 1763 public Object dfltValue; 1764 1765 public OneAttr(String name, int dvIndex, int valueIndex, Object dfltValue) { 1766 this.name = name; 1767 this.dvIndex = dvIndex; 1768 this.valueIndex = valueIndex; 1769 this.dfltValue = dfltValue; 1770 } 1771 } 1772 1773 abstract class Container { 1774 static final int THRESHOLD = 5; 1775 static Container getContainer(int size) { 1776 if (size > THRESHOLD) 1777 return new LargeContainer(size); 1778 else 1779 return new SmallContainer(size); 1780 } 1781 abstract void put(String key, OneAttr value); 1782 abstract OneAttr get(String key); 1783 1784 OneAttr[] values; 1785 int pos = 0; 1786 } 1787 1788 class SmallContainer extends Container { 1789 String[] keys; 1790 SmallContainer(int size) { 1791 keys = new String[size]; 1792 values = new OneAttr[size]; 1793 } 1794 void put(String key, OneAttr value) { 1795 keys[pos] = key; 1796 values[pos++] = value; 1797 } 1798 OneAttr get(String key) { 1799 for (int i = 0; i < pos; i++) { 1800 if (keys[i].equals(key)) { 1801 return values[i]; 1802 } 1803 } 1804 return null; 1805 } 1806 } 1807 1808 class LargeContainer extends Container { 1809 Map items; 1810 LargeContainer(int size) { 1811 items = new HashMap(size*2+1); 1812 values = new OneAttr[size]; 1813 } 1814 void put(String key, OneAttr value) { 1815 items.put(key, value); 1816 values[pos++] = value; 1817 } 1818 OneAttr get(String key) { 1819 OneAttr ret = (OneAttr)items.get(key); 1820 return ret; 1821 } 1822 }