KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > impl > xs > XSModelImpl


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2002-2004 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 2001, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package com.sun.org.apache.xerces.internal.impl.xs;
59
60 import java.util.Vector JavaDoc;
61
62 import com.sun.org.apache.xerces.internal.xs.StringList;
63 import com.sun.org.apache.xerces.internal.xs.XSAttributeDeclaration;
64 import com.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition;
65 import com.sun.org.apache.xerces.internal.xs.XSConstants;
66 import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration;
67 import com.sun.org.apache.xerces.internal.xs.XSModel;
68 import com.sun.org.apache.xerces.internal.xs.XSModelGroupDefinition;
69 import com.sun.org.apache.xerces.internal.xs.XSNamedMap;
70 import com.sun.org.apache.xerces.internal.xs.XSNamespaceItemList;
71 import com.sun.org.apache.xerces.internal.xs.XSNotationDeclaration;
72 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
73 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
74 import com.sun.org.apache.xerces.internal.impl.xs.util.NSItemListImpl;
75 import com.sun.org.apache.xerces.internal.impl.xs.util.StringListImpl;
76 import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMap4Types;
77 import com.sun.org.apache.xerces.internal.impl.xs.util.XSNamedMapImpl;
78 import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
79 import com.sun.org.apache.xerces.internal.util.SymbolHash;
80 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
81
82 /**
83  * @author elitani
84  *
85  * To change this generated comment edit the template variable "typecomment":
86  * Window>Preferences>Java>Templates.
87  * To enable and disable the creation of type comments go to
88  * Window>Preferences>Java>Code Generation.
89  */

90 /**
91  * @author elitani
92  *
93  * To change this generated comment edit the template variable "typecomment":
94  * Window>Preferences>Java>Templates.
95  * To enable and disable the creation of type comments go to
96  * Window>Preferences>Java>Code Generation.
97  */

98 /**
99  * Implements XSModel: a read-only interface that represents an XML Schema,
100  * which could be components from different namespaces.
101  *
102  * @author Sandy Gao, IBM
103  *
104  * @version $Id: XSModelImpl.java,v 1.12 2004/02/03 17:10:38 sandygao Exp $
105  */

106 public class XSModelImpl implements XSModel {
107
108     // the max index / the max value of XSObject type
109
private static final short MAX_COMP_IDX = XSTypeDefinition.SIMPLE_TYPE;
110     private static final boolean[] GLOBAL_COMP = {false, // null
111
true, // attribute
112
true, // element
113
true, // type
114
false, // attribute use
115
true, // attribute group
116
true, // group
117
false, // model group
118
false, // particle
119
false, // wildcard
120
false, // idc
121
true, // notation
122
false, // annotation
123
false, // facet
124
false, // multi value facet
125
true, // complex type
126
true // simple type
127
};
128
129     // number of grammars/namespaces stored here
130
private int fGrammarCount;
131     // all target namespaces
132
private String JavaDoc[] fNamespaces;
133     // all schema grammar objects (for each namespace)
134
private SchemaGrammar[] fGrammarList;
135     // a map from namespace to schema grammar
136
private SymbolHash fGrammarMap;
137     // a map from element declaration to its substitution group
138
private SymbolHash fSubGroupMap;
139     
140     // store a certain kind of components from all namespaces
141
private XSNamedMap[] fGlobalComponents;
142     // store a certain kind of components from one namespace
143
private XSNamedMap[][] fNSComponents;
144
145     // store all annotations
146
private XSObjectListImpl fAnnotations = null;
147     
148     // whether there is any IDC in this XSModel
149
private boolean fHasIDC = false;
150     
151    /**
152     * Construct an XSModelImpl, by storing some grammars and grammars imported
153     * by them to this object.
154     *
155     * @param grammars the array of schema grammars
156     */

157     public XSModelImpl(SchemaGrammar[] grammars) {
158         // copy namespaces/grammars from the array to our arrays
159
int len = grammars.length;
160         fNamespaces = new String JavaDoc[Math.max(len+1, 5)];
161         fGrammarList = new SchemaGrammar[Math.max(len+1, 5)];
162         boolean hasS4S = false;
163         for (int i = 0; i < len; i++) {
164             fNamespaces[i] = grammars[i].getTargetNamespace();
165             fGrammarList[i] = grammars[i];
166             if (fNamespaces[i] == SchemaSymbols.URI_SCHEMAFORSCHEMA)
167                 hasS4S = true;
168         }
169         // If a schema for the schema namespace isn't included, include it here.
170
if (!hasS4S) {
171             fNamespaces[len] = SchemaSymbols.URI_SCHEMAFORSCHEMA;
172             fGrammarList[len++] = SchemaGrammar.SG_SchemaNS;
173         }
174
175         SchemaGrammar sg1, sg2;
176         Vector JavaDoc gs;
177         int i, j, k;
178         // and recursively get all imported grammars, add them to our arrays
179
for (i = 0; i < len; i++) {
180             // get the grammar
181
sg1 = fGrammarList[i];
182             gs = sg1.getImportedGrammars();
183             // for each imported grammar
184
for (j = gs == null ? -1 : gs.size() - 1; j >= 0; j--) {
185                 sg2 = (SchemaGrammar)gs.elementAt(j);
186                 // check whether this grammar is already in the list
187
for (k = 0; k < len; k++) {
188                     if (sg2 == fGrammarList[k])
189                         break;
190                 }
191                 // if it's not, add it to the list
192
if (k == len) {
193                     // ensure the capacity of the arrays
194
if (len == fGrammarList.length) {
195                         String JavaDoc[] newSA = new String JavaDoc[len*2];
196                         System.arraycopy(fNamespaces, 0, newSA, 0, len);
197                         fNamespaces = newSA;
198                         SchemaGrammar[] newGA = new SchemaGrammar[len*2];
199                         System.arraycopy(fGrammarList, 0, newGA, 0, len);
200                         fGrammarList = newGA;
201                     }
202                     fNamespaces[len] = sg2.getTargetNamespace();
203                     fGrammarList[len] = sg2;
204                     len++;
205                 }
206             }
207         }
208
209         // establish the mapping from namespace to grammars
210
fGrammarMap = new SymbolHash(len*2);
211         for (i = 0; i < len; i++) {
212             fGrammarMap.put(null2EmptyString(fNamespaces[i]), fGrammarList[i]);
213             // update the idc field
214
if (fGrammarList[i].hasIDConstraints())
215                 fHasIDC = true;
216         }
217         
218         fGrammarCount = len;
219         fGlobalComponents = new XSNamedMap[MAX_COMP_IDX+1];
220         fNSComponents = new XSNamedMap[len][MAX_COMP_IDX+1];
221         
222         // build substitution groups
223
buildSubGroups();
224     }
225     
226     private void buildSubGroups() {
227         SubstitutionGroupHandler sgHandler = new SubstitutionGroupHandler(null);
228         for (int i = 0 ; i < fGrammarCount; i++) {
229             sgHandler.addSubstitutionGroup(fGrammarList[i].getSubstitutionGroups());
230         }
231
232         XSNamedMap elements = getComponents(XSConstants.ELEMENT_DECLARATION);
233         int len = elements.getLength();
234         fSubGroupMap = new SymbolHash(len*2);
235         XSElementDecl head;
236         XSElementDeclaration[] subGroup;
237         for (int i = 0; i < len; i++) {
238             head = (XSElementDecl)elements.item(i);
239             subGroup = sgHandler.getSubstitutionGroup(head);
240             fSubGroupMap.put(head, new XSObjectListImpl(subGroup, subGroup.length));
241         }
242     }
243     
244     /**
245      * Convenience method. Returns a list of all namespaces that belong to
246      * this schema.
247      * @return A list of all namespaces that belong to this schema or
248      * <code>null</code> if all components don't have a targetNamespace.
249      */

250     public StringList getNamespaces() {
251         // REVISIT: should the type of fNamespace be StringListImpl?
252
return new StringListImpl(fNamespaces, fGrammarCount);
253     }
254
255
256     public XSNamespaceItemList getNamespaceItems() {
257
258         // REVISIT: should the type of fGrammarList be NSItemListImpl?
259
return new NSItemListImpl(fGrammarList, fGrammarCount);
260     }
261
262     /**
263      * Returns a list of top-level components, i.e. element declarations,
264      * attribute declarations, etc.
265      * @param objectType The type of the declaration, i.e.
266      * ELEMENT_DECLARATION, ATTRIBUTE_DECLARATION, etc.
267      * @return A list of top-level definition of the specified type in
268      * <code>objectType</code> or <code>null</code>.
269      */

270     public synchronized XSNamedMap getComponents(short objectType) {
271         if (objectType <= 0 || objectType > MAX_COMP_IDX ||
272             !GLOBAL_COMP[objectType]) {
273             return null;
274         }
275         
276         SymbolHash[] tables = new SymbolHash[fGrammarCount];
277         // get all hashtables from all namespaces for this type of components
278
if (fGlobalComponents[objectType] == null) {
279             for (int i = 0; i < fGrammarCount; i++) {
280                 switch (objectType) {
281                 case XSConstants.TYPE_DEFINITION:
282                 case XSTypeDefinition.COMPLEX_TYPE:
283                 case XSTypeDefinition.SIMPLE_TYPE:
284                     tables[i] = fGrammarList[i].fGlobalTypeDecls;
285                     break;
286                 case XSConstants.ATTRIBUTE_DECLARATION:
287                     tables[i] = fGrammarList[i].fGlobalAttrDecls;
288                     break;
289                 case XSConstants.ELEMENT_DECLARATION:
290                     tables[i] = fGrammarList[i].fGlobalElemDecls;
291                     break;
292                 case XSConstants.ATTRIBUTE_GROUP:
293                     tables[i] = fGrammarList[i].fGlobalAttrGrpDecls;
294                     break;
295                 case XSConstants.MODEL_GROUP_DEFINITION:
296                     tables[i] = fGrammarList[i].fGlobalGroupDecls;
297                     break;
298                 case XSConstants.NOTATION_DECLARATION:
299                     tables[i] = fGrammarList[i].fGlobalNotationDecls;
300                     break;
301                 }
302             }
303             // for complex/simple types, create a special implementation,
304
// which take specific types out of the hash table
305
if (objectType == XSTypeDefinition.COMPLEX_TYPE ||
306                 objectType == XSTypeDefinition.SIMPLE_TYPE) {
307                 fGlobalComponents[objectType] = new XSNamedMap4Types(fNamespaces, tables, fGrammarCount, objectType);
308             }
309             else {
310                 fGlobalComponents[objectType] = new XSNamedMapImpl(fNamespaces, tables, fGrammarCount);
311             }
312         }
313         
314         return fGlobalComponents[objectType];
315     }
316
317     /**
318      * Convenience method. Returns a list of top-level component declarations
319      * that are defined within the specified namespace, i.e. element
320      * declarations, attribute declarations, etc.
321      * @param objectType The type of the declaration, i.e.
322      * ELEMENT_DECLARATION, ATTRIBUTE_DECLARATION, etc.
323      * @param namespace The namespace to which declaration belong or
324      * <code>null</code> (for components with no targetNamespace).
325      * @return A list of top-level definition of the specified type in
326      * <code>objectType</code> and defined in the specified
327      * <code>namespace</code> or <code>null</code>.
328      */

329     public synchronized XSNamedMap getComponentsByNamespace(short objectType,
330                                                             String JavaDoc namespace) {
331         if (objectType <= 0 || objectType > MAX_COMP_IDX ||
332             !GLOBAL_COMP[objectType]) {
333             return null;
334         }
335         
336         // try to find the grammar
337
int i = 0;
338         for (; i < fGrammarCount; i++) {
339             if (fNamespaces[i] == namespace)
340                 break;
341         }
342         if (i == fGrammarCount)
343             return null;
344         
345         // get the hashtable for this type of components
346
if (fNSComponents[i][objectType] == null) {
347             SymbolHash table = null;
348             switch (objectType) {
349             case XSConstants.TYPE_DEFINITION:
350             case XSTypeDefinition.COMPLEX_TYPE:
351             case XSTypeDefinition.SIMPLE_TYPE:
352                 table = fGrammarList[i].fGlobalTypeDecls;
353                 break;
354             case XSConstants.ATTRIBUTE_DECLARATION:
355                 table = fGrammarList[i].fGlobalAttrDecls;
356                 break;
357             case XSConstants.ELEMENT_DECLARATION:
358                 table = fGrammarList[i].fGlobalElemDecls;
359                 break;
360             case XSConstants.ATTRIBUTE_GROUP:
361                 table = fGrammarList[i].fGlobalAttrGrpDecls;
362                 break;
363             case XSConstants.MODEL_GROUP_DEFINITION:
364                 table = fGrammarList[i].fGlobalGroupDecls;
365                 break;
366             case XSConstants.NOTATION_DECLARATION:
367                 table = fGrammarList[i].fGlobalNotationDecls;
368                 break;
369             }
370             
371             // for complex/simple types, create a special implementation,
372
// which take specific types out of the hash table
373
if (objectType == XSTypeDefinition.COMPLEX_TYPE ||
374                 objectType == XSTypeDefinition.SIMPLE_TYPE) {
375                 fNSComponents[i][objectType] = new XSNamedMap4Types(namespace, table, objectType);
376             }
377             else {
378                 fNSComponents[i][objectType] = new XSNamedMapImpl(namespace, table);
379             }
380         }
381         
382         return fNSComponents[i][objectType];
383     }
384
385     /**
386      * Convenience method. Returns a top-level simple or complex type
387      * definition.
388      * @param name The name of the definition.
389      * @param namespace The namespace of the definition, otherwise null.
390      * @return An <code>XSTypeDefinition</code> or null if such definition
391      * does not exist.
392      */

393     public XSTypeDefinition getTypeDefinition(String JavaDoc name,
394                                               String JavaDoc namespace) {
395         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
396         if (sg == null)
397             return null;
398         return (XSTypeDefinition)sg.fGlobalTypeDecls.get(name);
399     }
400
401     /**
402      * Convenience method. Returns a top-level attribute declaration.
403      * @param name The name of the declaration.
404      * @param namespace The namespace of the definition, otherwise null.
405      * @return A top-level attribute declaration or null if such declaration
406      * does not exist.
407      */

408     public XSAttributeDeclaration getAttributeDeclaration(String JavaDoc name,
409                                                    String JavaDoc namespace) {
410         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
411         if (sg == null)
412             return null;
413         return (XSAttributeDeclaration)sg.fGlobalAttrDecls.get(name);
414     }
415
416     /**
417      * Convenience method. Returns a top-level element declaration.
418      * @param name The name of the declaration.
419      * @param namespace The namespace of the definition, otherwise null.
420      * @return A top-level element declaration or null if such declaration
421      * does not exist.
422      */

423     public XSElementDeclaration getElementDeclaration(String JavaDoc name,
424                                                String JavaDoc namespace) {
425         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
426         if (sg == null)
427             return null;
428         return (XSElementDeclaration)sg.fGlobalElemDecls.get(name);
429     }
430
431     /**
432      * Convenience method. Returns a top-level attribute group definition.
433      * @param name The name of the definition.
434      * @param namespace The namespace of the definition, otherwise null.
435      * @return A top-level attribute group definition or null if such
436      * definition does not exist.
437      */

438     public XSAttributeGroupDefinition getAttributeGroup(String JavaDoc name,
439                                                         String JavaDoc namespace) {
440         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
441         if (sg == null)
442             return null;
443         return (XSAttributeGroupDefinition)sg.fGlobalAttrGrpDecls.get(name);
444     }
445
446     /**
447      * Convenience method. Returns a top-level model group definition.
448      *
449      * @param name The name of the definition.
450      * @param namespace The namespace of the definition, otherwise null.
451      * @return A top-level model group definition definition or null if such
452      * definition does not exist.
453      */

454     public XSModelGroupDefinition getModelGroupDefinition(String JavaDoc name,
455                                                           String JavaDoc namespace) {
456         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
457         if (sg == null)
458             return null;
459         return (XSModelGroupDefinition)sg.fGlobalGroupDecls.get(name);
460     }
461
462
463     /**
464      * @see com.sun.org.apache.xerces.internal.xs.XSModel#getNotationDeclaration(String, String)
465      */

466     public XSNotationDeclaration getNotationDeclaration(String JavaDoc name,
467                                                  String JavaDoc namespace) {
468         SchemaGrammar sg = (SchemaGrammar)fGrammarMap.get(null2EmptyString(namespace));
469         if (sg == null)
470             return null;
471         return (XSNotationDeclaration)sg.fGlobalNotationDecls.get(name);
472     }
473
474     /**
475      * {annotations} A set of annotations.
476      */

477     public synchronized XSObjectList getAnnotations() {
478         if(fAnnotations != null)
479             return fAnnotations;
480
481         // do this in two passes to avoid inaccurate array size
482
int totalAnnotations = 0;
483         for (int i = 0; i < fGrammarCount; i++) {
484             totalAnnotations += fGrammarList[i].fNumAnnotations;
485         }
486         XSAnnotationImpl [] annotations = new XSAnnotationImpl [totalAnnotations];
487         int currPos = 0;
488         for (int i = 0; i < fGrammarCount; i++) {
489             SchemaGrammar currGrammar = fGrammarList[i];
490             System.arraycopy(currGrammar.fAnnotations, 0, annotations, currPos, currGrammar.fNumAnnotations);
491             currPos += currGrammar.fNumAnnotations;
492         }
493         fAnnotations = new XSObjectListImpl(annotations, annotations.length);
494         return fAnnotations;
495     }
496
497     private static final String JavaDoc null2EmptyString(String JavaDoc str) {
498         return str == null ? XMLSymbols.EMPTY_STRING : str;
499     }
500     
501     /**
502      * REVISIT: to expose identity constraints from XSModel.
503      * For now, we only expose whether there are any IDCs.
504      * We also need to add these methods to the public
505      * XSModel interface.
506      */

507     public boolean hasIDConstraints() {
508         return fHasIDC;
509     }
510
511     /**
512      * REVISIT: to expose substitution group of a given element.
513      * We need to add this to the XSModel interface.
514      */

515     public XSObjectList getSubstitutionGroup(XSElementDeclaration head) {
516         return (XSObjectList)fSubGroupMap.get(head);
517     }
518
519 } // class XSModelImpl
520
Popular Tags