KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > xml > binding > TypeBinding


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.xml.binding;
8
9 import org.jboss.logging.Logger;
10
11 import java.io.Serializable JavaDoc;
12 import java.io.ByteArrayOutputStream JavaDoc;
13 import java.math.BigInteger JavaDoc;
14 import java.math.BigDecimal JavaDoc;
15 import java.text.ParseException JavaDoc;
16 import java.util.Calendar JavaDoc;
17 import java.util.TimeZone JavaDoc;
18 import java.util.StringTokenizer JavaDoc;
19 import java.net.URISyntaxException JavaDoc;
20
21 /**
22  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
23  * @version <tt>$Revision: 1.6.2.6 $</tt>
24  */

25 public final class TypeBinding
26    implements Serializable JavaDoc
27 {
28    static final long serialVersionUID = 2815361862736153588L;
29    public static final String JavaDoc XS_ANYSIMPLETYPE_NAME = "anySimpleType";
30
31    //
32
// primitive datatypes
33
//
34
public static final String JavaDoc XS_STRING_NAME = "string";
35    public static final String JavaDoc XS_BOOLEAN_NAME = "boolean";
36    public static final String JavaDoc XS_DECIMAL_NAME = "decimal";
37    public static final String JavaDoc XS_FLOAT_NAME = "float";
38    public static final String JavaDoc XS_DOUBLE_NAME = "double";
39    public static final String JavaDoc XS_DURATION_NAME = "duration";
40    public static final String JavaDoc XS_DATETIME_NAME = "dateTime";
41    public static final String JavaDoc XS_TIME_NAME = "time";
42    public static final String JavaDoc XS_DATE_NAME = "date";
43    public static final String JavaDoc XS_GYEARMONTH_NAME = "gYearMonth";
44    public static final String JavaDoc XS_GYEAR_NAME = "gYear";
45    public static final String JavaDoc XS_GMONTHDAY_NAME = "gMonthDay";
46    public static final String JavaDoc XS_GDAY_NAME = "gDay";
47    public static final String JavaDoc XS_GMONTH_NAME = "gMonth";
48    public static final String JavaDoc XS_HEXBINARY_NAME = "hexBinary";
49    public static final String JavaDoc XS_BASE64BINARY_NAME = "base64Binary";
50    public static final String JavaDoc XS_ANYURI_NAME = "anyURI";
51    public static final String JavaDoc XS_QNAME_NAME = "QName";
52    public static final String JavaDoc XS_NOTATION_NAME = "NOTATION";
53
54    //
55
// derived datatypes
56
//
57

58    public static final String JavaDoc XS_NORMALIZEDSTRING_NAME = "normalizedString";
59    public static final String JavaDoc XS_TOKEN_NAME = "token";
60    public static final String JavaDoc XS_LANGUAGE_NAME = "language";
61    public static final String JavaDoc XS_NMTOKEN_NAME = "NMToken";
62    public static final String JavaDoc XS_NMTOKENS_NAME = "NMTokens";
63    public static final String JavaDoc XS_NAME_NAME = "Name";
64    public static final String JavaDoc XS_NCNAME_NAME = "NCName";
65    public static final String JavaDoc XS_ID_NAME = "ID";
66    public static final String JavaDoc XS_IDREF_NAME = "IDREF";
67    public static final String JavaDoc XS_IDREFS_NAME = "IDREFS";
68    public static final String JavaDoc XS_ENTITY_NAME = "ENTITY";
69    public static final String JavaDoc XS_ENTITIES_NAME = "ENTITIES";
70    public static final String JavaDoc XS_INTEGER_NAME = "integer";
71    public static final String JavaDoc XS_NONPOSITIVEINTEGER_NAME = "nonPositiveInteger";
72    public static final String JavaDoc XS_NEGATIVEINTEGER_NAME = "negativeInteger";
73    public static final String JavaDoc XS_LONG_NAME = "long";
74    public static final String JavaDoc XS_INT_NAME = "int";
75    public static final String JavaDoc XS_SHORT_NAME = "short";
76    public static final String JavaDoc XS_BYTE_NAME = "byte";
77    public static final String JavaDoc XS_NONNEGATIVEINTEGER_NAME = "nonNegativeInteger";
78    public static final String JavaDoc XS_UNSIGNEDLONG_NAME = "unsignedLong";
79    public static final String JavaDoc XS_UNSIGNEDINT_NAME = "unsignedInt";
80    public static final String JavaDoc XS_UNSIGNEDSHORT_NAME = "unsignedShort";
81    public static final String JavaDoc XS_UNSIGNEDBYTE_NAME = "unsignedByte";
82    public static final String JavaDoc XS_POSITIVEINTEGER_NAME = "positiveInteger";
83
84    public static final int XS_INT = XS_INT_NAME.hashCode();
85    public static final int XS_LONG = XS_LONG_NAME.hashCode();
86    public static final int XS_SHORT = XS_SHORT_NAME.hashCode();
87    public static final int XS_FLOAT = XS_FLOAT_NAME.hashCode();
88    public static final int XS_DOUBLE = XS_DOUBLE_NAME.hashCode();
89    public static final int XS_BOOLEAN = XS_BOOLEAN_NAME.hashCode();
90    public static final int XS_BYTE = XS_BYTE_NAME.hashCode();
91    public static final int XS_STRING = XS_STRING_NAME.hashCode();
92    public static final int XS_INTEGER = XS_INTEGER_NAME.hashCode();
93    public static final int XS_DECIMAL = XS_DECIMAL_NAME.hashCode();
94    public static final int XS_DATETIME = XS_DATETIME_NAME.hashCode();
95    public static final int XS_QNAME = XS_QNAME_NAME.hashCode();
96    public static final int XS_ANYURI = XS_ANYURI_NAME.hashCode();
97    public static final int XS_UNSIGNEDLONG = XS_UNSIGNEDLONG_NAME.hashCode();
98    public static final int XS_UNSIGNEDINT = XS_UNSIGNEDINT_NAME.hashCode();
99    public static final int XS_UNSIGNEDSHORT = XS_UNSIGNEDSHORT_NAME.hashCode();
100    public static final int XS_UNSIGNEDBYTE = XS_UNSIGNEDBYTE_NAME.hashCode();
101    public static final int XS_DATE = XS_DATE_NAME.hashCode();
102    public static final int XS_TIME = XS_TIME_NAME.hashCode();
103    public static final int XS_BASE64BINARY = XS_BASE64BINARY_NAME.hashCode();
104    public static final int XS_HEXBINARY = XS_HEXBINARY_NAME.hashCode();
105    public static final int XS_ANYSIMPLETYPE = XS_ANYSIMPLETYPE_NAME.hashCode();
106    public static final int XS_DURATION = XS_DURATION_NAME.hashCode();
107    public static final int XS_GYEARMONTH = XS_GYEARMONTH_NAME.hashCode();
108    public static final int XS_GYEAR = XS_GYEAR_NAME.hashCode();
109    public static final int XS_GMONTHDAY = XS_GMONTHDAY_NAME.hashCode();
110    public static final int XS_GMONTH = XS_GMONTH_NAME.hashCode();
111    public static final int XS_GDAY = XS_GDAY_NAME.hashCode();
112    public static final int XS_NORMALIZEDSTRING = XS_NORMALIZEDSTRING_NAME.hashCode();
113    public static final int XS_TOKEN = XS_TOKEN_NAME.hashCode();
114    public static final int XS_LANGUAGE = XS_LANGUAGE_NAME.hashCode();
115    public static final int XS_NAME = XS_NAME_NAME.hashCode();
116    public static final int XS_NCNAME = XS_NCNAME_NAME.hashCode();
117    public static final int XS_ID = XS_ID_NAME.hashCode();
118    public static final int XS_NMTOKEN = XS_NMTOKEN_NAME.hashCode();
119    public static final int XS_NMTOKENS = XS_NMTOKENS_NAME.hashCode();
120    public static final int XS_NONPOSITIVEINTEGER = XS_NONPOSITIVEINTEGER_NAME.hashCode();
121    public static final int XS_NEGATIVEINTEGER = XS_NEGATIVEINTEGER_NAME.hashCode();
122    public static final int XS_NONNEGATIVEINTEGER = XS_NONNEGATIVEINTEGER_NAME.hashCode();
123    public static final int XS_POSITIVEINTEGER = XS_POSITIVEINTEGER_NAME.hashCode();
124    public static final int XS_NOTATION = XS_NOTATION_NAME.hashCode();
125    public static final int XS_IDREF = XS_IDREF_NAME.hashCode();
126    public static final int XS_IDREFS = XS_IDREFS_NAME.hashCode();
127    public static final int XS_ENTITY = XS_ENTITY_NAME.hashCode();
128    public static final int XS_ENTITIES = XS_ENTITIES_NAME.hashCode();
129
130    // check for uniqueness of hashCode's
131
static
132    {
133       int[] codes = new int[45];
134       String JavaDoc[] names = new String JavaDoc[codes.length];
135       int i = 0;
136
137       names[i] = XS_INT_NAME;
138       codes[i++] = XS_INT;
139
140       names[i] = XS_LONG_NAME;
141       codes[i++] = XS_LONG;
142
143       names[i] = XS_SHORT_NAME;
144       codes[i++] = XS_SHORT;
145
146       names[i] = XS_FLOAT_NAME;
147       codes[i++] = XS_FLOAT;
148
149       names[i] = XS_DOUBLE_NAME;
150       codes[i++] = XS_DOUBLE;
151
152       names[i] = XS_BOOLEAN_NAME;
153       codes[i++] = XS_BOOLEAN;
154
155       names[i] = XS_BYTE_NAME;
156       codes[i++] = XS_BYTE;
157
158       names[i] = XS_STRING_NAME;
159       codes[i++] = XS_STRING;
160
161       names[i] = XS_INTEGER_NAME;
162       codes[i++] = XS_INTEGER;
163
164       names[i] = XS_DECIMAL_NAME;
165       codes[i++] = XS_DECIMAL;
166
167       names[i] = XS_DATETIME_NAME;
168       codes[i++] = XS_DATETIME;
169
170       names[i] = XS_QNAME_NAME;
171       codes[i++] = XS_QNAME;
172
173       names[i] = XS_ANYURI_NAME;
174       codes[i++] = XS_ANYURI;
175
176       names[i] = XS_UNSIGNEDINT_NAME;
177       codes[i++] = XS_UNSIGNEDINT;
178
179       names[i] = XS_UNSIGNEDSHORT_NAME;
180       codes[i++] = XS_UNSIGNEDSHORT;
181
182       names[i] = XS_UNSIGNEDBYTE_NAME;
183       codes[i++] = XS_UNSIGNEDBYTE;
184
185       names[i] = XS_DATE_NAME;
186       codes[i++] = XS_DATE;
187
188       names[i] = XS_TIME_NAME;
189       codes[i++] = XS_TIME;
190
191       names[i] = XS_BASE64BINARY_NAME;
192       codes[i++] = XS_BASE64BINARY;
193
194       names[i] = XS_HEXBINARY_NAME;
195       codes[i++] = XS_HEXBINARY;
196
197       names[i] = XS_ANYSIMPLETYPE_NAME;
198       codes[i++] = XS_ANYSIMPLETYPE;
199
200       names[i] = XS_DURATION_NAME;
201       codes[i++] = XS_DURATION;
202
203       names[i] = XS_GYEARMONTH_NAME;
204       codes[i++] = XS_GYEARMONTH;
205
206       names[i] = XS_GYEAR_NAME;
207       codes[i++] = XS_GYEAR;
208
209       names[i] = XS_GMONTHDAY_NAME;
210       codes[i++] = XS_GMONTHDAY;
211
212       names[i] = XS_GMONTH_NAME;
213       codes[i++] = XS_GMONTH;
214
215       names[i] = XS_GDAY_NAME;
216       codes[i++] = XS_GDAY;
217
218       names[i] = XS_NORMALIZEDSTRING_NAME;
219       codes[i++] = XS_NORMALIZEDSTRING;
220
221       names[i] = XS_TOKEN_NAME;
222       codes[i++] = XS_TOKEN;
223
224       names[i] = XS_LANGUAGE_NAME;
225       codes[i++] = XS_LANGUAGE;
226
227       names[i] = XS_NAME_NAME;
228       codes[i++] = XS_NAME;
229
230       names[i] = XS_NCNAME_NAME;
231       codes[i++] = XS_NCNAME;
232
233       names[i] = XS_ID_NAME;
234       codes[i++] = XS_ID;
235
236       names[i] = XS_NMTOKEN_NAME;
237       codes[i++] = XS_NMTOKEN;
238
239       names[i] = XS_NMTOKENS_NAME;
240       codes[i++] = XS_NMTOKENS;
241
242       names[i] = XS_NONPOSITIVEINTEGER_NAME;
243       codes[i++] = XS_NONPOSITIVEINTEGER;
244
245       names[i] = XS_NONNEGATIVEINTEGER_NAME;
246       codes[i++] = XS_NONNEGATIVEINTEGER;
247
248       names[i] = XS_POSITIVEINTEGER_NAME;
249       codes[i++] = XS_POSITIVEINTEGER;
250
251       names[i] = XS_NEGATIVEINTEGER_NAME;
252       codes[i++] = XS_NEGATIVEINTEGER;
253
254       names[i] = XS_UNSIGNEDLONG_NAME;
255       codes[i++] = XS_UNSIGNEDLONG;
256
257       names[i] = XS_NOTATION_NAME;
258       codes[i++] = XS_NOTATION;
259
260       names[i] = XS_IDREF_NAME;
261       codes[i++] = XS_IDREF;
262
263       names[i] = XS_IDREFS_NAME;
264       codes[i++] = XS_IDREFS;
265
266       names[i] = XS_ENTITY_NAME;
267       codes[i++] = XS_ENTITY;
268
269       names[i] = XS_ENTITIES_NAME;
270       codes[i++] = XS_ENTITIES;
271
272       Logger log = Logger.getLogger(TypeBinding.class);
273       boolean allAreUnique = true;
274       for(int outer = 0; outer < names.length; ++outer)
275       {
276          int outerCode = codes[outer];
277          String JavaDoc outerName = names[outer];
278
279          for(int inner = outer + 1; inner < names.length; ++inner)
280          {
281             int innerCode = codes[inner];
282             String JavaDoc innerName = names[inner];
283
284             if(outerCode == innerCode)
285             {
286                log.error("Types have the same hash code " + outerCode + ": " + outerName + " and " + innerName);
287                allAreUnique = false;
288             }
289          }
290       }
291
292       if(!allAreUnique)
293       {
294          throw new IllegalStateException JavaDoc("Not all the schema types have unique hash codes! See log for more details.");
295       }
296    }
297
298    public static Object JavaDoc unmarshal(String JavaDoc xsdType, String JavaDoc value)
299    {
300       int typeCode = xsdType.hashCode();
301       Object JavaDoc result;
302       if(typeCode == XS_INT)
303       {
304          result = Integer.valueOf(value);
305       }
306       else if(typeCode == XS_LONG)
307       {
308          result = Long.valueOf(value);
309       }
310       else if(typeCode == XS_SHORT)
311       {
312          result = Short.valueOf(value);
313       }
314       else if(typeCode == XS_BYTE)
315       {
316          result = Byte.valueOf(value);
317       }
318       else if(typeCode == XS_FLOAT)
319       {
320          if("INF".equals(value))
321          {
322             result = new Float JavaDoc(Float.POSITIVE_INFINITY);
323          }
324          else if("-INF".equals(value))
325          {
326             result = new Float JavaDoc(Float.NEGATIVE_INFINITY);
327          }
328          else
329          {
330             result = Float.valueOf(value);
331          }
332       }
333       else if(typeCode == XS_DOUBLE)
334       {
335          if("INF".equals(value))
336          {
337             result = new Double JavaDoc(Double.POSITIVE_INFINITY);
338          }
339          else if("-INF".equals(value))
340          {
341             result = new Double JavaDoc(Double.NEGATIVE_INFINITY);
342          }
343          else
344          {
345             result = Double.valueOf(value);
346          }
347       }
348       else if(typeCode == XS_BOOLEAN)
349       {
350          if(value.length() == 1)
351          {
352             switch(value.charAt(0))
353             {
354                case '1':
355                   result = Boolean.TRUE;
356                   break;
357                case '0':
358                   result = Boolean.FALSE;
359                   break;
360                default:
361                   throw new JBossXBValueFormatException("An instance of a datatype that is defined as ?boolean? can have the following legal literals" +
362                      " {true, false, 1, 0}. But got: " + value
363                   );
364             }
365          }
366          else
367          {
368             result = Boolean.valueOf(value);
369          }
370       }
371       else if(typeCode == XS_STRING)
372       {
373          result = value;
374       }
375       else if(typeCode == XS_INTEGER)
376       {
377          result = new BigInteger JavaDoc(value);
378       }
379       else if(typeCode == XS_DECIMAL)
380       {
381          result = new BigDecimal JavaDoc(value);
382       }
383       else if(typeCode == XS_DATETIME)
384       {
385          result = unmarshalDateTime(value);
386       }
387       else if(typeCode == XS_QNAME)
388       {
389          // todo XS_QNAME
390
throw new IllegalStateException JavaDoc("Recognized but not supported xsdType: " + XS_QNAME_NAME);
391       }
392       else if(typeCode == XS_ANYURI)
393       {
394          // anyUri is by default bound to java.net.URI for now. The following is the warning from JAXB2.0:
395
//
396
// Design Note � xs:anyURI is not bound to java.net.URI by default since not all
397
// possible values of xs:anyURI can be passed to the java.net.URI constructor. Using
398
// a global JAXB customization described in Section 7.9, �<javaType>
399
// Declaration", a JAXB user can override the default mapping to map xs:anyURI to
400
// java.net.URI.
401
//
402
try
403          {
404             result = new java.net.URI JavaDoc(value);
405          }
406          catch(URISyntaxException JavaDoc e)
407          {
408             throw new JBossXBValueFormatException("Failed to unmarshal anyURI value " + value, e);
409          }
410       }
411       else if(typeCode == XS_UNSIGNEDLONG)
412       {
413          double d = Double.parseDouble(value);
414          if(d < 0 || d > 18446744073709551615D)
415          {
416             throw new JBossXBValueFormatException("Invalid unsignedLong value: " + value);
417          }
418          result = new Double JavaDoc(d);
419       }
420       else if(typeCode == XS_UNSIGNEDINT)
421       {
422          long l = Long.parseLong(value);
423          if(l < 0 || l > 4294967295L)
424          {
425             throw new JBossXBValueFormatException("Invalid unsignedInt value: " + value);
426          }
427          result = new Long JavaDoc(l);
428       }
429       else if(typeCode == XS_UNSIGNEDSHORT)
430       {
431          int i = Integer.parseInt(value);
432          if(i < 0 || i > 65535)
433          {
434             throw new JBossXBValueFormatException("Invalid unsignedShort value: " + value);
435          }
436          result = new Integer JavaDoc(i);
437       }
438       else if(typeCode == XS_UNSIGNEDBYTE)
439       {
440          short s = Short.parseShort(value);
441          if(s < 0 || s > 255)
442          {
443             throw new JBossXBValueFormatException("Invalid unsignedByte value: " + value);
444          }
445          result = new Short JavaDoc(s);
446       }
447       else if(typeCode == XS_DATE)
448       {
449          result = unmarshalDate(value);
450       }
451       else if(typeCode == XS_TIME)
452       {
453          result = unmarshalTime(value);
454       }
455       else if(typeCode == XS_BASE64BINARY)
456       {
457          // todo XS_BASE64BINARY
458
throw new IllegalStateException JavaDoc("Recognized but not supported xsdType: " + XS_BASE64BINARY_NAME);
459       }
460       else if(typeCode == XS_HEXBINARY)
461       {
462          result = unmarshalHexBinary(value);
463       }
464       else if(typeCode == XS_ANYSIMPLETYPE)
465       {
466          result = value;
467       }
468       else if(typeCode == XS_DURATION)
469       {
470          // todo XS_DURATION
471
throw new IllegalStateException JavaDoc("Recognized but not supported xsdType: " + XS_DURATION_NAME);
472       }
473       else if(typeCode == XS_GYEARMONTH)
474       {
475          result = unmarshalGYearMonth(value);
476       }
477       else if(typeCode == XS_GYEAR)
478       {
479          result = unmarshalGYear(value);
480       }
481       else if(typeCode == XS_GMONTHDAY)
482       {
483          result = unmarshalGMonthDay(value);
484       }
485       else if(typeCode == XS_GMONTH)
486       {
487          return unmarshalGMonth(value);
488       }
489       else if(typeCode == XS_GDAY)
490       {
491          return unmarshalGDay(value);
492       }
493       else if(typeCode == XS_NORMALIZEDSTRING)
494       {
495          if(isNormalizedString(value))
496          {
497             result = value;
498          }
499          else
500          {
501             throw new JBossXBValueFormatException("Invalid normalizedString value: " + value);
502          }
503       }
504       else if(typeCode == XS_TOKEN)
505       {
506          if(isValidToken(value))
507          {
508             result = value;
509          }
510          else
511          {
512             throw new JBossXBValueFormatException("Invalid token value: " + value);
513          }
514       }
515       else if(typeCode == XS_LANGUAGE)
516       {
517          result = value;
518       }
519       else if(typeCode == XS_NAME)
520       {
521          result = value;
522       }
523       else if(typeCode == XS_NCNAME)
524       {
525          result = value;
526       }
527       else if(typeCode == XS_ID)
528       {
529          result = value;
530       }
531       else if(typeCode == XS_NMTOKEN)
532       {
533          result = value;
534       }
535       else if(typeCode == XS_NMTOKENS)
536       {
537          result = unmarshalNMTokens(value);
538       }
539       else if(typeCode == XS_NONPOSITIVEINTEGER)
540       {
541          result = new BigInteger JavaDoc(value);
542          if(BigInteger.ZERO.compareTo(result) < 0)
543          {
544             throw new JBossXBValueFormatException("Invalid nonPositiveInteger value: " + value);
545          }
546       }
547       else if(typeCode == XS_NEGATIVEINTEGER)
548       {
549          result = new BigInteger JavaDoc(value);
550          if(BigInteger.ZERO.compareTo(result) <= 0)
551          {
552             throw new JBossXBValueFormatException("Invalid negativeInteger value: " + value);
553          }
554       }
555       else if(typeCode == XS_NONNEGATIVEINTEGER)
556       {
557          result = new BigInteger JavaDoc(value);
558          if(BigInteger.ZERO.compareTo(result) > 0)
559          {
560             throw new JBossXBValueFormatException("Invalid nonNegativeInteger value: " + value);
561          }
562       }
563       else if(typeCode == XS_POSITIVEINTEGER)
564       {
565          result = new BigInteger JavaDoc(value);
566          if(BigInteger.ZERO.compareTo(result) >= 0)
567          {
568             throw new JBossXBValueFormatException("Invalid positiveInteger value: " + value);
569          }
570       }
571       else if(typeCode == XS_NOTATION)
572       {
573          // todo NOTATION
574
result = value;
575       }
576       else if(typeCode == XS_IDREF)
577       {
578          result = value;
579       }
580       else if(typeCode == XS_IDREFS)
581       {
582          result = unmarshalIdRefs(value);
583       }
584       else if(typeCode == XS_ENTITY)
585       {
586          result = value;
587       }
588       else if(typeCode == XS_ENTITIES)
589       {
590          result = unmarshalIdRefs(value);
591       }
592       else
593       {
594          throw new IllegalStateException JavaDoc("Not supported xsdType: " + xsdType + ", hashCode=" + xsdType.hashCode());
595       }
596       return result;
597    }
598
599    public static Object JavaDoc unmarshal(String JavaDoc value, Class JavaDoc javaType)
600    {
601       Object JavaDoc result;
602       if(String JavaDoc.class == javaType)
603       {
604          result = value;
605       }
606       else if(int.class == javaType || Integer JavaDoc.class == javaType)
607       {
608          result = Integer.valueOf(value);
609       }
610       else if(long.class == javaType || Long JavaDoc.class == javaType)
611       {
612          result = Long.valueOf(value);
613       }
614       else if(double.class == javaType || Double JavaDoc.class == javaType)
615       {
616          result = Double.valueOf(value);
617       }
618       else if(float.class == javaType || Float JavaDoc.class == javaType)
619       {
620          result = Float.valueOf(value);
621       }
622       else if(short.class == javaType || Short JavaDoc.class == javaType)
623       {
624          result = Short.valueOf(value);
625       }
626       else if(byte.class == javaType || Byte JavaDoc.class == javaType)
627       {
628          result = Byte.valueOf(value);
629       }
630       else if(char.class == javaType || Character JavaDoc.class == javaType)
631       {
632          result = new Character JavaDoc(value.charAt(0));
633       }
634       else if(java.util.Date JavaDoc.class == javaType)
635       {
636          final String JavaDoc FORMAT = "yyyy-MM-dd";
637          try
638          {
639             result = new java.text.SimpleDateFormat JavaDoc(FORMAT).parse(value);
640          }
641          catch(ParseException JavaDoc e)
642          {
643             throw new IllegalStateException JavaDoc(
644                "Failed to parse date accroding to " + FORMAT + " format: " + value + ": " + e.getMessage()
645             );
646          }
647       }
648       else if(Object JavaDoc.class == javaType)
649       {
650          result = value;
651       }
652       else
653       {
654          //todo do something
655
throw new IllegalStateException JavaDoc("Unexpected field type " + javaType);
656       }
657
658       return result;
659    }
660
661    public static String JavaDoc marshal(String JavaDoc xsdType, Object JavaDoc value)
662    {
663       if(value == null)
664       {
665          throw new IllegalArgumentException JavaDoc("Can't marshal null value!");
666       }
667
668       int typeCode = xsdType.hashCode();
669       String JavaDoc result;
670       if(typeCode == XS_INT)
671       {
672          Integer JavaDoc i = (Integer JavaDoc)value;
673          result = i.toString();
674       }
675       else if(typeCode == XS_LONG)
676       {
677          Long JavaDoc l = (Long JavaDoc)value;
678          result = l.toString();
679       }
680       else if(typeCode == XS_SHORT)
681       {
682          Short JavaDoc s = (Short JavaDoc)value;
683          result = s.toString();
684       }
685       else if(typeCode == XS_BYTE)
686       {
687          Byte JavaDoc b = (Byte JavaDoc)value;
688          result = b.toString();
689       }
690       else if(typeCode == XS_FLOAT)
691       {
692          Float JavaDoc f = (Float JavaDoc)value;
693          if(f.floatValue() == Float.POSITIVE_INFINITY)
694          {
695             result = "INF";
696          }
697          else if(f.floatValue() == Float.NEGATIVE_INFINITY)
698          {
699             result = "-INF";
700          }
701          else
702          {
703             result = f.toString();
704          }
705       }
706       else if(typeCode == XS_DOUBLE)
707       {
708          Double JavaDoc d = (Double JavaDoc)value;
709          if(d.doubleValue() == Double.POSITIVE_INFINITY)
710          {
711             result = "INF";
712          }
713          else if(d.doubleValue() == Double.NEGATIVE_INFINITY)
714          {
715             result = "-INF";
716          }
717          else
718          {
719             result = d.toString();
720          }
721       }
722       else if(typeCode == XS_BOOLEAN)
723       {
724          if(value instanceof Boolean JavaDoc)
725          {
726             result = ((Boolean JavaDoc)value).booleanValue() ? "true" : "false";
727          }
728          else if(value instanceof Number JavaDoc)
729          {
730             Number JavaDoc n = (Number JavaDoc)value;
731             switch(n.byteValue())
732             {
733                case 1:
734                   result = "1";
735                   break;
736                case 0:
737                   result = "0";
738                   break;
739                default:
740                   throw new JBossXBValueFormatException("An instance of a datatype that is defined as ?boolean? can have the following legal literals" +
741                      " {true, false, 1, 0}. But got: " + value
742                   );
743             }
744          }
745          else
746          {
747             throw new JBossXBValueFormatException("Java value for XSD boolean type expected to be an instance of java.lang.Boolean or java.lang.Number. But the value is of type " +
748                value.getClass().getName()
749             );
750          }
751       }
752       else if(typeCode == XS_STRING)
753       {
754          result = (String JavaDoc)value;
755       }
756       else if(typeCode == XS_INTEGER)
757       {
758          BigInteger JavaDoc bi = (BigInteger JavaDoc)value;
759          result = bi.toString();
760       }
761       else if(typeCode == XS_DECIMAL)
762       {
763          BigDecimal JavaDoc bd = (BigDecimal JavaDoc)value;
764          result = bd.toString();
765       }
766       else if(typeCode == XS_DATETIME)
767       {
768          Calendar JavaDoc c = (Calendar JavaDoc)value;
769          result = marshalDateTime(c);
770       }
771       else if(typeCode == XS_QNAME)
772       {
773          // todo XS_QNAME
774
throw new IllegalStateException JavaDoc("Recognized but not supported xsdType: " + xsdType);
775       }
776       else if(typeCode == XS_ANYURI)
777       {
778          java.net.URI JavaDoc u = (java.net.URI JavaDoc)value;
779          result = u.toString();
780       }
781       else if(typeCode == XS_UNSIGNEDLONG)
782       {
783          Double JavaDoc d = (Double JavaDoc)value;
784          if(d.doubleValue() < 0 || d.doubleValue() > 18446744073709551615D)
785          {
786             throw new JBossXBValueFormatException("Invalid unsignedLong value: " + value);
787          }
788          result = d.toString();
789       }
790       else if(typeCode == XS_UNSIGNEDINT)
791       {
792          Long JavaDoc l = (Long JavaDoc)value;
793          if(l.longValue() < 0 || l.longValue() > 4294967295L)
794          {
795             throw new JBossXBValueFormatException("Invalid unsignedInt value: " + value);
796          }
797          result = l.toString();
798       }
799       else if(typeCode == XS_UNSIGNEDSHORT)
800       {
801          Integer JavaDoc i = (Integer JavaDoc)value;
802          if(i.intValue() < 0 || i.intValue() > 65535)
803          {
804             throw new JBossXBValueFormatException("Invalid unsignedShort value: " + value);
805          }
806          result = i.toString();
807       }
808       else if(typeCode == XS_UNSIGNEDBYTE)
809       {
810          Short JavaDoc s = (Short JavaDoc)value;
811          if(s.shortValue() < 0 || s.shortValue() > 255)
812          {
813             throw new JBossXBValueFormatException("Invalid unsignedByte value: " + value);
814          }
815          result = s.toString();
816       }
817       else if(typeCode == XS_DATE)
818       {
819          Calendar JavaDoc c = (Calendar JavaDoc)value;
820          result = marshalDate(c);
821       }
822       else if(typeCode == XS_TIME)
823       {
824          Calendar JavaDoc c = (Calendar JavaDoc)value;
825          result = marshalTime(c);
826       }
827       else if(typeCode == XS_BASE64BINARY)
828       {
829          // todo XS_BASE64BINARY
830
throw new IllegalStateException JavaDoc("Recognized but not supported xsdType: " + xsdType);
831       }
832       else if(typeCode == XS_HEXBINARY)
833       {
834          byte[] b = (byte[])value;
835          result = marshalHexBinary(b);
836       }
837       else if(typeCode == XS_ANYSIMPLETYPE)
838       {
839          // todo XS_ANYSIMPLETYPE
840
throw new IllegalStateException JavaDoc("Recognized but not supported xsdType: " + xsdType);
841       }
842       else if(typeCode == XS_DURATION)
843       {
844          // todo XS_DURATION
845
throw new IllegalStateException JavaDoc("Recognized but not supported xsdType: " + xsdType);
846       }
847       else if(typeCode == XS_GYEARMONTH)
848       {
849          Calendar JavaDoc c = (Calendar JavaDoc)value;
850          result = marshalGYearMonth(c);
851       }
852       else if(typeCode == XS_GYEAR)
853       {
854          Calendar JavaDoc c = (Calendar JavaDoc)value;
855          result = marshalGYear(c);
856       }
857       else if(typeCode == XS_GMONTHDAY)
858       {
859          Calendar JavaDoc c = (Calendar JavaDoc)value;
860          result = marshalGMonthDay(c);
861       }
862       else if(typeCode == XS_GMONTH)
863       {
864          Calendar JavaDoc c = (Calendar JavaDoc)value;
865          result = marshalGMonth(c);
866       }
867       else if(typeCode == XS_GDAY)
868       {
869          Calendar JavaDoc c = (Calendar JavaDoc)value;
870          result = marshalGDay(c);
871       }
872       else if(typeCode == XS_NORMALIZEDSTRING)
873       {
874          String JavaDoc s = (String JavaDoc)value;
875          if(isNormalizedString(s))
876          {
877             result = s;
878          }
879          else
880          {
881             throw new JBossXBValueFormatException("Invalid normalizedString value: " + value);
882          }
883       }
884       else if(typeCode == XS_TOKEN)
885       {
886          String JavaDoc s = (String JavaDoc)value;
887          if(isValidToken(s))
888          {
889             result = s;
890          }
891          else
892          {
893             throw new JBossXBValueFormatException("Invalid token value: " + value);
894          }
895       }
896       else if(typeCode == XS_LANGUAGE)
897       {
898          String JavaDoc s = (String JavaDoc)value;
899          result = s;
900       }
901       else if(typeCode == XS_NAME)
902       {
903          String JavaDoc s = (String JavaDoc)value;
904          result = s;
905       }
906       else if(typeCode == XS_NCNAME)
907       {
908          String JavaDoc s = (String JavaDoc)value;
909          result = s;
910       }
911       else if(typeCode == XS_ID)
912       {
913          String JavaDoc s = (String JavaDoc)value;
914          result = s;
915       }
916       else if(typeCode == XS_NMTOKEN)
917       {
918          String JavaDoc s = (String JavaDoc)value;
919          result = s;
920       }
921       else if(typeCode == XS_NMTOKENS)
922       {
923          String JavaDoc[] tokens = (String JavaDoc[])value;
924          if(tokens.length > 0)
925          {
926             result = tokens[0];
927             for(int i = 1; i < tokens.length; ++i)
928             {
929                result += ' ' + tokens[i];
930             }
931          }
932          else
933          {
934             result = "";
935          }
936       }
937       else if(typeCode == XS_NONPOSITIVEINTEGER)
938       {
939          BigInteger JavaDoc bi = (BigInteger JavaDoc)value;
940          if(BigInteger.ZERO.compareTo(bi) < 0)
941          {
942             throw new JBossXBValueFormatException("Invalid nonPositiveInteger value: " + value);
943          }
944          result = bi.toString();
945       }
946       else if(typeCode == XS_NEGATIVEINTEGER)
947       {
948          BigInteger JavaDoc bi = (BigInteger JavaDoc)value;
949          if(BigInteger.ZERO.compareTo(bi) <= 0)
950          {
951             throw new JBossXBValueFormatException("Invalid negativeInteger value: " + value);
952          }
953          result = bi.toString();
954       }
955       else if(typeCode == XS_NONNEGATIVEINTEGER)
956       {
957          BigInteger JavaDoc bi = (BigInteger JavaDoc)value;
958          if(BigInteger.ZERO.compareTo(bi) > 0)
959          {
960             throw new JBossXBValueFormatException("Invalid nonNegativeInteger value: " + value);
961          }
962          result = bi.toString();
963       }
964       else if(typeCode == XS_POSITIVEINTEGER)
965       {
966          BigInteger JavaDoc bi = (BigInteger JavaDoc)value;
967          if(BigInteger.ZERO.compareTo(bi) >= 0)
968          {
969             throw new JBossXBValueFormatException("Invalid positiveInteger value: " + value);
970          }
971          result = bi.toString();
972       }
973       else if(typeCode == XS_NOTATION)
974       {
975          // todo NOTATION
976
result = (String JavaDoc)value;
977       }
978       else if(typeCode == XS_IDREF)
979       {
980          result = (String JavaDoc)value;
981       }
982       else if(typeCode == XS_IDREFS)
983       {
984          String JavaDoc[] refs = (String JavaDoc[])value;
985          if(refs.length > 0)
986          {
987             result = refs[0];
988             for(int i = 1; i < refs.length; ++i)
989             {
990                result += ' ' + refs[i];
991             }
992          }
993          else
994          {
995             result = "";
996          }
997       }
998       else if(typeCode == XS_ENTITY)
999       {
1000         result = (String JavaDoc)value;
1001      }
1002      else if(typeCode == XS_ENTITIES)
1003      {
1004         String JavaDoc[] refs = (String JavaDoc[])value;
1005         if(refs.length > 0)
1006         {
1007            result = refs[0];
1008            for(int i = 1; i < refs.length; ++i)
1009            {
1010               result += ' ' + refs[i];
1011            }
1012         }
1013         else
1014         {
1015            result = "";
1016         }
1017      }
1018      else
1019      {
1020         throw new IllegalStateException JavaDoc("Not supported xsdType: " + xsdType + ", hashCode=" + xsdType.hashCode());
1021      }
1022      return result;
1023   }
1024
1025   public static String JavaDoc[] unmarshalNMTokens(String JavaDoc value)
1026   {
1027      StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(value);
1028      String JavaDoc[] tokens = new String JavaDoc[tokenizer.countTokens()];
1029      for(int i = 0; i < tokens.length; ++i)
1030      {
1031         tokens[i] = tokenizer.nextToken();
1032      }
1033      return tokens;
1034   }
1035
1036   public static String JavaDoc[] unmarshalIdRefs(String JavaDoc value)
1037   {
1038      StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(value);
1039      String JavaDoc[] tokens = new String JavaDoc[tokenizer.countTokens()];
1040      for(int i = 0; i < tokens.length; ++i)
1041      {
1042         tokens[i] = tokenizer.nextToken();
1043      }
1044      return tokens;
1045   }
1046
1047   /**
1048    * --MM-DD[timezone]
1049    *
1050    * @param value
1051    * @return
1052    */

1053   public static Calendar JavaDoc unmarshalGMonthDay(String JavaDoc value)
1054   {
1055      if(value.length() < 6 ||
1056         value.charAt(0) != '-' ||
1057         value.charAt(1) != '-' ||
1058         value.charAt(4) != '-')
1059      {
1060         throw new JBossXBValueFormatException(
1061            "gMonthDay value does not follow the format '--MM-DD[timezone]: " + value
1062         );
1063      }
1064
1065      Calendar JavaDoc cal = Calendar.getInstance();
1066      cal.clear();
1067      cal.set(Calendar.MONTH, Integer.parseInt(value.substring(2, 4)) - 1);
1068      cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(value.substring(5, 7)));
1069      if(value.length() > 7)
1070      {
1071         cal.setTimeZone(parseTimeZone(value, 7));
1072      }
1073      return cal;
1074   }
1075
1076   /**
1077    * --MM-DD[timezone]
1078    *
1079    * @param value
1080    * @return
1081    */

1082   public static String JavaDoc marshalGMonthDay(Calendar JavaDoc value)
1083   {
1084      String JavaDoc result = "--";
1085      result += marshalInt(value.get(Calendar.MONTH) + 1, 2);
1086      result += '-';
1087      result += marshalInt(value.get(Calendar.DAY_OF_MONTH), 2);
1088      result += marshalTimeZone(value.getTimeZone());
1089      return result;
1090   }
1091
1092   /**
1093    * --MM[timezone]
1094    *
1095    * @param value
1096    * @return
1097    */

1098   public static Calendar JavaDoc unmarshalGMonth(String JavaDoc value)
1099   {
1100      if(value.length() < 4 || value.charAt(0) != '-' || value.charAt(1) != '-')
1101      {
1102         throw new JBossXBValueFormatException("gMonth value does not follow the format '--MM': " + value);
1103      }
1104
1105      Calendar JavaDoc cal = Calendar.getInstance();
1106      cal.clear();
1107
1108      cal.set(Calendar.MONTH, Integer.parseInt(value.substring(2, 4)) - 1);
1109      if(value.length() > 4)
1110      {
1111         cal.setTimeZone(parseTimeZone(value, 4));
1112      }
1113      return cal;
1114   }
1115
1116   /**
1117    * --MM[timezone]
1118    *
1119    * @param value
1120    * @return
1121    */

1122   public static String JavaDoc marshalGMonth(Calendar JavaDoc value)
1123   {
1124      String JavaDoc result = "--";
1125      result += marshalInt(value.get(Calendar.MONTH) + 1, 2);
1126      result += marshalTimeZone(value.getTimeZone());
1127      return result;
1128   }
1129
1130   public static Calendar JavaDoc unmarshalGYear(String JavaDoc value)
1131   {
1132      Calendar JavaDoc cal = Calendar.getInstance();
1133      cal.clear();
1134      int timeZone = parseGYear(value, 0, cal);
1135      if(value.length() > timeZone)
1136      {
1137         TimeZone JavaDoc tz = parseTimeZone(value, timeZone);
1138         cal.setTimeZone(tz);
1139      }
1140      return cal;
1141   }
1142
1143   public static String JavaDoc marshalGYear(Calendar JavaDoc value)
1144   {
1145      String JavaDoc result = String.valueOf(value.get(Calendar.YEAR));
1146      result += marshalTimeZone(value.getTimeZone());
1147      return result;
1148   }
1149
1150   /**
1151    * Unmarshals gYearDate string following the format [-]CCYY-MM[timezone]
1152    *
1153    * @param value
1154    * @return
1155    */

1156   public static Calendar JavaDoc unmarshalGYearMonth(String JavaDoc value)
1157   {
1158      Calendar JavaDoc cal = Calendar.getInstance();
1159      cal.clear();
1160
1161      int month = parseGYear(value, 0, cal);
1162      if(value.charAt(month) != '-')
1163      {
1164         throw new JBossXBValueFormatException(
1165            "gYearMonth value does not follow the format '[-]CCYY-MM[timezone]': " + value
1166         );
1167      }
1168
1169      cal.set(Calendar.MONTH, Integer.parseInt(value.substring(month + 1, month + 3)) - 1);
1170
1171      if(value.length() > month + 3)
1172      {
1173         TimeZone JavaDoc tz = parseTimeZone(value, month + 3);
1174         cal.setTimeZone(tz);
1175      }
1176
1177      return cal;
1178   }
1179
1180   /**
1181    * [-]CCYY-MM[timezone]
1182    *
1183    * @param value
1184    * @return
1185    */

1186   public static String JavaDoc marshalGYearMonth(Calendar JavaDoc value)
1187   {
1188      String JavaDoc result = String.valueOf(value.get(Calendar.YEAR));
1189      result += '-';
1190      result += marshalInt(value.get(Calendar.MONTH) + 1, 2);
1191      result += marshalTimeZone(value.getTimeZone());
1192      return result;
1193   }
1194
1195   /**
1196    * ---DD[timezonePart]
1197    *
1198    * @param value
1199    * @return
1200    */

1201   public static Calendar JavaDoc unmarshalGDay(String JavaDoc value)
1202   {
1203      if(value.length() < 5 || value.charAt(0) != '-' || value.charAt(1) != '-' || value.charAt(2) != '-')
1204      {
1205         throw new NumberFormatException JavaDoc("gDay value does not follow the format (---DD[timezonePart]): " + value);
1206      }
1207
1208      // validate day
1209
int day = Integer.parseInt(value.substring(3, 5));
1210      if(day < 1 || day > 31)
1211      {
1212         throw new NumberFormatException JavaDoc("gDay value is not in the interval [1..31]: " + day);
1213      }
1214
1215      // validate timezonePart
1216
TimeZone JavaDoc tz = parseTimeZone(value, 5);
1217
1218      Calendar JavaDoc cal = Calendar.getInstance();
1219      cal.clear();
1220      if(tz != null)
1221      {
1222         cal.setTimeZone(tz);
1223      }
1224      cal.set(Calendar.DAY_OF_MONTH, day);
1225
1226      return cal;
1227   }
1228
1229   /**
1230    * ---DD[timezonePart]
1231    *
1232    * @param value
1233    * @return
1234    */

1235   public static String JavaDoc marshalGDay(Calendar JavaDoc value)
1236   {
1237      String JavaDoc result = "---";
1238      result += marshalInt(value.get(Calendar.DAY_OF_MONTH), 2);
1239      result += marshalTimeZone(value.getTimeZone());
1240      return result;
1241   }
1242
1243   /**
1244    * Parses a string value that represents date following the format defined in
1245    * http://www.w3.org/TR/xmlschema-2/#dateTime, i.e. '-'? yyyy '-' mm '-' dd.
1246    * Creates an instance of java.util.Calendar and initializes it to the parsed values of the year, month and day.
1247    *
1248    * @param value string date value
1249    * @return equivalent date as an instance of java.util.Calendar.
1250    */

1251   public static Calendar JavaDoc unmarshalDate(String JavaDoc value)
1252   {
1253      Calendar JavaDoc cal = Calendar.getInstance();
1254      cal.clear();
1255
1256      int ind = parseDate(value, 0, cal);
1257
1258      TimeZone JavaDoc tz = null;
1259      if(ind < value.length())
1260      {
1261         tz = parseTimeZone(value, ind);
1262      }
1263
1264      if(tz != null)
1265      {
1266         cal.setTimeZone(tz);
1267      }
1268
1269      return cal;
1270   }
1271
1272   /**
1273    * [-]yyyy-mm-dd
1274    *
1275    * @param value string date value
1276    * @return equivalent date as an instance of java.util.Calendar.
1277    */

1278   public static String JavaDoc marshalDate(Calendar JavaDoc value)
1279   {
1280      String JavaDoc result = String.valueOf(value.get(Calendar.YEAR));
1281      result += '-';
1282      result += marshalInt(value.get(Calendar.MONTH) + 1, 2);
1283      result += '-';
1284      result += marshalInt(value.get(Calendar.DAY_OF_MONTH), 2);
1285      result += marshalTimeZone(value.getTimeZone());
1286      return result;
1287   }
1288
1289   /**
1290    * Parses string representation of time following the format hh:mm:ss:sss with optional timezone indicator.
1291    *
1292    * @param value
1293    * @return
1294    */

1295   public static Calendar JavaDoc unmarshalTime(String JavaDoc value)
1296   {
1297      Calendar JavaDoc cal = Calendar.getInstance();
1298      cal.clear();
1299
1300      parseTime(value, 0, cal);
1301
1302      TimeZone JavaDoc tz = null;
1303      if(value.length() > 12)
1304      {
1305         tz = parseTimeZone(value, 12);
1306      }
1307
1308      if(tz != null)
1309      {
1310         cal.setTimeZone(tz);
1311      }
1312      return cal;
1313   }
1314
1315   /**
1316    * hh:mm:ss:sss[timezone]
1317    *
1318    * @param value
1319    * @return
1320    */

1321   public static String JavaDoc marshalTime(Calendar JavaDoc value)
1322   {
1323      String JavaDoc result = marshalInt(value.get(Calendar.HOUR_OF_DAY), 2);
1324      result += ':';
1325      result += marshalInt(value.get(Calendar.MINUTE), 2);
1326      result += ':';
1327      result += marshalInt(value.get(Calendar.SECOND), 2);
1328      result += '.';
1329      result += String.valueOf(value.get(Calendar.MILLISECOND));
1330      result += marshalTimeZone(value.getTimeZone());
1331      return result;
1332   }
1333
1334   /**
1335    * Parses string value of datetime following the format [-]yyyy-mm-ddThh:mm:ss[.s+][timezone].
1336    *
1337    * @param value
1338    * @return
1339    */

1340   public static Calendar JavaDoc unmarshalDateTime(String JavaDoc value)
1341   {
1342      Calendar JavaDoc cal = Calendar.getInstance();
1343      cal.clear();
1344
1345      int timeInd = parseDate(value, 0, cal);
1346      if(value.charAt(timeInd) != 'T')
1347      {
1348         throw new JBossXBValueFormatException("DateTime value does not follow the format '[-]yyyy-mm-ddThh:mm:ss[.s+][timezone]': expected 'T' but got " +
1349            value.charAt(timeInd)
1350         );
1351      }
1352
1353      parseTime(value, timeInd + 1, cal);
1354
1355      TimeZone JavaDoc tz = null;
1356      if(value.length() > timeInd + 13)
1357      {
1358         tz = parseTimeZone(value, timeInd + 13);
1359      }
1360
1361      if(tz != null)
1362      {
1363         cal.setTimeZone(tz);
1364      }
1365
1366      return cal;
1367   }
1368
1369   /**
1370    * [-]yyyy-mm-ddThh:mm:ss[.s+][timezone]
1371    *
1372    * @param value
1373    * @return
1374    */

1375   public static String JavaDoc marshalDateTime(Calendar JavaDoc value)
1376   {
1377      String JavaDoc result = String.valueOf(value.get(Calendar.YEAR));
1378      result += '-';
1379      result += marshalInt(value.get(Calendar.MONTH) + 1, 2);
1380      result += '-';
1381      result += marshalInt(value.get(Calendar.DAY_OF_MONTH), 2);
1382      result += 'T';
1383      result += marshalInt(value.get(Calendar.HOUR_OF_DAY), 2);
1384      result += ':';
1385      result += marshalInt(value.get(Calendar.MINUTE), 2);
1386      result += ':';
1387      result += marshalInt(value.get(Calendar.SECOND), 2);
1388      result += '.';
1389      result += String.valueOf(value.get(Calendar.MILLISECOND));
1390      result += marshalTimeZone(value.getTimeZone());
1391      return result;
1392   }
1393
1394   /**
1395    * Converts hexBinary value into byte array by encoding two subsequent hexadecimal digits into one byte.
1396    *
1397    * @param value
1398    * @return
1399    */

1400   public static byte[] unmarshalHexBinary(String JavaDoc value)
1401   {
1402      if(value.length() % 2 != 0)
1403      {
1404         throw new IllegalArgumentException JavaDoc("hexBinary value must have even length.");
1405      }
1406
1407      ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
1408      for(int i = 0; i < value.length(); i += 2)
1409      {
1410         char c1 = value.charAt(i);
1411         char c2 = value.charAt(i + 1);
1412         byte b = 0;
1413         if((c1 >= '0') && (c1 <= '9'))
1414         {
1415            b += ((c1 - '0') * 16);
1416         }
1417         else if((c1 >= 'a') && (c1 <= 'f'))
1418         {
1419            b += ((c1 - 'a' + 10) * 16);
1420         }
1421         else if((c1 >= 'A') && (c1 <= 'F'))
1422         {
1423            b += ((c1 - 'A' + 10) * 16);
1424         }
1425         else
1426         {
1427            throw new IllegalArgumentException JavaDoc("hexBinary value contains illegal character: " + value);
1428         }
1429
1430         if((c2 >= '0') && (c2 <= '9'))
1431         {
1432            b += (c2 - '0');
1433         }
1434         else if((c2 >= 'a') && (c2 <= 'f'))
1435         {
1436            b += (c2 - 'a' + 10);
1437         }
1438         else if((c2 >= 'A') && (c2 <= 'F'))
1439         {
1440            b += (c2 - 'A' + 10);
1441         }
1442         else
1443         {
1444            throw new IllegalArgumentException JavaDoc("hexBinary value contains illegal character: " + value);
1445         }
1446         baos.write(b);
1447      }
1448      return (baos.toByteArray());
1449   }
1450
1451   /**
1452    * @param value
1453    * @return
1454    */

1455   public static String JavaDoc marshalHexBinary(byte[] value)
1456   {
1457      StringBuffer JavaDoc result = new StringBuffer JavaDoc(2 * value.length);
1458      for(int i = 0; i < value.length; ++i)
1459      {
1460         result.append(convertDigit((int)(value[i] >> 4)));
1461         result.append(convertDigit((int)(value[i] & 0x0f)));
1462      }
1463      return result.toString();
1464   }
1465
1466   public static boolean isNormalizedString(String JavaDoc value)
1467   {
1468      for(int i = 0; i < value.length(); ++i)
1469      {
1470         char c = value.charAt(i);
1471         if(c == 0x09 || c == 0x0A || c == 0x0D)
1472         {
1473            return false;
1474         }
1475      }
1476      return true;
1477   }
1478
1479   public static boolean isValidToken(String JavaDoc value)
1480   {
1481      if(value != null && value.length() > 0)
1482      {
1483         if(value.charAt(0) == 0x20 || value.charAt(value.length() - 1) == 0x20)
1484         {
1485            return false;
1486         }
1487
1488         for(int i = 0; i < value.length(); ++i)
1489         {
1490            char c = value.charAt(i);
1491            if(c == 0x09 || c == 0x0A || c == 0x0D)
1492            {
1493               return false;
1494            }
1495            else if(c == 0x20)
1496            {
1497               if(i + 1 < value.length() && value.charAt(i + 1) == 0x20)
1498               {
1499                  return false;
1500               }
1501            }
1502         }
1503      }
1504
1505      return true;
1506   }
1507
1508   private static int parseGYear(String JavaDoc value, int start, Calendar JavaDoc cal)
1509   {
1510      int negative = (value.charAt(start) == '-' ? 1 : 0);
1511      cal.set(Calendar.YEAR, Integer.parseInt(value.substring(start, start + 4 + negative)));
1512      return start + 4 + negative;
1513   }
1514
1515   private static int parseDate(String JavaDoc value, int start, Calendar JavaDoc cal)
1516   {
1517      if(value.charAt(start) == '-')
1518      {
1519         ++start;
1520      }
1521
1522      if(!Character.isDigit(value.charAt(start)))
1523      {
1524         throw new JBossXBValueFormatException(
1525            "Date value does not follow the format '-'? yyyy '-' mm '-' dd: " + value
1526         );
1527      }
1528
1529      int nextToken = value.indexOf('-', start);
1530      if(nextToken == -1 || nextToken - start < 4)
1531      {
1532         throw new JBossXBValueFormatException(
1533            "Date value does not follow the format '-'? yyyy '-' mm '-' dd: " + value
1534         );
1535      }
1536
1537      int year = Integer.parseInt(value.substring(start, nextToken));
1538
1539      start = nextToken + 1;
1540      nextToken = value.indexOf('-', start);
1541      if(nextToken == -1 || nextToken - start < 2)
1542      {
1543         throw new JBossXBValueFormatException(
1544            "Date value does not follow the format '-'? yyyy '-' mm '-' dd: " + value
1545         );
1546      }
1547
1548      int month = Integer.parseInt(value.substring(start, nextToken));
1549
1550      start = nextToken + 1;
1551      nextToken += 3;
1552      int day = Integer.parseInt(value.substring(start, nextToken));
1553
1554      cal.set(Calendar.YEAR, year);
1555      cal.set(Calendar.MONTH, month - 1);
1556      cal.set(Calendar.DAY_OF_MONTH, day);
1557
1558      return nextToken;
1559   }
1560
1561   /**
1562    * Parses string value of time following the format 'hh:mm:ss:sss' and sets time value on the passed in
1563    * java.util.Calendar instace.
1564    *
1565    * @param value
1566    * @param cal
1567    */

1568   private static void parseTime(String JavaDoc value, int start, Calendar JavaDoc cal)
1569   {
1570      if(value.charAt(start + 2) != ':' || value.charAt(start + 5) != ':' || value.charAt(start + 8) != '.')
1571      {
1572         throw new JBossXBValueFormatException("Time value does not follow the format 'hh:mm:ss:sss': " + value);
1573      }
1574
1575      int hh = Integer.parseInt(value.substring(start, start + 2));
1576      int mm = Integer.parseInt(value.substring(start + 3, start + 5));
1577      int ss = Integer.parseInt(value.substring(start + 6, start + 8));
1578      int sss = Integer.parseInt(value.substring(start + 9, start + 12));
1579
1580      cal.set(Calendar.HOUR_OF_DAY, hh);
1581      cal.set(Calendar.MINUTE, mm);
1582      cal.set(Calendar.SECOND, ss);
1583      cal.set(Calendar.MILLISECOND, sss);
1584   }
1585
1586   /**
1587    * Parses timzone.
1588    * Format: [+/-]HH:MM
1589    *
1590    * @return
1591    */

1592   private static TimeZone JavaDoc parseTimeZone(String JavaDoc value, int start)
1593   {
1594      TimeZone JavaDoc tz = null;
1595      if(value.charAt(start) == '+' || (value.charAt(start) == '-'))
1596      {
1597         if(value.length() - start == 6 &&
1598            Character.isDigit(value.charAt(start + 1)) &&
1599            Character.isDigit(value.charAt(start + 2)) &&
1600            value.charAt(start + 3) == ':' &&
1601            Character.isDigit(value.charAt(start + 4)) &&
1602            Character.isDigit(value.charAt(start + 5)))
1603         {
1604            tz = TimeZone.getTimeZone("GMT" + value.substring(start));
1605         }
1606         else
1607         {
1608            throw new NumberFormatException JavaDoc(
1609               "Timezone value does not follow the format ([+/-]HH:MM): " + value.substring(start)
1610            );
1611         }
1612      }
1613      else if(value.charAt(start) == 'Z')
1614      {
1615         tz = TimeZone.getTimeZone("GMT");
1616      }
1617      else
1618      {
1619         throw new NumberFormatException JavaDoc(
1620            "Timezone value does not follow the format ([+/-]HH:MM): " + value.substring(start)
1621         );
1622      }
1623      return tz;
1624   }
1625
1626   /**
1627    * Parses timzone.
1628    * Format: [+/-]HH:MM
1629    *
1630    * @return
1631    */

1632   private static String JavaDoc marshalTimeZone(TimeZone JavaDoc value)
1633   {
1634      String JavaDoc result = value.toString();
1635      return result;
1636   }
1637
1638   private static String JavaDoc marshalInt(int value, int length)
1639   {
1640      String JavaDoc result = String.valueOf(value);
1641      if(result.length() < length)
1642      {
1643         while(result.length() < length)
1644         {
1645            result = '0' + result;
1646         }
1647      }
1648      else if(result.length() > length)
1649      {
1650         throw new JBossXBValueFormatException(
1651            "Can't marshal int value " + value + " to a string with length of " + length
1652         );
1653      }
1654      return result;
1655   }
1656
1657   private static char convertDigit(int value)
1658   {
1659      value &= 0x0f;
1660      if(value >= 10)
1661      {
1662         return ((char)(value - 10 + 'a'));
1663      }
1664      else
1665      {
1666         return ((char)(value + '0'));
1667      }
1668   }
1669}
1670
Popular Tags