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