KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > xs > XSModelImpl


1 /*
2  * Copyright 2002-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.impl.xs;
18
19 import java.util.Vector JavaDoc;
20
21 import org.apache.xerces.xs.StringList;
22 import org.apache.xerces.xs.XSAttributeDeclaration;
23 import org.apache.xerces.xs.XSAttributeGroupDefinition;
24 import org.apache.xerces.xs.XSConstants;
25 import org.apache.xerces.xs.XSElementDeclaration;
26 import org.apache.xerces.xs.XSModel;
27 import org.apache.xerces.xs.XSModelGroupDefinition;
28 import org.apache.xerces.xs.XSNamedMap;
29 import org.apache.xerces.xs.XSNamespaceItemList;
30 import org.apache.xerces.xs.XSNotationDeclaration;
31 import org.apache.xerces.xs.XSObjectList;
32 import org.apache.xerces.xs.XSTypeDefinition;
33 import org.apache.xerces.impl.xs.util.NSItemListImpl;
34 import org.apache.xerces.impl.xs.util.StringListImpl;
35 import org.apache.xerces.impl.xs.util.XSNamedMap4Types;
36 import org.apache.xerces.impl.xs.util.XSNamedMapImpl;
37 import org.apache.xerces.impl.xs.util.XSObjectListImpl;
38 import org.apache.xerces.util.SymbolHash;
39 import org.apache.xerces.util.XMLSymbols;
40
41 /**
42  * Implements XSModel: a read-only interface that represents an XML Schema,
43  * which could be components from different namespaces.
44  *
45  * @xerces.internal
46  *
47  * @author Sandy Gao, IBM
48  *
49  * @version $Id: XSModelImpl.java,v 1.18 2005/05/25 04:24:40 mrglavas Exp $
50  */

51 public class XSModelImpl implements XSModel {
52
53     // the max index / the max value of XSObject type
54
private static final short MAX_COMP_IDX = XSTypeDefinition.SIMPLE_TYPE;
55     private static final boolean[] GLOBAL_COMP = {false, // null
56
true, // attribute
57
true, // element
58
true, // type
59
false, // attribute use
60
true, // attribute group
61
true, // group
62
false, // model group
63
false, // particle
64
false, // wildcard
65
false, // idc
66
true, // notation
67
false, // annotation
68
false, // facet
69
false, // multi value facet
70
true, // complex type
71
true // simple type
72
};
73
74     // number of grammars/namespaces stored here
75
private int fGrammarCount;
76     // all target namespaces
77
private String JavaDoc[] fNamespaces;
78     // all schema grammar objects (for each namespace)
79
private SchemaGrammar[] fGrammarList;
80     // a map from namespace to schema grammar
81
private SymbolHash fGrammarMap;
82     // a map from element declaration to its substitution group
83
private SymbolHash fSubGroupMap;
84     
85     // store a certain kind of components from all namespaces
86
private XSNamedMap[] fGlobalComponents;
87     // store a certain kind of components from one namespace
88
private XSNamedMap[][] fNSComponents;
89
90     // store all annotations
91
private XSObjectListImpl fAnnotations = null;
92     
93     // whether there is any IDC in this XSModel
94
private boolean fHasIDC = false;
95     
96    /**
97     * Construct an XSModelImpl, by storing some grammars and grammars imported
98     * by them to this object.
99     *
100     * @param grammars the array of schema grammars
101     */

102     public XSModelImpl(SchemaGrammar[] grammars) {
103         // copy namespaces/grammars from the array to our arrays
104
int len = grammars.length;
105         fNamespaces = new String JavaDoc[Math.max(len+1, 5)];
106         fGrammarList = new SchemaGrammar[Math.max(len+1, 5)];
107         boolean hasS4S = false;
108         for (int i = 0; i < len; i++) {
109             fNamespaces[i] = grammars[i].getTargetNamespace();
110             fGrammarList[i] = grammars[i];
111             if (fNamespaces[i] == SchemaSymbols.URI_SCHEMAFORSCHEMA)
112                 hasS4S = true;
113         }
114         // If a schema for the schema namespace isn't included, include it here.
115
if (!hasS4S) {
116             fNamespaces[len] = SchemaSymbols.URI_SCHEMAFORSCHEMA;
117             fGrammarList[len++] = SchemaGrammar.SG_SchemaNS;
118         }
119
120         SchemaGrammar sg1, sg2;
121         Vector JavaDoc gs;
122         int i, j, k;
123         // and recursively get all imported grammars, add them to our arrays
124
for (i = 0; i < len; i++) {
125             // get the grammar
126
sg1 = fGrammarList[i];
127             gs = sg1.getImportedGrammars();
128             // for each imported grammar
129
for (j = gs == null ? -1 : gs.size() - 1; j >= 0; j--) {
130                 sg2 = (SchemaGrammar)gs.elementAt(j);
131                 // check whether this grammar is already in the list
132
for (k = 0; k < len; k++) {
133                     if (sg2 == fGrammarList[k])
134                         break;
135                 }
136                 // if it's not, add it to the list
137
if (k == len) {
138                     // ensure the capacity of the arrays
139
if (len == fGrammarList.length) {
140                         String JavaDoc[] newSA = new String JavaDoc[len*2];
141                         System.arraycopy(fNamespaces, 0, newSA, 0, len);
142                         fNamespaces = newSA;
143                         SchemaGrammar[] newGA = new SchemaGrammar[len*2];
144                         System.arraycopy(fGrammarList, 0, newGA, 0, len);
145                         fGrammarList = newGA;
146                     }
147                     fNamespaces[len] = sg2.getTargetNamespace();
148                     fGrammarList[len] = sg2;
149                     len++;
150                 }
151             }
152         }
153
154         // establish the mapping from namespace to grammars
155
fGrammarMap = new SymbolHash(len*2);
156         for (i = 0; i < len; i++) {
157             fGrammarMap.put(null2EmptyString(fNamespaces[i]), fGrammarList[i]);
158             // update the idc field
159
if (fGrammarList[i].hasIDConstraints())
160                 fHasIDC = true;
161         }
162         
163         fGrammarCount = len;
164         fGlobalComponents = new XSNamedMap[MAX_COMP_IDX+1];
165         fNSComponents = new XSNamedMap[len][MAX_COMP_IDX+1];
166         
167         // build substitution groups
168
buildSubGroups();
169     }
170     
171     private void buildSubGroups() {
172         SubstitutionGroupHandler sgHandler = new SubstitutionGroupHandler(null);
173         for (int i = 0 ; i < fGrammarCount; i++) {
174             sgHandler.addSubstitutionGroup(fGrammarList[i].getSubstitutionGroups());
175         }
176
177         XSNamedMap elements = getComponents(XSConstants.ELEMENT_DECLARATION);
178         int len = elements.getLength();
179         fSubGroupMap = new SymbolHash(len*2);
180         XSElementDecl head;
181         XSElementDeclaration[] subGroup;
182         for (int i = 0; i < len; i++) {
183             head = (XSElementDecl)elements.item(i);
184             subGroup = sgHandler.getSubstitutionGroup(head);
185             fSubGroupMap.put(head, subGroup.length > 0 ?
186                     new XSObjectListImpl(subGroup, subGroup.length) : XSObjectListImpl.EMPTY_LIST);
187         }
188     }
189     
190     /**
191      * Convenience method. Returns a list of all namespaces that belong to
192      * this schema.
193      * @return A list of all namespaces that belong to this schema or
194      * <code>null</code> if all components don't have a targetNamespace.
195      */

196     public StringList getNamespaces() {
197         // REVISIT: should the type of fNamespace be StringListImpl?
198
return new StringListImpl(fNamespaces, fGrammarCount);
199     }
200
201
202     public XSNamespaceItemList getNamespaceItems() {
203
204         // REVISIT: should the type of fGrammarList be NSItemListImpl?
205
return new NSItemListImpl(fGrammarList, fGrammarCount);
206     }
207
208     /**
209      * Returns a list of top-level components, i.e. element declarations,
210      * attribute declarations, etc.
211      * @param objectType The type of the declaration, i.e.
212      * <code>ELEMENT_DECLARATION</code>. Note that
213      * <code>XSTypeDefinition.SIMPLE_TYPE</code> and
214      * <code>XSTypeDefinition.COMPLEX_TYPE</code> can also be used as the
215      * <code>objectType</code> to retrieve only complex types or simple
216      * types, instead of all types.
217      * @return A list of top-level definitions of the specified type in
218      * <code>objectType</code> or an empty <code>XSNamedMap</code> if no
219      * such definitions exist.
220      */

221     public synchronized XSNamedMap getComponents(short objectType) {
222         if (objectType <= 0 || objectType > MAX_COMP_IDX ||
223             !GLOBAL_COMP[objectType]) {
224             return XSNamedMapImpl.EMPTY_MAP;
225         }
226         
227         SymbolHash[] tables = new SymbolHash[fGrammarCount];
228         // get all hashtables from all namespaces for this type of components
229
if (fGlobalComponents[objectType] == null) {
230             for (int i = 0; i < fGrammarCount; i++) {
231                 switch (objectType) {
232                 case XSConstants.TYPE_DEFINITION:
233                 case XSTypeDefinition.COMPLEX_TYPE:
234                 case XSTypeDefinition.SIMPLE_TYPE:
235                     tables[i] = fGrammarList[i].fGlobalTypeDecls;
236                     break;
237                 case XSConstants.ATTRIBUTE_DECLARATION:
238                     tables[i] = fGrammarList[i].fGlobalAttrDecls;
239                     break;
240                 case XSConstants.ELEMENT_DECLARATION:
241                     tables[i] = fGrammarList[i].fGlobalElemDecls;
242                     break;
243                 case XSConstants.ATTRIBUTE_GROUP:
244                     tables[i] = fGrammarList[i].fGlobalAttrGrpDecls;
245                     break;
246                 case XSConstants.MODEL_GROUP_DEFINITION:
247                     tables[i] = fGrammarList[i].fGlobalGroupDecls;
248                     break;
249                 case XSConstants.NOTATION_DECLARATION:
250                     tables[i] = fGrammarList[i].fGlobalNotationDecls;
251                     break;
252                 }
253             }
254             // for complex/simple types, create a special implementation,
255
// which take specific types out of the hash table
256
if (objectType == XSTypeDefinition.COMPLEX_TYPE ||
257                 objectType == XSTypeDefinition.SIMPLE_TYPE) {
258                 fGlobalComponents[objectType] = new XSNamedMap4Types(fNamespaces, tables, fGrammarCount, objectType);
259             }
260             else {
261                 fGlobalComponents[objectType] = new XSNamedMapImpl(fNamespaces, tables, fGrammarCount);
262             }
263         }
264         
265         return fGlobalComponents[objectType];
266     }
267
268     /**
269      * Convenience method. Returns a list of top-level component declarations
270      * that are defined within the specified namespace, i.e. element
271      * declarations, attribute declarations, etc.
272      * @param objectType The type of the declaration, i.e.
273      * <code>ELEMENT_DECLARATION</code>.
274      * @param namespace The namespace to which the declaration belongs or
275      * <code>null</code> (for components with no target namespace).
276      * @return A list of top-level definitions of the specified type in
277      * <code>objectType</code> and defined in the specified
278      * <code>namespace</code> or an empty <code>XSNamedMap</code>.
279      */

280     public synchronized XSNamedMap getComponentsByNamespace(short objectType,
281                                                             String JavaDoc namespace) {
282         if (objectType <= 0 || objectType > MAX_COMP_IDX ||
283             !GLOBAL_COMP[objectType]) {
284             return XSNamedMapImpl.EMPTY_MAP;
285         }
286         
287         // try to find the grammar
288
int i = 0;
289         if (namespace != null) {
290             for (; i < fGrammarCount; ++i) {
291                 if (namespace.equals(fNamespaces[i]))
292                     break;
293             }
294         }
295         else {
296             for (; i < fGrammarCount; ++i) {
297                 if (fNamespaces[i] == null)
298                     break;
299             }
300         }
301         if (i == fGrammarCount)
302             return XSNamedMapImpl.EMPTY_MAP;
303         
304         // get the hashtable for this type of components
305
if (fNSComponents[i][objectType] == null) {
306             SymbolHash table = null;
307             switch (objectType) {
308             case XSConstants.TYPE_DEFINITION:
309             case XSTypeDefinition.COMPLEX_TYPE:
310             case XSTypeDefinition.SIMPLE_TYPE:
311                 table = fGrammarList[i].fGlobalTypeDecls;
312                 break;
313             case XSConstants.ATTRIBUTE_DECLARATION:
314                 table = fGrammarList[i].fGlobalAttrDecls;
315                 break;
316             case XSConstants.ELEMENT_DECLARATION:
317                 table = fGrammarList[i].fGlobalElemDecls;
318                 break;
319             case XSConstants.ATTRIBUTE_GROUP:
320                 table = fGrammarList[i].fGlobalAttrGrpDecls;
321                 break;
322             case XSConstants.MODEL_GROUP_DEFINITION:
323                 table = fGrammarList[i].fGlobalGroupDecls;
324                 break;
325             case XSConstants.NOTATION_DECLARATION:
326                 table = fGrammarList[i].fGlobalNotationDecls;
327                 break;
328             }
329             
330             // for complex/simple types, create a special implementation,
331
// which take specific types out of the hash table
332
if (objectType == XSTypeDefinition.COMPLEX_TYPE ||
333                 objectType == XSTypeDefinition.SIMPLE_TYPE) {
334                 fNSComponents[i][objectType] = new XSNamedMap4Types(namespace, table, objectType);
335             }
336             else {
337                 fNSComponents[i][objectType] = new XSNamedMapImpl(namespace, table);
338             }
339         }
340         
341         return fNSComponents[i][objectType];
342     }
343
344     /**
345      * Convenience method. Returns a top-level simple or complex type
346      * definition.
347      * @param name The name of the definition.
348      * @param namespace The namespace of the definition, otherwise null.
349      * @return An <code>XSTypeDefinition</code> or null if such definition
350      * does not exist.
351      */

352     public XSTypeDefinition getTypeDefinition(String JavaDoc name,
353                                               String JavaDoc namespace) {
354         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
355         if (sg == null)
356             return null;
357         return (XSTypeDefinition)sg.fGlobalTypeDecls.get(name);
358     }
359
360     /**
361      * Convenience method. Returns a top-level attribute declaration.
362      * @param name The name of the declaration.
363      * @param namespace The namespace of the definition, otherwise null.
364      * @return A top-level attribute declaration or null if such declaration
365      * does not exist.
366      */

367     public XSAttributeDeclaration getAttributeDeclaration(String JavaDoc name,
368                                                    String JavaDoc namespace) {
369         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
370         if (sg == null)
371             return null;
372         return (XSAttributeDeclaration)sg.fGlobalAttrDecls.get(name);
373     }
374
375     /**
376      * Convenience method. Returns a top-level element declaration.
377      * @param name The name of the declaration.
378      * @param namespace The namespace of the definition, otherwise null.
379      * @return A top-level element declaration or null if such declaration
380      * does not exist.
381      */

382     public XSElementDeclaration getElementDeclaration(String JavaDoc name,
383                                                String JavaDoc namespace) {
384         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
385         if (sg == null)
386             return null;
387         return (XSElementDeclaration)sg.fGlobalElemDecls.get(name);
388     }
389
390     /**
391      * Convenience method. Returns a top-level attribute group definition.
392      * @param name The name of the definition.
393      * @param namespace The namespace of the definition, otherwise null.
394      * @return A top-level attribute group definition or null if such
395      * definition does not exist.
396      */

397     public XSAttributeGroupDefinition getAttributeGroup(String JavaDoc name,
398                                                         String JavaDoc namespace) {
399         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
400         if (sg == null)
401             return null;
402         return (XSAttributeGroupDefinition)sg.fGlobalAttrGrpDecls.get(name);
403     }
404
405     /**
406      * Convenience method. Returns a top-level model group definition.
407      *
408      * @param name The name of the definition.
409      * @param namespace The namespace of the definition, otherwise null.
410      * @return A top-level model group definition definition or null if such
411      * definition does not exist.
412      */

413     public XSModelGroupDefinition getModelGroupDefinition(String JavaDoc name,
414                                                           String JavaDoc namespace) {
415         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
416         if (sg == null)
417             return null;
418         return (XSModelGroupDefinition)sg.fGlobalGroupDecls.get(name);
419     }
420
421
422     /**
423      * @see org.apache.xerces.xs.XSModel#getNotationDeclaration(String, String)
424      */

425     public XSNotationDeclaration getNotationDeclaration(String JavaDoc name,
426                                                  String JavaDoc namespace) {
427         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
428         if (sg == null)
429             return null;
430         return (XSNotationDeclaration)sg.fGlobalNotationDecls.get(name);
431     }
432
433     /**
434      * {annotations} A set of annotations.
435      */

436     public synchronized XSObjectList getAnnotations() {
437         if(fAnnotations != null)
438             return fAnnotations;
439
440         // do this in two passes to avoid inaccurate array size
441
int totalAnnotations = 0;
442         for (int i = 0; i < fGrammarCount; i++) {
443             totalAnnotations += fGrammarList[i].fNumAnnotations;
444         }
445         XSAnnotationImpl [] annotations = new XSAnnotationImpl [totalAnnotations];
446         int currPos = 0;
447         for (int i = 0; i < fGrammarCount; i++) {
448             SchemaGrammar currGrammar = fGrammarList[i];
449             if (currGrammar.fNumAnnotations > 0) {
450                 System.arraycopy(currGrammar.fAnnotations, 0, annotations, currPos, currGrammar.fNumAnnotations);
451                 currPos += currGrammar.fNumAnnotations;
452             }
453         }
454         fAnnotations = new XSObjectListImpl(annotations, annotations.length);
455         return fAnnotations;
456     }
457
458     private static final String JavaDoc null2EmptyString(String JavaDoc str) {
459         return str == null ? XMLSymbols.EMPTY_STRING : str;
460     }
461     
462     /**
463      * REVISIT: to expose identity constraints from XSModel.
464      * For now, we only expose whether there are any IDCs.
465      * We also need to add these methods to the public
466      * XSModel interface.
467      */

468     public boolean hasIDConstraints() {
469         return fHasIDC;
470     }
471
472     /**
473      * REVISIT: to expose substitution group of a given element.
474      * We need to add this to the XSModel interface.
475      */

476     public XSObjectList getSubstitutionGroup(XSElementDeclaration head) {
477         return (XSObjectList)fSubGroupMap.get(head);
478     }
479
480 } // class XSModelImpl
481
Popular Tags