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