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