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;
37
38 import java.io.InputStream;
39 import java.io.PrintStream;
40 import java.io.PrintWriter;
41 import java.util.Hashtable;
42 import java.util.Map;
43 import java.util.Vector;
44
45 import org.apache.commons.logging.Log;
46 import org.apache.commons.logging.LogFactory;
47 import org.castor.core.util.Messages;
48 import org.exolab.castor.mapping.Mapping;
49 import org.exolab.castor.xml.Unmarshaller;
50 import org.exolab.castor.xml.schema.simpletypes.AtomicType;
51 import org.exolab.castor.xml.schema.simpletypes.ListType;
52 import org.exolab.castor.xml.schema.simpletypes.RealType;
53 import org.exolab.castor.xml.schema.simpletypes.UrType;
54 import org.exolab.castor.xml.schema.simpletypes.factory.Type;
55 import org.exolab.castor.xml.schema.simpletypes.factory.TypeList;
56 import org.exolab.castor.xml.schema.simpletypes.factory.TypeProperty;
57 import org.xml.sax.InputSource;
58
59
60
61
62
63
64
65
66
67
68
69 public class SimpleTypesFactory {
70
71 private static final Log LOG = LogFactory.getLog(SimpleTypesFactory.class);
72
73
74
75
76 public static final int INVALID_TYPE = -1;
77
78
79 public static final int USER_TYPE = 0;
80
81
82 public static final int STRING_TYPE = 1;
83 public static final int DURATION_TYPE = 2;
84 public static final int DATETIME_TYPE = 3;
85 public static final int TIME_TYPE = 4;
86 public static final int DATE_TYPE = 5;
87 public static final int GYEARMONTH_TYPE = 6;
88 public static final int GYEAR_TYPE = 7;
89 public static final int GMONTHDAY_TYPE = 8;
90 public static final int GDAY_TYPE = 9;
91 public static final int GMONTH_TYPE = 10;
92 public static final int BOOLEAN_TYPE = 11;
93 public static final int BASE64BINARY_TYPE = 12;
94 public static final int HEXBINARY_TYPE = 13;
95 public static final int FLOAT_TYPE = 14;
96 public static final int DOUBLE_TYPE = 15;
97 public static final int DECIMAL_TYPE = 16;
98 public static final int ANYURI_TYPE = 17;
99 public static final int QNAME_TYPE = 18;
100 public static final int NOTATION_TYPE = 19;
101
102 public static final int NORMALIZEDSTRING_TYPE = 20;
103 public static final int TOKEN_TYPE = 21;
104 public static final int LANGUAGE_TYPE = 22;
105 public static final int NAME_TYPE = 23;
106 public static final int NCNAME_TYPE = 24;
107 public static final int ID_TYPE = 25;
108 public static final int IDREF_TYPE = 26;
109 public static final int IDREFS_TYPE = 27;
110 public static final int ENTITY_TYPE = 28;
111 public static final int ENTITIES_TYPE = 29;
112 public static final int NMTOKEN_TYPE = 30;
113 public static final int NMTOKENS_TYPE = 31;
114 public static final int INTEGER_TYPE = 32;
115 public static final int NON_POSITIVE_INTEGER_TYPE = 33;
116 public static final int NEGATIVE_INTEGER_TYPE = 34;
117 public static final int LONG_TYPE = 35;
118 public static final int INT_TYPE = 36;
119 public static final int SHORT_TYPE = 37;
120 public static final int BYTE_TYPE = 38;
121 public static final int NON_NEGATIVE_INTEGER_TYPE = 39;
122 public static final int UNSIGNED_LONG_TYPE = 40;
123 public static final int UNSIGNED_INT_TYPE = 41;
124 public static final int UNSIGNED_SHORT_TYPE = 42;
125 public static final int UNSIGNED_BYTE_TYPE = 43;
126 public static final int POSITIVE_INTEGER_TYPE = 44;
127
128 public static final int ANYSIMPLETYPE_TYPE = 100;
129
130
131 static final String RESOURCE_LOCATION = "/org/exolab/castor/util/resources/";
132
133
134 static final String TYPE_MAPPINGS = RESOURCE_LOCATION + "SimpleTypesMapping.properties";
135
136
137 static final String TYPE_DEFINITIONS = RESOURCE_LOCATION + "SimpleTypes.properties";
138
139
140
141
142
143 private static Map<String, Type> _typesByName = new Hashtable<String, Type>();
144
145
146
147
148 private static Map<Integer, Type> _typesByCode = new Hashtable<Integer, Type>();
149
150
151 private static final Schema BUILD_IN_SCHEMA = new Schema();
152
153
154
155
156
157 public SimpleTypesFactory() {
158 loadTypesDefinitions();
159 }
160
161
162
163
164
165
166
167 public static boolean isBuiltInType(final int codeType) {
168 return USER_TYPE < codeType;
169 }
170
171
172
173
174
175
176
177 public static boolean isPrimitiveType(final int codeType) {
178 return (STRING_TYPE <= codeType) && (codeType <= NOTATION_TYPE);
179 }
180
181
182
183
184
185
186
187 public static boolean isNumericType(final int codeType) {
188 return ((FLOAT_TYPE <= codeType) && (codeType <= DECIMAL_TYPE))
189 || ((INTEGER_TYPE <= codeType) && (codeType <= POSITIVE_INTEGER_TYPE));
190 }
191
192
193
194
195
196
197
198 public static boolean isDateTimeType(final int codeType) {
199 return (DURATION_TYPE <= codeType) && (codeType <= GMONTH_TYPE);
200 }
201
202
203
204
205
206
207
208
209
210 public SimpleType getBuiltInType(final String typeName) {
211 Type type = getType(typeName);
212 if (type == null) {
213 return null;
214 }
215 return type.getSimpleType();
216 }
217
218
219
220
221 public String getBuiltInTypeName(final int builtInTypeCode) {
222 Type type = getType(builtInTypeCode);
223 if (type == null) {
224 return null;
225 }
226 return type.getName();
227 }
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 SimpleType createUserSimpleType(final Schema schema, final String name, final String baseName,
250 final String derivation, final boolean createDeferredSimpleType) {
251 if ((baseName == null) || (baseName.length() == 0)) {
252
253 LOG.warn(Messages.format("schema.noBaseType", name));
254 return null;
255 }
256
257
258 SimpleType baseType = schema.getSimpleType(baseName);
259 if (baseType == null) {
260
261 if (createDeferredSimpleType) {
262 DeferredSimpleType result = new DeferredSimpleType();
263 result.setSchema(schema);
264 result.setName(name);
265 result.setBaseTypeName(baseName);
266 result.setDerivationMethod(derivation);
267 result.setTypeCode(USER_TYPE);
268 return result;
269 }
270 return null;
271 }
272
273 return createUserSimpleType(schema, name, baseType, derivation);
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294 SimpleType createUserSimpleType(final Schema schema, final String name, final SimpleType baseType,
295 final String derivation) {
296 String internalName = name;
297 if (name == null) {
298 internalName = "anonymous-simple-type";
299 }
300
301 if (baseType == null) {
302
303 LOG.warn(Messages.format("schema.noBaseType", internalName));
304 return null;
305 }
306
307 SimpleType result = null;
308
309 if ((derivation != null) && (derivation.equals(SchemaNames.LIST))) {
310
311
312
313
314
315
316
317 try {
318 result = new ListType(schema);
319 } catch (SchemaException sx) {
320 LOG.warn(Messages.format("schema.deriveByListError", internalName, baseType.getName()));
321 return null;
322 }
323 ((ListType) result).setItemType(baseType);
324 } else {
325
326
327 if (baseType instanceof Union) {
328
329
330 try {
331 result = new Union(schema);
332 } catch (SchemaException sx) {
333 LOG.warn(Messages.format("schema.deriveByListError", internalName, baseType.getName()));
334 return null;
335 }
336 } else {
337
338 SimpleType builtInBase = baseType.getBuiltInBaseType();
339 if (builtInBase == null) {
340 LOG.warn(Messages.format("schema.noBuiltInParent", internalName));
341 return null;
342 }
343
344 result = createInstance(schema, builtInBase.getName());
345 if (result == null) {
346 throw new SimpleTypesFactoryException(Messages.message("schema.cantLoadBuiltInTypes"));
347 }
348 }
349 }
350
351 result.setSchema(schema);
352 result.setName(name);
353 result.setBaseType(baseType);
354 result.setDerivationMethod(derivation);
355 result.setTypeCode(USER_TYPE);
356 return result;
357 }
358
359
360
361
362
363 private Type getType(final String typeName) {
364 return _typesByName.get(typeName);
365 }
366
367
368
369
370
371 private Type getType(final int typeCode) {
372 return _typesByCode.get(Integer.valueOf(typeCode));
373 }
374
375
376
377
378
379 private synchronized void loadTypesDefinitions() {
380 InputStream is = null;
381
382 try {
383 Mapping mapping = new Mapping(getClass().getClassLoader());
384
385 is = this.getClass().getResourceAsStream(TYPE_MAPPINGS);
386 mapping.loadMapping(new InputSource(is));
387
388
389 Unmarshaller unmarshaller = new Unmarshaller(TypeList.class);
390 unmarshaller.setMapping(mapping);
391
392 unmarshaller.setValidation(false);
393
394 is = this.getClass().getResourceAsStream(TYPE_DEFINITIONS);
395 TypeList typeList = (TypeList) unmarshaller.unmarshal(new org.xml.sax.InputSource(is));
396
397 if (LOG.isTraceEnabled()) {
398 LOG.trace(typeList.toString());
399 }
400
401
402
403 for (Type type : typeList.getTypes()) {
404 _typesByName.put(type.getName(), type);
405 type.setSimpleType(createSimpleType(BUILD_IN_SCHEMA, type));
406 _typesByCode.put(Integer.valueOf(type.getSimpleType().getTypeCode()), type);
407 }
408 } catch (Exception except) {
409
410 String err = Messages.message("schema.cantLoadBuiltInTypes") + "; " + except;
411 throw new SimpleTypesFactoryException(except, err);
412 }
413 }
414
415
416
417
418
419 private SimpleType createSimpleType(final Schema schema, final Type type) {
420
421 SimpleType result = createInstance(schema, type.getName());
422
423 if (result == null) {
424 String err = Messages.message("schema.cantLoadBuiltInTypes");
425 throw new SimpleTypesFactoryException(err);
426 }
427
428 result.setName(type.getName());
429
430
431 int intCode;
432 try {
433 intCode = getClass().getDeclaredField(type.getCode()).getInt(null);
434 } catch (Exception ex) {
435
436 String error = Messages.message("schema.cantLoadBuiltInTypes") + ex;
437 throw new SimpleTypesFactoryException(ex, error);
438 }
439
440 result.setTypeCode(intCode);
441
442
443 if (type.getBase() != null) {
444 result.setBaseType(getType(type.getBase()).getSimpleType());
445 }
446
447
448 Vector<TypeProperty> facets = type.getFacet();
449 FacetFactory facetFactory = FacetFactory.getInstance();
450 for (int index = 0; index < facets.size(); index++) {
451 TypeProperty prop = facets.elementAt(index);
452 if (!prop.getPseudo()) {
453
454 Facet facet = facetFactory.createFacet(prop.getName(), prop.getValue());
455 facet.setOwningType(result);
456 result.addFacet(facet);
457 } else {
458
459 if (RealType.class.isInstance(result)) {
460 RealType realResult = (RealType) result;
461 if (prop.getName().equals("minM")) {
462 realResult.setMinMantissa(Long.parseLong(prop.getValue()));
463 } else if (prop.getName().equals("maxM")) {
464 realResult.setMaxMantissa(Long.parseLong(prop.getValue()));
465 } else if (prop.getName().equals("minE")) {
466 realResult.setMinExponent(Long.parseLong(prop.getValue()));
467 } else if (prop.getName().equals("maxE")) {
468 realResult.setMaxExponent(Long.parseLong(prop.getValue()));
469 }
470 }
471 }
472 }
473 return result;
474 }
475
476
477
478
479 private SimpleType createInstance(final Schema schema, final String builtInTypeName) {
480 Type type = getType(builtInTypeName);
481
482
483 String derivation = type.getDerivedBy();
484 ListType resultList = null;
485 if ((derivation != null) && (derivation.equals(SchemaNames.LIST))) {
486 try {
487 resultList = new ListType(schema);
488 } catch (SchemaException sx) {
489
490 throw new SimpleTypesFactoryException(sx);
491 }
492 }
493
494
495 Class implClass = null;
496 while (type != null) {
497 if (type.getImplClass() != null) {
498 implClass = type.getImplClass();
499 break;
500 }
501 type = getType(type.getBase());
502 }
503
504 if (implClass == null) {
505 return null;
506 }
507
508 SimpleType result;
509 if (implClass.isAssignableFrom(UrType.class)) {
510 try {
511 result = (UrType) implClass.newInstance();
512 result.setSchema(schema);
513 } catch (Exception e) {
514 throw new SimpleTypesFactoryException(e);
515 }
516 } else {
517 try {
518 result = (AtomicType) implClass.newInstance();
519 result.setSchema(schema);
520 } catch (Exception except) {
521 except.printStackTrace();
522 result = null;
523 }
524 if (resultList != null) {
525 resultList.setItemType(result);
526 return resultList;
527 }
528 }
529 return result;
530 }
531 }
532
533
534
535
536
537
538
539
540
541 class SimpleTypesFactoryException extends RuntimeException {
542
543 private static final long serialVersionUID = -7343397006284999081L;
544
545
546 private Throwable _exception;
547
548
549
550
551
552
553
554 public SimpleTypesFactoryException(final String message) {
555 super(message);
556 }
557
558
559
560
561
562
563
564 public SimpleTypesFactoryException(final Throwable exception) {
565 super(exception.toString());
566 _exception = exception;
567 }
568
569
570
571
572
573
574
575 public SimpleTypesFactoryException(final Throwable exception, final String message) {
576 super(message);
577 _exception = exception;
578 }
579
580
581
582
583
584
585
586 public Throwable getException() {
587 return _exception;
588 }
589
590
591 public void printStackTrace() {
592 if (_exception == null) {
593 super.printStackTrace();
594 } else {
595 _exception.printStackTrace();
596 }
597 }
598
599
600 public void printStackTrace(final PrintStream print) {
601 if (_exception == null) {
602 super.printStackTrace(print);
603 } else {
604 _exception.printStackTrace(print);
605 }
606 }
607
608
609 public void printStackTrace(final PrintWriter print) {
610 if (_exception == null) {
611 super.printStackTrace(print);
612 } else {
613 _exception.printStackTrace(print);
614 }
615 }
616 }
617