|
1 /* |
|
2 * reserved comment block |
|
3 * DO NOT REMOVE OR ALTER! |
|
4 */ |
|
5 /* |
|
6 * Copyright 1999-2005 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.io.IOException; |
|
24 import java.io.StringReader; |
|
25 import java.util.ArrayList; |
|
26 import java.util.Enumeration; |
|
27 import java.util.Hashtable; |
|
28 import java.util.HashMap; |
|
29 import java.util.Locale; |
|
30 import java.util.Map; |
|
31 import java.util.Stack; |
|
32 import java.util.Vector; |
|
33 |
|
34 import javax.xml.stream.XMLEventReader; |
|
35 import javax.xml.stream.XMLStreamException; |
|
36 import javax.xml.stream.XMLStreamReader; |
|
37 |
|
38 import com.sun.org.apache.xerces.internal.impl.Constants; |
|
39 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; |
|
40 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; |
|
41 import com.sun.org.apache.xerces.internal.impl.dv.SchemaDVFactory; |
|
42 import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl; |
|
43 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar; |
|
44 import com.sun.org.apache.xerces.internal.impl.xs.SchemaNamespaceSupport; |
|
45 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols; |
|
46 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaException; |
|
47 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader; |
|
48 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeDecl; |
|
49 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeGroupDecl; |
|
50 import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl; |
|
51 import com.sun.org.apache.xerces.internal.impl.xs.XSDDescription; |
|
52 import com.sun.org.apache.xerces.internal.impl.xs.XSDeclarationPool; |
|
53 import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl; |
|
54 import com.sun.org.apache.xerces.internal.impl.xs.XSGrammarBucket; |
|
55 import com.sun.org.apache.xerces.internal.impl.xs.XSGroupDecl; |
|
56 import com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter; |
|
57 import com.sun.org.apache.xerces.internal.impl.xs.XSModelGroupImpl; |
|
58 import com.sun.org.apache.xerces.internal.impl.xs.XSNotationDecl; |
|
59 import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl; |
|
60 import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint; |
|
61 import com.sun.org.apache.xerces.internal.impl.xs.opti.ElementImpl; |
|
62 import com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOMParser; |
|
63 import com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaParsingConfig; |
|
64 import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator; |
|
65 import com.sun.org.apache.xerces.internal.impl.xs.util.XSInputSource; |
|
66 import com.sun.org.apache.xerces.internal.parsers.SAXParser; |
|
67 import com.sun.org.apache.xerces.internal.parsers.XML11Configuration; |
|
68 import com.sun.org.apache.xerces.internal.util.DOMInputSource; |
|
69 import com.sun.org.apache.xerces.internal.util.DOMUtil; |
|
70 import com.sun.org.apache.xerces.internal.util.DefaultErrorHandler; |
|
71 import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper; |
|
72 import com.sun.org.apache.xerces.internal.util.SAXInputSource; |
|
73 import com.sun.org.apache.xerces.internal.util.SecurityManager; |
|
74 import com.sun.org.apache.xerces.internal.util.StAXInputSource; |
|
75 import com.sun.org.apache.xerces.internal.util.StAXLocationWrapper; |
|
76 import com.sun.org.apache.xerces.internal.util.SymbolHash; |
|
77 import com.sun.org.apache.xerces.internal.util.SymbolTable; |
|
78 import com.sun.org.apache.xerces.internal.util.XMLSymbols; |
|
79 import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException; |
|
80 import com.sun.org.apache.xerces.internal.xni.QName; |
|
81 import com.sun.org.apache.xerces.internal.xni.XNIException; |
|
82 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; |
|
83 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; |
|
84 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; |
|
85 import com.sun.org.apache.xerces.internal.xni.grammars.XMLSchemaDescription; |
|
86 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; |
|
87 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; |
|
88 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver; |
|
89 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; |
|
90 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; |
|
91 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException; |
|
92 import com.sun.org.apache.xerces.internal.xs.StringList; |
|
93 import com.sun.org.apache.xerces.internal.xs.XSAttributeDeclaration; |
|
94 import com.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition; |
|
95 import com.sun.org.apache.xerces.internal.xs.XSAttributeUse; |
|
96 import com.sun.org.apache.xerces.internal.xs.XSConstants; |
|
97 import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration; |
|
98 import com.sun.org.apache.xerces.internal.xs.XSModelGroup; |
|
99 import com.sun.org.apache.xerces.internal.xs.XSModelGroupDefinition; |
|
100 import com.sun.org.apache.xerces.internal.xs.XSNamedMap; |
|
101 import com.sun.org.apache.xerces.internal.xs.XSObject; |
|
102 import com.sun.org.apache.xerces.internal.xs.XSObjectList; |
|
103 import com.sun.org.apache.xerces.internal.xs.XSParticle; |
|
104 import com.sun.org.apache.xerces.internal.xs.XSSimpleTypeDefinition; |
|
105 import com.sun.org.apache.xerces.internal.xs.XSTerm; |
|
106 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; |
|
107 import com.sun.org.apache.xerces.internal.xs.datatypes.ObjectList; |
|
108 import org.w3c.dom.Document; |
|
109 import org.w3c.dom.Element; |
|
110 import org.w3c.dom.Node; |
|
111 import org.xml.sax.InputSource; |
|
112 import org.xml.sax.SAXException; |
|
113 import org.xml.sax.SAXParseException; |
|
114 import org.xml.sax.XMLReader; |
|
115 import org.xml.sax.helpers.XMLReaderFactory; |
|
116 |
|
117 /** |
|
118 * The purpose of this class is to co-ordinate the construction of a |
|
119 * grammar object corresponding to a schema. To do this, it must be |
|
120 * prepared to parse several schema documents (for instance if the |
|
121 * schema document originally referred to contains <include> or |
|
122 * <redefined> information items). If any of the schemas imports a |
|
123 * schema, other grammars may be constructed as a side-effect. |
|
124 * |
|
125 * @xerces.internal |
|
126 * |
|
127 * @author Neil Graham, IBM |
|
128 * @author Pavani Mukthipudi, Sun Microsystems |
|
129 * |
|
130 * @version $Id: XSDHandler.java,v 1.9 2010-11-01 04:40:02 joehw Exp $ |
|
131 */ |
|
132 public class XSDHandler { |
|
133 |
|
134 /** Feature identifier: validation. */ |
|
135 protected static final String VALIDATION = |
|
136 Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; |
|
137 |
|
138 /** feature identifier: XML Schema validation */ |
|
139 protected static final String XMLSCHEMA_VALIDATION = |
|
140 Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE; |
|
141 |
|
142 /** Feature identifier: allow java encodings */ |
|
143 protected static final String ALLOW_JAVA_ENCODINGS = |
|
144 Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE; |
|
145 |
|
146 /** Feature identifier: continue after fatal error */ |
|
147 protected static final String CONTINUE_AFTER_FATAL_ERROR = |
|
148 Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE; |
|
149 |
|
150 /** Feature identifier: allow java encodings */ |
|
151 protected static final String STANDARD_URI_CONFORMANT_FEATURE = |
|
152 Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE; |
|
153 |
|
154 /** Feature: disallow doctype*/ |
|
155 protected static final String DISALLOW_DOCTYPE = |
|
156 Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE; |
|
157 |
|
158 /** Feature: generate synthetic annotations */ |
|
159 protected static final String GENERATE_SYNTHETIC_ANNOTATIONS = |
|
160 Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE; |
|
161 |
|
162 /** Feature identifier: validate annotations. */ |
|
163 protected static final String VALIDATE_ANNOTATIONS = |
|
164 Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE; |
|
165 |
|
166 /** Feature identifier: honour all schemaLocations */ |
|
167 protected static final String HONOUR_ALL_SCHEMALOCATIONS = |
|
168 Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE; |
|
169 |
|
170 /** Feature identifier: namespace growth */ |
|
171 protected static final String NAMESPACE_GROWTH = |
|
172 Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE; |
|
173 |
|
174 /** Feature identifier: tolerate duplicates */ |
|
175 protected static final String TOLERATE_DUPLICATES = |
|
176 Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE; |
|
177 |
|
178 /** Feature identifier: namespace prefixes. */ |
|
179 private static final String NAMESPACE_PREFIXES = |
|
180 Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE; |
|
181 |
|
182 /** Feature identifier: string interning. */ |
|
183 protected static final String STRING_INTERNING = |
|
184 Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE; |
|
185 |
|
186 /** Property identifier: error handler. */ |
|
187 protected static final String ERROR_HANDLER = |
|
188 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY; |
|
189 |
|
190 /** Property identifier: JAXP schema source. */ |
|
191 protected static final String JAXP_SCHEMA_SOURCE = |
|
192 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE; |
|
193 |
|
194 /** Property identifier: entity resolver. */ |
|
195 public static final String ENTITY_RESOLVER = |
|
196 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; |
|
197 /** Property identifier: entity manager. */ |
|
198 protected static final String ENTITY_MANAGER = |
|
199 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; |
|
200 |
|
201 /** Property identifier: error reporter. */ |
|
202 public static final String ERROR_REPORTER = |
|
203 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; |
|
204 |
|
205 /** Property identifier: grammar pool. */ |
|
206 public static final String XMLGRAMMAR_POOL = |
|
207 Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; |
|
208 |
|
209 /** Property identifier: symbol table. */ |
|
210 public static final String SYMBOL_TABLE = |
|
211 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; |
|
212 |
|
213 /** Property identifier: security manager. */ |
|
214 protected static final String SECURITY_MANAGER = |
|
215 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; |
|
216 |
|
217 private static final String SECURE_PROCESSING = |
|
218 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; |
|
219 |
|
220 /** Property identifier: locale. */ |
|
221 protected static final String LOCALE = |
|
222 Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY; |
|
223 |
|
224 protected static final boolean DEBUG_NODE_POOL = false; |
|
225 |
|
226 // Data |
|
227 |
|
228 // different sorts of declarations; should make lookup and |
|
229 // traverser calling more efficient/less bulky. |
|
230 final static int ATTRIBUTE_TYPE = 1; |
|
231 final static int ATTRIBUTEGROUP_TYPE = 2; |
|
232 final static int ELEMENT_TYPE = 3; |
|
233 final static int GROUP_TYPE = 4; |
|
234 final static int IDENTITYCONSTRAINT_TYPE = 5; |
|
235 final static int NOTATION_TYPE = 6; |
|
236 final static int TYPEDECL_TYPE = 7; |
|
237 |
|
238 // this string gets appended to redefined names; it's purpose is to be |
|
239 // as unlikely as possible to cause collisions. |
|
240 public final static String REDEF_IDENTIFIER = "_fn3dktizrknc9pi"; |
|
241 |
|
242 // |
|
243 //protected data that can be accessable by any traverser |
|
244 |
|
245 protected XSDeclarationPool fDeclPool = null; |
|
246 |
|
247 /** |
|
248 * <p>Security manager in effect.</p> |
|
249 * |
|
250 * <p>Protected to allow access by any traverser.</p> |
|
251 */ |
|
252 protected SecurityManager fSecureProcessing = null; |
|
253 |
|
254 // These tables correspond to the symbol spaces defined in the |
|
255 // spec. |
|
256 // They are keyed with a QName (that is, String("URI,localpart) and |
|
257 // their values are nodes corresponding to the given name's decl. |
|
258 // By asking the node for its ownerDocument and looking in |
|
259 // XSDocumentInfoRegistry we can easily get the corresponding |
|
260 // XSDocumentInfo object. |
|
261 private boolean registryEmpty = true; |
|
262 private Map<String, Element> fUnparsedAttributeRegistry = new HashMap(); |
|
263 private Map<String, Element> fUnparsedAttributeGroupRegistry = new HashMap(); |
|
264 private Map<String, Element> fUnparsedElementRegistry = new HashMap(); |
|
265 private Map<String, Element> fUnparsedGroupRegistry = new HashMap(); |
|
266 private Map<String, Element> fUnparsedIdentityConstraintRegistry = new HashMap(); |
|
267 private Map<String, Element> fUnparsedNotationRegistry = new HashMap(); |
|
268 private Map<String, Element> fUnparsedTypeRegistry = new HashMap(); |
|
269 // Compensation for the above hashtables to locate XSDocumentInfo, |
|
270 // Since we may take Schema Element directly, so can not get the |
|
271 // corresponding XSDocumentInfo object just using above hashtables. |
|
272 private Map<String, XSDocumentInfo> fUnparsedAttributeRegistrySub = new HashMap(); |
|
273 private Map<String, XSDocumentInfo> fUnparsedAttributeGroupRegistrySub = new HashMap(); |
|
274 private Map<String, XSDocumentInfo> fUnparsedElementRegistrySub = new HashMap(); |
|
275 private Map<String, XSDocumentInfo> fUnparsedGroupRegistrySub = new HashMap(); |
|
276 private Map<String, XSDocumentInfo> fUnparsedIdentityConstraintRegistrySub = new HashMap(); |
|
277 private Map<String, XSDocumentInfo> fUnparsedNotationRegistrySub = new HashMap(); |
|
278 private Map<String, XSDocumentInfo> fUnparsedTypeRegistrySub = new HashMap(); |
|
279 |
|
280 // Stores XSDocumentInfo (keyed by component name), to check for duplicate |
|
281 // components declared within the same xsd document |
|
282 private Map fUnparsedRegistriesExt[] = new HashMap[] { |
|
283 null, |
|
284 null, // ATTRIBUTE_TYPE |
|
285 null, // ATTRIBUTEGROUP_TYPE |
|
286 null, // ELEMENT_TYPE |
|
287 null, // GROUP_TYPE |
|
288 null, // IDENTITYCONSTRAINT_TYPE |
|
289 null, // NOTATION_TYPE |
|
290 null, // TYPEDECL_TYPE |
|
291 }; |
|
292 |
|
293 // this hashtable is keyed on by XSDocumentInfo objects. Its values |
|
294 // are Vectors containing the XSDocumentInfo objects <include>d, |
|
295 // <import>ed or <redefine>d by the key XSDocumentInfo. |
|
296 private Map<XSDocumentInfo, Vector> fDependencyMap = new HashMap(); |
|
297 |
|
298 // this hashtable is keyed on by a target namespace. Its values |
|
299 // are Vectors containing namespaces imported by schema documents |
|
300 // with the key target namespace. |
|
301 // if an imprted schema has absent namespace, the value "null" is stored. |
|
302 private Map<String, Vector> fImportMap = new HashMap(); |
|
303 // all namespaces that imports other namespaces |
|
304 // if the importing schema has absent namespace, empty string is stored. |
|
305 // (because the key of a hashtable can't be null.) |
|
306 private Vector fAllTNSs = new Vector(); |
|
307 // stores instance document mappings between namespaces and schema hints |
|
308 private Map fLocationPairs = null; |
|
309 private static final Map EMPTY_TABLE = new HashMap(); |
|
310 |
|
311 // Records which nodes are hidden when the input is a DOMInputSource. |
|
312 Hashtable fHiddenNodes = null; |
|
313 |
|
314 // convenience methods |
|
315 private String null2EmptyString(String ns) { |
|
316 return ns == null ? XMLSymbols.EMPTY_STRING : ns; |
|
317 } |
|
318 private String emptyString2Null(String ns) { |
|
319 return ns == XMLSymbols.EMPTY_STRING ? null : ns; |
|
320 } |
|
321 // use Schema Element to lookup the SystemId. |
|
322 private String doc2SystemId(Element ele) { |
|
323 String documentURI = null; |
|
324 /** |
|
325 * REVISIT: Casting until DOM Level 3 interfaces are available. -- mrglavas |
|
326 */ |
|
327 if(ele.getOwnerDocument() instanceof com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM){ |
|
328 documentURI = ((com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM) ele.getOwnerDocument()).getDocumentURI(); |
|
329 } |
|
330 return documentURI != null ? documentURI : (String) fDoc2SystemId.get(ele); |
|
331 } |
|
332 |
|
333 // This vector stores strings which are combinations of the |
|
334 // publicId and systemId of the inputSource corresponding to a |
|
335 // schema document. This combination is used so that the user's |
|
336 // EntityResolver can provide a consistent way of identifying a |
|
337 // schema document that is included in multiple other schemas. |
|
338 private Map fTraversed = new HashMap(); |
|
339 |
|
340 // this hashtable contains a mapping from Schema Element to its systemId |
|
341 // this is useful to resolve a uri relative to the referring document |
|
342 private Map fDoc2SystemId = new HashMap(); |
|
343 |
|
344 // the primary XSDocumentInfo we were called to parse |
|
345 private XSDocumentInfo fRoot = null; |
|
346 |
|
347 // This hashtable's job is to act as a link between the Schema Element and its |
|
348 // XSDocumentInfo object. |
|
349 private Map fDoc2XSDocumentMap = new HashMap(); |
|
350 |
|
351 // map between <redefine> elements and the XSDocumentInfo |
|
352 // objects that correspond to the documents being redefined. |
|
353 private Map fRedefine2XSDMap = null; |
|
354 |
|
355 // map between <redefine> elements and the namespace support |
|
356 private Map fRedefine2NSSupport = null; |
|
357 |
|
358 // these objects store a mapping between the names of redefining |
|
359 // groups/attributeGroups and the groups/AttributeGroups which |
|
360 // they redefine by restriction (implicitly). It is up to the |
|
361 // Group and AttributeGroup traversers to check these restrictions for |
|
362 // validity. |
|
363 private Map fRedefinedRestrictedAttributeGroupRegistry = new HashMap(); |
|
364 private Map fRedefinedRestrictedGroupRegistry = new HashMap(); |
|
365 |
|
366 // a variable storing whether the last schema document |
|
367 // processed (by getSchema) was a duplicate. |
|
368 private boolean fLastSchemaWasDuplicate; |
|
369 |
|
370 // validate annotations feature |
|
371 private boolean fValidateAnnotations = false; |
|
372 |
|
373 //handle multiple import feature |
|
374 private boolean fHonourAllSchemaLocations = false; |
|
375 |
|
376 //handle namespace growth feature |
|
377 boolean fNamespaceGrowth = false; |
|
378 |
|
379 // handle tolerate duplicates feature |
|
380 boolean fTolerateDuplicates = false; |
|
381 |
|
382 // the XMLErrorReporter |
|
383 private XMLErrorReporter fErrorReporter; |
|
384 private XMLEntityResolver fEntityResolver; |
|
385 |
|
386 // the XSAttributeChecker |
|
387 private XSAttributeChecker fAttributeChecker; |
|
388 |
|
389 // the symbol table |
|
390 private SymbolTable fSymbolTable; |
|
391 |
|
392 // the GrammarResolver |
|
393 private XSGrammarBucket fGrammarBucket; |
|
394 |
|
395 // the Grammar description |
|
396 private XSDDescription fSchemaGrammarDescription; |
|
397 |
|
398 // the Grammar Pool |
|
399 private XMLGrammarPool fGrammarPool; |
|
400 |
|
401 //************ Traversers ********** |
|
402 XSDAttributeGroupTraverser fAttributeGroupTraverser; |
|
403 XSDAttributeTraverser fAttributeTraverser; |
|
404 XSDComplexTypeTraverser fComplexTypeTraverser; |
|
405 XSDElementTraverser fElementTraverser; |
|
406 XSDGroupTraverser fGroupTraverser; |
|
407 XSDKeyrefTraverser fKeyrefTraverser; |
|
408 XSDNotationTraverser fNotationTraverser; |
|
409 XSDSimpleTypeTraverser fSimpleTypeTraverser; |
|
410 XSDUniqueOrKeyTraverser fUniqueOrKeyTraverser; |
|
411 XSDWildcardTraverser fWildCardTraverser; |
|
412 |
|
413 SchemaDVFactory fDVFactory; |
|
414 SchemaDOMParser fSchemaParser; |
|
415 SchemaContentHandler fXSContentHandler; |
|
416 StAXSchemaParser fStAXSchemaParser; |
|
417 XML11Configuration fAnnotationValidator; |
|
418 XSAnnotationGrammarPool fGrammarBucketAdapter; |
|
419 |
|
420 // these data members are needed for the deferred traversal |
|
421 // of local elements. |
|
422 |
|
423 // the initial size of the array to store deferred local elements |
|
424 private static final int INIT_STACK_SIZE = 30; |
|
425 // the incremental size of the array to store deferred local elements |
|
426 private static final int INC_STACK_SIZE = 10; |
|
427 // current position of the array (# of deferred local elements) |
|
428 private int fLocalElemStackPos = 0; |
|
429 |
|
430 private XSParticleDecl[] fParticle = new XSParticleDecl[INIT_STACK_SIZE]; |
|
431 private Element[] fLocalElementDecl = new Element[INIT_STACK_SIZE]; |
|
432 private XSDocumentInfo[] fLocalElementDecl_schema = new XSDocumentInfo[INIT_STACK_SIZE]; //JACK |
|
433 private int[] fAllContext = new int[INIT_STACK_SIZE]; |
|
434 private XSObject[] fParent = new XSObject[INIT_STACK_SIZE]; |
|
435 private String [][] fLocalElemNamespaceContext = new String [INIT_STACK_SIZE][1]; |
|
436 |
|
437 // these data members are needed for the deferred traversal |
|
438 // of keyrefs. |
|
439 |
|
440 // the initial size of the array to store deferred keyrefs |
|
441 private static final int INIT_KEYREF_STACK = 2; |
|
442 // the incremental size of the array to store deferred keyrefs |
|
443 private static final int INC_KEYREF_STACK_AMOUNT = 2; |
|
444 // current position of the array (# of deferred keyrefs) |
|
445 private int fKeyrefStackPos = 0; |
|
446 |
|
447 private Element [] fKeyrefs = new Element[INIT_KEYREF_STACK]; |
|
448 private XSDocumentInfo [] fKeyrefsMapXSDocumentInfo = new XSDocumentInfo[INIT_KEYREF_STACK]; |
|
449 private XSElementDecl [] fKeyrefElems = new XSElementDecl [INIT_KEYREF_STACK]; |
|
450 private String [][] fKeyrefNamespaceContext = new String[INIT_KEYREF_STACK][1]; |
|
451 |
|
452 // global decls: map from decl name to decl object |
|
453 SymbolHash fGlobalAttrDecls = new SymbolHash(); |
|
454 SymbolHash fGlobalAttrGrpDecls = new SymbolHash(); |
|
455 SymbolHash fGlobalElemDecls = new SymbolHash(); |
|
456 SymbolHash fGlobalGroupDecls = new SymbolHash(); |
|
457 SymbolHash fGlobalNotationDecls = new SymbolHash(); |
|
458 SymbolHash fGlobalIDConstraintDecls = new SymbolHash(); |
|
459 SymbolHash fGlobalTypeDecls = new SymbolHash(); |
|
460 |
|
461 // Constructors |
|
462 public XSDHandler(){ |
|
463 fHiddenNodes = new Hashtable(); |
|
464 fSchemaParser = new SchemaDOMParser(new SchemaParsingConfig()); |
|
465 } |
|
466 |
|
467 // it should be possible to use the same XSDHandler to parse |
|
468 // multiple schema documents; this will allow one to be |
|
469 // constructed. |
|
470 public XSDHandler (XSGrammarBucket gBucket) { |
|
471 this(); |
|
472 fGrammarBucket = gBucket; |
|
473 |
|
474 // Note: don't use SchemaConfiguration internally |
|
475 // we will get stack overflaw because |
|
476 // XMLSchemaValidator will be instantiating XSDHandler... |
|
477 fSchemaGrammarDescription = new XSDDescription(); |
|
478 } // end constructor |
|
479 |
|
480 /** |
|
481 * This method initiates the parse of a schema. It will likely be |
|
482 * called from the Validator and it will make the |
|
483 * resulting grammar available; it returns a reference to this object just |
|
484 * in case. A reset(XMLComponentManager) must be called before this methods is called. |
|
485 * @param is |
|
486 * @param desc |
|
487 * @param locationPairs |
|
488 * @return the SchemaGrammar |
|
489 * @throws IOException |
|
490 */ |
|
491 public SchemaGrammar parseSchema(XMLInputSource is, XSDDescription desc, |
|
492 Map locationPairs) |
|
493 throws IOException { |
|
494 fLocationPairs = locationPairs; |
|
495 fSchemaParser.resetNodePool(); |
|
496 SchemaGrammar grammar = null; |
|
497 String schemaNamespace = null; |
|
498 short referType = desc.getContextType(); |
|
499 |
|
500 // if loading using JAXP schemaSource property, or using grammar caching loadGrammar |
|
501 // the desc.targetNamespace is always null. |
|
502 // Therefore we should not attempt to find out if |
|
503 // the schema is already in the bucket, since in the case we have |
|
504 // no namespace schema in the bucket, findGrammar will always return the |
|
505 // no namespace schema. |
|
506 if (referType != XSDDescription.CONTEXT_PREPARSE){ |
|
507 // first try to find it in the bucket/pool, return if one is found |
|
508 if (fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT && isExistingGrammar(desc, fNamespaceGrowth)) { |
|
509 grammar = fGrammarBucket.getGrammar(desc.getTargetNamespace()); |
|
510 } |
|
511 else { |
|
512 grammar = findGrammar(desc, fNamespaceGrowth); |
|
513 } |
|
514 if (grammar != null) { |
|
515 if (!fNamespaceGrowth) { |
|
516 return grammar; |
|
517 } |
|
518 else { |
|
519 try { |
|
520 if (grammar.getDocumentLocations().contains(XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false))) { |
|
521 return grammar; |
|
522 } |
|
523 } |
|
524 catch (MalformedURIException e) { |
|
525 //REVISIT: return the grammar? |
|
526 } |
|
527 } |
|
528 } |
|
529 |
|
530 schemaNamespace = desc.getTargetNamespace(); |
|
531 // handle empty string URI as null |
|
532 if (schemaNamespace != null) { |
|
533 schemaNamespace = fSymbolTable.addSymbol(schemaNamespace); |
|
534 } |
|
535 } |
|
536 |
|
537 // before parsing a schema, need to clear registries associated with |
|
538 // parsing schemas |
|
539 prepareForParse(); |
|
540 |
|
541 Element schemaRoot = null; |
|
542 // first phase: construct trees. |
|
543 if (is instanceof DOMInputSource) { |
|
544 schemaRoot = getSchemaDocument(schemaNamespace, (DOMInputSource) is, |
|
545 referType == XSDDescription.CONTEXT_PREPARSE, |
|
546 referType, null); |
|
547 } // DOMInputSource |
|
548 else if (is instanceof SAXInputSource) { |
|
549 schemaRoot = getSchemaDocument(schemaNamespace, (SAXInputSource) is, |
|
550 referType == XSDDescription.CONTEXT_PREPARSE, |
|
551 referType, null); |
|
552 } // SAXInputSource |
|
553 else if (is instanceof StAXInputSource) { |
|
554 schemaRoot = getSchemaDocument(schemaNamespace, (StAXInputSource) is, |
|
555 referType == XSDDescription.CONTEXT_PREPARSE, |
|
556 referType, null); |
|
557 } // StAXInputSource |
|
558 else if (is instanceof XSInputSource) { |
|
559 schemaRoot = getSchemaDocument((XSInputSource) is, desc); |
|
560 } // XSInputSource |
|
561 else { |
|
562 schemaRoot = getSchemaDocument(schemaNamespace, is, |
|
563 referType == XSDDescription.CONTEXT_PREPARSE, |
|
564 referType, null); |
|
565 |
|
566 } //is instanceof XMLInputSource |
|
567 |
|
568 if (schemaRoot == null) { |
|
569 // something went wrong right off the hop |
|
570 if (is instanceof XSInputSource) { |
|
571 return fGrammarBucket.getGrammar(desc.getTargetNamespace()); |
|
572 } |
|
573 return grammar; |
|
574 } |
|
575 |
|
576 if (referType == XSDDescription.CONTEXT_PREPARSE) { |
|
577 Element schemaElem = schemaRoot; |
|
578 schemaNamespace = DOMUtil.getAttrValue(schemaElem, SchemaSymbols.ATT_TARGETNAMESPACE); |
|
579 if(schemaNamespace != null && schemaNamespace.length() > 0) { |
|
580 // Since now we've discovered a namespace, we need to update xsd key |
|
581 // and store this schema in traversed schemas bucket |
|
582 schemaNamespace = fSymbolTable.addSymbol(schemaNamespace); |
|
583 desc.setTargetNamespace(schemaNamespace); |
|
584 } |
|
585 else { |
|
586 schemaNamespace = null; |
|
587 } |
|
588 grammar = findGrammar(desc, fNamespaceGrowth); |
|
589 String schemaId = XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false); |
|
590 if (grammar != null) { |
|
591 // When namespace growth is enabled and a null location is provided we cannot tell |
|
592 // whether we've loaded this schema document before so we must assume that we haven't. |
|
593 if (!fNamespaceGrowth || (schemaId != null && grammar.getDocumentLocations().contains(schemaId))) { |
|
594 return grammar; |
|
595 } |
|
596 } |
|
597 |
|
598 XSDKey key = new XSDKey(schemaId, referType, schemaNamespace); |
|
599 fTraversed.put(key, schemaRoot); |
|
600 if (schemaId != null) { |
|
601 fDoc2SystemId.put(schemaRoot, schemaId); |
|
602 } |
|
603 } |
|
604 |
|
605 // before constructing trees and traversing a schema, need to reset |
|
606 // all traversers and clear all registries |
|
607 prepareForTraverse(); |
|
608 |
|
609 fRoot = constructTrees(schemaRoot, is.getSystemId(), desc, grammar != null); |
|
610 if (fRoot == null) { |
|
611 return null; |
|
612 } |
|
613 |
|
614 // second phase: fill global registries. |
|
615 buildGlobalNameRegistries(); |
|
616 |
|
617 // third phase: call traversers |
|
618 ArrayList annotationInfo = fValidateAnnotations ? new ArrayList() : null; |
|
619 traverseSchemas(annotationInfo); |
|
620 |
|
621 // fourth phase: handle local element decls |
|
622 traverseLocalElements(); |
|
623 |
|
624 // fifth phase: handle Keyrefs |
|
625 resolveKeyRefs(); |
|
626 |
|
627 // sixth phase: validate attribute of non-schema namespaces |
|
628 // REVISIT: skip this for now. we really don't want to do it. |
|
629 //fAttributeChecker.checkNonSchemaAttributes(fGrammarBucket); |
|
630 |
|
631 // seventh phase: store imported grammars |
|
632 // for all grammars with <import>s |
|
633 for (int i = fAllTNSs.size() - 1; i >= 0; i--) { |
|
634 // get its target namespace |
|
635 String tns = (String)fAllTNSs.elementAt(i); |
|
636 // get all namespaces it imports |
|
637 Vector ins = (Vector)fImportMap.get(tns); |
|
638 // get the grammar |
|
639 SchemaGrammar sg = fGrammarBucket.getGrammar(emptyString2Null(tns)); |
|
640 if (sg == null) |
|
641 continue; |
|
642 SchemaGrammar isg; |
|
643 // for imported namespace |
|
644 int count = 0; |
|
645 for (int j = 0; j < ins.size(); j++) { |
|
646 // get imported grammar |
|
647 isg = fGrammarBucket.getGrammar((String)ins.elementAt(j)); |
|
648 // reuse the same vector |
|
649 if (isg != null) |
|
650 ins.setElementAt(isg, count++); |
|
651 } |
|
652 ins.setSize(count); |
|
653 // set the imported grammars |
|
654 sg.setImportedGrammars(ins); |
|
655 } |
|
656 |
|
657 /** validate annotations **/ |
|
658 if (fValidateAnnotations && annotationInfo.size() > 0) { |
|
659 validateAnnotations(annotationInfo); |
|
660 } |
|
661 |
|
662 // and return. |
|
663 return fGrammarBucket.getGrammar(fRoot.fTargetNamespace); |
|
664 } // end parseSchema |
|
665 |
|
666 private void validateAnnotations(ArrayList annotationInfo) { |
|
667 if (fAnnotationValidator == null) { |
|
668 createAnnotationValidator(); |
|
669 } |
|
670 final int size = annotationInfo.size(); |
|
671 final XMLInputSource src = new XMLInputSource(null, null, null); |
|
672 fGrammarBucketAdapter.refreshGrammars(fGrammarBucket); |
|
673 for (int i = 0; i < size; i += 2) { |
|
674 src.setSystemId((String) annotationInfo.get(i)); |
|
675 XSAnnotationInfo annotation = (XSAnnotationInfo) annotationInfo.get(i+1); |
|
676 while (annotation != null) { |
|
677 src.setCharacterStream(new StringReader(annotation.fAnnotation)); |
|
678 try { |
|
679 fAnnotationValidator.parse(src); |
|
680 } |
|
681 catch (IOException exc) {} |
|
682 annotation = annotation.next; |
|
683 } |
|
684 } |
|
685 } |
|
686 |
|
687 private void createAnnotationValidator() { |
|
688 fAnnotationValidator = new XML11Configuration(); |
|
689 fGrammarBucketAdapter = new XSAnnotationGrammarPool(); |
|
690 fAnnotationValidator.setFeature(VALIDATION, true); |
|
691 fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true); |
|
692 fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter); |
|
693 /** Set error handler. **/ |
|
694 XMLErrorHandler errorHandler = fErrorReporter.getErrorHandler(); |
|
695 fAnnotationValidator.setProperty(ERROR_HANDLER, (errorHandler != null) ? errorHandler : new DefaultErrorHandler()); |
|
696 /** Set locale. **/ |
|
697 Locale locale = fErrorReporter.getLocale(); |
|
698 fAnnotationValidator.setProperty(LOCALE, locale); |
|
699 } |
|
700 |
|
701 /** |
|
702 * Pull the grammar out of the bucket simply using |
|
703 * its TNS as a key |
|
704 */ |
|
705 SchemaGrammar getGrammar(String tns) { |
|
706 return fGrammarBucket.getGrammar(tns); |
|
707 } |
|
708 |
|
709 /** |
|
710 * First try to find a grammar in the bucket, if failed, consult the |
|
711 * grammar pool. If a grammar is found in the pool, then add it (and all |
|
712 * imported ones) into the bucket. |
|
713 */ |
|
714 protected SchemaGrammar findGrammar(XSDDescription desc, boolean ignoreConflict) { |
|
715 SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace()); |
|
716 if (sg == null) { |
|
717 if (fGrammarPool != null) { |
|
718 sg = (SchemaGrammar)fGrammarPool.retrieveGrammar(desc); |
|
719 if (sg != null) { |
|
720 // put this grammar into the bucket, along with grammars |
|
721 // imported by it (directly or indirectly) |
|
722 if (!fGrammarBucket.putGrammar(sg, true, ignoreConflict)) { |
|
723 // REVISIT: a conflict between new grammar(s) and grammars |
|
724 // in the bucket. What to do? A warning? An exception? |
|
725 reportSchemaWarning("GrammarConflict", null, null); |
|
726 sg = null; |
|
727 } |
|
728 } |
|
729 } |
|
730 } |
|
731 return sg; |
|
732 } |
|
733 |
|
734 // may wish to have setter methods for ErrorHandler, |
|
735 // EntityResolver... |
|
736 |
|
737 private static final String[][] NS_ERROR_CODES = { |
|
738 {"src-include.2.1", "src-include.2.1"}, |
|
739 {"src-redefine.3.1", "src-redefine.3.1"}, |
|
740 {"src-import.3.1", "src-import.3.2"}, |
|
741 null, |
|
742 {"TargetNamespace.1", "TargetNamespace.2"}, |
|
743 {"TargetNamespace.1", "TargetNamespace.2"}, |
|
744 {"TargetNamespace.1", "TargetNamespace.2"}, |
|
745 {"TargetNamespace.1", "TargetNamespace.2"} |
|
746 }; |
|
747 |
|
748 private static final String[] ELE_ERROR_CODES = { |
|
749 "src-include.1", "src-redefine.2", "src-import.2", "schema_reference.4", |
|
750 "schema_reference.4", "schema_reference.4", "schema_reference.4", "schema_reference.4" |
|
751 }; |
|
752 |
|
753 // This method does several things: |
|
754 // It constructs an instance of an XSDocumentInfo object using the |
|
755 // schemaRoot node. Then, for each <include>, |
|
756 // <redefine>, and <import> children, it attempts to resolve the |
|
757 // requested schema document, initiates a DOM parse, and calls |
|
758 // itself recursively on that document's root. It also records in |
|
759 // the DependencyMap object what XSDocumentInfo objects its XSDocumentInfo |
|
760 // depends on. |
|
761 // It also makes sure the targetNamespace of the schema it was |
|
762 // called to parse is correct. |
|
763 protected XSDocumentInfo constructTrees(Element schemaRoot, String locationHint, XSDDescription desc, boolean nsCollision) { |
|
764 if (schemaRoot == null) return null; |
|
765 String callerTNS = desc.getTargetNamespace(); |
|
766 short referType = desc.getContextType(); |
|
767 |
|
768 XSDocumentInfo currSchemaInfo = null; |
|
769 try { |
|
770 // note that attributes are freed at end of traverseSchemas() |
|
771 currSchemaInfo = new XSDocumentInfo(schemaRoot, fAttributeChecker, fSymbolTable); |
|
772 } catch (XMLSchemaException se) { |
|
773 reportSchemaError(ELE_ERROR_CODES[referType], |
|
774 new Object[]{locationHint}, |
|
775 schemaRoot); |
|
776 return null; |
|
777 } |
|
778 // targetNamespace="" is not valid, issue a warning, and ignore it |
|
779 if (currSchemaInfo.fTargetNamespace != null && |
|
780 currSchemaInfo.fTargetNamespace.length() == 0) { |
|
781 reportSchemaWarning("EmptyTargetNamespace", |
|
782 new Object[]{locationHint}, |
|
783 schemaRoot); |
|
784 currSchemaInfo.fTargetNamespace = null; |
|
785 } |
|
786 |
|
787 if (callerTNS != null) { |
|
788 // the second index to the NS_ERROR_CODES array |
|
789 // if the caller/expected NS is not absent, we use the first column |
|
790 int secondIdx = 0; |
|
791 // for include and redefine |
|
792 if (referType == XSDDescription.CONTEXT_INCLUDE || |
|
793 referType == XSDDescription.CONTEXT_REDEFINE) { |
|
794 // if the referred document has no targetNamespace, |
|
795 // it's a chameleon schema |
|
796 if (currSchemaInfo.fTargetNamespace == null) { |
|
797 currSchemaInfo.fTargetNamespace = callerTNS; |
|
798 currSchemaInfo.fIsChameleonSchema = true; |
|
799 } |
|
800 // if the referred document has a target namespace differing |
|
801 // from the caller, it's an error |
|
802 else if (callerTNS != currSchemaInfo.fTargetNamespace) { |
|
803 reportSchemaError(NS_ERROR_CODES[referType][secondIdx], |
|
804 new Object [] {callerTNS, currSchemaInfo.fTargetNamespace}, |
|
805 schemaRoot); |
|
806 return null; |
|
807 } |
|
808 } |
|
809 // for instance and import, the two NS's must be the same |
|
810 else if (referType != XSDDescription.CONTEXT_PREPARSE && callerTNS != currSchemaInfo.fTargetNamespace) { |
|
811 reportSchemaError(NS_ERROR_CODES[referType][secondIdx], |
|
812 new Object [] {callerTNS, currSchemaInfo.fTargetNamespace}, |
|
813 schemaRoot); |
|
814 return null; |
|
815 } |
|
816 } |
|
817 // now there is no caller/expected NS, it's an error for the referred |
|
818 // document to have a target namespace, unless we are preparsing a schema |
|
819 else if (currSchemaInfo.fTargetNamespace != null) { |
|
820 // set the target namespace of the description |
|
821 if (referType == XSDDescription.CONTEXT_PREPARSE) { |
|
822 desc.setTargetNamespace(currSchemaInfo.fTargetNamespace); |
|
823 callerTNS = currSchemaInfo.fTargetNamespace; |
|
824 } |
|
825 else { |
|
826 // the second index to the NS_ERROR_CODES array |
|
827 // if the caller/expected NS is absent, we use the second column |
|
828 int secondIdx = 1; |
|
829 reportSchemaError(NS_ERROR_CODES[referType][secondIdx], |
|
830 new Object [] {callerTNS, currSchemaInfo.fTargetNamespace}, |
|
831 schemaRoot); |
|
832 return null; |
|
833 } |
|
834 } |
|
835 // the other cases (callerTNS == currSchemaInfo.fTargetNamespce == null) |
|
836 // are valid |
|
837 |
|
838 // a schema document can always access it's own target namespace |
|
839 currSchemaInfo.addAllowedNS(currSchemaInfo.fTargetNamespace); |
|
840 |
|
841 SchemaGrammar sg = null; |
|
842 |
|
843 // we have a namespace collision |
|
844 if (nsCollision) { |
|
845 SchemaGrammar sg2 = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace); |
|
846 if (sg2.isImmutable()) { |
|
847 sg = new SchemaGrammar(sg2); |
|
848 fGrammarBucket.putGrammar(sg); |
|
849 // update all the grammars in the bucket to point to the new grammar. |
|
850 updateImportListWith(sg); |
|
851 } |
|
852 else { |
|
853 sg = sg2; |
|
854 } |
|
855 |
|
856 // update import list of the new grammar |
|
857 updateImportListFor(sg); |
|
858 } |
|
859 else if (referType == XSDDescription.CONTEXT_INCLUDE || |
|
860 referType == XSDDescription.CONTEXT_REDEFINE) { |
|
861 sg = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace); |
|
862 } |
|
863 else if(fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT) { |
|
864 sg = findGrammar(desc, false); |
|
865 if(sg == null) { |
|
866 sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable); |
|
867 fGrammarBucket.putGrammar(sg); |
|
868 } |
|
869 } |
|
870 else { |
|
871 sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable); |
|
872 fGrammarBucket.putGrammar(sg); |
|
873 } |
|
874 |
|
875 // store the document and its location |
|
876 // REVISIT: don't expose the DOM tree |
|
877 sg.addDocument(null, (String)fDoc2SystemId.get(currSchemaInfo.fSchemaElement)); |
|
878 |
|
879 fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo); |
|
880 Vector dependencies = new Vector(); |
|
881 Element rootNode = schemaRoot; |
|
882 |
|
883 Element newSchemaRoot = null; |
|
884 for (Element child = DOMUtil.getFirstChildElement(rootNode); |
|
885 child != null; |
|
886 child = DOMUtil.getNextSiblingElement(child)) { |
|
887 String schemaNamespace=null; |
|
888 String schemaHint=null; |
|
889 String localName = DOMUtil.getLocalName(child); |
|
890 |
|
891 short refType = -1; |
|
892 boolean importCollision = false; |
|
893 |
|
894 if (localName.equals(SchemaSymbols.ELT_ANNOTATION)) |
|
895 continue; |
|
896 else if (localName.equals(SchemaSymbols.ELT_IMPORT)) { |
|
897 refType = XSDDescription.CONTEXT_IMPORT; |
|
898 // have to handle some validation here too! |
|
899 // call XSAttributeChecker to fill in attrs |
|
900 Object[] importAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo); |
|
901 schemaHint = (String)importAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION]; |
|
902 schemaNamespace = (String)importAttrs[XSAttributeChecker.ATTIDX_NAMESPACE]; |
|
903 if (schemaNamespace != null) |
|
904 schemaNamespace = fSymbolTable.addSymbol(schemaNamespace); |
|
905 |
|
906 // check contents and process optional annotations |
|
907 Element importChild = DOMUtil.getFirstChildElement(child); |
|
908 if(importChild != null ) { |
|
909 String importComponentType = DOMUtil.getLocalName(importChild); |
|
910 if (importComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { |
|
911 // promoting annotations to parent component |
|
912 sg.addAnnotation( |
|
913 fElementTraverser.traverseAnnotationDecl(importChild, importAttrs, true, currSchemaInfo)); |
|
914 } else { |
|
915 reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", importComponentType}, child); |
|
916 } |
|
917 if(DOMUtil.getNextSiblingElement(importChild) != null) { |
|
918 reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(importChild))}, child); |
|
919 } |
|
920 } |
|
921 else { |
|
922 String text = DOMUtil.getSyntheticAnnotation(child); |
|
923 if (text != null) { |
|
924 sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, importAttrs, true, currSchemaInfo)); |
|
925 } |
|
926 } |
|
927 fAttributeChecker.returnAttrArray(importAttrs, currSchemaInfo); |
|
928 |
|
929 // a document can't import another document with the same namespace |
|
930 if (schemaNamespace == currSchemaInfo.fTargetNamespace) { |
|
931 reportSchemaError(schemaNamespace != null ? |
|
932 "src-import.1.1" : "src-import.1.2", new Object [] {schemaNamespace}, child); |
|
933 continue; |
|
934 } |
|
935 |
|
936 // if this namespace has not been imported by this document, |
|
937 // then import if multiple imports support is enabled. |
|
938 if(currSchemaInfo.isAllowedNS(schemaNamespace)) { |
|
939 if(!fHonourAllSchemaLocations && !fNamespaceGrowth) |
|
940 continue; |
|
941 } |
|
942 else { |
|
943 currSchemaInfo.addAllowedNS(schemaNamespace); |
|
944 } |
|
945 // also record the fact that one namespace imports another one |
|
946 // convert null to "" |
|
947 String tns = null2EmptyString(currSchemaInfo.fTargetNamespace); |
|
948 // get all namespaces imported by this one |
|
949 Vector ins = (Vector)fImportMap.get(tns); |
|
950 // if no namespace was imported, create new Vector |
|
951 if (ins == null) { |
|
952 // record that this one imports other(s) |
|
953 fAllTNSs.addElement(tns); |
|
954 ins = new Vector(); |
|
955 fImportMap.put(tns, ins); |
|
956 ins.addElement(schemaNamespace); |
|
957 } |
|
958 else if (!ins.contains(schemaNamespace)){ |
|
959 ins.addElement(schemaNamespace); |
|
960 } |
|
961 |
|
962 fSchemaGrammarDescription.reset(); |
|
963 fSchemaGrammarDescription.setContextType(XSDDescription.CONTEXT_IMPORT); |
|
964 fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot)); |
|
965 fSchemaGrammarDescription.setLiteralSystemId(schemaHint); |
|
966 fSchemaGrammarDescription.setLocationHints(new String[]{schemaHint}); |
|
967 fSchemaGrammarDescription.setTargetNamespace(schemaNamespace); |
|
968 |
|
969 // if a grammar with the same namespace and location exists (or being |
|
970 // built), ignore this one (don't traverse it). |
|
971 SchemaGrammar isg = findGrammar(fSchemaGrammarDescription, fNamespaceGrowth); |
|
972 if (isg != null) { |
|
973 if (fNamespaceGrowth) { |
|
974 try { |
|
975 if (isg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(schemaHint, fSchemaGrammarDescription.getBaseSystemId(), false))) { |
|
976 continue; |
|
977 } |
|
978 else { |
|
979 importCollision = true; |
|
980 } |
|
981 } |
|
982 catch (MalformedURIException e) { |
|
983 } |
|
984 } |
|
985 else if (!fHonourAllSchemaLocations || isExistingGrammar(fSchemaGrammarDescription, false)) { |
|
986 continue; |
|
987 } |
|
988 } |
|
989 //if ((!fHonourAllSchemaLocations && findGrammar(fSchemaGrammarDescription) != null) || isExistingGrammar(fSchemaGrammarDescription)) |
|
990 // continue; |
|
991 |
|
992 // If "findGrammar" returns a grammar, then this is not the |
|
993 // the first time we see a location for a given namespace. |
|
994 // Don't consult the location pair hashtable in this case, |
|
995 // otherwise the location will be ignored because it'll get |
|
996 // resolved to the same location as the first hint. |
|
997 newSchemaRoot = resolveSchema(fSchemaGrammarDescription, false, child, isg == null); |
|
998 } |
|
999 else if ((localName.equals(SchemaSymbols.ELT_INCLUDE)) || |
|
1000 (localName.equals(SchemaSymbols.ELT_REDEFINE))) { |
|
1001 // validation for redefine/include will be the same here; just |
|
1002 // make sure TNS is right (don't care about redef contents |
|
1003 // yet). |
|
1004 Object[] includeAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo); |
|
1005 schemaHint = (String)includeAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION]; |
|
1006 // store the namespace decls of the redefine element |
|
1007 if (localName.equals(SchemaSymbols.ELT_REDEFINE)) { |
|
1008 if (fRedefine2NSSupport == null) fRedefine2NSSupport = new HashMap(); |
|
1009 fRedefine2NSSupport.put(child, new SchemaNamespaceSupport(currSchemaInfo.fNamespaceSupport)); |
|
1010 } |
|
1011 |
|
1012 // check annotations. Must do this here to avoid having to |
|
1013 // re-parse attributes later |
|
1014 if(localName.equals(SchemaSymbols.ELT_INCLUDE)) { |
|
1015 Element includeChild = DOMUtil.getFirstChildElement(child); |
|
1016 if(includeChild != null ) { |
|
1017 String includeComponentType = DOMUtil.getLocalName(includeChild); |
|
1018 if (includeComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { |
|
1019 // promoting annotations to parent component |
|
1020 sg.addAnnotation( |
|
1021 fElementTraverser.traverseAnnotationDecl(includeChild, includeAttrs, true, currSchemaInfo)); |
|
1022 } else { |
|
1023 reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", includeComponentType}, child); |
|
1024 } |
|
1025 if(DOMUtil.getNextSiblingElement(includeChild) != null) { |
|
1026 reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(includeChild))}, child); |
|
1027 } |
|
1028 } |
|
1029 else { |
|
1030 String text = DOMUtil.getSyntheticAnnotation(child); |
|
1031 if (text != null) { |
|
1032 sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo)); |
|
1033 } |
|
1034 } |
|
1035 } |
|
1036 else { |
|
1037 for (Element redefinedChild = DOMUtil.getFirstChildElement(child); |
|
1038 redefinedChild != null; |
|
1039 redefinedChild = DOMUtil.getNextSiblingElement(redefinedChild)) { |
|
1040 String redefinedComponentType = DOMUtil.getLocalName(redefinedChild); |
|
1041 if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { |
|
1042 // promoting annotations to parent component |
|
1043 sg.addAnnotation( |
|
1044 fElementTraverser.traverseAnnotationDecl(redefinedChild, includeAttrs, true, currSchemaInfo)); |
|
1045 DOMUtil.setHidden(redefinedChild, fHiddenNodes); |
|
1046 } |
|
1047 else { |
|
1048 String text = DOMUtil.getSyntheticAnnotation(child); |
|
1049 if (text != null) { |
|
1050 sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo)); |
|
1051 } |
|
1052 } |
|
1053 // catch all other content errors later |
|
1054 } |
|
1055 } |
|
1056 fAttributeChecker.returnAttrArray(includeAttrs, currSchemaInfo); |
|
1057 // schemaLocation is required on <include> and <redefine> |
|
1058 if (schemaHint == null) { |
|
1059 reportSchemaError("s4s-att-must-appear", new Object [] { |
|
1060 "<include> or <redefine>", "schemaLocation"}, |
|
1061 child); |
|
1062 } |
|
1063 // pass the systemId of the current document as the base systemId |
|
1064 boolean mustResolve = false; |
|
1065 refType = XSDDescription.CONTEXT_INCLUDE; |
|
1066 if(localName.equals(SchemaSymbols.ELT_REDEFINE)) { |
|
1067 mustResolve = nonAnnotationContent(child); |
|
1068 refType = XSDDescription.CONTEXT_REDEFINE; |
|
1069 } |
|
1070 fSchemaGrammarDescription.reset(); |
|
1071 fSchemaGrammarDescription.setContextType(refType); |
|
1072 fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot)); |
|
1073 fSchemaGrammarDescription.setLocationHints(new String[]{schemaHint}); |
|
1074 fSchemaGrammarDescription.setTargetNamespace(callerTNS); |
|
1075 |
|
1076 boolean alreadyTraversed = false; |
|
1077 XMLInputSource schemaSource = resolveSchemaSource(fSchemaGrammarDescription, mustResolve, child, true); |
|
1078 if (fNamespaceGrowth && refType == XSDDescription.CONTEXT_INCLUDE) { |
|
1079 try { |
|
1080 final String schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); |
|
1081 alreadyTraversed = sg.getDocumentLocations().contains(schemaId); |
|
1082 } |
|
1083 catch(MalformedURIException e) { |
|
1084 |
|
1085 } |
|
1086 } |
|
1087 |
|
1088 if (!alreadyTraversed) { |
|
1089 newSchemaRoot = resolveSchema(schemaSource, fSchemaGrammarDescription, mustResolve, child); |
|
1090 schemaNamespace = currSchemaInfo.fTargetNamespace; |
|
1091 } |
|
1092 else { |
|
1093 fLastSchemaWasDuplicate = true; |
|
1094 } |
|
1095 } |
|
1096 else { |
|
1097 // no more possibility of schema references in well-formed |
|
1098 // schema... |
|
1099 break; |
|
1100 } |
|
1101 |
|
1102 // If the schema is duplicate, we needn't call constructTrees() again. |
|
1103 // To handle mutual <include>s |
|
1104 XSDocumentInfo newSchemaInfo = null; |
|
1105 if (fLastSchemaWasDuplicate) { |
|
1106 newSchemaInfo = newSchemaRoot == null ? null : (XSDocumentInfo)fDoc2XSDocumentMap.get(newSchemaRoot); |
|
1107 } |
|
1108 else { |
|
1109 newSchemaInfo = constructTrees(newSchemaRoot, schemaHint, fSchemaGrammarDescription, importCollision); |
|
1110 } |
|
1111 |
|
1112 if (localName.equals(SchemaSymbols.ELT_REDEFINE) && |
|
1113 newSchemaInfo != null) { |
|
1114 // must record which schema we're redefining so that we can |
|
1115 // rename the right things later! |
|
1116 if (fRedefine2XSDMap == null) fRedefine2XSDMap = new HashMap(); |
|
1117 fRedefine2XSDMap.put(child, newSchemaInfo); |
|
1118 } |
|
1119 if (newSchemaRoot != null) { |
|
1120 if (newSchemaInfo != null) |
|
1121 dependencies.addElement(newSchemaInfo); |
|
1122 newSchemaRoot = null; |
|
1123 } |
|
1124 } |
|
1125 |
|
1126 fDependencyMap.put(currSchemaInfo, dependencies); |
|
1127 return currSchemaInfo; |
|
1128 } // end constructTrees |
|
1129 |
|
1130 private boolean isExistingGrammar(XSDDescription desc, boolean ignoreConflict) { |
|
1131 SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace()); |
|
1132 if (sg == null) { |
|
1133 return findGrammar(desc, ignoreConflict) != null; |
|
1134 } |
|
1135 else if (sg.isImmutable()) { |
|
1136 return true; |
|
1137 } |
|
1138 else { |
|
1139 try { |
|
1140 return sg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(desc.getLiteralSystemId(), desc.getBaseSystemId(), false)); |
|
1141 } |
|
1142 catch (MalformedURIException e) { |
|
1143 return false; |
|
1144 } |
|
1145 } |
|
1146 } |
|
1147 |
|
1148 /** |
|
1149 * Namespace growth |
|
1150 * |
|
1151 * Go through the import list of a given grammar and for each imported |
|
1152 * grammar, check to see if the grammar bucket has a newer version. |
|
1153 * If a new instance is found, we update the import list with the |
|
1154 * newer version. |
|
1155 */ |
|
1156 private void updateImportListFor(SchemaGrammar grammar) { |
|
1157 Vector importedGrammars = grammar.getImportedGrammars(); |
|
1158 if (importedGrammars != null) { |
|
1159 for (int i=0; i<importedGrammars.size(); i++) { |
|
1160 SchemaGrammar isg1 = (SchemaGrammar) importedGrammars.elementAt(i); |
|
1161 SchemaGrammar isg2 = fGrammarBucket.getGrammar(isg1.getTargetNamespace()); |
|
1162 if (isg2 != null && isg1 != isg2) { |
|
1163 importedGrammars.set(i, isg2); |
|
1164 } |
|
1165 } |
|
1166 } |
|
1167 } |
|
1168 |
|
1169 /** |
|
1170 * Namespace growth |
|
1171 * |
|
1172 * Go throuth the grammar bucket, and for each grammar in the bucket |
|
1173 * check the import list. If there exists a grammar in import list |
|
1174 * that has the same namespace as newGrammar, but a different instance, |
|
1175 * then update the import list and replace the old grammar instance with |
|
1176 * the new one |
|
1177 */ |
|
1178 private void updateImportListWith(SchemaGrammar newGrammar) { |
|
1179 SchemaGrammar[] schemaGrammars = fGrammarBucket.getGrammars(); |
|
1180 for (int i = 0; i < schemaGrammars.length; ++i) { |
|
1181 SchemaGrammar sg = schemaGrammars[i]; |
|
1182 if (sg != newGrammar) { |
|
1183 Vector importedGrammars = sg.getImportedGrammars(); |
|
1184 if (importedGrammars != null) { |
|
1185 for (int j=0; j<importedGrammars.size(); j++) { |
|
1186 SchemaGrammar isg = (SchemaGrammar) importedGrammars.elementAt(j); |
|
1187 if (null2EmptyString(isg.getTargetNamespace()).equals(null2EmptyString(newGrammar.getTargetNamespace()))) { |
|
1188 if (isg != newGrammar) { |
|
1189 importedGrammars.set(j, newGrammar); |
|
1190 } |
|
1191 break; |
|
1192 } |
|
1193 } |
|
1194 } |
|
1195 } |
|
1196 } |
|
1197 } |
|
1198 |
|
1199 // This method builds registries for all globally-referenceable |
|
1200 // names. A registry will be built for each symbol space defined |
|
1201 // by the spec. It is also this method's job to rename redefined |
|
1202 // components, and to record which components redefine others (so |
|
1203 // that implicit redefinitions of groups and attributeGroups can be handled). |
|
1204 protected void buildGlobalNameRegistries() { |
|
1205 |
|
1206 registryEmpty = false; |
|
1207 // Starting with fRoot, we examine each child of the schema |
|
1208 // element. Skipping all imports and includes, we record the names |
|
1209 // of all other global components (and children of <redefine>). We |
|
1210 // also put <redefine> names in a registry that we look through in |
|
1211 // case something needs renaming. Once we're done with a schema we |
|
1212 // set its Document node to hidden so that we don't try to traverse |
|
1213 // it again; then we look to its Dependency map entry. We keep a |
|
1214 // stack of schemas that we haven't yet finished processing; this |
|
1215 // is a depth-first traversal. |
|
1216 |
|
1217 Stack schemasToProcess = new Stack(); |
|
1218 schemasToProcess.push(fRoot); |
|
1219 |
|
1220 while (!schemasToProcess.empty()) { |
|
1221 XSDocumentInfo currSchemaDoc = |
|
1222 (XSDocumentInfo)schemasToProcess.pop(); |
|
1223 Element currDoc = currSchemaDoc.fSchemaElement; |
|
1224 if(DOMUtil.isHidden(currDoc, fHiddenNodes)){ |
|
1225 // must have processed this already! |
|
1226 continue; |
|
1227 } |
|
1228 |
|
1229 Element currRoot = currDoc; |
|
1230 // process this schema's global decls |
|
1231 boolean dependenciesCanOccur = true; |
|
1232 for (Element globalComp = |
|
1233 DOMUtil.getFirstChildElement(currRoot); |
|
1234 globalComp != null; |
|
1235 globalComp = DOMUtil.getNextSiblingElement(globalComp)) { |
|
1236 // this loop makes sure the <schema> element ordering is |
|
1237 // also valid. |
|
1238 if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_ANNOTATION)) { |
|
1239 //skip it; traverse it later |
|
1240 continue; |
|
1241 } |
|
1242 else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_INCLUDE) || |
|
1243 DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_IMPORT)) { |
|
1244 if (!dependenciesCanOccur) { |
|
1245 reportSchemaError("s4s-elt-invalid-content.3", new Object [] {DOMUtil.getLocalName(globalComp)}, globalComp); |
|
1246 } |
|
1247 DOMUtil.setHidden(globalComp, fHiddenNodes); |
|
1248 } |
|
1249 else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) { |
|
1250 if (!dependenciesCanOccur) { |
|
1251 reportSchemaError("s4s-elt-invalid-content.3", new Object [] {DOMUtil.getLocalName(globalComp)}, globalComp); |
|
1252 } |
|
1253 for (Element redefineComp = DOMUtil.getFirstChildElement(globalComp); |
|
1254 redefineComp != null; |
|
1255 redefineComp = DOMUtil.getNextSiblingElement(redefineComp)) { |
|
1256 String lName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME); |
|
1257 if (lName.length() == 0) // an error we'll catch later |
|
1258 continue; |
|
1259 String qName = currSchemaDoc.fTargetNamespace == null ? |
|
1260 ","+lName: |
|
1261 currSchemaDoc.fTargetNamespace +","+lName; |
|
1262 String componentType = DOMUtil.getLocalName(redefineComp); |
|
1263 if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { |
|
1264 checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, redefineComp, currSchemaDoc); |
|
1265 // the check will have changed our name; |
|
1266 String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER; |
|
1267 // and all we need to do is error-check+rename our kkids: |
|
1268 renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_ATTRIBUTEGROUP, |
|
1269 lName, targetLName); |
|
1270 } |
|
1271 else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) || |
|
1272 (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) { |
|
1273 checkForDuplicateNames(qName, TYPEDECL_TYPE, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, redefineComp, currSchemaDoc); |
|
1274 // the check will have changed our name; |
|
1275 String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME) + REDEF_IDENTIFIER; |
|
1276 // and all we need to do is error-check+rename our kkids: |
|
1277 if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { |
|
1278 renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_COMPLEXTYPE, |
|
1279 lName, targetLName); |
|
1280 } |
|
1281 else { // must be simpleType |
|
1282 renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_SIMPLETYPE, |
|
1283 lName, targetLName); |
|
1284 } |
|
1285 } |
|
1286 else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { |
|
1287 checkForDuplicateNames(qName, GROUP_TYPE, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, redefineComp, currSchemaDoc); |
|
1288 // the check will have changed our name; |
|
1289 String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER; |
|
1290 // and all we need to do is error-check+rename our kids: |
|
1291 renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_GROUP, |
|
1292 lName, targetLName); |
|
1293 } |
|
1294 } // end march through <redefine> children |
|
1295 // and now set as traversed |
|
1296 //DOMUtil.setHidden(globalComp); |
|
1297 } |
|
1298 else { |
|
1299 dependenciesCanOccur = false; |
|
1300 String lName = DOMUtil.getAttrValue(globalComp, SchemaSymbols.ATT_NAME); |
|
1301 if (lName.length() == 0) // an error we'll catch later |
|
1302 continue; |
|
1303 String qName = currSchemaDoc.fTargetNamespace == null? |
|
1304 ","+lName: |
|
1305 currSchemaDoc.fTargetNamespace +","+lName; |
|
1306 String componentType = DOMUtil.getLocalName(globalComp); |
|
1307 |
|
1308 if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) { |
|
1309 checkForDuplicateNames(qName, ATTRIBUTE_TYPE, fUnparsedAttributeRegistry, fUnparsedAttributeRegistrySub, globalComp, currSchemaDoc); |
|
1310 } |
|
1311 else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { |
|
1312 checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, globalComp, currSchemaDoc); |
|
1313 } |
|
1314 else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) || |
|
1315 (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) { |
|
1316 checkForDuplicateNames(qName, TYPEDECL_TYPE, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, globalComp, currSchemaDoc); |
|
1317 } |
|
1318 else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) { |
|
1319 checkForDuplicateNames(qName, ELEMENT_TYPE, fUnparsedElementRegistry, fUnparsedElementRegistrySub, globalComp, currSchemaDoc); |
|
1320 } |
|
1321 else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { |
|
1322 checkForDuplicateNames(qName, GROUP_TYPE, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, globalComp, currSchemaDoc); |
|
1323 } |
|
1324 else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) { |
|
1325 checkForDuplicateNames(qName, NOTATION_TYPE, fUnparsedNotationRegistry, fUnparsedNotationRegistrySub, globalComp, currSchemaDoc); |
|
1326 } |
|
1327 } |
|
1328 } // end for |
|
1329 |
|
1330 // now we're done with this one! |
|
1331 DOMUtil.setHidden(currDoc, fHiddenNodes); |
|
1332 // now add the schemas this guy depends on |
|
1333 Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc); |
|
1334 for (int i = 0; i < currSchemaDepends.size(); i++) { |
|
1335 schemasToProcess.push(currSchemaDepends.elementAt(i)); |
|
1336 } |
|
1337 } // while |
|
1338 |
|
1339 } // end buildGlobalNameRegistries |
|
1340 |
|
1341 // Beginning at the first schema processing was requested for |
|
1342 // (fRoot), this method |
|
1343 // examines each child (global schema information item) of each |
|
1344 // schema document (and of each <redefine> element) |
|
1345 // corresponding to an XSDocumentInfo object. If the |
|
1346 // readOnly field on that node has not been set, it calls an |
|
1347 // appropriate traverser to traverse it. Once all global decls in |
|
1348 // an XSDocumentInfo object have been traversed, it marks that object |
|
1349 // as traversed (or hidden) in order to avoid infinite loops. It completes |
|
1350 // when it has visited all XSDocumentInfo objects in the |
|
1351 // DependencyMap and marked them as traversed. |
|
1352 protected void traverseSchemas(ArrayList annotationInfo) { |
|
1353 // the process here is very similar to that in |
|
1354 // buildGlobalRegistries, except we can't set our schemas as |
|
1355 // hidden for a second time; so make them all visible again |
|
1356 // first! |
|
1357 setSchemasVisible(fRoot); |
|
1358 Stack schemasToProcess = new Stack(); |
|
1359 schemasToProcess.push(fRoot); |
|
1360 while (!schemasToProcess.empty()) { |
|
1361 XSDocumentInfo currSchemaDoc = |
|
1362 (XSDocumentInfo)schemasToProcess.pop(); |
|
1363 Element currDoc = currSchemaDoc.fSchemaElement; |
|
1364 |
|
1365 SchemaGrammar currSG = fGrammarBucket.getGrammar(currSchemaDoc.fTargetNamespace); |
|
1366 |
|
1367 if(DOMUtil.isHidden(currDoc, fHiddenNodes)) { |
|
1368 // must have processed this already! |
|
1369 continue; |
|
1370 } |
|
1371 Element currRoot = currDoc; |
|
1372 boolean sawAnnotation = false; |
|
1373 // traverse this schema's global decls |
|
1374 for (Element globalComp = |
|
1375 DOMUtil.getFirstVisibleChildElement(currRoot, fHiddenNodes); |
|
1376 globalComp != null; |
|
1377 globalComp = DOMUtil.getNextVisibleSiblingElement(globalComp, fHiddenNodes)) { |
|
1378 DOMUtil.setHidden(globalComp, fHiddenNodes); |
|
1379 String componentType = DOMUtil.getLocalName(globalComp); |
|
1380 // includes and imports will not show up here! |
|
1381 if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) { |
|
1382 // use the namespace decls for the redefine, instead of for the parent <schema> |
|
1383 currSchemaDoc.backupNSSupport((fRedefine2NSSupport!=null)?(SchemaNamespaceSupport)fRedefine2NSSupport.get(globalComp):null); |
|
1384 for (Element redefinedComp = DOMUtil.getFirstVisibleChildElement(globalComp, fHiddenNodes); |
|
1385 redefinedComp != null; |
|
1386 redefinedComp = DOMUtil.getNextVisibleSiblingElement(redefinedComp, fHiddenNodes)) { |
|
1387 String redefinedComponentType = DOMUtil.getLocalName(redefinedComp); |
|
1388 DOMUtil.setHidden(redefinedComp, fHiddenNodes); |
|
1389 if (redefinedComponentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { |
|
1390 fAttributeGroupTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); |
|
1391 } |
|
1392 else if (redefinedComponentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { |
|
1393 fComplexTypeTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); |
|
1394 } |
|
1395 else if (redefinedComponentType.equals(SchemaSymbols.ELT_GROUP)) { |
|
1396 fGroupTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); |
|
1397 } |
|
1398 else if (redefinedComponentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) { |
|
1399 fSimpleTypeTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG); |
|
1400 } |
|
1401 // annotations will have been processed already; this is now |
|
1402 // unnecessary |
|
1403 //else if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) { |
|
1404 // fElementTraverser.traverseAnnotationDecl(redefinedComp, null, true, currSchemaDoc); |
|
1405 //} |
|
1406 else { |
|
1407 reportSchemaError("s4s-elt-must-match.1", new Object [] {DOMUtil.getLocalName(globalComp), "(annotation | (simpleType | complexType | group | attributeGroup))*", redefinedComponentType}, redefinedComp); |
|
1408 } |
|
1409 } // end march through <redefine> children |
|
1410 currSchemaDoc.restoreNSSupport(); |
|
1411 } |
|
1412 else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) { |
|
1413 fAttributeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); |
|
1414 } |
|
1415 else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { |
|
1416 fAttributeGroupTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); |
|
1417 } |
|
1418 else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { |
|
1419 fComplexTypeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); |
|
1420 } |
|
1421 else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) { |
|
1422 fElementTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); |
|
1423 } |
|
1424 else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { |
|
1425 fGroupTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); |
|
1426 } |
|
1427 else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) { |
|
1428 fNotationTraverser.traverse(globalComp, currSchemaDoc, currSG); |
|
1429 } |
|
1430 else if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) { |
|
1431 fSimpleTypeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG); |
|
1432 } |
|
1433 else if (componentType.equals(SchemaSymbols.ELT_ANNOTATION)) { |
|
1434 currSG.addAnnotation(fElementTraverser.traverseAnnotationDecl(globalComp, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc)); |
|
1435 sawAnnotation = true; |
|
1436 } |
|
1437 else { |
|
1438 reportSchemaError("s4s-elt-invalid-content.1", new Object [] {SchemaSymbols.ELT_SCHEMA, DOMUtil.getLocalName(globalComp)}, globalComp); |
|
1439 } |
|
1440 } // end for |
|
1441 |
|
1442 if (!sawAnnotation) { |
|
1443 String text = DOMUtil.getSyntheticAnnotation(currRoot); |
|
1444 if (text != null) { |
|
1445 currSG.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(currRoot, text, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc)); |
|
1446 } |
|
1447 } |
|
1448 |
|
1449 /** Collect annotation information for validation. **/ |
|
1450 if (annotationInfo != null) { |
|
1451 XSAnnotationInfo info = currSchemaDoc.getAnnotations(); |
|
1452 /** Only add annotations to the list if there were any in this document. **/ |
|
1453 if (info != null) { |
|
1454 annotationInfo.add(doc2SystemId(currDoc)); |
|
1455 annotationInfo.add(info); |
|
1456 } |
|
1457 } |
|
1458 // now we're done with this one! |
|
1459 currSchemaDoc.returnSchemaAttrs(); |
|
1460 DOMUtil.setHidden(currDoc, fHiddenNodes); |
|
1461 |
|
1462 // now add the schemas this guy depends on |
|
1463 Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc); |
|
1464 for (int i = 0; i < currSchemaDepends.size(); i++) { |
|
1465 schemasToProcess.push(currSchemaDepends.elementAt(i)); |
|
1466 } |
|
1467 } // while |
|
1468 } // end traverseSchemas |
|
1469 |
|
1470 // store whether we have reported an error about that no grammar |
|
1471 // is found for the given namespace uri |
|
1472 private Vector fReportedTNS = null; |
|
1473 // check whether we need to report an error against the given uri. |
|
1474 // if we have reported an error, then we don't need to report again; |
|
1475 // otherwise we reported the error, and remember this fact. |
|
1476 private final boolean needReportTNSError(String uri) { |
|
1477 if (fReportedTNS == null) |
|
1478 fReportedTNS = new Vector(); |
|
1479 else if (fReportedTNS.contains(uri)) |
|
1480 return false; |
|
1481 fReportedTNS.addElement(uri); |
|
1482 return true; |
|
1483 } |
|
1484 |
|
1485 private static final String[] COMP_TYPE = { |
|
1486 null, // index 0 |
|
1487 "attribute declaration", |
|
1488 "attribute group", |
|
1489 "element declaration", |
|
1490 "group", |
|
1491 "identity constraint", |
|
1492 "notation", |
|
1493 "type definition", |
|
1494 }; |
|
1495 |
|
1496 private static final String[] CIRCULAR_CODES = { |
|
1497 "Internal-Error", |
|
1498 "Internal-Error", |
|
1499 "src-attribute_group.3", |
|
1500 "e-props-correct.6", |
|
1501 "mg-props-correct.2", |
|
1502 "Internal-Error", |
|
1503 "Internal-Error", |
|
1504 "st-props-correct.2", //or ct-props-correct.3 |
|
1505 }; |
|
1506 |
|
1507 // add a global attribute decl from a current schema load (only if no existing decl is found) |
|
1508 void addGlobalAttributeDecl(XSAttributeDecl decl) { |
|
1509 final String namespace = decl.getNamespace(); |
|
1510 final String declKey = (namespace == null || namespace.length() == 0) |
|
1511 ? "," + decl.getName() : namespace + "," + decl.getName(); |
|
1512 |
|
1513 if (fGlobalAttrDecls.get(declKey) == null) { |
|
1514 fGlobalAttrDecls.put(declKey, decl); |
|
1515 } |
|
1516 } |
|
1517 |
|
1518 // add a global attribute group decl from a current schema load (only if no existing decl is found) |
|
1519 void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl) { |
|
1520 final String namespace = decl.getNamespace(); |
|
1521 final String declKey = (namespace == null || namespace.length() == 0) |
|
1522 ? "," + decl.getName() : namespace + "," + decl.getName(); |
|
1523 |
|
1524 if (fGlobalAttrGrpDecls.get(declKey) == null) { |
|
1525 fGlobalAttrGrpDecls.put(declKey, decl); |
|
1526 } |
|
1527 } |
|
1528 |
|
1529 // add a global element decl from a current schema load (only if no existing decl is found) |
|
1530 void addGlobalElementDecl(XSElementDecl decl) { |
|
1531 final String namespace = decl.getNamespace(); |
|
1532 final String declKey = (namespace == null || namespace.length() == 0) |
|
1533 ? "," + decl.getName() : namespace + "," + decl.getName(); |
|
1534 |
|
1535 if (fGlobalElemDecls.get(declKey) == null) { |
|
1536 fGlobalElemDecls.put(declKey, decl); |
|
1537 } |
|
1538 } |
|
1539 |
|
1540 // add a global group decl from a current schema load (only if no existing decl is found) |
|
1541 void addGlobalGroupDecl(XSGroupDecl decl) { |
|
1542 final String namespace = decl.getNamespace(); |
|
1543 final String declKey = (namespace == null || namespace.length() == 0) |
|
1544 ? "," + decl.getName() : namespace + "," + decl.getName(); |
|
1545 |
|
1546 if (fGlobalGroupDecls.get(declKey) == null) { |
|
1547 fGlobalGroupDecls.put(declKey, decl); |
|
1548 } |
|
1549 } |
|
1550 |
|
1551 // add a global notation decl from a current schema load (only if no existing decl is found) |
|
1552 void addGlobalNotationDecl(XSNotationDecl decl) { |
|
1553 final String namespace = decl.getNamespace(); |
|
1554 final String declKey = (namespace == null || namespace.length() == 0) |
|
1555 ? "," + decl.getName() : namespace + "," + decl.getName(); |
|
1556 |
|
1557 if (fGlobalNotationDecls.get(declKey) == null) { |
|
1558 fGlobalNotationDecls.put(declKey, decl); |
|
1559 } |
|
1560 } |
|
1561 |
|
1562 // add a global type decl from a current schema load (only if no existing decl is found) |
|
1563 void addGlobalTypeDecl(XSTypeDefinition decl) { |
|
1564 final String namespace = decl.getNamespace(); |
|
1565 final String declKey = (namespace == null || namespace.length() == 0) |
|
1566 ? "," + decl.getName() : namespace + "," + decl.getName(); |
|
1567 |
|
1568 if (fGlobalTypeDecls.get(declKey) == null) { |
|
1569 fGlobalTypeDecls.put(declKey, decl); |
|
1570 } |
|
1571 } |
|
1572 |
|
1573 // add a identity constraint decl from a current schema load (only if no existing decl is found) |
|
1574 void addIDConstraintDecl(IdentityConstraint decl) { |
|
1575 final String namespace = decl.getNamespace(); |
|
1576 final String declKey = (namespace == null || namespace.length() == 0) |
|
1577 ? "," + decl.getIdentityConstraintName() : namespace + "," + decl.getIdentityConstraintName(); |
|
1578 |
|
1579 if (fGlobalIDConstraintDecls.get(declKey) == null) { |
|
1580 fGlobalIDConstraintDecls.put(declKey, decl); |
|
1581 } |
|
1582 } |
|
1583 |
|
1584 private XSAttributeDecl getGlobalAttributeDecl(String declKey) { |
|
1585 return (XSAttributeDecl)fGlobalAttrDecls.get(declKey); |
|
1586 } |
|
1587 |
|
1588 private XSAttributeGroupDecl getGlobalAttributeGroupDecl(String declKey) { |
|
1589 return (XSAttributeGroupDecl)fGlobalAttrGrpDecls.get(declKey); |
|
1590 } |
|
1591 |
|
1592 private XSElementDecl getGlobalElementDecl(String declKey) { |
|
1593 return (XSElementDecl)fGlobalElemDecls.get(declKey); |
|
1594 } |
|
1595 |
|
1596 private XSGroupDecl getGlobalGroupDecl(String declKey) { |
|
1597 return (XSGroupDecl)fGlobalGroupDecls.get(declKey); |
|
1598 } |
|
1599 |
|
1600 private XSNotationDecl getGlobalNotationDecl(String declKey) { |
|
1601 return (XSNotationDecl)fGlobalNotationDecls.get(declKey); |
|
1602 } |
|
1603 |
|
1604 private XSTypeDefinition getGlobalTypeDecl(String declKey) { |
|
1605 return (XSTypeDefinition)fGlobalTypeDecls.get(declKey); |
|
1606 } |
|
1607 |
|
1608 private IdentityConstraint getIDConstraintDecl(String declKey) { |
|
1609 return (IdentityConstraint)fGlobalIDConstraintDecls.get(declKey); |
|
1610 } |
|
1611 |
|
1612 // since it is forbidden for traversers to talk to each other |
|
1613 // directly (except wen a traverser encounters a local declaration), |
|
1614 // this provides a generic means for a traverser to call |
|
1615 // for the traversal of some declaration. An XSDocumentInfo is |
|
1616 // required because the XSDocumentInfo that the traverser is traversing |
|
1617 // may bear no relation to the one the handler is operating on. |
|
1618 // This method will: |
|
1619 // 1. See if a global definition matching declToTraverse exists; |
|
1620 // 2. if so, determine if there is a path from currSchema to the |
|
1621 // schema document where declToTraverse lives (i.e., do a lookup |
|
1622 // in DependencyMap); |
|
1623 // 3. depending on declType (which will be relevant to step 1 as |
|
1624 // well), call the appropriate traverser with the appropriate |
|
1625 // XSDocumentInfo object. |
|
1626 // This method returns whatever the traverser it called returned; |
|
1627 // this will be an Object of some kind |
|
1628 // that lives in the Grammar. |
|
1629 protected Object getGlobalDecl(XSDocumentInfo currSchema, |
|
1630 int declType, |
|
1631 QName declToTraverse, |
|
1632 Element elmNode) { |
|
1633 |
|
1634 if (DEBUG_NODE_POOL) { |
|
1635 System.out.println("TRAVERSE_GL: "+declToTraverse.toString()); |
|
1636 } |
|
1637 |
|
1638 // from the schema spec, all built-in types are present in all schemas, |
|
1639 // so if the requested component is a type, and could be found in the |
|
1640 // default schema grammar, we should return that type. |
|
1641 // otherwise (since we would support user-defined schema grammar) we'll |
|
1642 // use the normal way to get the decl |
|
1643 if (declToTraverse.uri != null && |
|
1644 declToTraverse.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) { |
|
1645 if (declType == TYPEDECL_TYPE) { |
|
1646 Object retObj = SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(declToTraverse.localpart); |
|
1647 if (retObj != null) |
|
1648 return retObj; |
|
1649 } |
|
1650 } |
|
1651 |
|
1652 // now check whether this document can access the requsted namespace |
|
1653 if (!currSchema.isAllowedNS(declToTraverse.uri)) { |
|
1654 // cannot get to this schema from the one containing the requesting decl |
|
1655 if (currSchema.needReportTNSError(declToTraverse.uri)) { |
|
1656 String code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2"; |
|
1657 reportSchemaError(code, new Object[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode); |
|
1658 } |
|
1659 // Recover and continue to look for the component. |
|
1660 // return null; |
|
1661 } |
|
1662 |
|
1663 // check whether there is grammar for the requested namespace |
|
1664 SchemaGrammar sGrammar = fGrammarBucket.getGrammar(declToTraverse.uri); |
|
1665 if (sGrammar == null) { |
|
1666 if (needReportTNSError(declToTraverse.uri)) |
|
1667 reportSchemaError("src-resolve", new Object[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode); |
|
1668 return null; |
|
1669 } |
|
1670 |
|
1671 // if there is such grammar, check whether the requested component is in the grammar |
|
1672 Object retObj = getGlobalDeclFromGrammar(sGrammar, declType, declToTraverse.localpart); |
|
1673 String declKey = declToTraverse.uri == null? ","+declToTraverse.localpart: |
|
1674 declToTraverse.uri+","+declToTraverse.localpart; |
|
1675 |
|
1676 // if the component is parsed, return it |
|
1677 if (!fTolerateDuplicates) { |
|
1678 if (retObj != null) { |
|
1679 return retObj; |
|
1680 } |
|
1681 } |
|
1682 else { |
|
1683 Object retObj2 = getGlobalDecl(declKey, declType); |
|
1684 if (retObj2 != null) { |
|
1685 return retObj2; |
|
1686 } |
|
1687 } |
|
1688 |
|
1689 XSDocumentInfo schemaWithDecl = null; |
|
1690 Element decl = null; |
|
1691 XSDocumentInfo declDoc = null; |
|
1692 |
|
1693 // the component is not parsed, try to find a DOM element for it |
|
1694 switch (declType) { |
|
1695 case ATTRIBUTE_TYPE : |
|
1696 decl = getElementFromMap(fUnparsedAttributeRegistry, declKey); |
|
1697 declDoc = getDocInfoFromMap(fUnparsedAttributeRegistrySub, declKey); |
|
1698 break; |
|
1699 case ATTRIBUTEGROUP_TYPE : |
|
1700 decl = getElementFromMap(fUnparsedAttributeGroupRegistry, declKey); |
|
1701 declDoc = getDocInfoFromMap(fUnparsedAttributeGroupRegistrySub, declKey); |
|
1702 break; |
|
1703 case ELEMENT_TYPE : |
|
1704 decl = getElementFromMap(fUnparsedElementRegistry, declKey); |
|
1705 declDoc = getDocInfoFromMap(fUnparsedElementRegistrySub, declKey); |
|
1706 break; |
|
1707 case GROUP_TYPE : |
|
1708 decl = getElementFromMap(fUnparsedGroupRegistry, declKey); |
|
1709 declDoc = getDocInfoFromMap(fUnparsedGroupRegistrySub, declKey); |
|
1710 break; |
|
1711 case IDENTITYCONSTRAINT_TYPE : |
|
1712 decl = getElementFromMap(fUnparsedIdentityConstraintRegistry, declKey); |
|
1713 declDoc = getDocInfoFromMap(fUnparsedIdentityConstraintRegistrySub, declKey); |
|
1714 break; |
|
1715 case NOTATION_TYPE : |
|
1716 decl = getElementFromMap(fUnparsedNotationRegistry, declKey); |
|
1717 declDoc = getDocInfoFromMap(fUnparsedNotationRegistrySub, declKey); |
|
1718 break; |
|
1719 case TYPEDECL_TYPE : |
|
1720 decl = getElementFromMap(fUnparsedTypeRegistry, declKey); |
|
1721 declDoc = getDocInfoFromMap(fUnparsedTypeRegistrySub, declKey); |
|
1722 break; |
|
1723 default: |
|
1724 reportSchemaError("Internal-Error", new Object [] {"XSDHandler asked to locate component of type " + declType + "; it does not recognize this type!"}, elmNode); |
|
1725 } |
|
1726 |
|
1727 // no DOM element found, so the component can't be located |
|
1728 if (decl == null) { |
|
1729 if (retObj == null) { |
|
1730 reportSchemaError("src-resolve", new Object[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode); |
|
1731 } |
|
1732 return retObj; |
|
1733 } |
|
1734 |
|
1735 // get the schema doc containing the component to be parsed |
|
1736 // it should always return non-null value, but since null-checking |
|
1737 // comes for free, let's be safe and check again |
|
1738 schemaWithDecl = findXSDocumentForDecl(currSchema, decl, declDoc); |
|
1739 if (schemaWithDecl == null) { |
|
1740 // cannot get to this schema from the one containing the requesting decl |
|
1741 if (retObj == null) { |
|
1742 String code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2"; |
|
1743 reportSchemaError(code, new Object[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode); |
|
1744 } |
|
1745 return retObj; |
|
1746 } |
|
1747 |
|
1748 // a component is hidden, meaning either it's traversed, or being traversed. |
|
1749 // but we didn't find it in the grammar, so it's the latter case, and |
|
1750 // a circular reference. error! |
|
1751 if (DOMUtil.isHidden(decl, fHiddenNodes)) { |
|
1752 if (retObj == null) { |
|
1753 String code = CIRCULAR_CODES[declType]; |
|
1754 if (declType == TYPEDECL_TYPE) { |
|
1755 if (SchemaSymbols.ELT_COMPLEXTYPE.equals(DOMUtil.getLocalName(decl))) { |
|
1756 code = "ct-props-correct.3"; |
|
1757 } |
|
1758 } |
|
1759 // decl must not be null if we're here... |
|
1760 reportSchemaError(code, new Object [] {declToTraverse.prefix+":"+declToTraverse.localpart}, elmNode); |
|
1761 } |
|
1762 return retObj; |
|
1763 } |
|
1764 |
|
1765 return traverseGlobalDecl(declType, decl, schemaWithDecl, sGrammar); |
|
1766 } // getGlobalDecl(XSDocumentInfo, int, QName): Object |
|
1767 |
|
1768 // If we are tolerating duplicate declarations and allowing namespace growth |
|
1769 // use the declaration from the current schema load (if it exists) |
|
1770 protected Object getGlobalDecl(String declKey, int declType) { |
|
1771 Object retObj = null; |
|
1772 |
|
1773 switch (declType) { |
|
1774 case ATTRIBUTE_TYPE : |
|
1775 retObj = getGlobalAttributeDecl(declKey); |
|
1776 break; |
|
1777 case ATTRIBUTEGROUP_TYPE : |
|
1778 retObj = getGlobalAttributeGroupDecl(declKey); |
|
1779 break; |
|
1780 case ELEMENT_TYPE : |
|
1781 retObj = getGlobalElementDecl(declKey); |
|
1782 break; |
|
1783 case GROUP_TYPE : |
|
1784 retObj = getGlobalGroupDecl(declKey); |
|
1785 break; |
|
1786 case IDENTITYCONSTRAINT_TYPE : |
|
1787 retObj = getIDConstraintDecl(declKey); |
|
1788 break; |
|
1789 case NOTATION_TYPE : |
|
1790 retObj = getGlobalNotationDecl(declKey); |
|
1791 break; |
|
1792 case TYPEDECL_TYPE : |
|
1793 retObj = getGlobalTypeDecl(declKey); |
|
1794 break; |
|
1795 } |
|
1796 |
|
1797 return retObj; |
|
1798 } |
|
1799 |
|
1800 protected Object getGlobalDeclFromGrammar(SchemaGrammar sGrammar, int declType, String localpart) { |
|
1801 Object retObj = null; |
|
1802 |
|
1803 switch (declType) { |
|
1804 case ATTRIBUTE_TYPE : |
|
1805 retObj = sGrammar.getGlobalAttributeDecl(localpart); |
|
1806 break; |
|
1807 case ATTRIBUTEGROUP_TYPE : |
|
1808 retObj = sGrammar.getGlobalAttributeGroupDecl(localpart); |
|
1809 break; |
|
1810 case ELEMENT_TYPE : |
|
1811 retObj = sGrammar.getGlobalElementDecl(localpart); |
|
1812 break; |
|
1813 case GROUP_TYPE : |
|
1814 retObj = sGrammar.getGlobalGroupDecl(localpart); |
|
1815 break; |
|
1816 case IDENTITYCONSTRAINT_TYPE : |
|
1817 retObj = sGrammar.getIDConstraintDecl(localpart); |
|
1818 break; |
|
1819 case NOTATION_TYPE : |
|
1820 retObj = sGrammar.getGlobalNotationDecl(localpart); |
|
1821 break; |
|
1822 case TYPEDECL_TYPE : |
|
1823 retObj = sGrammar.getGlobalTypeDecl(localpart); |
|
1824 break; |
|
1825 } |
|
1826 |
|
1827 return retObj; |
|
1828 } |
|
1829 |
|
1830 protected Object getGlobalDeclFromGrammar(SchemaGrammar sGrammar, int declType, String localpart, String schemaLoc) { |
|
1831 Object retObj = null; |
|
1832 |
|
1833 switch (declType) { |
|
1834 case ATTRIBUTE_TYPE : |
|
1835 retObj = sGrammar.getGlobalAttributeDecl(localpart, schemaLoc); |
|
1836 break; |
|
1837 case ATTRIBUTEGROUP_TYPE : |
|
1838 retObj = sGrammar.getGlobalAttributeGroupDecl(localpart, schemaLoc); |
|
1839 break; |
|
1840 case ELEMENT_TYPE : |
|
1841 retObj = sGrammar.getGlobalElementDecl(localpart, schemaLoc); |
|
1842 break; |
|
1843 case GROUP_TYPE : |
|
1844 retObj = sGrammar.getGlobalGroupDecl(localpart, schemaLoc); |
|
1845 break; |
|
1846 case IDENTITYCONSTRAINT_TYPE : |
|
1847 retObj = sGrammar.getIDConstraintDecl(localpart, schemaLoc); |
|
1848 break; |
|
1849 case NOTATION_TYPE : |
|
1850 retObj = sGrammar.getGlobalNotationDecl(localpart, schemaLoc); |
|
1851 break; |
|
1852 case TYPEDECL_TYPE : |
|
1853 retObj = sGrammar.getGlobalTypeDecl(localpart, schemaLoc); |
|
1854 break; |
|
1855 } |
|
1856 |
|
1857 return retObj; |
|
1858 } |
|
1859 |
|
1860 protected Object traverseGlobalDecl(int declType, Element decl, XSDocumentInfo schemaDoc, SchemaGrammar grammar) { |
|
1861 Object retObj = null; |
|
1862 |
|
1863 DOMUtil.setHidden(decl, fHiddenNodes); |
|
1864 SchemaNamespaceSupport nsSupport = null; |
|
1865 // if the parent is <redefine> use the namespace delcs for it. |
|
1866 Element parent = DOMUtil.getParent(decl); |
|
1867 if (DOMUtil.getLocalName(parent).equals(SchemaSymbols.ELT_REDEFINE)) |
|
1868 nsSupport = (fRedefine2NSSupport!=null)?(SchemaNamespaceSupport)fRedefine2NSSupport.get(parent):null; |
|
1869 // back up the current SchemaNamespaceSupport, because we need to provide |
|
1870 // a fresh one to the traverseGlobal methods. |
|
1871 schemaDoc.backupNSSupport(nsSupport); |
|
1872 |
|
1873 // traverse the referenced global component |
|
1874 switch (declType) { |
|
1875 case TYPEDECL_TYPE : |
|
1876 if (DOMUtil.getLocalName(decl).equals(SchemaSymbols.ELT_COMPLEXTYPE)) { |
|
1877 retObj = fComplexTypeTraverser.traverseGlobal(decl, schemaDoc, grammar); |
|
1878 } |
|
1879 else { |
|
1880 retObj = fSimpleTypeTraverser.traverseGlobal(decl, schemaDoc, grammar); |
|
1881 } |
|
1882 break; |
|
1883 case ATTRIBUTE_TYPE : |
|
1884 retObj = fAttributeTraverser.traverseGlobal(decl, schemaDoc, grammar); |
|
1885 break; |
|
1886 case ELEMENT_TYPE : |
|
1887 retObj = fElementTraverser.traverseGlobal(decl, schemaDoc, grammar); |
|
1888 break; |
|
1889 case ATTRIBUTEGROUP_TYPE : |
|
1890 retObj = fAttributeGroupTraverser.traverseGlobal(decl, schemaDoc, grammar); |
|
1891 break; |
|
1892 case GROUP_TYPE : |
|
1893 retObj = fGroupTraverser.traverseGlobal(decl, schemaDoc, grammar); |
|
1894 break; |
|
1895 case NOTATION_TYPE : |
|
1896 retObj = fNotationTraverser.traverse(decl, schemaDoc, grammar); |
|
1897 break; |
|
1898 case IDENTITYCONSTRAINT_TYPE : |
|
1899 // identity constraints should have been parsed already... |
|
1900 // we should never get here |
|
1901 break; |
|
1902 } |
|
1903 |
|
1904 // restore the previous SchemaNamespaceSupport, so that the caller can get |
|
1905 // proper namespace binding. |
|
1906 schemaDoc.restoreNSSupport(); |
|
1907 |
|
1908 return retObj; |
|
1909 } |
|
1910 |
|
1911 public String schemaDocument2SystemId(XSDocumentInfo schemaDoc) { |
|
1912 return (String)fDoc2SystemId.get(schemaDoc.fSchemaElement); |
|
1913 } |
|
1914 |
|
1915 // This method determines whether there is a group |
|
1916 // (attributeGroup) which the given one has redefined by |
|
1917 // restriction. If so, it returns it; else it returns null. |
|
1918 // @param type: whether what's been redefined is an |
|
1919 // attributeGroup or a group; |
|
1920 // @param name: the QName of the component doing the redefining. |
|
1921 // @param currSchema: schema doc in which the redefining component lives. |
|
1922 // @return: Object representing decl redefined if present, null |
|
1923 // otherwise. |
|
1924 Object getGrpOrAttrGrpRedefinedByRestriction(int type, QName name, XSDocumentInfo currSchema, Element elmNode) { |
|
1925 String realName = name.uri != null?name.uri+","+name.localpart: |
|
1926 ","+name.localpart; |
|
1927 String nameToFind = null; |
|
1928 switch (type) { |
|
1929 case ATTRIBUTEGROUP_TYPE: |
|
1930 nameToFind = (String)fRedefinedRestrictedAttributeGroupRegistry.get(realName); |
|
1931 break; |
|
1932 case GROUP_TYPE: |
|
1933 nameToFind = (String)fRedefinedRestrictedGroupRegistry.get(realName); |
|
1934 break; |
|
1935 default: |
|
1936 return null; |
|
1937 } |
|
1938 if (nameToFind == null) return null; |
|
1939 int commaPos = nameToFind.indexOf(","); |
|
1940 QName qNameToFind = new QName(XMLSymbols.EMPTY_STRING, nameToFind.substring(commaPos+1), |
|
1941 nameToFind.substring(commaPos), (commaPos == 0)? null : nameToFind.substring(0, commaPos)); |
|
1942 Object retObj = getGlobalDecl(currSchema, type, qNameToFind, elmNode); |
|
1943 if(retObj == null) { |
|
1944 switch (type) { |
|
1945 case ATTRIBUTEGROUP_TYPE: |
|
1946 reportSchemaError("src-redefine.7.2.1", new Object []{name.localpart}, elmNode); |
|
1947 break; |
|
1948 case GROUP_TYPE: |
|
1949 reportSchemaError("src-redefine.6.2.1", new Object []{name.localpart}, elmNode); |
|
1950 break; |
|
1951 } |
|
1952 return null; |
|
1953 } |
|
1954 return retObj; |
|
1955 } // getGrpOrAttrGrpRedefinedByRestriction(int, QName, XSDocumentInfo): Object |
|
1956 |
|
1957 // Since ID constraints can occur in local elements, unless we |
|
1958 // wish to completely traverse all our DOM trees looking for ID |
|
1959 // constraints while we're building our global name registries, |
|
1960 // which seems terribly inefficient, we need to resolve keyrefs |
|
1961 // after all parsing is complete. This we can simply do by running through |
|
1962 // fIdentityConstraintRegistry and calling traverseKeyRef on all |
|
1963 // of the KeyRef nodes. This unfortunately removes this knowledge |
|
1964 // from the elementTraverser class (which must ignore keyrefs), |
|
1965 // but there seems to be no efficient way around this... |
|
1966 protected void resolveKeyRefs() { |
|
1967 for (int i=0; i<fKeyrefStackPos; i++) { |
|
1968 XSDocumentInfo keyrefSchemaDoc = fKeyrefsMapXSDocumentInfo[i]; |
|
1969 keyrefSchemaDoc.fNamespaceSupport.makeGlobal(); |
|
1970 keyrefSchemaDoc.fNamespaceSupport.setEffectiveContext( fKeyrefNamespaceContext[i] ); |
|
1971 SchemaGrammar keyrefGrammar = fGrammarBucket.getGrammar(keyrefSchemaDoc.fTargetNamespace); |
|
1972 // need to set <keyref> to hidden before traversing it, |
|
1973 // because it has global scope |
|
1974 DOMUtil.setHidden(fKeyrefs[i], fHiddenNodes); |
|
1975 fKeyrefTraverser.traverse(fKeyrefs[i], fKeyrefElems[i], keyrefSchemaDoc, keyrefGrammar); |
|
1976 } |
|
1977 } // end resolveKeyRefs |
|
1978 |
|
1979 // an accessor method. Just makes sure callers |
|
1980 // who want the Identity constraint registry vaguely know what they're about. |
|
1981 protected Map getIDRegistry() { |
|
1982 return fUnparsedIdentityConstraintRegistry; |
|
1983 } |
|
1984 // an accessor method. |
|
1985 protected Map getIDRegistry_sub() { |
|
1986 return fUnparsedIdentityConstraintRegistrySub; |
|
1987 } |
|
1988 |
|
1989 |
|
1990 |
|
1991 // This method squirrels away <keyref> declarations--along with the element |
|
1992 // decls and namespace bindings they might find handy. |
|
1993 protected void storeKeyRef (Element keyrefToStore, XSDocumentInfo schemaDoc, |
|
1994 XSElementDecl currElemDecl) { |
|
1995 String keyrefName = DOMUtil.getAttrValue(keyrefToStore, SchemaSymbols.ATT_NAME); |
|
1996 if (keyrefName.length() != 0) { |
|
1997 String keyrefQName = schemaDoc.fTargetNamespace == null? |
|
1998 "," + keyrefName: schemaDoc.fTargetNamespace+","+keyrefName; |
|
1999 checkForDuplicateNames(keyrefQName, IDENTITYCONSTRAINT_TYPE, fUnparsedIdentityConstraintRegistry, fUnparsedIdentityConstraintRegistrySub, keyrefToStore, schemaDoc); |
|
2000 } |
|
2001 // now set up all the registries we'll need... |
|
2002 |
|
2003 // check array sizes |
|
2004 if (fKeyrefStackPos == fKeyrefs.length) { |
|
2005 Element [] elemArray = new Element [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT]; |
|
2006 System.arraycopy(fKeyrefs, 0, elemArray, 0, fKeyrefStackPos); |
|
2007 fKeyrefs = elemArray; |
|
2008 XSElementDecl [] declArray = new XSElementDecl [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT]; |
|
2009 System.arraycopy(fKeyrefElems, 0, declArray, 0, fKeyrefStackPos); |
|
2010 fKeyrefElems = declArray; |
|
2011 String[][] stringArray = new String [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT][]; |
|
2012 System.arraycopy(fKeyrefNamespaceContext, 0, stringArray, 0, fKeyrefStackPos); |
|
2013 fKeyrefNamespaceContext = stringArray; |
|
2014 |
|
2015 XSDocumentInfo [] xsDocumentInfo = new XSDocumentInfo [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT]; |
|
2016 System.arraycopy(fKeyrefsMapXSDocumentInfo, 0, xsDocumentInfo, 0, fKeyrefStackPos); |
|
2017 fKeyrefsMapXSDocumentInfo = xsDocumentInfo; |
|
2018 |
|
2019 } |
|
2020 fKeyrefs[fKeyrefStackPos] = keyrefToStore; |
|
2021 fKeyrefElems[fKeyrefStackPos] = currElemDecl; |
|
2022 fKeyrefNamespaceContext[fKeyrefStackPos] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext(); |
|
2023 |
|
2024 fKeyrefsMapXSDocumentInfo[fKeyrefStackPos++] = schemaDoc; |
|
2025 } // storeKeyref (Element, XSDocumentInfo, XSElementDecl): void |
|
2026 |
|
2027 |
|
2028 /** |
|
2029 * resolveSchema method is responsible for resolving location of the schema (using XMLEntityResolver), |
|
2030 * and if it was succefully resolved getting the schema Document. |
|
2031 * @param desc |
|
2032 * @param mustResolve |
|
2033 * @param referElement |
|
2034 * @return A schema Element or null. |
|
2035 */ |
|
2036 private Element resolveSchema(XSDDescription desc, boolean mustResolve, |
|
2037 Element referElement, boolean usePairs) { |
|
2038 XMLInputSource schemaSource = null; |
|
2039 try { |
|
2040 Map pairs = usePairs ? fLocationPairs : EMPTY_TABLE; |
|
2041 schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver); |
|
2042 } |
|
2043 catch (IOException ex) { |
|
2044 if (mustResolve) { |
|
2045 reportSchemaError("schema_reference.4", |
|
2046 new Object[]{desc.getLocationHints()[0]}, |
|
2047 referElement); |
|
2048 } |
|
2049 else { |
|
2050 reportSchemaWarning("schema_reference.4", |
|
2051 new Object[]{desc.getLocationHints()[0]}, |
|
2052 referElement); |
|
2053 } |
|
2054 } |
|
2055 if (schemaSource instanceof DOMInputSource) { |
|
2056 return getSchemaDocument(desc.getTargetNamespace(), (DOMInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); |
|
2057 } // DOMInputSource |
|
2058 else if (schemaSource instanceof SAXInputSource) { |
|
2059 return getSchemaDocument(desc.getTargetNamespace(), (SAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); |
|
2060 } // SAXInputSource |
|
2061 else if (schemaSource instanceof StAXInputSource) { |
|
2062 return getSchemaDocument(desc.getTargetNamespace(), (StAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); |
|
2063 } // StAXInputSource |
|
2064 else if (schemaSource instanceof XSInputSource) { |
|
2065 return getSchemaDocument((XSInputSource) schemaSource, desc); |
|
2066 } // XSInputSource |
|
2067 return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement); |
|
2068 } // getSchema(String, String, String, boolean, short): Document |
|
2069 |
|
2070 private Element resolveSchema(XMLInputSource schemaSource, XSDDescription desc, |
|
2071 boolean mustResolve, Element referElement) { |
|
2072 |
|
2073 if (schemaSource instanceof DOMInputSource) { |
|
2074 return getSchemaDocument(desc.getTargetNamespace(), (DOMInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); |
|
2075 } // DOMInputSource |
|
2076 else if (schemaSource instanceof SAXInputSource) { |
|
2077 return getSchemaDocument(desc.getTargetNamespace(), (SAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); |
|
2078 } // SAXInputSource |
|
2079 else if (schemaSource instanceof StAXInputSource) { |
|
2080 return getSchemaDocument(desc.getTargetNamespace(), (StAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement); |
|
2081 } // StAXInputSource |
|
2082 else if (schemaSource instanceof XSInputSource) { |
|
2083 return getSchemaDocument((XSInputSource) schemaSource, desc); |
|
2084 } // XSInputSource |
|
2085 return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement); |
|
2086 } |
|
2087 |
|
2088 private XMLInputSource resolveSchemaSource(XSDDescription desc, boolean mustResolve, |
|
2089 Element referElement, boolean usePairs) { |
|
2090 |
|
2091 XMLInputSource schemaSource = null; |
|
2092 try { |
|
2093 Map pairs = usePairs ? fLocationPairs : EMPTY_TABLE; |
|
2094 schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver); |
|
2095 } |
|
2096 catch (IOException ex) { |
|
2097 if (mustResolve) { |
|
2098 reportSchemaError("schema_reference.4", |
|
2099 new Object[]{desc.getLocationHints()[0]}, |
|
2100 referElement); |
|
2101 } |
|
2102 else { |
|
2103 reportSchemaWarning("schema_reference.4", |
|
2104 new Object[]{desc.getLocationHints()[0]}, |
|
2105 referElement); |
|
2106 } |
|
2107 } |
|
2108 |
|
2109 return schemaSource; |
|
2110 } |
|
2111 |
|
2112 /** |
|
2113 * getSchemaDocument method uses XMLInputSource to parse a schema document. |
|
2114 * @param schemaNamespace |
|
2115 * @param schemaSource |
|
2116 * @param mustResolve |
|
2117 * @param referType |
|
2118 * @param referElement |
|
2119 * @return A schema Element. |
|
2120 */ |
|
2121 private Element getSchemaDocument(String schemaNamespace, XMLInputSource schemaSource, |
|
2122 boolean mustResolve, short referType, Element referElement) { |
|
2123 |
|
2124 boolean hasInput = true; |
|
2125 IOException exception = null; |
|
2126 // contents of this method will depend on the system we adopt for entity resolution--i.e., XMLEntityHandler, EntityHandler, etc. |
|
2127 Element schemaElement = null; |
|
2128 try { |
|
2129 // when the system id and byte stream and character stream |
|
2130 // of the input source are all null, it's |
|
2131 // impossible to find the schema document. so we skip in |
|
2132 // this case. otherwise we'll receive some NPE or |
|
2133 // file not found errors. but schemaHint=="" is perfectly |
|
2134 // legal for import. |
|
2135 if (schemaSource != null && |
|
2136 (schemaSource.getSystemId() != null || |
|
2137 schemaSource.getByteStream() != null || |
|
2138 schemaSource.getCharacterStream() != null)) { |
|
2139 |
|
2140 // When the system id of the input source is used, first try to |
|
2141 // expand it, and check whether the same document has been |
|
2142 // parsed before. If so, return the document corresponding to |
|
2143 // that system id. |
|
2144 XSDKey key = null; |
|
2145 String schemaId = null; |
|
2146 if (referType != XSDDescription.CONTEXT_PREPARSE){ |
|
2147 schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); |
|
2148 key = new XSDKey(schemaId, referType, schemaNamespace); |
|
2149 if((schemaElement = (Element)fTraversed.get(key)) != null) { |
|
2150 fLastSchemaWasDuplicate = true; |
|
2151 return schemaElement; |
|
2152 } |
|
2153 } |
|
2154 |
|
2155 fSchemaParser.parse(schemaSource); |
|
2156 Document schemaDocument = fSchemaParser.getDocument(); |
|
2157 schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null; |
|
2158 return getSchemaDocument0(key, schemaId, schemaElement); |
|
2159 } |
|
2160 else { |
|
2161 hasInput = false; |
|
2162 } |
|
2163 } |
|
2164 catch (IOException ex) { |
|
2165 exception = ex; |
|
2166 } |
|
2167 return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception); |
|
2168 } // getSchemaDocument(String, XMLInputSource, boolean, short, Element): Element |
|
2169 |
|
2170 /** |
|
2171 * getSchemaDocument method uses SAXInputSource to parse a schema document. |
|
2172 * @param schemaNamespace |
|
2173 * @param schemaSource |
|
2174 * @param mustResolve |
|
2175 * @param referType |
|
2176 * @param referElement |
|
2177 * @return A schema Element. |
|
2178 */ |
|
2179 private Element getSchemaDocument(String schemaNamespace, SAXInputSource schemaSource, |
|
2180 boolean mustResolve, short referType, Element referElement) { |
|
2181 XMLReader parser = schemaSource.getXMLReader(); |
|
2182 InputSource inputSource = schemaSource.getInputSource(); |
|
2183 boolean hasInput = true; |
|
2184 IOException exception = null; |
|
2185 Element schemaElement = null; |
|
2186 try { |
|
2187 if (inputSource != null && |
|
2188 (inputSource.getSystemId() != null || |
|
2189 inputSource.getByteStream() != null || |
|
2190 inputSource.getCharacterStream() != null)) { |
|
2191 |
|
2192 // check whether the same document has been parsed before. |
|
2193 // If so, return the document corresponding to that system id. |
|
2194 XSDKey key = null; |
|
2195 String schemaId = null; |
|
2196 if (referType != XSDDescription.CONTEXT_PREPARSE) { |
|
2197 schemaId = XMLEntityManager.expandSystemId(inputSource.getSystemId(), schemaSource.getBaseSystemId(), false); |
|
2198 key = new XSDKey(schemaId, referType, schemaNamespace); |
|
2199 if ((schemaElement = (Element) fTraversed.get(key)) != null) { |
|
2200 fLastSchemaWasDuplicate = true; |
|
2201 return schemaElement; |
|
2202 } |
|
2203 } |
|
2204 |
|
2205 boolean namespacePrefixes = false; |
|
2206 if (parser != null) { |
|
2207 try { |
|
2208 namespacePrefixes = parser.getFeature(NAMESPACE_PREFIXES); |
|
2209 } |
|
2210 catch (SAXException se) {} |
|
2211 } |
|
2212 else { |
|
2213 try { |
|
2214 parser = XMLReaderFactory.createXMLReader(); |
|
2215 } |
|
2216 // If something went wrong with the factory |
|
2217 // just use our own SAX parser. |
|
2218 catch (SAXException se) { |
|
2219 parser = new SAXParser(); |
|
2220 } |
|
2221 try { |
|
2222 parser.setFeature(NAMESPACE_PREFIXES, true); |
|
2223 namespacePrefixes = true; |
|
2224 // If this is a Xerces SAX parser set the security manager if there is one |
|
2225 if (parser instanceof SAXParser) { |
|
2226 Object securityManager = fSchemaParser.getProperty(SECURITY_MANAGER); |
|
2227 if (securityManager != null) { |
|
2228 parser.setProperty(SECURITY_MANAGER, securityManager); |
|
2229 } |
|
2230 } |
|
2231 } |
|
2232 catch (SAXException se) {} |
|
2233 } |
|
2234 // If XML names and Namespace URIs are already internalized we |
|
2235 // can avoid running them through the SymbolTable. |
|
2236 boolean stringsInternalized = false; |
|
2237 try { |
|
2238 stringsInternalized = parser.getFeature(STRING_INTERNING); |
|
2239 } |
|
2240 catch (SAXException exc) { |
|
2241 // The feature isn't recognized or getting it is not supported. |
|
2242 // In either case, assume that strings are not internalized. |
|
2243 } |
|
2244 if (fXSContentHandler == null) { |
|
2245 fXSContentHandler = new SchemaContentHandler(); |
|
2246 } |
|
2247 fXSContentHandler.reset(fSchemaParser, fSymbolTable, |
|
2248 namespacePrefixes, stringsInternalized); |
|
2249 parser.setContentHandler(fXSContentHandler); |
|
2250 parser.setErrorHandler(fErrorReporter.getSAXErrorHandler()); |
|
2251 |
|
2252 parser.parse(inputSource); |
|
2253 // Disconnect the schema loader and other objects from the XMLReader |
|
2254 try { |
|
2255 parser.setContentHandler(null); |
|
2256 parser.setErrorHandler(null); |
|
2257 } |
|
2258 // Ignore any exceptions thrown by the XMLReader. Old versions of SAX |
|
2259 // required an XMLReader to throw a NullPointerException if an attempt |
|
2260 // to set a handler to null was made. |
|
2261 catch (Exception e) {} |
|
2262 |
|
2263 Document schemaDocument = fXSContentHandler.getDocument(); |
|
2264 schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null; |
|
2265 return getSchemaDocument0(key, schemaId, schemaElement); |
|
2266 } |
|
2267 else { |
|
2268 hasInput = false; |
|
2269 } |
|
2270 } |
|
2271 catch (SAXParseException spe) { |
|
2272 throw SAX2XNIUtil.createXMLParseException0(spe); |
|
2273 } |
|
2274 catch (SAXException se) { |
|
2275 throw SAX2XNIUtil.createXNIException0(se); |
|
2276 } |
|
2277 catch (IOException ioe) { |
|
2278 exception = ioe; |
|
2279 } |
|
2280 return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception); |
|
2281 } // getSchemaDocument(String, SAXInputSource, boolean, short, Element): Element |
|
2282 |
|
2283 /** |
|
2284 * getSchemaDocument method uses DOMInputSource to parse a schema document. |
|
2285 * @param schemaNamespace |
|
2286 * @param schemaSource |
|
2287 * @param mustResolve |
|
2288 * @param referType |
|
2289 * @param referElement |
|
2290 * @return A schema Element. |
|
2291 */ |
|
2292 private Element getSchemaDocument(String schemaNamespace, DOMInputSource schemaSource, |
|
2293 boolean mustResolve, short referType, Element referElement) { |
|
2294 boolean hasInput = true; |
|
2295 IOException exception = null; |
|
2296 Element schemaElement = null; |
|
2297 Element schemaRootElement = null; |
|
2298 |
|
2299 final Node node = schemaSource.getNode(); |
|
2300 short nodeType = -1; |
|
2301 if (node != null) { |
|
2302 nodeType = node.getNodeType(); |
|
2303 if (nodeType == Node.DOCUMENT_NODE) { |
|
2304 schemaRootElement = DOMUtil.getRoot((Document) node); |
|
2305 } |
|
2306 else if (nodeType == Node.ELEMENT_NODE) { |
|
2307 schemaRootElement = (Element) node; |
|
2308 } |
|
2309 } |
|
2310 |
|
2311 try { |
|
2312 if (schemaRootElement != null) { |
|
2313 // check whether the same document has been parsed before. |
|
2314 // If so, return the document corresponding to that system id. |
|
2315 XSDKey key = null; |
|
2316 String schemaId = null; |
|
2317 if (referType != XSDDescription.CONTEXT_PREPARSE) { |
|
2318 schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); |
|
2319 boolean isDocument = (nodeType == Node.DOCUMENT_NODE); |
|
2320 if (!isDocument) { |
|
2321 Node parent = schemaRootElement.getParentNode(); |
|
2322 if (parent != null) { |
|
2323 isDocument = (parent.getNodeType() == Node.DOCUMENT_NODE); |
|
2324 } |
|
2325 } |
|
2326 if (isDocument) { |
|
2327 key = new XSDKey(schemaId, referType, schemaNamespace); |
|
2328 if ((schemaElement = (Element) fTraversed.get(key)) != null) { |
|
2329 fLastSchemaWasDuplicate = true; |
|
2330 return schemaElement; |
|
2331 } |
|
2332 } |
|
2333 } |
|
2334 |
|
2335 schemaElement = schemaRootElement; |
|
2336 return getSchemaDocument0(key, schemaId, schemaElement); |
|
2337 } |
|
2338 else { |
|
2339 hasInput = false; |
|
2340 } |
|
2341 } |
|
2342 catch (IOException ioe) { |
|
2343 exception = ioe; |
|
2344 } |
|
2345 return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception); |
|
2346 } // getSchemaDocument(String, DOMInputSource, boolean, short, Element): Element |
|
2347 |
|
2348 /** |
|
2349 * getSchemaDocument method uses StAXInputSource to parse a schema document. |
|
2350 * @param schemaNamespace |
|
2351 * @param schemaSource |
|
2352 * @param mustResolve |
|
2353 * @param referType |
|
2354 * @param referElement |
|
2355 * @return A schema Element. |
|
2356 */ |
|
2357 private Element getSchemaDocument(String schemaNamespace, StAXInputSource schemaSource, |
|
2358 boolean mustResolve, short referType, Element referElement) { |
|
2359 IOException exception = null; |
|
2360 Element schemaElement = null; |
|
2361 try { |
|
2362 final boolean consumeRemainingContent = schemaSource.shouldConsumeRemainingContent(); |
|
2363 final XMLStreamReader streamReader = schemaSource.getXMLStreamReader(); |
|
2364 final XMLEventReader eventReader = schemaSource.getXMLEventReader(); |
|
2365 |
|
2366 // check whether the same document has been parsed before. |
|
2367 // If so, return the document corresponding to that system id. |
|
2368 XSDKey key = null; |
|
2369 String schemaId = null; |
|
2370 if (referType != XSDDescription.CONTEXT_PREPARSE) { |
|
2371 schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); |
|
2372 boolean isDocument = consumeRemainingContent; |
|
2373 if (!isDocument) { |
|
2374 if (streamReader != null) { |
|
2375 isDocument = (streamReader.getEventType() == XMLStreamReader.START_DOCUMENT); |
|
2376 } |
|
2377 else { |
|
2378 isDocument = eventReader.peek().isStartDocument(); |
|
2379 } |
|
2380 } |
|
2381 if (isDocument) { |
|
2382 key = new XSDKey(schemaId, referType, schemaNamespace); |
|
2383 if ((schemaElement = (Element) fTraversed.get(key)) != null) { |
|
2384 fLastSchemaWasDuplicate = true; |
|
2385 return schemaElement; |
|
2386 } |
|
2387 } |
|
2388 } |
|
2389 |
|
2390 if (fStAXSchemaParser == null) { |
|
2391 fStAXSchemaParser = new StAXSchemaParser(); |
|
2392 } |
|
2393 fStAXSchemaParser.reset(fSchemaParser, fSymbolTable); |
|
2394 |
|
2395 if (streamReader != null) { |
|
2396 fStAXSchemaParser.parse(streamReader); |
|
2397 if (consumeRemainingContent) { |
|
2398 while (streamReader.hasNext()) { |
|
2399 streamReader.next(); |
|
2400 } |
|
2401 } |
|
2402 } |
|
2403 else { |
|
2404 fStAXSchemaParser.parse(eventReader); |
|
2405 if (consumeRemainingContent) { |
|
2406 while (eventReader.hasNext()) { |
|
2407 eventReader.nextEvent(); |
|
2408 } |
|
2409 } |
|
2410 } |
|
2411 Document schemaDocument = fStAXSchemaParser.getDocument(); |
|
2412 schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null; |
|
2413 return getSchemaDocument0(key, schemaId, schemaElement); |
|
2414 } |
|
2415 catch (XMLStreamException e) { |
|
2416 StAXLocationWrapper slw = new StAXLocationWrapper(); |
|
2417 slw.setLocation(e.getLocation()); |
|
2418 throw new XMLParseException(slw, e.getMessage(), e); |
|
2419 } |
|
2420 catch (IOException e) { |
|
2421 exception = e; |
|
2422 } |
|
2423 return getSchemaDocument1(mustResolve, true, schemaSource, referElement, exception); |
|
2424 } // getSchemaDocument(String, StAXInputSource, boolean, short, Element): Element |
|
2425 |
|
2426 /** |
|
2427 * Code shared between the various getSchemaDocument() methods which |
|
2428 * stores mapping information for the document. |
|
2429 */ |
|
2430 private Element getSchemaDocument0(XSDKey key, String schemaId, Element schemaElement) { |
|
2431 // now we need to store the mapping information from system id |
|
2432 // to the document. also from the document to the system id. |
|
2433 if (key != null) { |
|
2434 fTraversed.put(key, schemaElement); |
|
2435 } |
|
2436 if (schemaId != null) { |
|
2437 fDoc2SystemId.put(schemaElement, schemaId); |
|
2438 } |
|
2439 fLastSchemaWasDuplicate = false; |
|
2440 return schemaElement; |
|
2441 } // getSchemaDocument0(XSDKey, String, Element): Element |
|
2442 |
|
2443 /** |
|
2444 * Error handling code shared between the various getSchemaDocument() methods. |
|
2445 */ |
|
2446 private Element getSchemaDocument1(boolean mustResolve, boolean hasInput, |
|
2447 XMLInputSource schemaSource, Element referElement, IOException ioe) { |
|
2448 // either an error occured (exception), or empty input source was |
|
2449 // returned, we need to report an error or a warning |
|
2450 if (mustResolve) { |
|
2451 if (hasInput) { |
|
2452 reportSchemaError("schema_reference.4", |
|
2453 new Object[]{schemaSource.getSystemId()}, |
|
2454 referElement, ioe); |
|
2455 } |
|
2456 else { |
|
2457 reportSchemaError("schema_reference.4", |
|
2458 new Object[]{schemaSource == null ? "" : schemaSource.getSystemId()}, |
|
2459 referElement, ioe); |
|
2460 } |
|
2461 } |
|
2462 else if (hasInput) { |
|
2463 reportSchemaWarning("schema_reference.4", |
|
2464 new Object[]{schemaSource.getSystemId()}, |
|
2465 referElement, ioe); |
|
2466 } |
|
2467 |
|
2468 fLastSchemaWasDuplicate = false; |
|
2469 return null; |
|
2470 } // getSchemaDocument1(boolean, boolean, XMLInputSource, Element): Element |
|
2471 |
|
2472 /** |
|
2473 * getSchemaDocument method uses XMLInputSource to parse a schema document. |
|
2474 * @param schemaNamespace |
|
2475 * @param schemaSource |
|
2476 * @param mustResolve |
|
2477 * @param referType |
|
2478 * @param referElement |
|
2479 * @return A schema Element. |
|
2480 */ |
|
2481 private Element getSchemaDocument(XSInputSource schemaSource, XSDDescription desc) { |
|
2482 |
|
2483 SchemaGrammar[] grammars = schemaSource.getGrammars(); |
|
2484 short referType = desc.getContextType(); |
|
2485 |
|
2486 if (grammars != null && grammars.length > 0) { |
|
2487 Vector expandedGrammars = expandGrammars(grammars); |
|
2488 // check for existing grammars in our bucket |
|
2489 // and if there exist any, and namespace growth is |
|
2490 // not enabled - we do nothing |
|
2491 if (fNamespaceGrowth || !existingGrammars(expandedGrammars)) { |
|
2492 addGrammars(expandedGrammars); |
|
2493 if (referType == XSDDescription.CONTEXT_PREPARSE) { |
|
2494 desc.setTargetNamespace(grammars[0].getTargetNamespace()); |
|
2495 } |
|
2496 } |
|
2497 } |
|
2498 else { |
|
2499 XSObject[] components = schemaSource.getComponents(); |
|
2500 if (components != null && components.length > 0) { |
|
2501 Map<String, Vector> importDependencies = new HashMap(); |
|
2502 Vector expandedComponents = expandComponents(components, importDependencies); |
|
2503 if (fNamespaceGrowth || canAddComponents(expandedComponents)) { |
|
2504 addGlobalComponents(expandedComponents, importDependencies); |
|
2505 if (referType == XSDDescription.CONTEXT_PREPARSE) { |
|
2506 desc.setTargetNamespace(components[0].getNamespace()); |
|
2507 } |
|
2508 } |
|
2509 } |
|
2510 } |
|
2511 return null; |
|
2512 } // getSchemaDocument(String, XSInputSource, boolean, short, Element): Element |
|
2513 |
|
2514 private Vector expandGrammars(SchemaGrammar[] grammars) { |
|
2515 Vector currGrammars = new Vector(); |
|
2516 |
|
2517 for (int i=0; i<grammars.length; i++) { |
|
2518 if (!currGrammars.contains(grammars[i])) { |
|
2519 currGrammars.add(grammars[i]); |
|
2520 } |
|
2521 } |
|
2522 |
|
2523 // for all (recursively) imported grammars |
|
2524 SchemaGrammar sg1, sg2; |
|
2525 Vector gs; |
|
2526 for (int i = 0; i < currGrammars.size(); i++) { |
|
2527 // get the grammar |
|
2528 sg1 = (SchemaGrammar)currGrammars.elementAt(i); |
|
2529 // we need to add grammars imported by sg1 too |
|
2530 gs = sg1.getImportedGrammars(); |
|
2531 // for all grammars imported by sg2, but not in the vector |
|
2532 // we add them to the vector |
|
2533 if (gs == null) { |
|
2534 continue; |
|
2535 } |
|
2536 |
|
2537 for (int j = gs.size() - 1; j >= 0; j--) { |
|
2538 sg2 = (SchemaGrammar)gs.elementAt(j); |
|
2539 if (!currGrammars.contains(sg2)) { |
|
2540 currGrammars.addElement(sg2); |
|
2541 } |
|
2542 } |
|
2543 } |
|
2544 |
|
2545 return currGrammars; |
|
2546 } |
|
2547 |
|
2548 private boolean existingGrammars(Vector grammars) { |
|
2549 int length = grammars.size(); |
|
2550 final XSDDescription desc = new XSDDescription(); |
|
2551 |
|
2552 for (int i=0; i < length; i++) { |
|
2553 final SchemaGrammar sg1 = (SchemaGrammar)grammars.elementAt(i); |
|
2554 desc.setNamespace(sg1.getTargetNamespace()); |
|
2555 |
|
2556 final SchemaGrammar sg2 = findGrammar(desc, false); |
|
2557 if (sg2 != null) { |
|
2558 return true; |
|
2559 } |
|
2560 } |
|
2561 |
|
2562 return false; |
|
2563 } |
|
2564 |
|
2565 private boolean canAddComponents(Vector components) { |
|
2566 final int size = components.size(); |
|
2567 final XSDDescription desc = new XSDDescription(); |
|
2568 for (int i=0; i<size; i++) { |
|
2569 XSObject component = (XSObject) components.elementAt(i); |
|
2570 if (!canAddComponent(component, desc)) { |
|
2571 return false; |
|
2572 } |
|
2573 } |
|
2574 return true; |
|
2575 } |
|
2576 |
|
2577 private boolean canAddComponent(XSObject component, XSDDescription desc) { |
|
2578 desc.setNamespace(component.getNamespace()); |
|
2579 |
|
2580 final SchemaGrammar sg = findGrammar(desc, false); |
|
2581 if (sg == null) { |
|
2582 return true; |
|
2583 } |
|
2584 else if (sg.isImmutable()) { |
|
2585 return false; |
|
2586 } |
|
2587 |
|
2588 short componentType = component.getType(); |
|
2589 final String name = component.getName(); |
|
2590 |
|
2591 switch (componentType) { |
|
2592 case XSConstants.TYPE_DEFINITION : |
|
2593 if (sg.getGlobalTypeDecl(name) == component) { |
|
2594 return true; |
|
2595 } |
|
2596 break; |
|
2597 case XSConstants.ATTRIBUTE_DECLARATION : |
|
2598 if (sg.getGlobalAttributeDecl(name) == component) { |
|
2599 return true; |
|
2600 } |
|
2601 break; |
|
2602 case XSConstants.ATTRIBUTE_GROUP : |
|
2603 if (sg.getGlobalAttributeDecl(name) == component) { |
|
2604 return true; |
|
2605 } |
|
2606 break; |
|
2607 case XSConstants.ELEMENT_DECLARATION : |
|
2608 if (sg.getGlobalElementDecl(name) == component) { |
|
2609 return true; |
|
2610 } |
|
2611 break; |
|
2612 case XSConstants.MODEL_GROUP_DEFINITION : |
|
2613 if (sg.getGlobalGroupDecl(name) == component) { |
|
2614 return true; |
|
2615 } |
|
2616 break; |
|
2617 case XSConstants.NOTATION_DECLARATION : |
|
2618 if (sg.getGlobalNotationDecl(name) == component) { |
|
2619 return true; |
|
2620 } |
|
2621 break; |
|
2622 case XSConstants.IDENTITY_CONSTRAINT : |
|
2623 case XSConstants.ATTRIBUTE_USE : |
|
2624 default : |
|
2625 return true; |
|
2626 } |
|
2627 return false; |
|
2628 } |
|
2629 |
|
2630 private void addGrammars(Vector grammars) { |
|
2631 int length = grammars.size(); |
|
2632 XSDDescription desc = new XSDDescription(); |
|
2633 |
|
2634 for (int i=0; i < length; i++) { |
|
2635 final SchemaGrammar sg1 = (SchemaGrammar)grammars.elementAt(i); |
|
2636 desc.setNamespace(sg1.getTargetNamespace()); |
|
2637 |
|
2638 final SchemaGrammar sg2 = findGrammar(desc, fNamespaceGrowth); |
|
2639 if (sg1 != sg2) { |
|
2640 addGrammarComponents(sg1, sg2); |
|
2641 } |
|
2642 } |
|
2643 } |
|
2644 |
|
2645 private void addGrammarComponents(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { |
|
2646 if (dstGrammar == null) { |
|
2647 createGrammarFrom(srcGrammar); |
|
2648 return; |
|
2649 } |
|
2650 |
|
2651 SchemaGrammar tmpGrammar = dstGrammar; |
|
2652 if (tmpGrammar.isImmutable()) { |
|
2653 tmpGrammar = createGrammarFrom(dstGrammar); |
|
2654 } |
|
2655 |
|
2656 // add any new locations |
|
2657 addNewGrammarLocations(srcGrammar, tmpGrammar); |
|
2658 |
|
2659 // add any new imported grammars |
|
2660 addNewImportedGrammars(srcGrammar, tmpGrammar); |
|
2661 |
|
2662 // add any new global components |
|
2663 addNewGrammarComponents(srcGrammar, tmpGrammar); |
|
2664 } |
|
2665 |
|
2666 private SchemaGrammar createGrammarFrom(SchemaGrammar grammar) { |
|
2667 SchemaGrammar newGrammar = new SchemaGrammar(grammar); |
|
2668 fGrammarBucket.putGrammar(newGrammar); |
|
2669 // update all the grammars in the bucket to point to the new grammar. |
|
2670 updateImportListWith(newGrammar); |
|
2671 // update import list of the new grammar |
|
2672 updateImportListFor(newGrammar); |
|
2673 return newGrammar; |
|
2674 } |
|
2675 |
|
2676 private void addNewGrammarLocations(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { |
|
2677 final StringList locations = srcGrammar.getDocumentLocations(); |
|
2678 final int locSize = locations.size(); |
|
2679 final StringList locations2 = dstGrammar.getDocumentLocations(); |
|
2680 |
|
2681 for (int i=0; i<locSize; i++) { |
|
2682 String loc = locations.item(i); |
|
2683 if (!locations2.contains(loc)) { |
|
2684 dstGrammar.addDocument(null, loc); |
|
2685 } |
|
2686 } |
|
2687 } |
|
2688 |
|
2689 private void addNewImportedGrammars(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { |
|
2690 final Vector igs1 = srcGrammar.getImportedGrammars(); |
|
2691 if (igs1 != null) { |
|
2692 Vector igs2 = dstGrammar.getImportedGrammars(); |
|
2693 |
|
2694 if (igs2 == null) { |
|
2695 igs2 = ((Vector) igs1.clone()); |
|
2696 dstGrammar.setImportedGrammars(igs2); |
|
2697 } |
|
2698 else { |
|
2699 updateImportList(igs1, igs2); |
|
2700 } |
|
2701 } |
|
2702 } |
|
2703 |
|
2704 private void updateImportList(Vector importedSrc, Vector importedDst) |
|
2705 { |
|
2706 final int size = importedSrc.size(); |
|
2707 |
|
2708 for (int i=0; i<size; i++) { |
|
2709 final SchemaGrammar sg = (SchemaGrammar) importedSrc.elementAt(i); |
|
2710 if (!containedImportedGrammar(importedDst, sg)) { |
|
2711 importedDst.add(sg); |
|
2712 } |
|
2713 } |
|
2714 } |
|
2715 |
|
2716 private void addNewGrammarComponents(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { |
|
2717 dstGrammar.resetComponents(); |
|
2718 addGlobalElementDecls(srcGrammar, dstGrammar); |
|
2719 addGlobalAttributeDecls(srcGrammar, dstGrammar); |
|
2720 addGlobalAttributeGroupDecls(srcGrammar, dstGrammar); |
|
2721 addGlobalGroupDecls(srcGrammar, dstGrammar); |
|
2722 addGlobalTypeDecls(srcGrammar, dstGrammar); |
|
2723 addGlobalNotationDecls(srcGrammar, dstGrammar); |
|
2724 } |
|
2725 |
|
2726 private void addGlobalElementDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { |
|
2727 XSNamedMap components = srcGrammar.getComponents(XSConstants.ELEMENT_DECLARATION); |
|
2728 int len = components.getLength(); |
|
2729 XSElementDecl srcDecl, dstDecl; |
|
2730 |
|
2731 // add global components |
|
2732 for (int i=0; i<len; i++) { |
|
2733 srcDecl = (XSElementDecl) components.item(i); |
|
2734 dstDecl = dstGrammar.getGlobalElementDecl(srcDecl.getName()); |
|
2735 if (dstDecl == null) { |
|
2736 dstGrammar.addGlobalElementDecl(srcDecl); |
|
2737 } |
|
2738 else if (dstDecl != srcDecl){ |
|
2739 // TODO: if not tolerating duplicate, generate an error message |
|
2740 } |
|
2741 } |
|
2742 |
|
2743 // add any extended (duplicate) global components |
|
2744 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ELEMENT_DECLARATION); |
|
2745 len = componentsExt.getLength(); |
|
2746 |
|
2747 for (int i=0; i<len; i+= 2) { |
|
2748 final String key = (String) componentsExt.item(i); |
|
2749 final int index = key.indexOf(','); |
|
2750 final String location = key.substring(0, index); |
|
2751 final String name = key.substring(index + 1, key.length()); |
|
2752 |
|
2753 srcDecl = (XSElementDecl)componentsExt.item(i+1); |
|
2754 dstDecl = dstGrammar.getGlobalElementDecl(name, location); |
|
2755 if ( dstDecl == null) { |
|
2756 dstGrammar.addGlobalElementDecl(srcDecl, location); |
|
2757 } |
|
2758 else if (dstDecl != srcDecl){ |
|
2759 // TODO: if not tolerating duplicate, generate an error message |
|
2760 } |
|
2761 } |
|
2762 } |
|
2763 |
|
2764 private void addGlobalAttributeDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { |
|
2765 XSNamedMap components = srcGrammar.getComponents(XSConstants.ATTRIBUTE_DECLARATION); |
|
2766 int len = components.getLength(); |
|
2767 XSAttributeDecl srcDecl, dstDecl; |
|
2768 |
|
2769 // add global components |
|
2770 for (int i=0; i<len; i++) { |
|
2771 srcDecl = (XSAttributeDecl) components.item(i); |
|
2772 dstDecl = dstGrammar.getGlobalAttributeDecl(srcDecl.getName()); |
|
2773 if (dstDecl == null) { |
|
2774 dstGrammar.addGlobalAttributeDecl(srcDecl); |
|
2775 } |
|
2776 else if (dstDecl != srcDecl && !fTolerateDuplicates) { |
|
2777 reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); |
|
2778 } |
|
2779 } |
|
2780 |
|
2781 // add any extended (duplicate) global components |
|
2782 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ATTRIBUTE_DECLARATION); |
|
2783 len = componentsExt.getLength(); |
|
2784 |
|
2785 for (int i=0; i<len; i+= 2) { |
|
2786 final String key = (String) componentsExt.item(i); |
|
2787 final int index = key.indexOf(','); |
|
2788 final String location = key.substring(0, index); |
|
2789 final String name = key.substring(index + 1, key.length()); |
|
2790 |
|
2791 srcDecl = (XSAttributeDecl)componentsExt.item(i+1); |
|
2792 dstDecl = dstGrammar.getGlobalAttributeDecl(name, location); |
|
2793 if (dstDecl == null) { |
|
2794 dstGrammar.addGlobalAttributeDecl(srcDecl, location); |
|
2795 } |
|
2796 // REVISIT - do we report an error? |
|
2797 else if (dstDecl != srcDecl) { |
|
2798 } |
|
2799 } |
|
2800 } |
|
2801 |
|
2802 private void addGlobalAttributeGroupDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { |
|
2803 XSNamedMap components = srcGrammar.getComponents(XSConstants.ATTRIBUTE_GROUP); |
|
2804 int len = components.getLength(); |
|
2805 XSAttributeGroupDecl srcDecl, dstDecl; |
|
2806 |
|
2807 // add global components |
|
2808 for (int i=0; i<len; i++) { |
|
2809 srcDecl = (XSAttributeGroupDecl) components.item(i); |
|
2810 dstDecl = dstGrammar.getGlobalAttributeGroupDecl(srcDecl.getName()); |
|
2811 if (dstDecl == null) { |
|
2812 dstGrammar.addGlobalAttributeGroupDecl(srcDecl); |
|
2813 } |
|
2814 else if (dstDecl != srcDecl && !fTolerateDuplicates) { |
|
2815 reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); |
|
2816 } |
|
2817 } |
|
2818 |
|
2819 // add any extended (duplicate) global components |
|
2820 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ATTRIBUTE_GROUP); |
|
2821 len = componentsExt.getLength(); |
|
2822 |
|
2823 for (int i=0; i<len; i+= 2) { |
|
2824 final String key = (String) componentsExt.item(i); |
|
2825 final int index = key.indexOf(','); |
|
2826 final String location = key.substring(0, index); |
|
2827 final String name = key.substring(index + 1, key.length()); |
|
2828 |
|
2829 srcDecl = (XSAttributeGroupDecl)componentsExt.item(i+1); |
|
2830 dstDecl = dstGrammar.getGlobalAttributeGroupDecl(name, location); |
|
2831 if (dstDecl == null) { |
|
2832 dstGrammar.addGlobalAttributeGroupDecl(srcDecl, location); |
|
2833 } |
|
2834 // REVISIT - do we report an error? |
|
2835 else if (dstDecl != srcDecl) { |
|
2836 } |
|
2837 } |
|
2838 } |
|
2839 |
|
2840 private void addGlobalNotationDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { |
|
2841 XSNamedMap components = srcGrammar.getComponents(XSConstants.NOTATION_DECLARATION); |
|
2842 int len = components.getLength(); |
|
2843 XSNotationDecl srcDecl, dstDecl; |
|
2844 |
|
2845 // add global components |
|
2846 for (int i=0; i<len; i++) { |
|
2847 srcDecl = (XSNotationDecl) components.item(i); |
|
2848 dstDecl = dstGrammar.getGlobalNotationDecl(srcDecl.getName()); |
|
2849 if (dstDecl == null) { |
|
2850 dstGrammar.addGlobalNotationDecl(srcDecl); |
|
2851 } |
|
2852 else if (dstDecl != srcDecl && !fTolerateDuplicates) { |
|
2853 reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); |
|
2854 } |
|
2855 } |
|
2856 |
|
2857 // add any extended (duplicate) global components |
|
2858 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.NOTATION_DECLARATION); |
|
2859 len = componentsExt.getLength(); |
|
2860 |
|
2861 for (int i=0; i<len; i+= 2) { |
|
2862 final String key = (String) componentsExt.item(i); |
|
2863 final int index = key.indexOf(','); |
|
2864 final String location = key.substring(0, index); |
|
2865 final String name = key.substring(index + 1, key.length()); |
|
2866 |
|
2867 srcDecl = (XSNotationDecl)componentsExt.item(i+1); |
|
2868 dstDecl = dstGrammar.getGlobalNotationDecl(name, location); |
|
2869 if (dstDecl == null) { |
|
2870 dstGrammar.addGlobalNotationDecl(srcDecl, location); |
|
2871 } |
|
2872 // REVISIT - do we report an error? |
|
2873 else if (dstDecl != srcDecl) { |
|
2874 } |
|
2875 } |
|
2876 } |
|
2877 |
|
2878 private void addGlobalGroupDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { |
|
2879 XSNamedMap components = srcGrammar.getComponents(XSConstants.MODEL_GROUP_DEFINITION); |
|
2880 int len = components.getLength(); |
|
2881 XSGroupDecl srcDecl, dstDecl; |
|
2882 |
|
2883 // add global components |
|
2884 for (int i=0; i<len; i++) { |
|
2885 srcDecl = (XSGroupDecl) components.item(i); |
|
2886 dstDecl = dstGrammar.getGlobalGroupDecl(srcDecl.getName()); |
|
2887 if (dstDecl == null) { |
|
2888 dstGrammar.addGlobalGroupDecl(srcDecl); |
|
2889 } |
|
2890 else if (srcDecl != dstDecl && !fTolerateDuplicates) { |
|
2891 reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); |
|
2892 } |
|
2893 } |
|
2894 |
|
2895 // add any extended (duplicate) global components |
|
2896 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.MODEL_GROUP_DEFINITION); |
|
2897 len = componentsExt.getLength(); |
|
2898 |
|
2899 for (int i=0; i<len; i+= 2) { |
|
2900 final String key = (String) componentsExt.item(i); |
|
2901 final int index = key.indexOf(','); |
|
2902 final String location = key.substring(0, index); |
|
2903 final String name = key.substring(index + 1, key.length()); |
|
2904 |
|
2905 srcDecl = (XSGroupDecl)componentsExt.item(i+1); |
|
2906 dstDecl = dstGrammar.getGlobalGroupDecl(name, location); |
|
2907 if (dstDecl == null) { |
|
2908 dstGrammar.addGlobalGroupDecl(srcDecl, location); |
|
2909 } |
|
2910 // REVIST - do we report an error? |
|
2911 else if (dstDecl != srcDecl) { |
|
2912 } |
|
2913 } |
|
2914 } |
|
2915 |
|
2916 private void addGlobalTypeDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { |
|
2917 XSNamedMap components = srcGrammar.getComponents(XSConstants.TYPE_DEFINITION); |
|
2918 int len = components.getLength(); |
|
2919 XSTypeDefinition srcDecl, dstDecl; |
|
2920 |
|
2921 // add global components |
|
2922 for (int i=0; i<len; i++) { |
|
2923 srcDecl = (XSTypeDefinition) components.item(i); |
|
2924 dstDecl = dstGrammar.getGlobalTypeDecl(srcDecl.getName()); |
|
2925 if (dstDecl == null) { |
|
2926 dstGrammar.addGlobalTypeDecl(srcDecl); |
|
2927 } |
|
2928 else if (dstDecl != srcDecl && !fTolerateDuplicates) { |
|
2929 reportSharingError(srcDecl.getNamespace(), srcDecl.getName()); |
|
2930 } |
|
2931 } |
|
2932 |
|
2933 // add any extended (duplicate) global components |
|
2934 ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.TYPE_DEFINITION); |
|
2935 len = componentsExt.getLength(); |
|
2936 |
|
2937 for (int i=0; i<len; i+= 2) { |
|
2938 final String key = (String) componentsExt.item(i); |
|
2939 final int index = key.indexOf(','); |
|
2940 final String location = key.substring(0, index); |
|
2941 final String name = key.substring(index + 1, key.length()); |
|
2942 |
|
2943 srcDecl = (XSTypeDefinition)componentsExt.item(i+1); |
|
2944 dstDecl = dstGrammar.getGlobalTypeDecl(name, location); |
|
2945 if (dstDecl == null) { |
|
2946 dstGrammar.addGlobalTypeDecl(srcDecl, location); |
|
2947 } |
|
2948 // REVISIT - do we report an error? |
|
2949 else if (dstDecl != srcDecl) { |
|
2950 } |
|
2951 } |
|
2952 } |
|
2953 |
|
2954 private Vector expandComponents(XSObject[] components, Map<String, Vector> dependencies) { |
|
2955 Vector newComponents = new Vector(); |
|
2956 |
|
2957 for (int i=0; i<components.length; i++) { |
|
2958 if (!newComponents.contains(components[i])) { |
|
2959 newComponents.add(components[i]); |
|
2960 } |
|
2961 } |
|
2962 |
|
2963 for (int i=0; i<newComponents.size(); i++) { |
|
2964 final XSObject component = (XSObject) newComponents.elementAt(i); |
|
2965 expandRelatedComponents(component, newComponents, dependencies); |
|
2966 } |
|
2967 |
|
2968 return newComponents; |
|
2969 } |
|
2970 |
|
2971 private void expandRelatedComponents(XSObject component, Vector componentList, Map<String, Vector> dependencies) { |
|
2972 short componentType = component.getType(); |
|
2973 switch (componentType) { |
|
2974 case XSConstants.TYPE_DEFINITION : |
|
2975 expandRelatedTypeComponents((XSTypeDefinition) component, componentList, component.getNamespace(), dependencies); |
|
2976 break; |
|
2977 case XSConstants.ATTRIBUTE_DECLARATION : |
|
2978 expandRelatedAttributeComponents((XSAttributeDeclaration) component, componentList, component.getNamespace(), dependencies); |
|
2979 break; |
|
2980 case XSConstants.ATTRIBUTE_GROUP : |
|
2981 expandRelatedAttributeGroupComponents((XSAttributeGroupDefinition) component, componentList, component.getNamespace(), dependencies); |
|
2982 case XSConstants.ELEMENT_DECLARATION : |
|
2983 expandRelatedElementComponents((XSElementDeclaration) component, componentList, component.getNamespace(), dependencies); |
|
2984 break; |
|
2985 case XSConstants.MODEL_GROUP_DEFINITION : |
|
2986 expandRelatedModelGroupDefinitionComponents((XSModelGroupDefinition) component, componentList, component.getNamespace(), dependencies); |
|
2987 case XSConstants.ATTRIBUTE_USE : |
|
2988 //expandRelatedAttributeUseComponents((XSAttributeUse)component, componentList, dependencies); |
|
2989 case XSConstants.NOTATION_DECLARATION : |
|
2990 case XSConstants.IDENTITY_CONSTRAINT : |
|
2991 default : |
|
2992 break; |
|
2993 } |
|
2994 } |
|
2995 |
|
2996 private void expandRelatedAttributeComponents(XSAttributeDeclaration decl, Vector componentList, String namespace, Map<String, Vector> dependencies) { |
|
2997 addRelatedType(decl.getTypeDefinition(), componentList, namespace, dependencies); |
|
2998 |
|
2999 /*final XSComplexTypeDefinition enclosingType = decl.getEnclosingCTDefinition(); |
|
3000 if (enclosingType != null) { |
|
3001 addRelatedType(enclosingType, componentList, namespace, dependencies); |
|
3002 }*/ |
|
3003 } |
|
3004 |
|
3005 private void expandRelatedElementComponents(XSElementDeclaration decl, Vector componentList, String namespace, Map<String, Vector> dependencies) { |
|
3006 addRelatedType(decl.getTypeDefinition(), componentList, namespace, dependencies); |
|
3007 |
|
3008 /*final XSTypeDefinition enclosingType = decl.getEnclosingCTDefinition(); |
|
3009 if (enclosingType != null) { |
|
3010 addRelatedType(enclosingType, componentList, namespace, dependencies); |
|
3011 }*/ |
|
3012 |
|
3013 final XSElementDeclaration subElemDecl = decl.getSubstitutionGroupAffiliation(); |
|
3014 if (subElemDecl != null) { |
|
3015 addRelatedElement(subElemDecl, componentList, namespace, dependencies); |
|
3016 } |
|
3017 } |
|
3018 |
|
3019 private void expandRelatedTypeComponents(XSTypeDefinition type, Vector componentList, String namespace, Map<String, Vector> dependencies) { |
|
3020 if (type instanceof XSComplexTypeDecl) { |
|
3021 expandRelatedComplexTypeComponents((XSComplexTypeDecl) type, componentList, namespace, dependencies); |
|
3022 } |
|
3023 else if (type instanceof XSSimpleTypeDecl) { |
|
3024 expandRelatedSimpleTypeComponents((XSSimpleTypeDefinition) type, componentList, namespace, dependencies); |
|
3025 } |
|
3026 } |
|
3027 |
|
3028 private void expandRelatedModelGroupDefinitionComponents(XSModelGroupDefinition modelGroupDef, Vector componentList, |
|
3029 String namespace, Map<String, Vector> dependencies) { |
|
3030 expandRelatedModelGroupComponents(modelGroupDef.getModelGroup(), componentList, namespace, dependencies); |
|
3031 } |
|
3032 |
|
3033 private void expandRelatedAttributeGroupComponents(XSAttributeGroupDefinition attrGroup, Vector componentList |
|
3034 , String namespace, Map<String, Vector> dependencies) { |
|
3035 expandRelatedAttributeUsesComponents(attrGroup.getAttributeUses(), componentList, namespace, dependencies); |
|
3036 } |
|
3037 |
|
3038 private void expandRelatedComplexTypeComponents(XSComplexTypeDecl type, Vector componentList, String namespace, Map<String, Vector> dependencies) { |
|
3039 addRelatedType(type.getBaseType(), componentList, namespace, dependencies); |
|
3040 expandRelatedAttributeUsesComponents(type.getAttributeUses(), componentList, namespace, dependencies); |
|
3041 final XSParticle particle = type.getParticle(); |
|
3042 if (particle != null) { |
|
3043 expandRelatedParticleComponents(particle, componentList, namespace, dependencies); |
|
3044 } |
|
3045 } |
|
3046 |
|
3047 private void expandRelatedSimpleTypeComponents(XSSimpleTypeDefinition type, Vector componentList, String namespace, Map<String, Vector> dependencies) { |
|
3048 final XSTypeDefinition baseType = type.getBaseType(); |
|
3049 if (baseType != null) { |
|
3050 addRelatedType(baseType, componentList, namespace, dependencies); |
|
3051 } |
|
3052 |
|
3053 final XSTypeDefinition itemType = type.getItemType(); |
|
3054 if (itemType != null) { |
|
3055 addRelatedType(itemType, componentList, namespace, dependencies); |
|
3056 } |
|
3057 |
|
3058 final XSTypeDefinition primitiveType = type.getPrimitiveType(); |
|
3059 if (primitiveType != null) { |
|
3060 addRelatedType(primitiveType, componentList, namespace, dependencies); |
|
3061 } |
|
3062 |
|
3063 final XSObjectList memberTypes = type.getMemberTypes(); |
|
3064 if (memberTypes.size() > 0) { |
|
3065 for (int i=0; i<memberTypes.size(); i++) { |
|
3066 addRelatedType((XSTypeDefinition)memberTypes.item(i), componentList, namespace, dependencies); |
|
3067 } |
|
3068 } |
|
3069 } |
|
3070 |
|
3071 private void expandRelatedAttributeUsesComponents(XSObjectList attrUses, Vector componentList, |
|
3072 String namespace, Map<String, Vector> dependencies) { |
|
3073 final int attrUseSize = (attrUses == null) ? 0 : attrUses.size(); |
|
3074 for (int i=0; i<attrUseSize; i++) { |
|
3075 expandRelatedAttributeUseComponents((XSAttributeUse)attrUses.item(i), componentList, namespace, dependencies); |
|
3076 } |
|
3077 } |
|
3078 |
|
3079 private void expandRelatedAttributeUseComponents(XSAttributeUse component, Vector componentList, |
|
3080 String namespace, Map<String, Vector> dependencies) { |
|
3081 addRelatedAttribute(component.getAttrDeclaration(), componentList, namespace, dependencies); |
|
3082 } |
|
3083 |
|
3084 private void expandRelatedParticleComponents(XSParticle component, Vector componentList, |
|
3085 String namespace, Map<String, Vector> dependencies) { |
|
3086 XSTerm term = component.getTerm(); |
|
3087 switch (term.getType()) { |
|
3088 case XSConstants.ELEMENT_DECLARATION : |
|
3089 addRelatedElement((XSElementDeclaration) term, componentList, namespace, dependencies); |
|
3090 break; |
|
3091 case XSConstants.MODEL_GROUP : |
|
3092 expandRelatedModelGroupComponents((XSModelGroup) term, componentList, namespace, dependencies); |
|
3093 break; |
|
3094 default: |
|
3095 break; |
|
3096 } |
|
3097 } |
|
3098 |
|
3099 private void expandRelatedModelGroupComponents(XSModelGroup modelGroup, Vector componentList, |
|
3100 String namespace, Map<String, Vector> dependencies) { |
|
3101 XSObjectList particles = modelGroup.getParticles(); |
|
3102 final int length = (particles == null) ? 0 : particles.getLength(); |
|
3103 for (int i=0; i<length; i++) { |
|
3104 expandRelatedParticleComponents((XSParticle)particles.item(i), componentList, namespace, dependencies); |
|
3105 } |
|
3106 } |
|
3107 |
|
3108 private void addRelatedType(XSTypeDefinition type, Vector componentList, String namespace, Map<String, Vector> dependencies) { |
|
3109 if (!type.getAnonymous()) { |
|
3110 if (!type.getNamespace().equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) { //REVISIT - do we use == instead |
|
3111 if (!componentList.contains(type)) { |
|
3112 final Vector importedNamespaces = findDependentNamespaces(namespace, dependencies); |
|
3113 addNamespaceDependency(namespace, type.getNamespace(), importedNamespaces); |
|
3114 componentList.add(type); |
|
3115 } |
|
3116 } |
|
3117 } |
|
3118 else { |
|
3119 expandRelatedTypeComponents(type, componentList, namespace, dependencies); |
|
3120 } |
|
3121 } |
|
3122 |
|
3123 private void addRelatedElement(XSElementDeclaration decl, Vector componentList, String namespace, Map<String, Vector> dependencies) { |
|
3124 if (decl.getScope() == XSConstants.SCOPE_GLOBAL) { |
|
3125 if (!componentList.contains(decl)) { |
|
3126 Vector importedNamespaces = findDependentNamespaces(namespace, dependencies); |
|
3127 addNamespaceDependency(namespace, decl.getNamespace(), importedNamespaces); |
|
3128 componentList.add(decl); |
|
3129 } |
|
3130 } |
|
3131 else { |
|
3132 expandRelatedElementComponents(decl, componentList, namespace, dependencies); |
|
3133 } |
|
3134 } |
|
3135 |
|
3136 private void addRelatedAttribute(XSAttributeDeclaration decl, Vector componentList, String namespace, Map<String, Vector> dependencies) { |
|
3137 if (decl.getScope() == XSConstants.SCOPE_GLOBAL) { |
|
3138 if (!componentList.contains(decl)) { |
|
3139 Vector importedNamespaces = findDependentNamespaces(namespace, dependencies); |
|
3140 addNamespaceDependency(namespace, decl.getNamespace(), importedNamespaces); |
|
3141 componentList.add(decl); |
|
3142 } |
|
3143 } |
|
3144 else { |
|
3145 expandRelatedAttributeComponents(decl, componentList, namespace, dependencies); |
|
3146 } |
|
3147 } |
|
3148 |
|
3149 private void addGlobalComponents(Vector components, Map<String, Vector> importDependencies) { |
|
3150 final XSDDescription desc = new XSDDescription(); |
|
3151 final int size = components.size(); |
|
3152 |
|
3153 for (int i=0; i<size; i++) { |
|
3154 addGlobalComponent((XSObject) components.elementAt(i), desc); |
|
3155 } |
|
3156 updateImportDependencies(importDependencies); |
|
3157 } |
|
3158 |
|
3159 private void addGlobalComponent(XSObject component, XSDDescription desc) { |
|
3160 final String namespace = component.getNamespace(); |
|
3161 |
|
3162 desc.setNamespace(namespace); |
|
3163 final SchemaGrammar sg = getSchemaGrammar(desc); |
|
3164 |
|
3165 short componentType = component.getType(); |
|
3166 final String name = component.getName(); |
|
3167 |
|
3168 switch (componentType) { |
|
3169 case XSConstants.TYPE_DEFINITION : |
|
3170 if (!((XSTypeDefinition) component).getAnonymous()) { |
|
3171 if (sg.getGlobalTypeDecl(name) == null) { |
|
3172 sg.addGlobalTypeDecl((XSTypeDefinition) component); |
|
3173 } |
|
3174 // store the declaration in the extended map, using an empty location |
|
3175 if (sg.getGlobalTypeDecl(name, "") == null) { |
|
3176 sg.addGlobalTypeDecl((XSTypeDefinition) component, ""); |
|
3177 } |
|
3178 } |
|
3179 break; |
|
3180 case XSConstants.ATTRIBUTE_DECLARATION : |
|
3181 if (((XSAttributeDecl) component).getScope() == XSAttributeDecl.SCOPE_GLOBAL) { |
|
3182 if (sg.getGlobalAttributeDecl(name) == null) { |
|
3183 sg.addGlobalAttributeDecl((XSAttributeDecl) component); |
|
3184 } |
|
3185 // store the declaration in the extended map, using an empty location |
|
3186 if (sg.getGlobalAttributeDecl(name, "") == null) { |
|
3187 sg.addGlobalAttributeDecl((XSAttributeDecl) component, ""); |
|
3188 } |
|
3189 } |
|
3190 break; |
|
3191 case XSConstants.ATTRIBUTE_GROUP : |
|
3192 if (sg.getGlobalAttributeDecl(name) == null) { |
|
3193 sg.addGlobalAttributeGroupDecl((XSAttributeGroupDecl) component); |
|
3194 } |
|
3195 // store the declaration in the extended map, using an empty location |
|
3196 if (sg.getGlobalAttributeDecl(name, "") == null) { |
|
3197 sg.addGlobalAttributeGroupDecl((XSAttributeGroupDecl) component, ""); |
|
3198 } |
|
3199 break; |
|
3200 case XSConstants.ELEMENT_DECLARATION : |
|
3201 if (((XSElementDecl) component).getScope() == XSElementDecl.SCOPE_GLOBAL) { |
|
3202 sg.addGlobalElementDeclAll((XSElementDecl) component); |
|
3203 |
|
3204 if (sg.getGlobalElementDecl(name) == null) { |
|
3205 sg.addGlobalElementDecl((XSElementDecl) component); |
|
3206 } |
|
3207 // store the declaration in the extended map, using an empty location |
|
3208 if (sg.getGlobalElementDecl(name, "") == null) { |
|
3209 sg.addGlobalElementDecl((XSElementDecl) component, ""); |
|
3210 } |
|
3211 } |
|
3212 break; |
|
3213 case XSConstants.MODEL_GROUP_DEFINITION : |
|
3214 if (sg.getGlobalGroupDecl(name) == null) { |
|
3215 sg.addGlobalGroupDecl((XSGroupDecl) component); |
|
3216 } |
|
3217 // store the declaration in the extended map, using an empty location |
|
3218 if (sg.getGlobalGroupDecl(name, "") == null) { |
|
3219 sg.addGlobalGroupDecl((XSGroupDecl) component, ""); |
|
3220 } |
|
3221 break; |
|
3222 case XSConstants.NOTATION_DECLARATION : |
|
3223 if (sg.getGlobalNotationDecl(name) == null) { |
|
3224 sg.addGlobalNotationDecl((XSNotationDecl) component); |
|
3225 } |
|
3226 // store the declaration in the extended map, using an empty location |
|
3227 if (sg.getGlobalNotationDecl(name, "") == null) { |
|
3228 sg.addGlobalNotationDecl((XSNotationDecl) component, ""); |
|
3229 } |
|
3230 break; |
|
3231 case XSConstants.IDENTITY_CONSTRAINT : |
|
3232 case XSConstants.ATTRIBUTE_USE : |
|
3233 default : |
|
3234 break; |
|
3235 } |
|
3236 } |
|
3237 |
|
3238 private void updateImportDependencies(Map<String, Vector> table) { |
|
3239 if (table == null) return; |
|
3240 String namespace; |
|
3241 Vector importList; |
|
3242 |
|
3243 for(Map.Entry<String, Vector> entry : table.entrySet()){ |
|
3244 namespace = entry.getKey(); |
|
3245 importList = entry.getValue(); |
|
3246 if (importList.size() > 0) { |
|
3247 expandImportList(namespace, importList); |
|
3248 } |
|
3249 } |
|
3250 } |
|
3251 |
|
3252 private void expandImportList(String namespace, Vector namespaceList) { |
|
3253 SchemaGrammar sg = fGrammarBucket.getGrammar(namespace); |
|
3254 // shouldn't be null |
|
3255 if (sg != null) { |
|
3256 Vector isgs = sg.getImportedGrammars(); |
|
3257 if (isgs == null) { |
|
3258 isgs = new Vector(); |
|
3259 addImportList(sg, isgs, namespaceList); |
|
3260 sg.setImportedGrammars(isgs); |
|
3261 } |
|
3262 else { |
|
3263 updateImportList(sg, isgs, namespaceList); |
|
3264 } |
|
3265 } |
|
3266 } |
|
3267 |
|
3268 private void addImportList(SchemaGrammar sg, Vector importedGrammars, Vector namespaceList) { |
|
3269 final int size = namespaceList.size(); |
|
3270 SchemaGrammar isg; |
|
3271 |
|
3272 for (int i=0; i<size; i++) { |
|
3273 isg = fGrammarBucket.getGrammar((String)namespaceList.elementAt(i)); |
|
3274 if (isg != null) { |
|
3275 importedGrammars.add(isg); |
|
3276 } |
|
3277 else { |
|
3278 //REVIST: report an error message |
|
3279 } |
|
3280 } |
|
3281 } |
|
3282 |
|
3283 private void updateImportList(SchemaGrammar sg, Vector importedGrammars, Vector namespaceList) { |
|
3284 final int size = namespaceList.size(); |
|
3285 SchemaGrammar isg; |
|
3286 |
|
3287 for (int i=0; i<size; i++) { |
|
3288 isg = fGrammarBucket.getGrammar((String)namespaceList.elementAt(i)); |
|
3289 if (isg != null) { |
|
3290 if (!containedImportedGrammar(importedGrammars, isg)) { |
|
3291 importedGrammars.add(isg); |
|
3292 } |
|
3293 } |
|
3294 else { |
|
3295 //REVIST: report an error message |
|
3296 } |
|
3297 } |
|
3298 } |
|
3299 |
|
3300 private boolean containedImportedGrammar(Vector importedGrammar, SchemaGrammar grammar) { |
|
3301 final int size = importedGrammar.size(); |
|
3302 SchemaGrammar sg; |
|
3303 |
|
3304 for (int i=0; i<size; i++) { |
|
3305 sg = (SchemaGrammar) importedGrammar.elementAt(i); |
|
3306 if (null2EmptyString(sg.getTargetNamespace()).equals(null2EmptyString(grammar.getTargetNamespace()))) { |
|
3307 return true; |
|
3308 } |
|
3309 } |
|
3310 return false; |
|
3311 } |
|
3312 |
|
3313 // NOTE: always assuming that fNamespaceGrowth is enabled |
|
3314 // otherwise the grammar should have existed |
|
3315 private SchemaGrammar getSchemaGrammar(XSDDescription desc) { |
|
3316 SchemaGrammar sg = findGrammar(desc, fNamespaceGrowth); |
|
3317 |
|
3318 if (sg == null) { |
|
3319 sg = new SchemaGrammar(desc.getNamespace(), desc.makeClone(), fSymbolTable); |
|
3320 fGrammarBucket.putGrammar(sg); |
|
3321 } |
|
3322 else if (sg.isImmutable()){ |
|
3323 sg = createGrammarFrom(sg); |
|
3324 } |
|
3325 |
|
3326 return sg; |
|
3327 } |
|
3328 |
|
3329 private Vector findDependentNamespaces(String namespace, Map table) { |
|
3330 final String ns = null2EmptyString(namespace); |
|
3331 Vector namespaceList = (Vector) getFromMap(table, ns); |
|
3332 |
|
3333 if (namespaceList == null) { |
|
3334 namespaceList = new Vector(); |
|
3335 table.put(ns, namespaceList); |
|
3336 } |
|
3337 |
|
3338 return namespaceList; |
|
3339 } |
|
3340 |
|
3341 private void addNamespaceDependency(String namespace1, String namespace2, Vector list) { |
|
3342 final String ns1 = null2EmptyString(namespace1); |
|
3343 final String ns2 = null2EmptyString(namespace2); |
|
3344 if (!ns1.equals(ns2)) { |
|
3345 if (!list.contains(ns2)) { |
|
3346 list.add(ns2); |
|
3347 } |
|
3348 } |
|
3349 } |
|
3350 |
|
3351 private void reportSharingError(String namespace, String name) { |
|
3352 final String qName = (namespace == null) |
|
3353 ? "," + name : namespace + "," + name; |
|
3354 |
|
3355 reportSchemaError("sch-props-correct.2", new Object [] {qName}, null); |
|
3356 } |
|
3357 |
|
3358 // initialize all the traversers. |
|
3359 // this should only need to be called once during the construction |
|
3360 // of this object; it creates the traversers that will be used to |
|
3361 |
|
3362 // construct schemaGrammars. |
|
3363 private void createTraversers() { |
|
3364 fAttributeChecker = new XSAttributeChecker(this); |
|
3365 fAttributeGroupTraverser = new XSDAttributeGroupTraverser(this, fAttributeChecker); |
|
3366 fAttributeTraverser = new XSDAttributeTraverser(this, fAttributeChecker); |
|
3367 fComplexTypeTraverser = new XSDComplexTypeTraverser(this, fAttributeChecker); |
|
3368 fElementTraverser = new XSDElementTraverser(this, fAttributeChecker); |
|
3369 fGroupTraverser = new XSDGroupTraverser(this, fAttributeChecker); |
|
3370 fKeyrefTraverser = new XSDKeyrefTraverser(this, fAttributeChecker); |
|
3371 fNotationTraverser = new XSDNotationTraverser(this, fAttributeChecker); |
|
3372 fSimpleTypeTraverser = new XSDSimpleTypeTraverser(this, fAttributeChecker); |
|
3373 fUniqueOrKeyTraverser = new XSDUniqueOrKeyTraverser(this, fAttributeChecker); |
|
3374 fWildCardTraverser = new XSDWildcardTraverser(this, fAttributeChecker); |
|
3375 } // createTraversers() |
|
3376 |
|
3377 // before parsing a schema, need to clear registries associated with |
|
3378 // parsing schemas |
|
3379 void prepareForParse() { |
|
3380 fTraversed.clear(); |
|
3381 fDoc2SystemId.clear(); |
|
3382 fHiddenNodes.clear(); |
|
3383 fLastSchemaWasDuplicate = false; |
|
3384 } |
|
3385 |
|
3386 // before traversing a schema's parse tree, need to reset all traversers and |
|
3387 // clear all registries |
|
3388 void prepareForTraverse() { |
|
3389 if (!registryEmpty) { |
|
3390 fUnparsedAttributeRegistry.clear(); |
|
3391 fUnparsedAttributeGroupRegistry.clear(); |
|
3392 fUnparsedElementRegistry.clear(); |
|
3393 fUnparsedGroupRegistry.clear(); |
|
3394 fUnparsedIdentityConstraintRegistry.clear(); |
|
3395 fUnparsedNotationRegistry.clear(); |
|
3396 fUnparsedTypeRegistry.clear(); |
|
3397 |
|
3398 fUnparsedAttributeRegistrySub.clear(); |
|
3399 fUnparsedAttributeGroupRegistrySub.clear(); |
|
3400 fUnparsedElementRegistrySub.clear(); |
|
3401 fUnparsedGroupRegistrySub.clear(); |
|
3402 fUnparsedIdentityConstraintRegistrySub.clear(); |
|
3403 fUnparsedNotationRegistrySub.clear(); |
|
3404 fUnparsedTypeRegistrySub.clear(); |
|
3405 } |
|
3406 |
|
3407 for (int i=1; i<= TYPEDECL_TYPE; i++) { |
|
3408 if (fUnparsedRegistriesExt[i] != null) |
|
3409 fUnparsedRegistriesExt[i].clear(); |
|
3410 } |
|
3411 |
|
3412 fDependencyMap.clear(); |
|
3413 fDoc2XSDocumentMap.clear(); |
|
3414 if (fRedefine2XSDMap != null) fRedefine2XSDMap.clear(); |
|
3415 if (fRedefine2NSSupport != null) fRedefine2NSSupport.clear(); |
|
3416 fAllTNSs.removeAllElements(); |
|
3417 fImportMap.clear(); |
|
3418 fRoot = null; |
|
3419 |
|
3420 // clear local element stack |
|
3421 for (int i = 0; i < fLocalElemStackPos; i++) { |
|
3422 fParticle[i] = null; |
|
3423 fLocalElementDecl[i] = null; |
|
3424 fLocalElementDecl_schema[i] = null; |
|
3425 fLocalElemNamespaceContext[i] = null; |
|
3426 } |
|
3427 fLocalElemStackPos = 0; |
|
3428 |
|
3429 // and do same for keyrefs. |
|
3430 for (int i = 0; i < fKeyrefStackPos; i++) { |
|
3431 fKeyrefs[i] = null; |
|
3432 fKeyrefElems[i] = null; |
|
3433 fKeyrefNamespaceContext[i] = null; |
|
3434 fKeyrefsMapXSDocumentInfo[i] = null; |
|
3435 } |
|
3436 fKeyrefStackPos = 0; |
|
3437 |
|
3438 // create traversers if necessary |
|
3439 if (fAttributeChecker == null) { |
|
3440 createTraversers(); |
|
3441 } |
|
3442 |
|
3443 // reset traversers |
|
3444 Locale locale = fErrorReporter.getLocale(); |
|
3445 fAttributeChecker.reset(fSymbolTable); |
|
3446 fAttributeGroupTraverser.reset(fSymbolTable, fValidateAnnotations, locale); |
|
3447 fAttributeTraverser.reset(fSymbolTable, fValidateAnnotations, locale); |
|
3448 fComplexTypeTraverser.reset(fSymbolTable, fValidateAnnotations, locale); |
|
3449 fElementTraverser.reset(fSymbolTable, fValidateAnnotations, locale); |
|
3450 fGroupTraverser.reset(fSymbolTable, fValidateAnnotations, locale); |
|
3451 fKeyrefTraverser.reset(fSymbolTable, fValidateAnnotations, locale); |
|
3452 fNotationTraverser.reset(fSymbolTable, fValidateAnnotations, locale); |
|
3453 fSimpleTypeTraverser.reset(fSymbolTable, fValidateAnnotations, locale); |
|
3454 fUniqueOrKeyTraverser.reset(fSymbolTable, fValidateAnnotations, locale); |
|
3455 fWildCardTraverser.reset(fSymbolTable, fValidateAnnotations, locale); |
|
3456 |
|
3457 fRedefinedRestrictedAttributeGroupRegistry.clear(); |
|
3458 fRedefinedRestrictedGroupRegistry.clear(); |
|
3459 |
|
3460 fGlobalAttrDecls.clear(); |
|
3461 fGlobalAttrGrpDecls.clear(); |
|
3462 fGlobalElemDecls.clear(); |
|
3463 fGlobalGroupDecls.clear(); |
|
3464 fGlobalNotationDecls.clear(); |
|
3465 fGlobalIDConstraintDecls.clear(); |
|
3466 fGlobalTypeDecls.clear(); |
|
3467 } |
|
3468 public void setDeclPool (XSDeclarationPool declPool){ |
|
3469 fDeclPool = declPool; |
|
3470 } |
|
3471 public void setDVFactory(SchemaDVFactory dvFactory){ |
|
3472 fDVFactory = dvFactory; |
|
3473 } |
|
3474 public SchemaDVFactory getDVFactory(){ |
|
3475 return fDVFactory; |
|
3476 } |
|
3477 |
|
3478 public void reset(XMLComponentManager componentManager) { |
|
3479 |
|
3480 // set symbol table |
|
3481 fSymbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE); |
|
3482 |
|
3483 fSecureProcessing = null; |
|
3484 if( componentManager!=null ) { |
|
3485 fSecureProcessing = (SecurityManager) componentManager.getProperty(SECURE_PROCESSING, null); |
|
3486 } |
|
3487 |
|
3488 //set entity resolver |
|
3489 fEntityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER); |
|
3490 XMLEntityResolver er = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER); |
|
3491 if (er != null) |
|
3492 fSchemaParser.setEntityResolver(er); |
|
3493 |
|
3494 // set error reporter |
|
3495 fErrorReporter = |
|
3496 (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); |
|
3497 try { |
|
3498 XMLErrorHandler currErrorHandler = fErrorReporter.getErrorHandler(); |
|
3499 // Setting a parser property can be much more expensive |
|
3500 // than checking its value. Don't set the ERROR_HANDLER |
|
3501 // or LOCALE properties unless they've actually changed. |
|
3502 if (currErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) { |
|
3503 fSchemaParser.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler()); |
|
3504 if (fAnnotationValidator != null) { |
|
3505 fAnnotationValidator.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler()); |
|
3506 } |
|
3507 } |
|
3508 Locale currentLocale = fErrorReporter.getLocale(); |
|
3509 if (currentLocale != fSchemaParser.getProperty(LOCALE)) { |
|
3510 fSchemaParser.setProperty(LOCALE, currentLocale); |
|
3511 if (fAnnotationValidator != null) { |
|
3512 fAnnotationValidator.setProperty(LOCALE, currentLocale); |
|
3513 } |
|
3514 } |
|
3515 } |
|
3516 catch (XMLConfigurationException e) {} |
|
3517 |
|
3518 fValidateAnnotations = componentManager.getFeature(VALIDATE_ANNOTATIONS, false); |
|
3519 fHonourAllSchemaLocations = componentManager.getFeature(HONOUR_ALL_SCHEMALOCATIONS, false); |
|
3520 fNamespaceGrowth = componentManager.getFeature(NAMESPACE_GROWTH, false); |
|
3521 fTolerateDuplicates = componentManager.getFeature(TOLERATE_DUPLICATES, false); |
|
3522 |
|
3523 try { |
|
3524 fSchemaParser.setFeature( |
|
3525 CONTINUE_AFTER_FATAL_ERROR, |
|
3526 fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR)); |
|
3527 } catch (XMLConfigurationException e) { |
|
3528 } |
|
3529 |
|
3530 try { |
|
3531 if (componentManager.getFeature(ALLOW_JAVA_ENCODINGS, false)) { |
|
3532 fSchemaParser.setFeature(ALLOW_JAVA_ENCODINGS, true); |
|
3533 } |
|
3534 } catch (XMLConfigurationException e) { |
|
3535 } |
|
3536 try { |
|
3537 if (componentManager.getFeature(STANDARD_URI_CONFORMANT_FEATURE, false)) { |
|
3538 fSchemaParser.setFeature(STANDARD_URI_CONFORMANT_FEATURE, true); |
|
3539 } |
|
3540 } catch (XMLConfigurationException e) { |
|
3541 } |
|
3542 |
|
3543 try { |
|
3544 fGrammarPool = |
|
3545 (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL); |
|
3546 } catch (XMLConfigurationException e) { |
|
3547 fGrammarPool = null; |
|
3548 } |
|
3549 // security features |
|
3550 try { |
|
3551 if (componentManager.getFeature(DISALLOW_DOCTYPE, false)) { |
|
3552 fSchemaParser.setFeature(DISALLOW_DOCTYPE, true); |
|
3553 } |
|
3554 } catch (XMLConfigurationException e) { |
|
3555 } |
|
3556 try { |
|
3557 Object security = componentManager.getProperty(SECURITY_MANAGER, null); |
|
3558 if (security != null){ |
|
3559 fSchemaParser.setProperty(SECURITY_MANAGER, security); |
|
3560 } |
|
3561 } catch (XMLConfigurationException e) { |
|
3562 } |
|
3563 |
|
3564 } // reset(XMLComponentManager) |
|
3565 |
|
3566 |
|
3567 /** |
|
3568 * Traverse all the deferred local elements. This method should be called |
|
3569 * by traverseSchemas after we've done with all the global declarations. |
|
3570 */ |
|
3571 void traverseLocalElements() { |
|
3572 fElementTraverser.fDeferTraversingLocalElements = false; |
|
3573 |
|
3574 for (int i = 0; i < fLocalElemStackPos; i++) { |
|
3575 Element currElem = fLocalElementDecl[i]; |
|
3576 //XSDocumentInfo currSchema = (XSDocumentInfo)fDoc2XSDocumentMap.get(DOMUtil.getDocument(currElem)); |
|
3577 //XSDocumentInfo currSchema = (XSDocumentInfo)fDoc2XSDocumentMap.get(DOMUtil.getRoot(DOMUtil.getDocument(currElem))); |
|
3578 XSDocumentInfo currSchema = fLocalElementDecl_schema[i]; |
|
3579 SchemaGrammar currGrammar = fGrammarBucket.getGrammar(currSchema.fTargetNamespace); |
|
3580 fElementTraverser.traverseLocal (fParticle[i], currElem, currSchema, currGrammar, fAllContext[i], fParent[i], fLocalElemNamespaceContext[i]); |
|
3581 // If it's an empty particle, remove it from the containing component. |
|
3582 if (fParticle[i].fType == XSParticleDecl.PARTICLE_EMPTY) { |
|
3583 XSModelGroupImpl group = null; |
|
3584 if (fParent[i] instanceof XSComplexTypeDecl) { |
|
3585 XSParticle p = ((XSComplexTypeDecl)fParent[i]).getParticle(); |
|
3586 if (p != null) |
|
3587 group = (XSModelGroupImpl)p.getTerm(); |
|
3588 } |
|
3589 else { |
|
3590 group = ((XSGroupDecl)fParent[i]).fModelGroup; |
|
3591 } |
|
3592 if (group != null) |
|
3593 removeParticle(group, fParticle[i]); |
|
3594 } |
|
3595 } |
|
3596 } |
|
3597 |
|
3598 private boolean removeParticle(XSModelGroupImpl group, XSParticleDecl particle) { |
|
3599 XSParticleDecl member; |
|
3600 for (int i = 0; i < group.fParticleCount; i++) { |
|
3601 member = group.fParticles[i]; |
|
3602 if (member == particle) { |
|
3603 for (int j = i; j < group.fParticleCount-1; j++) |
|
3604 group.fParticles[j] = group.fParticles[j+1]; |
|
3605 group.fParticleCount--; |
|
3606 return true; |
|
3607 } |
|
3608 if (member.fType == XSParticleDecl.PARTICLE_MODELGROUP) { |
|
3609 if (removeParticle((XSModelGroupImpl)member.fValue, particle)) |
|
3610 return true; |
|
3611 } |
|
3612 } |
|
3613 return false; |
|
3614 } |
|
3615 |
|
3616 // the purpose of this method is to keep up-to-date structures |
|
3617 // we'll need for the feferred traversal of local elements. |
|
3618 void fillInLocalElemInfo(Element elmDecl, |
|
3619 XSDocumentInfo schemaDoc, |
|
3620 int allContextFlags, |
|
3621 XSObject parent, |
|
3622 XSParticleDecl particle) { |
|
3623 |
|
3624 // if the stack is full, increase the size |
|
3625 if (fParticle.length == fLocalElemStackPos) { |
|
3626 // increase size |
|
3627 XSParticleDecl[] newStackP = new XSParticleDecl[fLocalElemStackPos+INC_STACK_SIZE]; |
|
3628 System.arraycopy(fParticle, 0, newStackP, 0, fLocalElemStackPos); |
|
3629 fParticle = newStackP; |
|
3630 Element[] newStackE = new Element[fLocalElemStackPos+INC_STACK_SIZE]; |
|
3631 System.arraycopy(fLocalElementDecl, 0, newStackE, 0, fLocalElemStackPos); |
|
3632 fLocalElementDecl = newStackE; |
|
3633 XSDocumentInfo [] newStackE_schema = new XSDocumentInfo[fLocalElemStackPos+INC_STACK_SIZE]; |
|
3634 System.arraycopy(fLocalElementDecl_schema, 0, newStackE_schema, 0, fLocalElemStackPos); |
|
3635 fLocalElementDecl_schema = newStackE_schema; |
|
3636 int[] newStackI = new int[fLocalElemStackPos+INC_STACK_SIZE]; |
|
3637 System.arraycopy(fAllContext, 0, newStackI, 0, fLocalElemStackPos); |
|
3638 fAllContext = newStackI; |
|
3639 XSObject[] newStackC = new XSObject[fLocalElemStackPos+INC_STACK_SIZE]; |
|
3640 System.arraycopy(fParent, 0, newStackC, 0, fLocalElemStackPos); |
|
3641 fParent = newStackC; |
|
3642 String [][] newStackN = new String [fLocalElemStackPos+INC_STACK_SIZE][]; |
|
3643 System.arraycopy(fLocalElemNamespaceContext, 0, newStackN, 0, fLocalElemStackPos); |
|
3644 fLocalElemNamespaceContext = newStackN; |
|
3645 } |
|
3646 |
|
3647 fParticle[fLocalElemStackPos] = particle; |
|
3648 fLocalElementDecl[fLocalElemStackPos] = elmDecl; |
|
3649 fLocalElementDecl_schema[fLocalElemStackPos] = schemaDoc; |
|
3650 fAllContext[fLocalElemStackPos] = allContextFlags; |
|
3651 fParent[fLocalElemStackPos] = parent; |
|
3652 fLocalElemNamespaceContext[fLocalElemStackPos++] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext(); |
|
3653 } // end fillInLocalElemInfo(...) |
|
3654 |
|
3655 /** This method makes sure that |
|
3656 * if this component is being redefined that it lives in the |
|
3657 * right schema. It then renames the component correctly. If it |
|
3658 * detects a collision--a duplicate definition--then it complains. |
|
3659 * Note that redefines must be handled carefully: if there |
|
3660 * is a collision, it may be because we're redefining something we know about |
|
3661 * or because we've found the thing we're redefining. |
|
3662 */ |
|
3663 void checkForDuplicateNames(String qName, int declType, |
|
3664 Map<String,Element> registry, Map<String,XSDocumentInfo> registry_sub, Element currComp, |
|
3665 XSDocumentInfo currSchema) { |
|
3666 Object objElem = null; |
|
3667 // REVISIT: when we add derivation checking, we'll have to make |
|
3668 // sure that ID constraint collisions don't necessarily result in error messages. |
|
3669 if ((objElem = registry.get(qName)) == null) { |
|
3670 // need to check whether we have a global declaration in the corresponding |
|
3671 // grammar |
|
3672 if (fNamespaceGrowth && !fTolerateDuplicates) { |
|
3673 checkForDuplicateNames(qName, declType, currComp); |
|
3674 } |
|
3675 // just add it in! |
|
3676 registry.put(qName, currComp); |
|
3677 registry_sub.put(qName, currSchema); |
|
3678 } |
|
3679 else { |
|
3680 Element collidingElem = (Element)objElem; |
|
3681 XSDocumentInfo collidingElemSchema = (XSDocumentInfo)registry_sub.get(qName); |
|
3682 if (collidingElem == currComp) return; |
|
3683 Element elemParent = null; |
|
3684 XSDocumentInfo redefinedSchema = null; |
|
3685 // case where we've collided with a redefining element |
|
3686 // (the parent of the colliding element is a redefine) |
|
3687 boolean collidedWithRedefine = true; |
|
3688 if ((DOMUtil.getLocalName((elemParent = DOMUtil.getParent(collidingElem))).equals(SchemaSymbols.ELT_REDEFINE))) { |
|
3689 redefinedSchema = (fRedefine2XSDMap != null)?(XSDocumentInfo) (fRedefine2XSDMap.get(elemParent)): null; |
|
3690 // case where we're a redefining element. |
|
3691 } |
|
3692 else if ((DOMUtil.getLocalName(DOMUtil.getParent(currComp)).equals(SchemaSymbols.ELT_REDEFINE))) { |
|
3693 redefinedSchema = collidingElemSchema; |
|
3694 collidedWithRedefine = false; |
|
3695 } |
|
3696 if (redefinedSchema != null) { //redefinition involved somehow |
|
3697 // If both components belong to the same document then |
|
3698 // report an error and return. |
|
3699 if(collidingElemSchema == currSchema){ |
|
3700 reportSchemaError("sch-props-correct.2", new Object[]{qName}, currComp); |
|
3701 return; |
|
3702 } |
|
3703 |
|
3704 String newName = qName.substring(qName.lastIndexOf(',')+1)+REDEF_IDENTIFIER; |
|
3705 if (redefinedSchema == currSchema) { // object comp. okay here |
|
3706 // now have to do some renaming... |
|
3707 currComp.setAttribute(SchemaSymbols.ATT_NAME, newName); |
|
3708 if (currSchema.fTargetNamespace == null){ |
|
3709 registry.put(","+newName, currComp); |
|
3710 registry_sub.put(","+newName, currSchema); |
|
3711 } |
|
3712 else{ |
|
3713 registry.put(currSchema.fTargetNamespace+","+newName, currComp); |
|
3714 registry_sub.put(currSchema.fTargetNamespace+","+newName, currSchema); |
|
3715 } |
|
3716 // and take care of nested redefines by calling recursively: |
|
3717 if (currSchema.fTargetNamespace == null) |
|
3718 checkForDuplicateNames(","+newName, declType, registry, registry_sub, currComp, currSchema); |
|
3719 else |
|
3720 checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, declType, registry, registry_sub, currComp, currSchema); |
|
3721 } |
|
3722 else { // we may be redefining the wrong schema |
|
3723 if (collidedWithRedefine) { |
|
3724 if (currSchema.fTargetNamespace == null) |
|
3725 checkForDuplicateNames(","+newName, declType, registry, registry_sub, currComp, currSchema); |
|
3726 else |
|
3727 checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, declType, registry, registry_sub, currComp, currSchema); |
|
3728 } |
|
3729 else { |
|
3730 // error that redefined element in wrong schema |
|
3731 reportSchemaError("sch-props-correct.2", new Object [] {qName}, currComp); |
|
3732 } |
|
3733 } |
|
3734 } |
|
3735 else { |
|
3736 // we've just got a flat-out collision (we tolerate duplicate |
|
3737 // declarations, only if they are defined in different schema |
|
3738 // documents) |
|
3739 if (!fTolerateDuplicates) { |
|
3740 reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp); |
|
3741 } else if (fUnparsedRegistriesExt[declType] != null) { |
|
3742 if (fUnparsedRegistriesExt[declType].get(qName) == currSchema) { |
|
3743 reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp); |
|
3744 } |
|
3745 } |
|
3746 } |
|
3747 } |
|
3748 |
|
3749 // store the lastest current document info |
|
3750 if (fTolerateDuplicates) { |
|
3751 if (fUnparsedRegistriesExt[declType] == null) |
|
3752 fUnparsedRegistriesExt[declType] = new HashMap(); |
|
3753 fUnparsedRegistriesExt[declType].put(qName, currSchema); |
|
3754 } |
|
3755 |
|
3756 } // checkForDuplicateNames(String, Hashtable, Element, XSDocumentInfo):void |
|
3757 |
|
3758 void checkForDuplicateNames(String qName, int declType, Element currComp) { |
|
3759 int namespaceEnd = qName.indexOf(','); |
|
3760 String namespace = qName.substring(0, namespaceEnd); |
|
3761 SchemaGrammar grammar = fGrammarBucket.getGrammar(emptyString2Null(namespace)); |
|
3762 |
|
3763 if (grammar != null) { |
|
3764 Object obj = getGlobalDeclFromGrammar(grammar, declType, qName.substring(namespaceEnd + 1)); |
|
3765 if (obj != null) { |
|
3766 reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp); |
|
3767 } |
|
3768 } |
|
3769 } |
|
3770 |
|
3771 // the purpose of this method is to take the component of the |
|
3772 // specified type and rename references to itself so that they |
|
3773 // refer to the object being redefined. It takes special care of |
|
3774 // <group>s and <attributeGroup>s to ensure that information |
|
3775 // relating to implicit restrictions is preserved for those |
|
3776 // traversers. |
|
3777 private void renameRedefiningComponents(XSDocumentInfo currSchema, |
|
3778 Element child, String componentType, |
|
3779 String oldName, String newName) { |
|
3780 if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) { |
|
3781 Element grandKid = DOMUtil.getFirstChildElement(child); |
|
3782 if (grandKid == null) { |
|
3783 reportSchemaError("src-redefine.5.a.a", null, child); |
|
3784 } |
|
3785 else { |
|
3786 String grandKidName = DOMUtil.getLocalName(grandKid); |
|
3787 if (grandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) { |
|
3788 grandKid = DOMUtil.getNextSiblingElement(grandKid); |
|
3789 } |
|
3790 if (grandKid == null) { |
|
3791 reportSchemaError("src-redefine.5.a.a", null, child); |
|
3792 } |
|
3793 else { |
|
3794 grandKidName = DOMUtil.getLocalName(grandKid); |
|
3795 if (!grandKidName.equals(SchemaSymbols.ELT_RESTRICTION)) { |
|
3796 reportSchemaError("src-redefine.5.a.b", new Object[]{grandKidName}, child); |
|
3797 } |
|
3798 else { |
|
3799 Object[] attrs = fAttributeChecker.checkAttributes(grandKid, false, currSchema); |
|
3800 QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE]; |
|
3801 if (derivedBase == null || |
|
3802 derivedBase.uri != currSchema.fTargetNamespace || |
|
3803 !derivedBase.localpart.equals(oldName)) { |
|
3804 reportSchemaError("src-redefine.5.a.c", |
|
3805 new Object[]{grandKidName, |
|
3806 (currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace) |
|
3807 + "," + oldName}, |
|
3808 child); |
|
3809 } |
|
3810 else { |
|
3811 // now we have to do the renaming... |
|
3812 if (derivedBase.prefix != null && derivedBase.prefix.length() > 0) |
|
3813 grandKid.setAttribute( SchemaSymbols.ATT_BASE, |
|
3814 derivedBase.prefix + ":" + newName ); |
|
3815 else |
|
3816 grandKid.setAttribute( SchemaSymbols.ATT_BASE, newName ); |
|
3817 // return true; |
|
3818 } |
|
3819 fAttributeChecker.returnAttrArray(attrs, currSchema); |
|
3820 } |
|
3821 } |
|
3822 } |
|
3823 } |
|
3824 else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) { |
|
3825 Element grandKid = DOMUtil.getFirstChildElement(child); |
|
3826 if (grandKid == null) { |
|
3827 reportSchemaError("src-redefine.5.b.a", null, child); |
|
3828 } |
|
3829 else { |
|
3830 if (DOMUtil.getLocalName(grandKid).equals(SchemaSymbols.ELT_ANNOTATION)) { |
|
3831 grandKid = DOMUtil.getNextSiblingElement(grandKid); |
|
3832 } |
|
3833 if (grandKid == null) { |
|
3834 reportSchemaError("src-redefine.5.b.a", null, child); |
|
3835 } |
|
3836 else { |
|
3837 // have to go one more level down; let another pass worry whether complexType is valid. |
|
3838 Element greatGrandKid = DOMUtil.getFirstChildElement(grandKid); |
|
3839 if (greatGrandKid == null) { |
|
3840 reportSchemaError("src-redefine.5.b.b", null, grandKid); |
|
3841 } |
|
3842 else { |
|
3843 String greatGrandKidName = DOMUtil.getLocalName(greatGrandKid); |
|
3844 if (greatGrandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) { |
|
3845 greatGrandKid = DOMUtil.getNextSiblingElement(greatGrandKid); |
|
3846 } |
|
3847 if (greatGrandKid == null) { |
|
3848 reportSchemaError("src-redefine.5.b.b", null, grandKid); |
|
3849 } |
|
3850 else { |
|
3851 greatGrandKidName = DOMUtil.getLocalName(greatGrandKid); |
|
3852 if (!greatGrandKidName.equals(SchemaSymbols.ELT_RESTRICTION) && |
|
3853 !greatGrandKidName.equals(SchemaSymbols.ELT_EXTENSION)) { |
|
3854 reportSchemaError("src-redefine.5.b.c", new Object[]{greatGrandKidName}, greatGrandKid); |
|
3855 } |
|
3856 else { |
|
3857 Object[] attrs = fAttributeChecker.checkAttributes(greatGrandKid, false, currSchema); |
|
3858 QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE]; |
|
3859 if (derivedBase == null || |
|
3860 derivedBase.uri != currSchema.fTargetNamespace || |
|
3861 !derivedBase.localpart.equals(oldName)) { |
|
3862 reportSchemaError("src-redefine.5.b.d", |
|
3863 new Object[]{greatGrandKidName, |
|
3864 (currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace) |
|
3865 + "," + oldName}, |
|
3866 greatGrandKid); |
|
3867 } |
|
3868 else { |
|
3869 // now we have to do the renaming... |
|
3870 if (derivedBase.prefix != null && derivedBase.prefix.length() > 0) |
|
3871 greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE, |
|
3872 derivedBase.prefix + ":" + newName ); |
|
3873 else |
|
3874 greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE, |
|
3875 newName ); |
|
3876 // return true; |
|
3877 } |
|
3878 } |
|
3879 } |
|
3880 } |
|
3881 } |
|
3882 } |
|
3883 } |
|
3884 else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { |
|
3885 String processedBaseName = (currSchema.fTargetNamespace == null)? |
|
3886 ","+oldName:currSchema.fTargetNamespace+","+oldName; |
|
3887 int attGroupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema); |
|
3888 if (attGroupRefsCount > 1) { |
|
3889 reportSchemaError("src-redefine.7.1", new Object []{new Integer(attGroupRefsCount)}, child); |
|
3890 } |
|
3891 else if (attGroupRefsCount == 1) { |
|
3892 // return true; |
|
3893 } |
|
3894 else |
|
3895 if (currSchema.fTargetNamespace == null) |
|
3896 fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, ","+newName); |
|
3897 else |
|
3898 fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName); |
|
3899 } |
|
3900 else if (componentType.equals(SchemaSymbols.ELT_GROUP)) { |
|
3901 String processedBaseName = (currSchema.fTargetNamespace == null)? |
|
3902 ","+oldName:currSchema.fTargetNamespace+","+oldName; |
|
3903 int groupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema); |
|
3904 if (groupRefsCount > 1) { |
|
3905 reportSchemaError("src-redefine.6.1.1", new Object []{new Integer(groupRefsCount)}, child); |
|
3906 } |
|
3907 else if (groupRefsCount == 1) { |
|
3908 // return true; |
|
3909 } |
|
3910 else { |
|
3911 if (currSchema.fTargetNamespace == null) |
|
3912 fRedefinedRestrictedGroupRegistry.put(processedBaseName, ","+newName); |
|
3913 else |
|
3914 fRedefinedRestrictedGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName); |
|
3915 } |
|
3916 } |
|
3917 else { |
|
3918 reportSchemaError("Internal-Error", new Object [] {"could not handle this particular <redefine>; please submit your schemas and instance document in a bug report!"}, child); |
|
3919 } |
|
3920 // if we get here then we must have reported an error and failed somewhere... |
|
3921 // return false; |
|
3922 } // renameRedefiningComponents(XSDocumentInfo, Element, String, String, String):void |
|
3923 |
|
3924 // this method takes a name of the form a:b, determines the URI mapped |
|
3925 // to by a in the current SchemaNamespaceSupport object, and returns this |
|
3926 // information in the form (nsURI,b) suitable for lookups in the global |
|
3927 // decl Hashtables. |
|
3928 // REVISIT: should have it return QName, instead of String. this would |
|
3929 // save lots of string concatenation time. we can use |
|
3930 // QName#equals() to compare two QNames, and use QName directly |
|
3931 // as a key to the SymbolHash. |
|
3932 // And when the DV's are ready to return compiled values from |
|
3933 // validate() method, we should just call QNameDV.validate() |
|
3934 // in this method. |
|
3935 private String findQName(String name, XSDocumentInfo schemaDoc) { |
|
3936 SchemaNamespaceSupport currNSMap = schemaDoc.fNamespaceSupport; |
|
3937 int colonPtr = name.indexOf(':'); |
|
3938 String prefix = XMLSymbols.EMPTY_STRING; |
|
3939 if (colonPtr > 0) |
|
3940 prefix = name.substring(0, colonPtr); |
|
3941 String uri = currNSMap.getURI(fSymbolTable.addSymbol(prefix)); |
|
3942 String localpart = (colonPtr == 0)?name:name.substring(colonPtr+1); |
|
3943 if (prefix == XMLSymbols.EMPTY_STRING && uri == null && schemaDoc.fIsChameleonSchema) |
|
3944 uri = schemaDoc.fTargetNamespace; |
|
3945 if (uri == null) |
|
3946 return ","+localpart; |
|
3947 return uri+","+localpart; |
|
3948 } // findQName(String, XSDocumentInfo): String |
|
3949 |
|
3950 // This function looks among the children of curr for an element of type elementSought. |
|
3951 // If it finds one, it evaluates whether its ref attribute contains a reference |
|
3952 // to originalQName. If it does, it returns 1 + the value returned by |
|
3953 // calls to itself on all other children. In all other cases it returns 0 plus |
|
3954 // the sum of the values returned by calls to itself on curr's children. |
|
3955 // It also resets the value of ref so that it will refer to the renamed type from the schema |
|
3956 // being redefined. |
|
3957 private int changeRedefineGroup(String originalQName, String elementSought, |
|
3958 String newName, Element curr, XSDocumentInfo schemaDoc) { |
|
3959 int result = 0; |
|
3960 for (Element child = DOMUtil.getFirstChildElement(curr); |
|
3961 child != null; child = DOMUtil.getNextSiblingElement(child)) { |
|
3962 String name = DOMUtil.getLocalName(child); |
|
3963 if (!name.equals(elementSought)) |
|
3964 result += changeRedefineGroup(originalQName, elementSought, newName, child, schemaDoc); |
|
3965 else { |
|
3966 String ref = child.getAttribute( SchemaSymbols.ATT_REF ); |
|
3967 if (ref.length() != 0) { |
|
3968 String processedRef = findQName(ref, schemaDoc); |
|
3969 if (originalQName.equals(processedRef)) { |
|
3970 String prefix = XMLSymbols.EMPTY_STRING; |
|
3971 int colonptr = ref.indexOf(":"); |
|
3972 if (colonptr > 0) { |
|
3973 prefix = ref.substring(0,colonptr); |
|
3974 child.setAttribute(SchemaSymbols.ATT_REF, prefix + ":" + newName); |
|
3975 } |
|
3976 else |
|
3977 child.setAttribute(SchemaSymbols.ATT_REF, newName); |
|
3978 result++; |
|
3979 if (elementSought.equals(SchemaSymbols.ELT_GROUP)) { |
|
3980 String minOccurs = child.getAttribute( SchemaSymbols.ATT_MINOCCURS ); |
|
3981 String maxOccurs = child.getAttribute( SchemaSymbols.ATT_MAXOCCURS ); |
|
3982 if (!((maxOccurs.length() == 0 || maxOccurs.equals("1")) |
|
3983 && (minOccurs.length() == 0 || minOccurs.equals("1")))) { |
|
3984 reportSchemaError("src-redefine.6.1.2", new Object [] {ref}, child); |
|
3985 } |
|
3986 } |
|
3987 } |
|
3988 } // if ref was null some other stage of processing will flag the error |
|
3989 } |
|
3990 } |
|
3991 return result; |
|
3992 } // changeRedefineGroup |
|
3993 |
|
3994 // this method returns the XSDocumentInfo object that contains the |
|
3995 // component corresponding to decl. If components from this |
|
3996 // document cannot be referred to from those of currSchema, this |
|
3997 // method returns null; it's up to the caller to throw an error. |
|
3998 // @param: currSchema: the XSDocumentInfo object containing the |
|
3999 // decl ref'ing us. |
|
4000 // @param: decl: the declaration being ref'd. |
|
4001 // this method is superficial now. ---Jack |
|
4002 private XSDocumentInfo findXSDocumentForDecl(XSDocumentInfo currSchema, |
|
4003 Element decl, XSDocumentInfo decl_Doc) { |
|
4004 |
|
4005 if (DEBUG_NODE_POOL) { |
|
4006 System.out.println("DOCUMENT NS:"+ currSchema.fTargetNamespace+" hashcode:"+ ((Object)currSchema.fSchemaElement).hashCode()); |
|
4007 } |
|
4008 Object temp = decl_Doc; |
|
4009 if (temp == null) { |
|
4010 // something went badly wrong; we don't know this doc? |
|
4011 return null; |
|
4012 } |
|
4013 XSDocumentInfo declDocInfo = (XSDocumentInfo)temp; |
|
4014 return declDocInfo; |
|
4015 /********* |
|
4016 Logic here is unnecessary after schema WG's recent decision to allow |
|
4017 schema components from one document to refer to components of any other, |
|
4018 so long as there's some include/import/redefine path amongst them. |
|
4019 If they rver reverse this decision the code's right here though... - neilg |
|
4020 // now look in fDependencyMap to see if this is reachable |
|
4021 if(((Vector)fDependencyMap.get(currSchema)).contains(declDocInfo)) { |
|
4022 return declDocInfo; |
|
4023 } |
|
4024 // obviously the requesting doc didn't include, redefine or |
|
4025 // import the one containing decl... |
|
4026 return null; |
|
4027 **********/ |
|
4028 } // findXSDocumentForDecl(XSDocumentInfo, Element): XSDocumentInfo |
|
4029 |
|
4030 // returns whether more than <annotation>s occur in children of elem |
|
4031 private boolean nonAnnotationContent(Element elem) { |
|
4032 for(Element child = DOMUtil.getFirstChildElement(elem); child != null; child = DOMUtil.getNextSiblingElement(child)) { |
|
4033 if(!(DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION))) return true; |
|
4034 } |
|
4035 return false; |
|
4036 } // nonAnnotationContent(Element): boolean |
|
4037 |
|
4038 private void setSchemasVisible(XSDocumentInfo startSchema) { |
|
4039 if (DOMUtil.isHidden(startSchema.fSchemaElement, fHiddenNodes)) { |
|
4040 // make it visible |
|
4041 DOMUtil.setVisible(startSchema.fSchemaElement, fHiddenNodes); |
|
4042 Vector dependingSchemas = (Vector)fDependencyMap.get(startSchema); |
|
4043 for (int i = 0; i < dependingSchemas.size(); i++) { |
|
4044 setSchemasVisible((XSDocumentInfo)dependingSchemas.elementAt(i)); |
|
4045 } |
|
4046 } |
|
4047 // if it's visible already than so must be its children |
|
4048 } // setSchemasVisible(XSDocumentInfo): void |
|
4049 |
|
4050 private SimpleLocator xl = new SimpleLocator(); |
|
4051 |
|
4052 /** |
|
4053 * Extract location information from an Element node, and create a |
|
4054 * new SimpleLocator object from such information. Returning null means |
|
4055 * no information can be retrieved from the element. |
|
4056 */ |
|
4057 public SimpleLocator element2Locator(Element e) { |
|
4058 if (!( e instanceof ElementImpl)) |
|
4059 return null; |
|
4060 |
|
4061 SimpleLocator l = new SimpleLocator(); |
|
4062 return element2Locator(e, l) ? l : null; |
|
4063 } |
|
4064 |
|
4065 /** |
|
4066 * Extract location information from an Element node, store such |
|
4067 * information in the passed-in SimpleLocator object, then return |
|
4068 * true. Returning false means can't extract or store such information. |
|
4069 */ |
|
4070 public boolean element2Locator(Element e, SimpleLocator l) { |
|
4071 if (l == null) |
|
4072 return false; |
|
4073 if (e instanceof ElementImpl) { |
|
4074 ElementImpl ele = (ElementImpl)e; |
|
4075 // get system id from document object |
|
4076 Document doc = ele.getOwnerDocument(); |
|
4077 String sid = (String)fDoc2SystemId.get(DOMUtil.getRoot(doc)); |
|
4078 // line/column numbers are stored in the element node |
|
4079 int line = ele.getLineNumber(); |
|
4080 int column = ele.getColumnNumber(); |
|
4081 l.setValues(sid, sid, line, column, ele.getCharacterOffset()); |
|
4082 return true; |
|
4083 } |
|
4084 return false; |
|
4085 } |
|
4086 |
|
4087 private Element getElementFromMap(Map<String, Element> registry, String declKey) { |
|
4088 if (registry == null) return null; |
|
4089 return registry.get(declKey); |
|
4090 } |
|
4091 |
|
4092 private XSDocumentInfo getDocInfoFromMap(Map<String, XSDocumentInfo> registry, String declKey) { |
|
4093 if (registry == null) return null; |
|
4094 return registry.get(declKey); |
|
4095 } |
|
4096 |
|
4097 private Object getFromMap(Map registry, String key) { |
|
4098 if (registry == null) return null; |
|
4099 return registry.get(key); |
|
4100 } |
|
4101 |
|
4102 void reportSchemaFatalError(String key, Object[] args, Element ele) { |
|
4103 reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_FATAL_ERROR, null); |
|
4104 } |
|
4105 |
|
4106 void reportSchemaError(String key, Object[] args, Element ele) { |
|
4107 reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_ERROR, null); |
|
4108 } |
|
4109 |
|
4110 void reportSchemaError(String key, Object[] args, Element ele, Exception exception) { |
|
4111 reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_ERROR, exception); |
|
4112 } |
|
4113 |
|
4114 void reportSchemaWarning(String key, Object[] args, Element ele) { |
|
4115 reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_WARNING, null); |
|
4116 } |
|
4117 |
|
4118 void reportSchemaWarning(String key, Object[] args, Element ele, Exception exception) { |
|
4119 reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_WARNING, exception); |
|
4120 } |
|
4121 |
|
4122 void reportSchemaErr(String key, Object[] args, Element ele, short type, Exception exception) { |
|
4123 if (element2Locator(ele, xl)) { |
|
4124 fErrorReporter.reportError(xl, XSMessageFormatter.SCHEMA_DOMAIN, |
|
4125 key, args, type, exception); |
|
4126 } |
|
4127 else { |
|
4128 fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN, |
|
4129 key, args, type, exception); |
|
4130 } |
|
4131 } |
|
4132 |
|
4133 /** |
|
4134 * Grammar pool used for validating annotations. This will return all of the |
|
4135 * grammars from the grammar bucket. It will also return an object for the |
|
4136 * schema for schemas which will contain at least the relevant declarations |
|
4137 * for annotations. |
|
4138 */ |
|
4139 private static class XSAnnotationGrammarPool implements XMLGrammarPool { |
|
4140 |
|
4141 private XSGrammarBucket fGrammarBucket; |
|
4142 private Grammar [] fInitialGrammarSet; |
|
4143 |
|
4144 public Grammar[] retrieveInitialGrammarSet(String grammarType) { |
|
4145 if (grammarType == XMLGrammarDescription.XML_SCHEMA) { |
|
4146 if (fInitialGrammarSet == null) { |
|
4147 if (fGrammarBucket == null) { |
|
4148 fInitialGrammarSet = new Grammar [] {SchemaGrammar.Schema4Annotations.INSTANCE}; |
|
4149 } |
|
4150 else { |
|
4151 SchemaGrammar [] schemaGrammars = fGrammarBucket.getGrammars(); |
|
4152 /** |
|
4153 * If the grammar bucket already contains the schema for schemas |
|
4154 * then we already have the definitions for the parts relevant |
|
4155 * to annotations. |
|
4156 */ |
|
4157 for (int i = 0; i < schemaGrammars.length; ++i) { |
|
4158 if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(schemaGrammars[i].getTargetNamespace())) { |
|
4159 fInitialGrammarSet = schemaGrammars; |
|
4160 return fInitialGrammarSet; |
|
4161 } |
|
4162 } |
|
4163 Grammar [] grammars = new Grammar[schemaGrammars.length + 1]; |
|
4164 System.arraycopy(schemaGrammars, 0, grammars, 0, schemaGrammars.length); |
|
4165 grammars[grammars.length - 1] = SchemaGrammar.Schema4Annotations.INSTANCE; |
|
4166 fInitialGrammarSet = grammars; |
|
4167 } |
|
4168 } |
|
4169 return fInitialGrammarSet; |
|
4170 } |
|
4171 return new Grammar[0]; |
|
4172 } |
|
4173 |
|
4174 public void cacheGrammars(String grammarType, Grammar[] grammars) { |
|
4175 |
|
4176 } |
|
4177 |
|
4178 public Grammar retrieveGrammar(XMLGrammarDescription desc) { |
|
4179 if (desc.getGrammarType() == XMLGrammarDescription.XML_SCHEMA) { |
|
4180 final String tns = ((XMLSchemaDescription) desc).getTargetNamespace(); |
|
4181 if (fGrammarBucket != null) { |
|
4182 Grammar grammar = fGrammarBucket.getGrammar(tns); |
|
4183 if (grammar != null) { |
|
4184 return grammar; |
|
4185 } |
|
4186 } |
|
4187 if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(tns)) { |
|
4188 return SchemaGrammar.Schema4Annotations.INSTANCE; |
|
4189 } |
|
4190 } |
|
4191 return null; |
|
4192 } |
|
4193 |
|
4194 public void refreshGrammars(XSGrammarBucket gBucket) { |
|
4195 fGrammarBucket = gBucket; |
|
4196 fInitialGrammarSet = null; |
|
4197 } |
|
4198 |
|
4199 public void lockPool() {} |
|
4200 |
|
4201 public void unlockPool() {} |
|
4202 |
|
4203 public void clear() {} |
|
4204 } |
|
4205 |
|
4206 /** |
|
4207 * used to identify a reference to a schema document |
|
4208 * if the same document is referenced twice with the same key, then |
|
4209 * we only need to parse it once. |
|
4210 * |
|
4211 * When 2 XSDKey's are compared, the following table can be used to |
|
4212 * determine whether they are equal: |
|
4213 * inc red imp pre ins |
|
4214 * inc N/L ? N/L N/L N/L |
|
4215 * red ? N/L ? ? ? |
|
4216 * imp N/L ? N/P N/P N/P |
|
4217 * pre N/L ? N/P N/P N/P |
|
4218 * ins N/L ? N/P N/P N/P |
|
4219 * |
|
4220 * Where: N/L: duplicate when they have the same namespace and location. |
|
4221 * ? : not clear from the spec. |
|
4222 * REVISIT: to simplify the process, also considering |
|
4223 * it's very rare, we treat them as not duplicate. |
|
4224 * N/P: not possible. imp/pre/ins are referenced by namespace. |
|
4225 * when the first time we encounter a schema document for a |
|
4226 * namespace, we create a grammar and store it in the grammar |
|
4227 * bucket. when we see another reference to the same namespace, |
|
4228 * we first check whether a grammar with the same namespace is |
|
4229 * already in the bucket, which is true in this case, so we |
|
4230 * won't create another XSDKey. |
|
4231 * |
|
4232 * Conclusion from the table: two XSDKey's are duplicate only when all of |
|
4233 * the following are true: |
|
4234 * 1. They are both "redefine", or neither is "redefine"; |
|
4235 * 2. They have the same namespace; |
|
4236 * 3. They have the same non-null location. |
|
4237 * |
|
4238 * About 3: if neither has a non-null location, then it's the case where |
|
4239 * 2 input streams are provided, but no system ID is provided. We can't tell |
|
4240 * whether the 2 streams have the same content, so we treat them as not |
|
4241 * duplicate. |
|
4242 */ |
|
4243 private static class XSDKey { |
|
4244 String systemId; |
|
4245 short referType; |
|
4246 // for inclue/redefine, this is the enclosing namespace |
|
4247 // for import/preparse/instance, this is the target namespace |
|
4248 String referNS; |
|
4249 |
|
4250 XSDKey(String systemId, short referType, String referNS) { |
|
4251 this.systemId = systemId; |
|
4252 this.referType = referType; |
|
4253 this.referNS = referNS; |
|
4254 } |
|
4255 |
|
4256 public int hashCode() { |
|
4257 // according to the description at the beginning of this class, |
|
4258 // we use the hashcode of the namespace as the hashcoe of this key. |
|
4259 return referNS == null ? 0 : referNS.hashCode(); |
|
4260 } |
|
4261 |
|
4262 public boolean equals(Object obj) { |
|
4263 if (!(obj instanceof XSDKey)) { |
|
4264 return false; |
|
4265 } |
|
4266 XSDKey key = (XSDKey)obj; |
|
4267 |
|
4268 // condition 1: both are redefine |
|
4269 /** if (referType == XSDDescription.CONTEXT_REDEFINE || |
|
4270 key.referType == XSDDescription.CONTEXT_REDEFINE) { |
|
4271 if (referType != key.referType) |
|
4272 return false; |
|
4273 }**/ |
|
4274 |
|
4275 // condition 2: same namespace |
|
4276 if (referNS != key.referNS) |
|
4277 return false; |
|
4278 |
|
4279 // condition 3: same non-null location |
|
4280 if (systemId == null || !systemId.equals(key.systemId)) { |
|
4281 return false; |
|
4282 } |
|
4283 |
|
4284 return true; |
|
4285 } |
|
4286 } |
|
4287 |
|
4288 private static final class SAX2XNIUtil extends ErrorHandlerWrapper { |
|
4289 public static XMLParseException createXMLParseException0(SAXParseException exception) { |
|
4290 return createXMLParseException(exception); |
|
4291 } |
|
4292 public static XNIException createXNIException0(SAXException exception) { |
|
4293 return createXNIException(exception); |
|
4294 } |
|
4295 } |
|
4296 |
|
4297 /** |
|
4298 * @param state |
|
4299 */ |
|
4300 public void setGenerateSyntheticAnnotations(boolean state) { |
|
4301 fSchemaParser.setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, state); |
|
4302 } |
|
4303 |
|
4304 } // XSDHandler |