1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 package org.exolab.castor.xml.schema.reader;
37
38 import org.exolab.castor.net.URILocation;
39 import org.exolab.castor.net.URIResolver;
40 import org.exolab.castor.xml.AttributeSet;
41 import org.exolab.castor.xml.Namespaces;
42 import org.exolab.castor.xml.XMLException;
43 import org.exolab.castor.xml.schema.Annotation;
44 import org.exolab.castor.xml.schema.AttributeGroup;
45 import org.exolab.castor.xml.schema.AttributeGroupDecl;
46 import org.exolab.castor.xml.schema.ComplexType;
47 import org.exolab.castor.xml.schema.Group;
48 import org.exolab.castor.xml.schema.ModelGroup;
49 import org.exolab.castor.xml.schema.RedefineSchema;
50 import org.exolab.castor.xml.schema.Schema;
51 import org.exolab.castor.xml.schema.SchemaContext;
52 import org.exolab.castor.xml.schema.SchemaException;
53 import org.exolab.castor.xml.schema.SchemaNames;
54 import org.exolab.castor.xml.schema.SimpleType;
55 import org.exolab.castor.xml.schema.XMLType;
56 import org.xml.sax.Locator;
57 import org.xml.sax.Parser;
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public class RedefineUnmarshaller extends ComponentReader {
73
74
75
76
77 private ComponentReader _unmarshaller;
78
79
80
81
82 private int _depth = 0;
83
84
85
86
87 private Schema _schema;
88
89
90
91
92 private Schema _importedSchema;
93
94 private RedefineSchema _redefineSchema;
95
96
97
98
99
100 public RedefineUnmarshaller(final SchemaContext schemaContext, final Schema schema,
101 final AttributeSet atts, final URIResolver uriResolver, final Locator locator,
102 final SchemaUnmarshallerState state) throws XMLException {
103 super(schemaContext);
104 if (schema == null) {
105 String err = SchemaNames.REDEFINE + " must be used with an existing parent XML Schema.";
106 throw new SchemaException(err);
107 }
108 setURIResolver(uriResolver);
109
110 URILocation uri = null;
111
112 String schemaLocation = atts.getValue(SchemaNames.SCHEMALOCATION_ATTR);
113 _schema = schema;
114
115 if (schemaLocation == null) {
116
117 _redefineSchema = new RedefineSchema(schema);
118 _schema.addRedefineSchema(_redefineSchema);
119 return;
120 }
121
122
123 if (schemaLocation.indexOf("\\") != -1) {
124 String err = "'" + schemaLocation + "' is not a valid URI as defined by IETF RFC 2396.";
125 err += "The URI mustn't contain '\\'.";
126 error(err);
127 }
128
129 uri = derive(locator, schemaLocation);
130 if (uri != null) {
131 schemaLocation = uri.getAbsoluteURI();
132 }
133
134
135 boolean addSchema = false;
136 _redefineSchema = schema.getRedefineSchema(schemaLocation);
137 Schema importedSchema = null;
138
139 boolean alreadyLoaded = false;
140
141
142 if (_redefineSchema == null) {
143 if (uri instanceof SchemaLocation) {
144 importedSchema = ((SchemaLocation) uri).getSchema();
145
146
147
148
149
150 _redefineSchema = new RedefineSchema(schema, importedSchema);
151 schema.addRedefineSchema(_redefineSchema);
152 alreadyLoaded = true;
153 } else {
154 importedSchema = new Schema();
155 addSchema = true;
156 }
157 } else {
158
159 String tmpLocation = _redefineSchema.getOriginalSchema().getSchemaLocation();
160 alreadyLoaded = schemaLocation.equals(tmpLocation);
161 }
162
163 state.markAsProcessed(schemaLocation, importedSchema);
164
165 if (alreadyLoaded)
166 return;
167
168
169 Parser parser = createParser("import");
170
171
172 SchemaUnmarshaller schemaUnmarshaller = new SchemaUnmarshaller(getSchemaContext(), state);
173 schemaUnmarshaller.setURIResolver(getURIResolver());
174 schemaUnmarshaller.setSchema(importedSchema);
175
176
177 parseSchema(parser, schemaUnmarshaller, uri, schemaLocation, "import");
178
179
180 String namespace = importedSchema.getTargetNamespace();
181 if (namespace != null) {
182
183
184
185 if (!namespace.equals(schema.getTargetNamespace())) {
186 String err =
187 "The 'namespace' attribute in the <redefine> element must be the same of the targetNamespace of the global schema.\n"
188 + namespace + " is different from:" + schema.getTargetNamespace();
189 error(err);
190 }
191 } else {
192 importedSchema.setTargetNamespace(schema.getTargetNamespace());
193 }
194
195
196
197
198
199
200 _importedSchema = importedSchema;
201 _redefineSchema = new RedefineSchema(schema, _importedSchema);
202
203 if (addSchema) {
204 importedSchema.setSchemaLocation(schemaLocation);
205 _schema.addRedefineSchema(_redefineSchema);
206 }
207 }
208
209
210
211
212
213
214
215
216
217
218
219 public void startElement(String name, String namespace, AttributeSet atts, Namespaces nsDecls)
220 throws XMLException {
221
222
223 if (_unmarshaller != null) {
224 try {
225 _unmarshaller.startElement(name, namespace, atts, nsDecls);
226 _depth++;
227 return;
228 } catch (RuntimeException rtx) {
229 error(rtx);
230 }
231 }
232
233 if (name.equals(SchemaNames.ANNOTATION)) {
234 _unmarshaller = new AnnotationUnmarshaller(getSchemaContext(), atts);
235 } else if (name.equals(SchemaNames.ATTRIBUTE_GROUP)) {
236 _unmarshaller = new AttributeGroupUnmarshaller(getSchemaContext(), _schema, atts);
237 } else if (name.equals(SchemaNames.COMPLEX_TYPE)) {
238 _unmarshaller = new ComplexTypeUnmarshaller(getSchemaContext(), _schema, atts);
239 } else if (name.equals(SchemaNames.SIMPLE_TYPE)) {
240 _unmarshaller = new SimpleTypeUnmarshaller(getSchemaContext(), _schema, atts);
241 } else if (name.equals(SchemaNames.GROUP)) {
242 _unmarshaller = new ModelGroupUnmarshaller(getSchemaContext(), _schema, atts);
243 } else {
244 String err = "<" + name + "> elements cannot be used in a redefine.";
245 error(err);
246 }
247
248 _unmarshaller.setDocumentLocator(getDocumentLocator());
249
250 }
251
252
253
254
255
256
257
258
259 public void endElement(String name, String namespace) throws XMLException {
260
261
262 if ((_unmarshaller != null) && (_depth > 0)) {
263 _unmarshaller.endElement(name, namespace);
264 --_depth;
265 return;
266 }
267
268
269 name = name.intern();
270
271
272 if ((_unmarshaller != null)) {
273 if (!name.equals(_unmarshaller.elementName())) {
274 String err = "error: missing end element for ";
275 err += _unmarshaller.elementName();
276 error(err);
277 }
278 } else {
279 String err = "error: missing start element for " + name;
280 throw new SchemaException(err);
281 }
282
283
284 _unmarshaller.finish();
285
286 if (name.equals(SchemaNames.ANNOTATION)) {
287 _redefineSchema.addAnnotation((Annotation) _unmarshaller.getObject());
288 } else if (name.equals(SchemaNames.ATTRIBUTE_GROUP)) {
289 endElementForAttributeGroup();
290 } else if (name.equals(SchemaNames.COMPLEX_TYPE)) {
291 endElementForComplexType();
292 } else if (name.equals(SchemaNames.SIMPLE_TYPE)) {
293 endElementForSimpleType();
294 } else if (name.equals(SchemaNames.GROUP)) {
295 endElementForGroup();
296 } else {
297 String err =
298 "In a <redefine>, only complexTypes|simpleTypes|groups or attributeGroups can be redefined.";
299 error(err);
300 }
301
302 _unmarshaller = null;
303 }
304
305 private void endElementForGroup() throws XMLException, SchemaException {
306 addErrorIfNoSchemaLocationDefinedUponRedefine();
307
308 ModelGroup group = (((ModelGroupUnmarshaller) _unmarshaller).getGroup());
309
310 String structureName = group.getName();
311 addErrorIfRedefinedTypeDoesNotHaveAName(structureName, "group");
312
313
314 Group original = _importedSchema.getModelGroup(structureName);
315 if (original == null) {
316 String err =
317 "When redefining a group, the group must be present in the imported XML schema.\n"
318 + "Group: " + structureName + " is not defined in XML Schema:"
319 + _importedSchema.getSchemaLocation();
320 error(err);
321 }
322
323
324
325
326 group.setRedefined();
327 _redefineSchema.addGroup(group);
328 }
329
330 private void endElementForSimpleType() throws XMLException, SchemaException {
331 addErrorIfNoSchemaLocationDefinedUponRedefine();
332
333 SimpleType simpleType = ((SimpleTypeUnmarshaller) _unmarshaller).getSimpleType();
334
335 String structureName = simpleType.getName();
336 addErrorIfRedefinedTypeDoesNotHaveAName(structureName, "simpleType");
337
338
339 SimpleType original =
340 _importedSchema.getSimpleType(structureName, _schema.getTargetNamespace());
341 if (original == null) {
342 String err =
343 "When redefining a simpleType, the simpleType must be present in the imported XML schema.\n"
344 + "SimpleType: " + structureName + " is not defined in XML Schema:"
345 + _importedSchema.getSchemaLocation();
346 error(err);
347 }
348
349
350 XMLType baseType = simpleType.getBaseType();
351
352 if (!baseType.getName().equals(structureName)) {
353 String err =
354 "When redefining a simpleType, the simpleType must use itself as the base type definition.\n"
355 + "SimpleType: " + structureName + " uses:" + baseType.getName()
356 + " as its base type.";
357 error(err);
358 }
359
360 simpleType.setRedefined();
361 _redefineSchema.addSimpleType(simpleType);
362 getResolver().addResolvable(simpleType.getReferenceId(), simpleType);
363 }
364
365 private void endElementForComplexType() throws XMLException, SchemaException {
366 addErrorIfNoSchemaLocationDefinedUponRedefine();
367 ComplexType complexType = ((ComplexTypeUnmarshaller) _unmarshaller).getComplexType();
368
369
370 String structureName = complexType.getName();
371 addErrorIfRedefinedTypeDoesNotHaveAName(structureName, "complexType");
372
373
374 ComplexType original = _importedSchema.getComplexType(structureName);
375 if (original == null) {
376 String err =
377 "When redefining a complexType, the complexType must be present in the imported XML schema.\n"
378 + "ComplexType: " + structureName + " is not defined in XML Schema:"
379 + _importedSchema.getSchemaLocation();
380 error(err);
381 }
382
383
384 XMLType baseType = complexType.getBaseType();
385
386 if (baseType == null || !baseType.getName().equals(structureName)) {
387 String err =
388 "When redefining a complexType, the complexType must use itself as the base type definition.\n"
389 + "ComplexType: " + structureName + " uses:" + baseType + " as its base type.";
390 error(err);
391 }
392
393 complexType.setRedefined();
394 _redefineSchema.addComplexType(complexType);
395 getResolver().addResolvable(complexType.getReferenceId(), complexType);
396 }
397
398 private void endElementForAttributeGroup() throws XMLException, SchemaException {
399 addErrorIfNoSchemaLocationDefinedUponRedefine();
400
401 AttributeGroupDecl group =
402 (AttributeGroupDecl) (((AttributeGroupUnmarshaller) _unmarshaller).getAttributeGroup());
403
404 String structureName = group.getName();
405 addErrorIfRedefinedTypeDoesNotHaveAName(structureName, "attribute group");
406
407
408 AttributeGroup original = _importedSchema.getAttributeGroup(structureName);
409 if (original == null) {
410 String err =
411 "When redefining an AttributeGroup, the AttributeGroup must be present in the imported XML schema.\n"
412 + "AttributeGroup: " + structureName + " is not defined in XML Schema:"
413 + _importedSchema.getSchemaLocation();
414 error(err);
415 }
416
417
418 group.setRedefined();
419 _redefineSchema.addAttributeGroup(group);
420 }
421
422 public void characters(char[] ch, int start, int length) throws XMLException {
423
424 if (_unmarshaller != null) {
425 _unmarshaller.characters(ch, start, length);
426 }
427 }
428
429
430
431
432
433 private void addErrorIfNoSchemaLocationDefinedUponRedefine() throws XMLException {
434 if (_redefineSchema.getSchemaLocation() == "") {
435 String err =
436 "In a <redefine>, only annotations can be defined when no -schemaLocation- is specified.";
437 error(err);
438 }
439 }
440
441
442
443
444
445
446
447 private void addErrorIfRedefinedTypeDoesNotHaveAName(String structureName, String typeName) throws XMLException {
448
449 if (structureName == null) {
450 String err = "When redefining a " + typeName + ", the " + typeName + " must have a name.\n";
451 error(err);
452 }
453 }
454
455
456
457
458 public String elementName() {
459 return SchemaNames.REDEFINE;
460 }
461
462
463
464
465
466
467 public Object getObject() {
468 return _redefineSchema;
469 }
470
471 }