12005
|
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
|