1 /*
   2  * Copyright (c) 2016, 2017, 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.ArrayList;
  41 import java.util.HashMap;
  42 import java.util.List;
  43 import java.util.Map;
  44 import java.util.StringTokenizer;
  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  * @LastModified: Nov 2017
  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 &lt;schema&gt; or &lt;redefine&gt;
 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 &lt;schema&gt; or &lt;redefine&gt;
 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 = 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 = items.get(key);
1828         return ret;
1829     }
1830 }