1 22 package org.jboss.xb.binding; 23 24 import org.jboss.logging.Logger; 25 import org.jboss.util.Base64; 26 27 import javax.xml.namespace.QName ; 28 import javax.xml.namespace.NamespaceContext ; 29 import java.io.ByteArrayOutputStream ; 30 import java.io.Serializable ; 31 import java.math.BigDecimal ; 32 import java.math.BigInteger ; 33 import java.net.URISyntaxException ; 34 import java.text.DecimalFormat ; 35 import java.text.ParseException ; 36 import java.util.Calendar ; 37 import java.util.StringTokenizer ; 38 import java.util.TimeZone ; 39 import java.util.List ; 40 import java.util.ArrayList ; 41 42 43 48 public final class SimpleTypeBindings 49 implements Serializable 50 { 51 static final long serialVersionUID = 4372272109355825813L; 52 53 public static final String XS_ANYSIMPLETYPE_NAME = "anySimpleType"; 54 55 public static final String XS_STRING_NAME = "string"; 59 public static final String XS_BOOLEAN_NAME = "boolean"; 60 public static final String XS_DECIMAL_NAME = "decimal"; 61 public static final String XS_FLOAT_NAME = "float"; 62 public static final String XS_DOUBLE_NAME = "double"; 63 public static final String XS_DURATION_NAME = "duration"; 64 public static final String XS_DATETIME_NAME = "dateTime"; 65 public static final String XS_TIME_NAME = "time"; 66 public static final String XS_DATE_NAME = "date"; 67 public static final String XS_GYEARMONTH_NAME = "gYearMonth"; 68 public static final String XS_GYEAR_NAME = "gYear"; 69 public static final String XS_GMONTHDAY_NAME = "gMonthDay"; 70 public static final String XS_GDAY_NAME = "gDay"; 71 public static final String XS_GMONTH_NAME = "gMonth"; 72 public static final String XS_HEXBINARY_NAME = "hexBinary"; 73 public static final String XS_BASE64BINARY_NAME = "base64Binary"; 74 public static final String XS_ANYURI_NAME = "anyURI"; 75 public static final String XS_QNAME_NAME = "QName"; 76 public static final String XS_NOTATION_NAME = "NOTATION"; 77 78 82 public static final String XS_NORMALIZEDSTRING_NAME = "normalizedString"; 83 public static final String XS_TOKEN_NAME = "token"; 84 public static final String XS_LANGUAGE_NAME = "language"; 85 public static final String XS_NMTOKEN_NAME = "NMTOKEN"; 86 public static final String XS_NMTOKENS_NAME = "NMTOKENS"; 87 public static final String XS_NAME_NAME = "Name"; 88 public static final String XS_NCNAME_NAME = "NCName"; 89 public static final String XS_ID_NAME = "ID"; 90 public static final String XS_IDREF_NAME = "IDREF"; 91 public static final String XS_IDREFS_NAME = "IDREFS"; 92 public static final String XS_ENTITY_NAME = "ENTITY"; 93 public static final String XS_ENTITIES_NAME = "ENTITIES"; 94 public static final String XS_INTEGER_NAME = "integer"; 95 public static final String XS_NONPOSITIVEINTEGER_NAME = "nonPositiveInteger"; 96 public static final String XS_NEGATIVEINTEGER_NAME = "negativeInteger"; 97 public static final String XS_LONG_NAME = "long"; 98 public static final String XS_INT_NAME = "int"; 99 public static final String XS_SHORT_NAME = "short"; 100 public static final String XS_BYTE_NAME = "byte"; 101 public static final String XS_NONNEGATIVEINTEGER_NAME = "nonNegativeInteger"; 102 public static final String XS_UNSIGNEDLONG_NAME = "unsignedLong"; 103 public static final String XS_UNSIGNEDINT_NAME = "unsignedInt"; 104 public static final String XS_UNSIGNEDSHORT_NAME = "unsignedShort"; 105 public static final String XS_UNSIGNEDBYTE_NAME = "unsignedByte"; 106 public static final String XS_POSITIVEINTEGER_NAME = "positiveInteger"; 107 108 public static final int XS_INT = XS_INT_NAME.hashCode(); 109 public static final int XS_LONG = XS_LONG_NAME.hashCode(); 110 public static final int XS_SHORT = XS_SHORT_NAME.hashCode(); 111 public static final int XS_FLOAT = XS_FLOAT_NAME.hashCode(); 112 public static final int XS_DOUBLE = XS_DOUBLE_NAME.hashCode(); 113 public static final int XS_BOOLEAN = XS_BOOLEAN_NAME.hashCode(); 114 public static final int XS_BYTE = XS_BYTE_NAME.hashCode(); 115 public static final int XS_STRING = XS_STRING_NAME.hashCode(); 116 public static final int XS_INTEGER = XS_INTEGER_NAME.hashCode(); 117 public static final int XS_DECIMAL = XS_DECIMAL_NAME.hashCode(); 118 public static final int XS_DATETIME = XS_DATETIME_NAME.hashCode(); 119 public static final int XS_QNAME = XS_QNAME_NAME.hashCode(); 120 public static final int XS_ANYURI = XS_ANYURI_NAME.hashCode(); 121 public static final int XS_UNSIGNEDLONG = XS_UNSIGNEDLONG_NAME.hashCode(); 122 public static final int XS_UNSIGNEDINT = XS_UNSIGNEDINT_NAME.hashCode(); 123 public static final int XS_UNSIGNEDSHORT = XS_UNSIGNEDSHORT_NAME.hashCode(); 124 public static final int XS_UNSIGNEDBYTE = XS_UNSIGNEDBYTE_NAME.hashCode(); 125 public static final int XS_DATE = XS_DATE_NAME.hashCode(); 126 public static final int XS_TIME = XS_TIME_NAME.hashCode(); 127 public static final int XS_BASE64BINARY = XS_BASE64BINARY_NAME.hashCode(); 128 public static final int XS_HEXBINARY = XS_HEXBINARY_NAME.hashCode(); 129 public static final int XS_ANYSIMPLETYPE = XS_ANYSIMPLETYPE_NAME.hashCode(); 130 public static final int XS_DURATION = XS_DURATION_NAME.hashCode(); 131 public static final int XS_GYEARMONTH = XS_GYEARMONTH_NAME.hashCode(); 132 public static final int XS_GYEAR = XS_GYEAR_NAME.hashCode(); 133 public static final int XS_GMONTHDAY = XS_GMONTHDAY_NAME.hashCode(); 134 public static final int XS_GMONTH = XS_GMONTH_NAME.hashCode(); 135 public static final int XS_GDAY = XS_GDAY_NAME.hashCode(); 136 public static final int XS_NORMALIZEDSTRING = XS_NORMALIZEDSTRING_NAME.hashCode(); 137 public static final int XS_TOKEN = XS_TOKEN_NAME.hashCode(); 138 public static final int XS_LANGUAGE = XS_LANGUAGE_NAME.hashCode(); 139 public static final int XS_NAME = XS_NAME_NAME.hashCode(); 140 public static final int XS_NCNAME = XS_NCNAME_NAME.hashCode(); 141 public static final int XS_ID = XS_ID_NAME.hashCode(); 142 public static final int XS_NMTOKEN = XS_NMTOKEN_NAME.hashCode(); 143 public static final int XS_NMTOKENS = XS_NMTOKENS_NAME.hashCode(); 144 public static final int XS_NONPOSITIVEINTEGER = XS_NONPOSITIVEINTEGER_NAME.hashCode(); 145 public static final int XS_NEGATIVEINTEGER = XS_NEGATIVEINTEGER_NAME.hashCode(); 146 public static final int XS_NONNEGATIVEINTEGER = XS_NONNEGATIVEINTEGER_NAME.hashCode(); 147 public static final int XS_POSITIVEINTEGER = XS_POSITIVEINTEGER_NAME.hashCode(); 148 public static final int XS_NOTATION = XS_NOTATION_NAME.hashCode(); 149 public static final int XS_IDREF = XS_IDREF_NAME.hashCode(); 150 public static final int XS_IDREFS = XS_IDREFS_NAME.hashCode(); 151 public static final int XS_ENTITY = XS_ENTITY_NAME.hashCode(); 152 public static final int XS_ENTITIES = XS_ENTITIES_NAME.hashCode(); 153 154 public static final TypeBinding STRING = new TypeBinding() 155 { 156 public Object unmarshal(String value) 157 { 158 return value; 159 } 160 161 public String marshal(Object value) 162 { 163 return (String )value; 164 } 165 }; 166 167 public static final TypeBinding INT = new TypeBinding() 168 { 169 public Object unmarshal(String value) 170 { 171 return Integer.valueOf(value); 172 } 173 174 public String marshal(Object value) 175 { 176 return String.valueOf(value); 177 } 178 }; 179 180 public static final TypeBinding LONG = new TypeBinding() 181 { 182 public Object unmarshal(String value) 183 { 184 return Long.valueOf(value); 185 } 186 187 public String marshal(Object value) 188 { 189 return String.valueOf(value); 190 } 191 }; 192 193 public static final TypeBinding DOUBLE = new TypeBinding() 194 { 195 public Object unmarshal(String value) 196 { 197 return Double.valueOf(value); 198 } 199 200 public String marshal(Object value) 201 { 202 return String.valueOf(value); 203 } 204 }; 205 206 public static final TypeBinding FLOAT = new TypeBinding() 207 { 208 public Object unmarshal(String value) 209 { 210 return Float.valueOf(value); 211 } 212 213 public String marshal(Object value) 214 { 215 return String.valueOf(value); 216 } 217 }; 218 219 public static final TypeBinding SHORT = new TypeBinding() 220 { 221 public Object unmarshal(String value) 222 { 223 return Short.valueOf(value); 224 } 225 226 public String marshal(Object value) 227 { 228 return String.valueOf(value); 229 } 230 }; 231 232 public static final TypeBinding BYTE = new TypeBinding() 233 { 234 public Object unmarshal(String value) 235 { 236 return Byte.valueOf(value); 237 } 238 239 public String marshal(Object value) 240 { 241 return String.valueOf(value); 242 } 243 }; 244 245 public static final TypeBinding CHAR = new TypeBinding() 246 { 247 public Object unmarshal(String value) 248 { 249 return value == null ? null : new Character (value.charAt(0)); 250 } 251 252 public String marshal(Object value) 253 { 254 return String.valueOf(value); 255 } 256 }; 257 258 public static final TypeBinding JAVA_UTIL_DATE = new TypeBinding() 259 { 260 public Object unmarshal(String value) 261 { 262 return unmarshalDate(value).getTime(); 263 } 264 265 public String marshal(Object value) 266 { 267 Calendar c = Calendar.getInstance(); 268 c.setTime((java.util.Date )value); 269 return marshalDate(c); 270 } 271 }; 272 273 static 275 { 276 int[] codes = new int[45]; 277 String [] names = new String [codes.length]; 278 int i = 0; 279 280 names[i] = XS_INT_NAME; 281 codes[i++] = XS_INT; 282 283 names[i] = XS_LONG_NAME; 284 codes[i++] = XS_LONG; 285 286 names[i] = XS_SHORT_NAME; 287 codes[i++] = XS_SHORT; 288 289 names[i] = XS_FLOAT_NAME; 290 codes[i++] = XS_FLOAT; 291 292 names[i] = XS_DOUBLE_NAME; 293 codes[i++] = XS_DOUBLE; 294 295 names[i] = XS_BOOLEAN_NAME; 296 codes[i++] = XS_BOOLEAN; 297 298 names[i] = XS_BYTE_NAME; 299 codes[i++] = XS_BYTE; 300 301 names[i] = XS_STRING_NAME; 302 codes[i++] = XS_STRING; 303 304 names[i] = XS_INTEGER_NAME; 305 codes[i++] = XS_INTEGER; 306 307 names[i] = XS_DECIMAL_NAME; 308 codes[i++] = XS_DECIMAL; 309 310 names[i] = XS_DATETIME_NAME; 311 codes[i++] = XS_DATETIME; 312 313 names[i] = XS_QNAME_NAME; 314 codes[i++] = XS_QNAME; 315 316 names[i] = XS_ANYURI_NAME; 317 codes[i++] = XS_ANYURI; 318 319 names[i] = XS_UNSIGNEDINT_NAME; 320 codes[i++] = XS_UNSIGNEDINT; 321 322 names[i] = XS_UNSIGNEDSHORT_NAME; 323 codes[i++] = XS_UNSIGNEDSHORT; 324 325 names[i] = XS_UNSIGNEDBYTE_NAME; 326 codes[i++] = XS_UNSIGNEDBYTE; 327 328 names[i] = XS_DATE_NAME; 329 codes[i++] = XS_DATE; 330 331 names[i] = XS_TIME_NAME; 332 codes[i++] = XS_TIME; 333 334 names[i] = XS_BASE64BINARY_NAME; 335 codes[i++] = XS_BASE64BINARY; 336 337 names[i] = XS_HEXBINARY_NAME; 338 codes[i++] = XS_HEXBINARY; 339 340 names[i] = XS_ANYSIMPLETYPE_NAME; 341 codes[i++] = XS_ANYSIMPLETYPE; 342 343 names[i] = XS_DURATION_NAME; 344 codes[i++] = XS_DURATION; 345 346 names[i] = XS_GYEARMONTH_NAME; 347 codes[i++] = XS_GYEARMONTH; 348 349 names[i] = XS_GYEAR_NAME; 350 codes[i++] = XS_GYEAR; 351 352 names[i] = XS_GMONTHDAY_NAME; 353 codes[i++] = XS_GMONTHDAY; 354 355 names[i] = XS_GMONTH_NAME; 356 codes[i++] = XS_GMONTH; 357 358 names[i] = XS_GDAY_NAME; 359 codes[i++] = XS_GDAY; 360 361 names[i] = XS_NORMALIZEDSTRING_NAME; 362 codes[i++] = XS_NORMALIZEDSTRING; 363 364 names[i] = XS_TOKEN_NAME; 365 codes[i++] = XS_TOKEN; 366 367 names[i] = XS_LANGUAGE_NAME; 368 codes[i++] = XS_LANGUAGE; 369 370 names[i] = XS_NAME_NAME; 371 codes[i++] = XS_NAME; 372 373 names[i] = XS_NCNAME_NAME; 374 codes[i++] = XS_NCNAME; 375 376 names[i] = XS_ID_NAME; 377 codes[i++] = XS_ID; 378 379 names[i] = XS_NMTOKEN_NAME; 380 codes[i++] = XS_NMTOKEN; 381 382 names[i] = XS_NMTOKENS_NAME; 383 codes[i++] = XS_NMTOKENS; 384 385 names[i] = XS_NONPOSITIVEINTEGER_NAME; 386 codes[i++] = XS_NONPOSITIVEINTEGER; 387 388 names[i] = XS_NONNEGATIVEINTEGER_NAME; 389 codes[i++] = XS_NONNEGATIVEINTEGER; 390 391 names[i] = XS_POSITIVEINTEGER_NAME; 392 codes[i++] = XS_POSITIVEINTEGER; 393 394 names[i] = XS_NEGATIVEINTEGER_NAME; 395 codes[i++] = XS_NEGATIVEINTEGER; 396 397 names[i] = XS_UNSIGNEDLONG_NAME; 398 codes[i++] = XS_UNSIGNEDLONG; 399 400 names[i] = XS_NOTATION_NAME; 401 codes[i++] = XS_NOTATION; 402 403 names[i] = XS_IDREF_NAME; 404 codes[i++] = XS_IDREF; 405 406 names[i] = XS_IDREFS_NAME; 407 codes[i++] = XS_IDREFS; 408 409 names[i] = XS_ENTITY_NAME; 410 codes[i++] = XS_ENTITY; 411 412 names[i] = XS_ENTITIES_NAME; 413 codes[i++] = XS_ENTITIES; 414 415 Logger log = Logger.getLogger(SimpleTypeBindings.class); 416 boolean allAreUnique = true; 417 for(int outer = 0; outer < names.length; ++outer) 418 { 419 int outerCode = codes[outer]; 420 String outerName = names[outer]; 421 422 for(int inner = outer + 1; inner < names.length; ++inner) 423 { 424 int innerCode = codes[inner]; 425 String innerName = names[inner]; 426 427 if(outerCode == innerCode) 428 { 429 log.error("Types have the same hash code " + outerCode + ": " + outerName + " and " + innerName); 430 allAreUnique = false; 431 } 432 } 433 } 434 435 if(!allAreUnique) 436 { 437 throw new IllegalStateException ("Not all the schema types have unique hash codes! See log for more details."); 438 } 439 } 440 441 public static Class classForType(String xsdType, boolean nillable) 442 { 443 Class result; 444 int typeCode = xsdType.hashCode(); 445 if(typeCode == XS_INT) 446 { 447 result = nillable ? Integer .class : int.class; 448 } 449 else if(typeCode == XS_LONG) 450 { 451 result = nillable ? Long .class : long.class; 452 } 453 else if(typeCode == XS_SHORT) 454 { 455 result = nillable ? Short .class : short.class; 456 } 457 else if(typeCode == XS_BYTE) 458 { 459 result = nillable ? Byte .class : byte.class; 460 } 461 else if(typeCode == XS_FLOAT) 462 { 463 result = nillable ? Float .class : float.class; 464 } 465 else if(typeCode == XS_DOUBLE) 466 { 467 result = nillable ? Double .class : double.class; 468 } 469 else if(typeCode == XS_BOOLEAN) 470 { 471 result = nillable ? Boolean .class : boolean.class; 472 } 473 else if(typeCode == XS_STRING) 474 { 475 result = String .class; 476 } 477 else if(typeCode == XS_INTEGER) 478 { 479 result = BigInteger .class; 480 } 481 else if(typeCode == XS_DECIMAL) 482 { 483 result = BigDecimal .class; 484 } 485 else if(typeCode == XS_DATETIME) 486 { 487 result = java.util.Calendar .class; 488 } 489 else if(typeCode == XS_QNAME) 490 { 491 result = QName .class; 492 } 493 else if(typeCode == XS_ANYURI) 494 { 495 result = java.net.URI .class; 504 } 505 else if(typeCode == XS_UNSIGNEDLONG) 506 { 507 result = BigInteger .class; 508 } 509 else if(typeCode == XS_UNSIGNEDINT) 510 { 511 result = nillable ? Long .class : long.class; 512 } 513 else if(typeCode == XS_UNSIGNEDSHORT) 514 { 515 result = nillable ? Integer .class : int.class; 516 } 517 else if(typeCode == XS_UNSIGNEDBYTE) 518 { 519 result = nillable ? Short .class : short.class; 520 } 521 else if(typeCode == XS_DATE) 522 { 523 result = Calendar .class; 524 } 525 else if(typeCode == XS_TIME) 526 { 527 result = Calendar .class; 528 } 529 else if(typeCode == XS_BASE64BINARY) 530 { 531 result = byte[].class; 532 } 533 else if(typeCode == XS_HEXBINARY) 534 { 535 result = byte[].class; 536 } 537 else if(typeCode == XS_ANYSIMPLETYPE) 538 { 539 result = String .class; 540 } 541 else if(typeCode == XS_DURATION) 542 { 543 throw new IllegalStateException ("Recognized but not supported xsdType: " + XS_DURATION_NAME); 545 } 546 else if(typeCode == XS_GYEARMONTH) 547 { 548 result = Calendar .class; 549 } 550 else if(typeCode == XS_GYEAR) 551 { 552 result = Calendar .class; 553 } 554 else if(typeCode == XS_GMONTHDAY) 555 { 556 result = Calendar .class; 557 } 558 else if(typeCode == XS_GMONTH) 559 { 560 result = Calendar .class; 561 } 562 else if(typeCode == XS_GDAY) 563 { 564 result = Calendar .class; 565 } 566 else if(typeCode == XS_NORMALIZEDSTRING) 567 { 568 result = String .class; 569 } 570 else if(typeCode == XS_TOKEN) 571 { 572 result = String .class; 573 } 574 else if(typeCode == XS_LANGUAGE) 575 { 576 result = String .class; 577 } 578 else if(typeCode == XS_NAME) 579 { 580 result = String .class; 581 } 582 else if(typeCode == XS_NCNAME) 583 { 584 result = String .class; 585 } 586 else if(typeCode == XS_ID) 587 { 588 result = String .class; 589 } 590 else if(typeCode == XS_NMTOKEN) 591 { 592 result = String .class; 593 } 594 else if(typeCode == XS_NMTOKENS) 595 { 596 result = String [].class; 597 } 598 else if(typeCode == XS_NONPOSITIVEINTEGER) 599 { 600 result = BigInteger .class; 601 } 602 else if(typeCode == XS_NEGATIVEINTEGER) 603 { 604 result = BigInteger .class; 605 } 606 else if(typeCode == XS_NONNEGATIVEINTEGER) 607 { 608 result = BigInteger .class; 609 } 610 else if(typeCode == XS_POSITIVEINTEGER) 611 { 612 result = BigInteger .class; 613 } 614 else if(typeCode == XS_NOTATION) 615 { 616 result = String .class; 617 } 618 else if(typeCode == XS_IDREF) 619 { 620 result = String .class; 621 } 622 else if(typeCode == XS_IDREFS) 623 { 624 result = String [].class; 625 } 626 else if(typeCode == XS_ENTITY) 627 { 628 result = String .class; 629 } 630 else if(typeCode == XS_ENTITIES) 631 { 632 result = String [].class; 633 } 634 else 635 { 636 throw new IllegalStateException ("Not supported xsdType: " + xsdType + ", hashCode=" + xsdType.hashCode()); 637 } 638 return result; 639 } 640 641 public static Object unmarshal(String xsdType, String value, NamespaceContext nsCtx) 642 { 643 if (xsdType == null) 644 throw new IllegalArgumentException ("Schema type cannot be null"); 645 if (value == null) 646 throw new IllegalArgumentException ("Value string cannot be null"); 647 648 int typeCode = xsdType.hashCode(); 649 Object result; 650 if(typeCode == XS_INT) 651 { 652 result = Integer.valueOf(value); 653 } 654 else if(typeCode == XS_LONG) 655 { 656 result = Long.valueOf(value); 657 } 658 else if(typeCode == XS_SHORT) 659 { 660 result = Short.valueOf(value); 661 } 662 else if(typeCode == XS_BYTE) 663 { 664 result = Byte.valueOf(value); 665 } 666 else if(typeCode == XS_FLOAT) 667 { 668 if("INF".equals(value)) 669 { 670 result = new Float (Float.POSITIVE_INFINITY); 671 } 672 else if("-INF".equals(value)) 673 { 674 result = new Float (Float.NEGATIVE_INFINITY); 675 } 676 else 677 { 678 result = Float.valueOf(value); 679 } 680 } 681 else if(typeCode == XS_DOUBLE) 682 { 683 if("INF".equals(value)) 684 { 685 result = new Double (Double.POSITIVE_INFINITY); 686 } 687 else if("-INF".equals(value)) 688 { 689 result = new Double (Double.NEGATIVE_INFINITY); 690 } 691 else 692 { 693 result = Double.valueOf(value); 694 } 695 } 696 else if(typeCode == XS_BOOLEAN) 697 { 698 if(value.length() == 1) 699 { 700 switch(value.charAt(0)) 701 { 702 case '1': 703 result = Boolean.TRUE; 704 break; 705 case '0': 706 result = Boolean.FALSE; 707 break; 708 default: 709 throw new JBossXBValueFormatException("An instance of a datatype that is defined as ?boolean? can have the following legal literals" + 710 " {true, false, 1, 0}. But got: " + value 711 ); 712 } 713 } 714 else 715 { 716 result = Boolean.valueOf(value); 717 } 718 } 719 else if(typeCode == XS_STRING) 720 { 721 result = value; 722 } 723 else if(typeCode == XS_INTEGER) 724 { 725 result = new BigInteger (value); 726 } 727 else if(typeCode == XS_DECIMAL) 728 { 729 result = new BigDecimal (value); 730 } 731 else if(typeCode == XS_DATETIME) 732 { 733 result = unmarshalDateTime(value); 734 } 735 else if(typeCode == XS_QNAME) 736 { 737 result = unmarshalQName(value, nsCtx); 738 } 739 else if(typeCode == XS_ANYURI) 740 { 741 try 750 { 751 result = new java.net.URI (value); 752 } 753 catch(URISyntaxException e) 754 { 755 throw new JBossXBValueFormatException("Failed to unmarshal anyURI value " + value, e); 756 } 757 } 758 else if(typeCode == XS_UNSIGNEDLONG) 759 { 760 BigInteger d = new BigInteger (value); 761 if(d.doubleValue() < 0 || d.doubleValue() > 18446744073709551615D) 762 { 763 throw new JBossXBValueFormatException("Invalid unsignedLong value: " + value); 764 } 765 result = d; 766 } 767 else if(typeCode == XS_UNSIGNEDINT) 768 { 769 long l = Long.parseLong(value); 770 if(l < 0 || l > 4294967295L) 771 { 772 throw new JBossXBValueFormatException("Invalid unsignedInt value: " + value); 773 } 774 result = new Long (l); 775 } 776 else if(typeCode == XS_UNSIGNEDSHORT) 777 { 778 int i = Integer.parseInt(value); 779 if(i < 0 || i > 65535) 780 { 781 throw new JBossXBValueFormatException("Invalid unsignedShort value: " + value); 782 } 783 result = new Integer (i); 784 } 785 else if(typeCode == XS_UNSIGNEDBYTE) 786 { 787 short s = Short.parseShort(value); 788 if(s < 0 || s > 255) 789 { 790 throw new JBossXBValueFormatException("Invalid unsignedByte value: " + value); 791 } 792 result = new Short (s); 793 } 794 else if(typeCode == XS_DATE) 795 { 796 result = unmarshalDate(value); 797 } 798 else if(typeCode == XS_TIME) 799 { 800 result = unmarshalTime(value); 801 } 802 else if(typeCode == XS_BASE64BINARY) 803 { 804 result = unmarshalBase64(value); 805 } 806 else if(typeCode == XS_HEXBINARY) 807 { 808 result = unmarshalHexBinary(value); 809 } 810 else if(typeCode == XS_ANYSIMPLETYPE) 811 { 812 result = value; 813 } 814 else if(typeCode == XS_DURATION) 815 { 816 throw new IllegalStateException ("Recognized but not supported xsdType: " + XS_DURATION_NAME); 818 } 819 else if(typeCode == XS_GYEARMONTH) 820 { 821 result = unmarshalGYearMonth(value); 822 } 823 else if(typeCode == XS_GYEAR) 824 { 825 result = unmarshalGYear(value); 826 } 827 else if(typeCode == XS_GMONTHDAY) 828 { 829 result = unmarshalGMonthDay(value); 830 } 831 else if(typeCode == XS_GMONTH) 832 { 833 return unmarshalGMonth(value); 834 } 835 else if(typeCode == XS_GDAY) 836 { 837 return unmarshalGDay(value); 838 } 839 else if(typeCode == XS_NORMALIZEDSTRING) 840 { 841 if(isNormalizedString(value)) 842 { 843 result = value; 844 } 845 else 846 { 847 throw new JBossXBValueFormatException("Invalid normalizedString value: " + value); 848 } 849 } 850 else if(typeCode == XS_TOKEN) 851 { 852 if(isValidToken(value)) 853 { 854 result = value; 855 } 856 else 857 { 858 throw new JBossXBValueFormatException("Invalid token value: " + value); 859 } 860 } 861 else if(typeCode == XS_LANGUAGE) 862 { 863 result = value; 864 } 865 else if(typeCode == XS_NAME) 866 { 867 result = value; 868 } 869 else if(typeCode == XS_NCNAME) 870 { 871 result = value; 872 } 873 else if(typeCode == XS_ID) 874 { 875 result = value; 876 } 877 else if(typeCode == XS_NMTOKEN) 878 { 879 result = value; 880 } 881 else if(typeCode == XS_NMTOKENS) 882 { 883 result = unmarshalNMTokens(value); 884 } 885 else if(typeCode == XS_NONPOSITIVEINTEGER) 886 { 887 result = new BigInteger (value); 888 if(BigInteger.ZERO.compareTo((BigInteger )result) < 0) 889 { 890 throw new JBossXBValueFormatException("Invalid nonPositiveInteger value: " + value); 891 } 892 } 893 else if(typeCode == XS_NEGATIVEINTEGER) 894 { 895 result = new BigInteger (value); 896 if(BigInteger.ZERO.compareTo((BigInteger )result) <= 0) 897 { 898 throw new JBossXBValueFormatException("Invalid negativeInteger value: " + value); 899 } 900 } 901 else if(typeCode == XS_NONNEGATIVEINTEGER) 902 { 903 result = new BigInteger (value); 904 if(BigInteger.ZERO.compareTo((BigInteger )result) > 0) 905 { 906 throw new JBossXBValueFormatException("Invalid nonNegativeInteger value: " + value); 907 } 908 } 909 else if(typeCode == XS_POSITIVEINTEGER) 910 { 911 result = new BigInteger (value); 912 if(BigInteger.ZERO.compareTo((BigInteger )result) >= 0) 913 { 914 throw new JBossXBValueFormatException("Invalid positiveInteger value: " + value); 915 } 916 } 917 else if(typeCode == XS_NOTATION) 918 { 919 result = value; 921 } 922 else if(typeCode == XS_IDREF) 923 { 924 result = value; 925 } 926 else if(typeCode == XS_IDREFS) 927 { 928 result = unmarshalIdRefs(value); 929 } 930 else if(typeCode == XS_ENTITY) 931 { 932 result = value; 933 } 934 else if(typeCode == XS_ENTITIES) 935 { 936 result = unmarshalIdRefs(value); 937 } 938 else 939 { 940 throw new IllegalStateException ("Not supported xsdType: " + xsdType + ", hashCode=" + xsdType.hashCode()); 941 } 942 return result; 943 } 944 945 public static List unmarshalList(String itemType, String value, NamespaceContext nsCtx) 946 { 947 StringTokenizer tokenizer = new StringTokenizer (value); 948 int total = tokenizer.countTokens(); 949 List list = new ArrayList (total); 950 for(int i = 0; i < total; ++i) 951 { 952 Object o = unmarshal(itemType, tokenizer.nextToken(), nsCtx); 953 list.add(o); 954 } 955 return list; 956 } 957 958 public static String marshalList(String itemType, List value, NamespaceContext nsCtx) 959 { 960 StringBuffer buf = new StringBuffer (); 961 for(int i = 0; i < value.size(); ++i) 962 { 963 String item = marshal(itemType, value.get(i), nsCtx); 964 if(i > 0) 965 { 966 buf.append(' '); 967 } 968 buf.append(item); 969 } 970 return buf.toString(); 971 } 972 973 public static Object unmarshal(String value, Class javaType) 974 { 975 Object result; 976 if(String .class == javaType) 977 { 978 result = value; 979 } 980 else if(int.class == javaType || Integer .class == javaType) 981 { 982 result = Integer.valueOf(value); 983 } 984 else if(long.class == javaType || Long .class == javaType) 985 { 986 result = Long.valueOf(value); 987 } 988 else if(double.class == javaType || Double .class == javaType) 989 { 990 result = Double.valueOf(value); 991 } 992 else if(float.class == javaType || Float .class == javaType) 993 { 994 result = Float.valueOf(value); 995 } 996 else if(short.class == javaType || Short .class == javaType) 997 { 998 result = Short.valueOf(value); 999 } 1000 else if(byte.class == javaType || Byte .class == javaType) 1001 { 1002 result = Byte.valueOf(value); 1003 } 1004 else if(char.class == javaType || Character .class == javaType) 1005 { 1006 result = new Character (value.charAt(0)); 1007 } 1008 else if(java.util.Date .class == javaType) 1009 { 1010 final String FORMAT = "yyyy-MM-dd"; 1011 try 1012 { 1013 result = new java.text.SimpleDateFormat (FORMAT).parse(value); 1014 } 1015 catch(ParseException e) 1016 { 1017 throw new JBossXBRuntimeException( 1018 "Failed to parse date accroding to " + FORMAT + " format: " + value + ": " + e.getMessage() 1019 ); 1020 } 1021 } 1022 else if(Object .class == javaType) 1023 { 1024 result = value; 1025 } 1026 else 1027 { 1028 throw new JBossXBRuntimeException("Unexpected field type " + javaType); 1029 } 1030 1031 return result; 1032 } 1033 1034 public static String marshal(String xsdType, Object value, NamespaceContext nsCtx) 1035 { 1036 if(value == null) 1037 { 1038 throw new IllegalArgumentException ("Can't marshal null value!"); 1039 } 1040 1041 int typeCode = xsdType.hashCode(); 1042 String result; 1043 if(typeCode == XS_INT) 1044 { 1045 Integer i = (Integer )value; 1046 result = i.toString(); 1047 } 1048 else if(typeCode == XS_LONG) 1049 { 1050 Long l = (Long )value; 1051 result = l.toString(); 1052 } 1053 else if(typeCode == XS_SHORT) 1054 { 1055 Short s = (Short )value; 1056 result = s.toString(); 1057 } 1058 else if(typeCode == XS_BYTE) 1059 { 1060 Byte b = (Byte )value; 1061 result = b.toString(); 1062 } 1063 else if(typeCode == XS_FLOAT) 1064 { 1065 Float f = (Float )value; 1066 if(f.floatValue() == Float.POSITIVE_INFINITY) 1067 { 1068 result = "INF"; 1069 } 1070 else if(f.floatValue() == Float.NEGATIVE_INFINITY) 1071 { 1072 result = "-INF"; 1073 } 1074 else 1075 { 1076 result = f.toString(); 1077 } 1078 } 1079 else if(typeCode == XS_DOUBLE) 1080 { 1081 Double d = (Double )value; 1082 if(d.doubleValue() == Double.POSITIVE_INFINITY) 1083 { 1084 result = "INF"; 1085 } 1086 else if(d.doubleValue() == Double.NEGATIVE_INFINITY) 1087 { 1088 result = "-INF"; 1089 } 1090 else 1091 { 1092 result = d.toString(); 1093 } 1094 } 1095 else if(typeCode == XS_BOOLEAN) 1096 { 1097 if(value instanceof Boolean ) 1098 { 1099 result = ((Boolean )value).booleanValue() ? "true" : "false"; 1100 } 1101 else if(value instanceof Number ) 1102 { 1103 Number n = (Number )value; 1104 switch(n.byteValue()) 1105 { 1106 case 1: 1107 result = "1"; 1108 break; 1109 case 0: 1110 result = "0"; 1111 break; 1112 default: 1113 throw new JBossXBValueFormatException("An instance of a datatype that is defined as ?boolean? can have the following legal literals" + 1114 " {true, false, 1, 0}. But got: " + value 1115 ); 1116 } 1117 } 1118 else 1119 { 1120 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 " + 1121 value.getClass().getName() 1122 ); 1123 } 1124 } 1125 else if(typeCode == XS_STRING) 1126 { 1127 result = (String )value; 1128 } 1129 else if(typeCode == XS_INTEGER) 1130 { 1131 BigInteger bi = (BigInteger )value; 1132 result = bi.toString(); 1133 } 1134 else if(typeCode == XS_DECIMAL) 1135 { 1136 BigDecimal bd = (BigDecimal )value; 1137 result = bd.toString(); 1138 } 1139 else if(typeCode == XS_DATETIME) 1140 { 1141 Calendar c; 1142 if(value.getClass() == java.util.Date .class) 1143 { 1144 c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 1145 c.clear(); 1146 c.setTime((java.util.Date )value); 1147 } 1148 else 1149 { 1150 c = (Calendar )value; 1151 } 1152 result = marshalDateTime(c); 1153 } 1154 else if(typeCode == XS_QNAME) 1155 { 1156 QName qName = (QName )value; 1157 result = marshalQName(qName, nsCtx); 1158 } 1159 else if(typeCode == XS_ANYURI) 1160 { 1161 java.net.URI u = (java.net.URI )value; 1162 result = u.toString(); 1163 } 1164 else if(typeCode == XS_UNSIGNEDLONG) 1165 { 1166 BigInteger d = (BigInteger )value; 1167 if (d.doubleValue() < 0 || d.doubleValue() > 18446744073709551615D) 1168 { 1169 throw new JBossXBValueFormatException("Invalid unsignedLong value: " + value); 1170 } 1171 result = d.toString(); 1172 } 1173 else if(typeCode == XS_UNSIGNEDINT) 1174 { 1175 Long l = (Long )value; 1176 if(l.longValue() < 0 || l.longValue() > 4294967295L) 1177 { 1178 throw new JBossXBValueFormatException("Invalid unsignedInt value: " + value); 1179 } 1180 result = l.toString(); 1181 } 1182 else if(typeCode == XS_UNSIGNEDSHORT) 1183 { 1184 Integer i = (Integer )value; 1185 if(i.intValue() < 0 || i.intValue() > 65535) 1186 { 1187 throw new JBossXBValueFormatException("Invalid unsignedShort value: " + value); 1188 } 1189 result = i.toString(); 1190 } 1191 else if(typeCode == XS_UNSIGNEDBYTE) 1192 { 1193 Short s = (Short )value; 1194 if(s.shortValue() < 0 || s.shortValue() > 255) 1195 { 1196 throw new JBossXBValueFormatException("Invalid unsignedByte value: " + value); 1197 } 1198 result = s.toString(); 1199 } 1200 else if(typeCode == XS_DATE) 1201 { 1202 Calendar c = (Calendar )value; 1203 result = marshalDate(c); 1204 } 1205 else if(typeCode == XS_TIME) 1206 { 1207 Calendar c = (Calendar )value; 1208 result = marshalTime(c); 1209 } 1210 else if(typeCode == XS_BASE64BINARY) 1211 { 1212 byte[] b = (byte[])value; 1213 result = marshalBase64(b); 1214 } 1215 else if(typeCode == XS_HEXBINARY) 1216 { 1217 byte[] b = (byte[])value; 1218 result = marshalHexBinary(b); 1219 } 1220 else if(typeCode == XS_ANYSIMPLETYPE) 1221 { 1222 return (String )value; 1223 } 1224 else if(typeCode == XS_DURATION) 1225 { 1226 throw new IllegalStateException ("Recognized but not supported xsdType: " + xsdType); 1228 } 1229 else if(typeCode == XS_GYEARMONTH) 1230 { 1231 Calendar c = (Calendar )value; 1232 result = marshalGYearMonth(c); 1233 } 1234 else if(typeCode == XS_GYEAR) 1235 { 1236 Calendar c = (Calendar )value; 1237 result = marshalGYear(c); 1238 } 1239 else if(typeCode == XS_GMONTHDAY) 1240 { 1241 Calendar c = (Calendar )value; 1242 result = marshalGMonthDay(c); 1243 } 1244 else if(typeCode == XS_GMONTH) 1245 { 1246 Calendar c = (Calendar )value; 1247 result = marshalGMonth(c); 1248 } 1249 else if(typeCode == XS_GDAY) 1250 { 1251 Calendar c = (Calendar )value; 1252 result = marshalGDay(c); 1253 } 1254 else if(typeCode == XS_NORMALIZEDSTRING) 1255 { 1256 String s = (String )value; 1257 if(isNormalizedString(s)) 1258 { 1259 result = s; 1260 } 1261 else 1262 { 1263 throw new JBossXBValueFormatException("Invalid normalizedString value: " + value); 1264 } 1265 } 1266 else if(typeCode == XS_TOKEN) 1267 { 1268 String s = (String )value; 1269 if(isValidToken(s)) 1270 { 1271 result = s; 1272 } 1273 else 1274 { 1275 throw new JBossXBValueFormatException("Invalid token value: " + value); 1276 } 1277 } 1278 else if(typeCode == XS_LANGUAGE) 1279 { 1280 result = (String )value; 1281 } 1282 else if(typeCode == XS_NAME) 1283 { 1284 result = (String )value; 1285 } 1286 else if(typeCode == XS_NCNAME) 1287 { 1288 result = (String )value; 1289 } 1290 else if(typeCode == XS_ID) 1291 { 1292 result = (String )value; 1293 } 1294 else if(typeCode == XS_NMTOKEN) 1295 { 1296 result = (String )value; 1297 } 1298 else if(typeCode == XS_NMTOKENS) 1299 { 1300 String [] tokens = (String [])value; 1301 if(tokens.length > 0) 1302 { 1303 result = tokens[0]; 1304 for(int i = 1; i < tokens.length; ++i) 1305 { 1306 result += ' ' + tokens[i]; 1307 } 1308 } 1309 else 1310 { 1311 result = ""; 1312 } 1313 } 1314 else if(typeCode == XS_NONPOSITIVEINTEGER) 1315 { 1316 BigInteger bi = (BigInteger )value; 1317 if(BigInteger.ZERO.compareTo(bi) < 0) 1318 { 1319 throw new JBossXBValueFormatException("Invalid nonPositiveInteger value: " + value); 1320 } 1321 result = bi.toString(); 1322 } 1323 else if(typeCode == XS_NEGATIVEINTEGER) 1324 { 1325 BigInteger bi = (BigInteger )value; 1326 if(BigInteger.ZERO.compareTo(bi) <= 0) 1327 { 1328 throw new JBossXBValueFormatException("Invalid negativeInteger value: " + value); 1329 } 1330 result = bi.toString(); 1331 } 1332 else if(typeCode == XS_NONNEGATIVEINTEGER) 1333 { 1334 BigInteger bi = (BigInteger )value; 1335 if(BigInteger.ZERO.compareTo(bi) > 0) 1336 { 1337 throw new JBossXBValueFormatException("Invalid nonNegativeInteger value: " + value); 1338 } 1339 result = bi.toString(); 1340 } 1341 else if(typeCode == XS_POSITIVEINTEGER) 1342 { 1343 BigInteger bi = (BigInteger )value; 1344 if(BigInteger.ZERO.compareTo(bi) >= 0) 1345 { 1346 throw new JBossXBValueFormatException("Invalid positiveInteger value: " + value); 1347 } 1348 result = bi.toString(); 1349 } 1350 else if(typeCode == XS_NOTATION) 1351 { 1352 result = (String )value; 1354 } 1355 else if(typeCode == XS_IDREF) 1356 { 1357 result = (String )value; 1358 } 1359 else if(typeCode == XS_IDREFS) 1360 { 1361 String [] refs = (String [])value; 1362 if(refs.length > 0) 1363 { 1364 result = refs[0]; 1365 for(int i = 1; i < refs.length; ++i) 1366 { 1367 result += ' ' + refs[i]; 1368 } 1369 } 1370 else 1371 { 1372 result = ""; 1373 } 1374 } 1375 else if(typeCode == XS_ENTITY) 1376 { 1377 result = (String )value; 1378 } 1379 else if(typeCode == XS_ENTITIES) 1380 { 1381 String [] refs = (String [])value; 1382 if(refs.length > 0) 1383 { 1384 result = refs[0]; 1385 for(int i = 1; i < refs.length; ++i) 1386 { 1387 result += ' ' + refs[i]; 1388 } 1389 } 1390 else 1391 { 1392 result = ""; 1393 } 1394 } 1395 else 1396 { 1397 throw new IllegalStateException ("Not supported xsdType: " + xsdType + ", hashCode=" + xsdType.hashCode()); 1398 } 1399 return result; 1400 } 1401 1402 public static QName typeQName(Class cls) 1403 { 1404 if(cls == null) 1405 { 1406 throw new IllegalArgumentException ("The argument must not be null."); 1407 } 1408 1409 QName result = null; 1410 if(Integer .class == cls) 1411 { 1412 result = Constants.QNAME_INT; 1413 } 1414 else if(cls == Long .class) 1415 { 1416 result = Constants.QNAME_LONG; 1417 } 1418 else if(cls == Short .class) 1419 { 1420 result = Constants.QNAME_SHORT; 1421 } 1422 else if(cls == Byte .class) 1423 { 1424 result = Constants.QNAME_BYTE; 1425 } 1426 else if(cls == Float .class) 1427 { 1428 result = Constants.QNAME_FLOAT; 1429 } 1430 else if(cls == Double .class) 1431 { 1432 result = Constants.QNAME_DOUBLE; 1433 } 1434 else if(cls == Boolean .class) 1435 { 1436 result = Constants.QNAME_BOOLEAN; 1437 } 1438 else if(cls == String .class) 1439 { 1440 result = Constants.QNAME_STRING; 1441 } 1442 else if(cls == BigInteger .class) 1443 { 1444 result = Constants.QNAME_INTEGER; 1445 } 1446 else if(cls == BigDecimal .class) 1447 { 1448 result = Constants.QNAME_DECIMAL; 1449 } 1450 else if(cls == java.util.Date .class || java.util.Calendar .class.isAssignableFrom(cls)) 1451 { 1452 result = Constants.QNAME_DATETIME; 1453 } 1454 else if(cls == QName .class) 1455 { 1456 result = Constants.QNAME_QNAME; 1457 } 1458 else if(cls == java.net.URI .class) 1459 { 1460 result = Constants.QNAME_ANYURI; 1461 } 1462 else if(cls == byte[].class) 1463 { 1464 result = Constants.QNAME_BASE64BINARY; 1465 } 1466 return result; 1467 } 1468 1469 public static String [] unmarshalNMTokens(String value) 1470 { 1471 StringTokenizer tokenizer = new StringTokenizer (value); 1472 String [] tokens = new String [tokenizer.countTokens()]; 1473 for(int i = 0; i < tokens.length; ++i) 1474 { 1475 tokens[i] = tokenizer.nextToken(); 1476 } 1477 return tokens; 1478 } 1479 1480 public static String [] unmarshalIdRefs(String value) 1481 { 1482 StringTokenizer tokenizer = new StringTokenizer (value); 1483 String [] tokens = new String [tokenizer.countTokens()]; 1484 for(int i = 0; i < tokens.length; ++i) 1485 { 1486 tokens[i] = tokenizer.nextToken(); 1487 } 1488 return tokens; 1489 } 1490 1491 1497 public static Calendar unmarshalGMonthDay(String value) 1498 { 1499 if(value.length() < 6 || 1500 value.charAt(0) != '-' || 1501 value.charAt(1) != '-' || 1502 value.charAt(4) != '-') 1503 { 1504 throw new JBossXBValueFormatException( 1505 "gMonthDay value does not follow the format '--MM-DD[timezone]: " + value 1506 ); 1507 } 1508 1509 Calendar cal = Calendar.getInstance(); 1510 cal.clear(); 1511 cal.set(Calendar.MONTH, Integer.parseInt(value.substring(2, 4)) - 1); 1512 cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(value.substring(5, 7))); 1513 if(value.length() > 7) 1514 { 1515 cal.setTimeZone(parseTimeZone(value, 7)); 1516 } 1517 return cal; 1518 } 1519 1520 1526 public static String marshalGMonthDay(Calendar value) 1527 { 1528 String result = "--"; 1529 result += marshalInt(value.get(Calendar.MONTH) + 1, 2); 1530 result += '-'; 1531 result += marshalInt(value.get(Calendar.DAY_OF_MONTH), 2); 1532 result += marshalTimeZone(value); 1533 return result; 1534 } 1535 1536 1542 public static Calendar unmarshalGMonth(String value) 1543 { 1544 if(value.length() < 4 || value.charAt(0) != '-' || value.charAt(1) != '-') 1545 { 1546 throw new JBossXBValueFormatException("gMonth value does not follow the format '--MM': " + value); 1547 } 1548 1549 Calendar cal = Calendar.getInstance(); 1550 cal.clear(); 1551 1552 cal.set(Calendar.MONTH, Integer.parseInt(value.substring(2, 4)) - 1); 1553 if(value.length() > 4) 1554 { 1555 cal.setTimeZone(parseTimeZone(value, 4)); 1556 } 1557 return cal; 1558 } 1559 1560 1566 public static String marshalGMonth(Calendar value) 1567 { 1568 String result = "--"; 1569 result += marshalInt(value.get(Calendar.MONTH) + 1, 2); 1570 result += marshalTimeZone(value); 1571 return result; 1572 } 1573 1574 public static Calendar unmarshalGYear(String value) 1575 { 1576 Calendar cal = Calendar.getInstance(); 1577 cal.clear(); 1578 int timeZone = parseGYear(value, 0, cal); 1579 if(value.length() > timeZone) 1580 { 1581 TimeZone tz = parseTimeZone(value, timeZone); 1582 cal.setTimeZone(tz); 1583 } 1584 return cal; 1585 } 1586 1587 public static String marshalGYear(Calendar value) 1588 { 1589 String result = String.valueOf(value.get(Calendar.YEAR)); 1590 result += marshalTimeZone(value); 1591 return result; 1592 } 1593 1594 1600 public static Calendar unmarshalGYearMonth(String value) 1601 { 1602 Calendar cal = Calendar.getInstance(); 1603 cal.clear(); 1604 1605 int month = parseGYear(value, 0, cal); 1606 if(value.charAt(month) != '-') 1607 { 1608 throw new JBossXBValueFormatException( 1609 "gYearMonth value does not follow the format '[-]CCYY-MM[timezone]': " + value 1610 ); 1611 } 1612 1613 cal.set(Calendar.MONTH, Integer.parseInt(value.substring(month + 1, month + 3)) - 1); 1614 1615 if(value.length() > month + 3) 1616 { 1617 TimeZone tz = parseTimeZone(value, month + 3); 1618 cal.setTimeZone(tz); 1619 } 1620 1621 return cal; 1622 } 1623 1624 1630 public static String marshalGYearMonth(Calendar value) 1631 { 1632 String result = String.valueOf(value.get(Calendar.YEAR)); 1633 result += '-'; 1634 result += marshalInt(value.get(Calendar.MONTH) + 1, 2); 1635 result += marshalTimeZone(value); 1636 return result; 1637 } 1638 1639 1645 public static Calendar unmarshalGDay(String value) 1646 { 1647 if(value.length() < 5 || value.charAt(0) != '-' || value.charAt(1) != '-' || value.charAt(2) != '-') 1648 { 1649 throw new NumberFormatException ("gDay value does not follow the format (---DD[timezonePart]): " + value); 1650 } 1651 1652 int day = Integer.parseInt(value.substring(3, 5)); 1654 if(day < 1 || day > 31) 1655 { 1656 throw new NumberFormatException ("gDay value is not in the interval [1..31]: " + day); 1657 } 1658 1659 TimeZone tz = parseTimeZone(value, 5); 1661 1662 Calendar cal = Calendar.getInstance(); 1663 cal.clear(); 1664 if(tz != null) 1665 { 1666 cal.setTimeZone(tz); 1667 } 1668 cal.set(Calendar.DAY_OF_MONTH, day); 1669 1670 return cal; 1671 } 1672 1673 1679 public static String marshalGDay(Calendar value) 1680 { 1681 String result = "---"; 1682 result += marshalInt(value.get(Calendar.DAY_OF_MONTH), 2); 1683 result += marshalTimeZone(value); 1684 return result; 1685 } 1686 1687 1695 public static Calendar unmarshalDate(String value) 1696 { 1697 Calendar cal = Calendar.getInstance(); 1698 cal.clear(); 1699 1700 int ind = parseDate(value, 0, cal); 1701 1702 TimeZone tz = null; 1703 if(ind < value.length()) 1704 { 1705 tz = parseTimeZone(value, ind); 1706 } 1707 1708 if(tz != null) 1709 { 1710 cal.setTimeZone(tz); 1711 } 1712 1713 return cal; 1714 } 1715 1716 1722 public static String marshalDate(Calendar value) 1723 { 1724 String result = String.valueOf(value.get(Calendar.YEAR)); 1725 result += '-'; 1726 result += marshalInt(value.get(Calendar.MONTH) + 1, 2); 1727 result += '-'; 1728 result += marshalInt(value.get(Calendar.DAY_OF_MONTH), 2); 1729 result += marshalTimeZone(value); 1730 return result; 1731 } 1732 1733 1739 public static Calendar unmarshalTime(String value) 1740 { 1741 Calendar cal = Calendar.getInstance(); 1742 cal.clear(); 1743 1744 int tzLoc = parseTime(value, 0, cal); 1745 1746 TimeZone tz = null; 1747 if(value.length() > tzLoc) 1748 { 1749 tz = parseTimeZone(value, tzLoc); 1750 } 1751 1752 if(tz != null) 1753 { 1754 cal.setTimeZone(tz); 1755 } 1756 return cal; 1757 } 1758 1759 1765 public static String marshalTime(Calendar value) 1766 { 1767 String result = marshalInt(value.get(Calendar.HOUR_OF_DAY), 2); 1768 result += ':'; 1769 result += marshalInt(value.get(Calendar.MINUTE), 2); 1770 result += ':'; 1771 result += marshalInt(value.get(Calendar.SECOND), 2); 1772 result += '.'; 1773 1774 int millis = value.get(Calendar.MILLISECOND); 1775 if(millis > 99) 1776 { 1777 result += String.valueOf(millis); 1778 } 1779 else if(millis > 9) 1780 { 1781 result += "0" + String.valueOf(millis); 1782 } 1783 else 1784 { 1785 result += "00" + String.valueOf(millis); 1786 } 1787 1788 result += marshalTimeZone(value); 1789 return result; 1790 } 1791 1792 1798 public static Calendar unmarshalDateTime(String value) 1799 { 1800 Calendar cal = Calendar.getInstance(); 1801 cal.clear(); 1802 1803 int timeInd = parseDate(value, 0, cal); 1804 if(value.charAt(timeInd) != 'T') 1805 { 1806 throw new JBossXBValueFormatException("DateTime value does not follow the format '[-]yyyy-mm-ddThh:mm:ss[.s+][timezone]': expected 'T' but got " + 1807 value.charAt(timeInd) 1808 ); 1809 } 1810 1811 int tzStart = parseTime(value, timeInd + 1, cal); 1812 1813 TimeZone tz = null; 1814 if(value.length() > tzStart) 1815 { 1816 tz = parseTimeZone(value, tzStart); 1817 } 1818 1819 if(tz != null) 1820 { 1821 cal.setTimeZone(tz); 1822 } 1823 1824 return cal; 1825 } 1826 1827 1833 public static String marshalDateTime(Calendar value) 1834 { 1835 String result = marshalInt(value.get(Calendar.YEAR), 4); 1836 result += '-'; 1837 result += marshalInt(value.get(Calendar.MONTH) + 1, 2); 1838 result += '-'; 1839 result += marshalInt(value.get(Calendar.DAY_OF_MONTH), 2); 1840 result += 'T'; 1841 result += marshalInt(value.get(Calendar.HOUR_OF_DAY), 2); 1842 result += ':'; 1843 result += marshalInt(value.get(Calendar.MINUTE), 2); 1844 result += ':'; 1845 result += marshalInt(value.get(Calendar.SECOND), 2); 1846 result += '.'; 1847 1848 int millis = value.get(Calendar.MILLISECOND); 1849 if(millis > 99) 1850 { 1851 result += String.valueOf(millis); 1852 } 1853 else if(millis > 9) 1854 { 1855 result += "0" + String.valueOf(millis); 1856 } 1857 else 1858 { 1859 result += "00" + String.valueOf(millis); 1860 } 1861 1862 result += marshalTimeZone(value); 1863 return result; 1864 } 1865 1866 1872 public static byte[] unmarshalHexBinary(String value) 1873 { 1874 if(value.length() % 2 != 0) 1875 { 1876 throw new IllegalArgumentException ("hexBinary value must have even length."); 1877 } 1878 1879 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 1880 for(int i = 0; i < value.length(); i += 2) 1881 { 1882 char c1 = value.charAt(i); 1883 char c2 = value.charAt(i + 1); 1884 byte b = 0; 1885 if((c1 >= '0') && (c1 <= '9')) 1886 { 1887 b += ((c1 - '0') * 16); 1888 } 1889 else if((c1 >= 'a') && (c1 <= 'f')) 1890 { 1891 b += ((c1 - 'a' + 10) * 16); 1892 } 1893 else if((c1 >= 'A') && (c1 <= 'F')) 1894 { 1895 b += ((c1 - 'A' + 10) * 16); 1896 } 1897 else 1898 { 1899 throw new IllegalArgumentException ("hexBinary value contains illegal character: " + value); 1900 } 1901 1902 if((c2 >= '0') && (c2 <= '9')) 1903 { 1904 b += (c2 - '0'); 1905 } 1906 else if((c2 >= 'a') && (c2 <= 'f')) 1907 { 1908 b += (c2 - 'a' + 10); 1909 } 1910 else if((c2 >= 'A') && (c2 <= 'F')) 1911 { 1912 b += (c2 - 'A' + 10); 1913 } 1914 else 1915 { 1916 throw new IllegalArgumentException ("hexBinary value contains illegal character: " + value); 1917 } 1918 baos.write(b); 1919 } 1920 return (baos.toByteArray()); 1921 } 1922 1923 1927 public static String marshalHexBinary(byte[] value) 1928 { 1929 StringBuffer result = new StringBuffer (2 * value.length); 1930 for(int i = 0; i < value.length; ++i) 1931 { 1932 result.append(convertDigit((value[i] >> 4))); 1933 result.append(convertDigit((value[i] & 0x0f))); 1934 } 1935 return result.toString(); 1936 } 1937 1938 public static boolean isNormalizedString(String value) 1939 { 1940 for(int i = 0; i < value.length(); ++i) 1941 { 1942 char c = value.charAt(i); 1943 if(c == 0x09 || c == 0x0A || c == 0x0D) 1944 { 1945 return false; 1946 } 1947 } 1948 return true; 1949 } 1950 1951 1954 public static byte[] unmarshalBase64(String value) 1955 { 1956 return Base64.decode(value); 1957 } 1958 1959 1962 public static String marshalBase64(byte[] value) 1963 { 1964 return Base64.encodeBytes(value); 1965 } 1966 1967 1971 public static QName unmarshalQName(String value, NamespaceContext nsRegistry) 1972 { 1973 int colonIndex = value.lastIndexOf(":"); 1974 if(colonIndex > 0) 1975 { 1976 String prefix = value.substring(0, colonIndex); 1977 String nsURI = nsRegistry.getNamespaceURI(prefix); 1978 if(nsURI == null) 1979 { 1980 throw new IllegalStateException ("No namespace URI registered for prefix: " + prefix); 1981 } 1982 1983 String localPart = value.substring(colonIndex + 1); 1984 return new QName (nsURI, localPart, prefix); 1985 } 1986 else 1987 { 1988 return new QName (value); 1989 } 1990 } 1991 1992 1996 public static String marshalQName(QName value, NamespaceContext nsRegistry) 1997 { 1998 String nsURI = value.getNamespaceURI(); 1999 if(nsURI.length() > 0) 2000 { 2001 String prefix; 2002 if(nsRegistry != null) 2003 { 2004 prefix = nsRegistry.getPrefix(nsURI); 2005 if(prefix == null) 2006 { 2007 throw new IllegalStateException ("Namespace URI not registered: " + nsURI); 2008 } 2009 } 2010 else 2011 { 2012 prefix = value.getPrefix(); 2014 } 2015 return prefix.length() > 0 ? prefix + ":" + value.getLocalPart() : value.getLocalPart(); 2016 } 2017 else 2018 { 2019 return value.getLocalPart(); 2020 } 2021 } 2022 2023 public static boolean isValidToken(String value) 2024 { 2025 if(value != null && value.length() > 0) 2026 { 2027 if(value.charAt(0) == 0x20 || value.charAt(value.length() - 1) == 0x20) 2028 { 2029 return false; 2030 } 2031 2032 for(int i = 0; i < value.length(); ++i) 2033 { 2034 char c = value.charAt(i); 2035 if(c == 0x09 || c == 0x0A || c == 0x0D) 2036 { 2037 return false; 2038 } 2039 else if(c == 0x20) 2040 { 2041 if(i + 1 < value.length() && value.charAt(i + 1) == 0x20) 2042 { 2043 return false; 2044 } 2045 } 2046 } 2047 } 2048 2049 return true; 2050 } 2051 2052 private static int parseGYear(String value, int start, Calendar cal) 2053 { 2054 int negative = (value.charAt(start) == '-' ? 1 : 0); 2055 cal.set(Calendar.YEAR, Integer.parseInt(value.substring(start, start + 4 + negative))); 2056 return start + 4 + negative; 2057 } 2058 2059 private static int parseDate(String value, int start, Calendar cal) 2060 { 2061 if(value.charAt(start) == '-') 2062 { 2063 ++start; 2064 } 2065 2066 if(!Character.isDigit(value.charAt(start))) 2067 { 2068 throw new JBossXBValueFormatException( 2069 "Date value does not follow the format '-'? yyyy '-' mm '-' dd: " + value 2070 ); 2071 } 2072 2073 int nextToken = value.indexOf('-', start); 2074 if(nextToken == -1 || nextToken - start < 4) 2075 { 2076 throw new JBossXBValueFormatException( 2077 "Date value does not follow the format '-'? yyyy '-' mm '-' dd: " + value 2078 ); 2079 } 2080 2081 int year = Integer.parseInt(value.substring(start, nextToken)); 2082 2083 start = nextToken + 1; 2084 nextToken = value.indexOf('-', start); 2085 if(nextToken == -1 || nextToken - start < 2) 2086 { 2087 throw new JBossXBValueFormatException( 2088 "Date value does not follow the format '-'? yyyy '-' mm '-' dd: " + value 2089 ); 2090 } 2091 2092 int month = Integer.parseInt(value.substring(start, nextToken)); 2093 2094 start = nextToken + 1; 2095 nextToken += 3; 2096 int day = Integer.parseInt(value.substring(start, nextToken)); 2097 2098 cal.set(Calendar.YEAR, year); 2099 cal.set(Calendar.MONTH, month - 1); 2100 cal.set(Calendar.DAY_OF_MONTH, day); 2101 2102 return nextToken; 2103 } 2104 2105 2112 private static int parseTime(String value, int start, Calendar cal) 2113 { 2114 if(value.charAt(start + 2) != ':' || value.charAt(start + 5) != ':') 2115 { 2116 throw new JBossXBValueFormatException("Time value does not follow the format 'hh:mm:ss.[s+]': " + value); 2117 } 2118 2119 int hh = Integer.parseInt(value.substring(start, start + 2)); 2120 int mm = Integer.parseInt(value.substring(start + 3, start + 5)); 2121 int ss = Integer.parseInt(value.substring(start + 6, start + 8)); 2122 2123 int millis = 0; 2124 2125 int x = start + 8; 2126 2127 if(value.length() > x && value.charAt(x) == '.') 2128 { 2129 int mul = 100; 2130 for(x += 1; x < value.length(); x++) 2131 { 2132 char c = value.charAt(x); 2133 2134 if(Character.isDigit(c)) 2135 { 2136 if(mul != 0) 2137 { 2138 millis += Character.digit(c, 10) * mul; 2139 mul = (mul == 1) ? 0 : mul / 10; 2140 } 2141 } 2142 else 2143 { 2144 break; 2145 } 2146 } 2147 } 2148 2149 cal.set(Calendar.HOUR_OF_DAY, hh); 2150 cal.set(Calendar.MINUTE, mm); 2151 cal.set(Calendar.SECOND, ss); 2152 cal.set(Calendar.MILLISECOND, millis); 2153 2154 return x; 2155 } 2156 2157 2163 private static TimeZone parseTimeZone(String value, int start) 2164 { 2165 TimeZone tz; 2166 if(value.charAt(start) == '+' || (value.charAt(start) == '-')) 2167 { 2168 if(value.length() - start == 6 && 2169 Character.isDigit(value.charAt(start + 1)) && 2170 Character.isDigit(value.charAt(start + 2)) && 2171 value.charAt(start + 3) == ':' && 2172 Character.isDigit(value.charAt(start + 4)) && 2173 Character.isDigit(value.charAt(start + 5))) 2174 { 2175 tz = TimeZone.getTimeZone("GMT" + value.substring(start)); 2176 } 2177 else 2178 { 2179 throw new NumberFormatException ( 2180 "Timezone value does not follow the format ([+/-]HH:MM): " + value.substring(start) 2181 ); 2182 } 2183 } 2184 else if(value.charAt(start) == 'Z') 2185 { 2186 tz = TimeZone.getTimeZone("GMT"); 2187 } 2188 else 2189 { 2190 throw new NumberFormatException ( 2191 "Timezone value does not follow the format ([+/-]HH:MM): " + value.substring(start) 2192 ); 2193 } 2194 return tz; 2195 } 2196 2197 2203 private static String marshalTimeZone(Calendar value) 2204 { 2205 int offset = value.get(Calendar.ZONE_OFFSET) + value.get(Calendar.DST_OFFSET); 2206 if(offset == 0) 2207 { 2208 return "Z"; 2209 } 2210 2211 DecimalFormat hourFormat = new DecimalFormat ("'+'00;-00"); 2212 DecimalFormat minuteFormat = new DecimalFormat ("00"); 2213 2214 int minutes = offset / (1000 * 60); 2215 int hours = minutes / 60; 2216 2217 minutes -= (hours * 60); 2218 2219 return hourFormat.format(hours) + ":" + minuteFormat.format(minutes); 2220 } 2221 2222 private static String marshalInt(int value, int length) 2223 { 2224 String result = String.valueOf(value); 2225 if(result.length() < length) 2226 { 2227 while(result.length() < length) 2228 { 2229 result = '0' + result; 2230 } 2231 } 2232 else if(result.length() > length) 2233 { 2234 throw new JBossXBValueFormatException( 2235 "Can't marshal int value " + value + " to a string with length of " + length 2236 ); 2237 } 2238 return result; 2239 } 2240 2241 private static char convertDigit(int value) 2242 { 2243 value &= 0x0f; 2244 if(value >= 10) 2245 { 2246 return ((char)(value - 10 + 'a')); 2247 } 2248 else 2249 { 2250 return ((char)(value + '0')); 2251 } 2252 } 2253} 2254 | Popular Tags |