1 16 package org.apache.commons.beanutils; 17 18 import java.util.List ; 19 import java.util.ArrayList ; 20 import java.util.Map ; 21 import java.util.HashMap ; 22 import java.util.Date ; 23 import java.lang.reflect.Array ; 24 import java.math.BigDecimal ; 25 import java.math.BigInteger ; 26 import java.io.Serializable ; 27 import org.apache.commons.logging.Log; 28 import org.apache.commons.logging.LogFactory; 29 30 109 public class LazyDynaBean implements DynaBean, Serializable { 110 111 112 115 private static Log logger = LogFactory.getLog(LazyDynaBean.class); 116 117 protected static final BigInteger BigInteger_ZERO = new BigInteger ("0"); 118 protected static final BigDecimal BigDecimal_ZERO = new BigDecimal ("0"); 119 protected static final Character Character_SPACE = new Character (' '); 120 protected static final Byte Byte_ZERO = new Byte ((byte)0); 121 protected static final Short Short_ZERO = new Short ((short)0); 122 protected static final Integer Integer_ZERO = new Integer (0); 123 protected static final Long Long_ZERO = new Long ((long)0); 124 protected static final Float Float_ZERO = new Float ((byte)0); 125 protected static final Double Double_ZERO = new Double ((byte)0); 126 127 131 protected Map values; 132 133 137 protected MutableDynaClass dynaClass; 138 139 140 142 145 public LazyDynaBean() { 146 this(new LazyDynaClass()); 147 } 148 149 154 public LazyDynaBean(String name) { 155 this(new LazyDynaClass(name)); 156 } 157 158 165 public LazyDynaBean(DynaClass dynaClass) { 166 167 values = newMap(); 168 169 if (dynaClass instanceof MutableDynaClass) { 170 this.dynaClass = (MutableDynaClass)dynaClass; 171 } else { 172 this.dynaClass = new LazyDynaClass(dynaClass.getName(), dynaClass.getDynaProperties()); 173 } 174 175 } 176 177 178 180 183 public Map getMap() { 184 return values; 185 } 186 187 193 public int size(String name) { 194 195 if (name == null) { 196 throw new IllegalArgumentException ("No property name specified"); 197 } 198 199 Object value = values.get(name); 200 if (value == null) { 201 return 0; 202 } 203 204 if (value instanceof Map ) { 205 return ((Map )value).size(); 206 } 207 208 if (value instanceof List ) { 209 return ((List )value).size(); 210 } 211 212 if ((value.getClass().isArray())) { 213 return Array.getLength(value); 214 } 215 216 return 0; 217 218 } 219 220 222 231 public boolean contains(String name, String key) { 232 233 if (name == null) { 234 throw new IllegalArgumentException ("No property name specified"); 235 } 236 237 Object value = values.get(name); 238 if (value == null) { 239 return false; 240 } 241 242 if (value instanceof Map ) { 243 return (((Map ) value).containsKey(key)); 244 } 245 246 return false; 247 248 } 249 250 259 public Object get(String name) { 260 261 if (name == null) { 262 throw new IllegalArgumentException ("No property name specified"); 263 } 264 265 Object value = values.get(name); 267 if (value != null) { 268 return value; 269 } 270 271 if (!isDynaProperty(name)) { 273 return null; 274 } 275 276 value = createProperty(name, dynaClass.getDynaProperty(name).getType()); 278 279 if (value != null) { 280 set(name, value); 281 } 282 283 return value; 284 285 } 286 287 301 public Object get(String name, int index) { 302 303 if (!isDynaProperty(name)) { 305 set(name, defaultIndexedProperty(name)); 306 } 307 308 Object indexedProperty = get(name); 310 311 if (!dynaClass.getDynaProperty(name).isIndexed()) { 313 throw new IllegalArgumentException 314 ("Non-indexed property for '" + name + "[" + index + "]' " 315 + dynaClass.getDynaProperty(name).getName()); 316 } 317 318 indexedProperty = growIndexedProperty(name, indexedProperty, index); 320 321 if (indexedProperty.getClass().isArray()) { 323 return Array.get(indexedProperty, index); 324 } else if (indexedProperty instanceof List ) { 325 return ((List )indexedProperty).get(index); 326 } else { 327 throw new IllegalArgumentException 328 ("Non-indexed property for '" + name + "[" + index + "]' " 329 + indexedProperty.getClass().getName()); 330 } 331 332 } 333 334 346 public Object get(String name, String key) { 347 348 if (!isDynaProperty(name)) { 350 set(name, defaultMappedProperty(name)); 351 } 352 353 Object mappedProperty = get(name); 355 356 if (!dynaClass.getDynaProperty(name).isMapped()) { 358 throw new IllegalArgumentException 359 ("Non-mapped property for '" + name + "(" + key + ")' " 360 + dynaClass.getDynaProperty(name).getType().getName()); 361 } 362 363 if (mappedProperty instanceof Map ) { 365 return (((Map ) mappedProperty).get(key)); 366 } else { 367 throw new IllegalArgumentException 368 ("Non-mapped property for '" + name + "(" + key + ")'" 369 + mappedProperty.getClass().getName()); 370 } 371 372 } 373 374 375 379 public DynaClass getDynaClass() { 380 return (DynaClass)dynaClass; 381 } 382 383 394 public void remove(String name, String key) { 395 396 if (name == null) { 397 throw new IllegalArgumentException ("No property name specified"); 398 } 399 400 Object value = values.get(name); 401 if (value == null) { 402 return; 403 } 404 405 if (value instanceof Map ) { 406 ((Map ) value).remove(key); 407 } else { 408 throw new IllegalArgumentException 409 ("Non-mapped property for '" + name + "(" + key + ")'" 410 + value.getClass().getName()); 411 } 412 413 } 414 415 428 public void set(String name, Object value) { 429 430 if (!isDynaProperty(name)) { 432 433 if (dynaClass.isRestricted()) { 434 throw new IllegalArgumentException 435 ("Invalid property name '" + name + "' (DynaClass is restricted)"); 436 } 437 if (value == null) { 438 dynaClass.add(name); 439 } else { 440 dynaClass.add(name, value.getClass()); 441 } 442 443 } 444 445 DynaProperty descriptor = dynaClass.getDynaProperty(name); 446 447 if (value == null) { 448 if (descriptor.getType().isPrimitive()) { 449 throw new NullPointerException 450 ("Primitive value for '" + name + "'"); 451 } 452 } else if (!isAssignable(descriptor.getType(), value.getClass())) { 453 throw new ConversionException 454 ("Cannot assign value of type '" + 455 value.getClass().getName() + 456 "' to property '" + name + "' of type '" + 457 descriptor.getType().getName() + "'"); 458 } 459 460 values.put(name, value); 462 463 } 464 465 481 public void set(String name, int index, Object value) { 482 483 if (!isDynaProperty(name)) { 485 set(name, defaultIndexedProperty(name)); 486 } 487 488 Object indexedProperty = get(name); 490 491 if (!dynaClass.getDynaProperty(name).isIndexed()) { 493 throw new IllegalArgumentException 494 ("Non-indexed property for '" + name + "[" + index + "]'" 495 + dynaClass.getDynaProperty(name).getType().getName()); 496 } 497 498 indexedProperty = growIndexedProperty(name, indexedProperty, index); 500 501 if (indexedProperty.getClass().isArray()) { 503 Array.set(indexedProperty, index, value); 504 } else if (indexedProperty instanceof List ) { 505 ((List )indexedProperty).set(index, value); 506 } else { 507 throw new IllegalArgumentException 508 ("Non-indexed property for '" + name + "[" + index + "]' " 509 + indexedProperty.getClass().getName()); 510 } 511 512 } 513 514 528 public void set(String name, String key, Object value) { 529 530 if (!isDynaProperty(name)) { 532 set(name, defaultMappedProperty(name)); 533 } 534 535 Object mappedProperty = get(name); 537 538 if (!dynaClass.getDynaProperty(name).isMapped()) { 540 throw new IllegalArgumentException 541 ("Non-mapped property for '" + name + "(" + key + ")'" 542 + dynaClass.getDynaProperty(name).getType().getName()); 543 } 544 545 ((Map )mappedProperty).put(key, value); 547 548 } 549 550 552 protected Object growIndexedProperty(String name, Object indexedProperty, int index) { 553 554 if (indexedProperty instanceof List ) { 556 557 List list = (List )indexedProperty; 558 while (index >= list.size()) { 559 list.add(null); 560 } 561 562 } 563 564 if ((indexedProperty.getClass().isArray())) { 566 567 int length = Array.getLength(indexedProperty); 568 if (index >= length) { 569 Class componentType = indexedProperty.getClass().getComponentType(); 570 Object newArray = Array.newInstance(componentType, (index + 1)); 571 System.arraycopy(indexedProperty, 0, newArray, 0, length); 572 indexedProperty = newArray; 573 set(name, indexedProperty); 574 int newLength = Array.getLength(indexedProperty); 575 for (int i = length; i < newLength; i++) { 576 Array.set(indexedProperty, i, createProperty(name+"["+i+"]", componentType)); 577 } 578 } 579 } 580 581 return indexedProperty; 582 583 } 584 585 588 protected Object createProperty(String name, Class type) { 589 590 if (type.isArray() || List .class.isAssignableFrom(type)) { 592 return createIndexedProperty(name, type); 593 } 594 595 if (Map .class.isAssignableFrom(type)) { 596 return createMappedProperty(name, type); 597 } 598 599 if (DynaBean.class.isAssignableFrom(type)) { 600 return createDynaBeanProperty(name, type); 601 } 602 603 if (type.isPrimitive()) { 604 return createPrimitiveProperty(name, type); 605 } 606 607 if (Number .class.isAssignableFrom(type)) { 608 return createNumberProperty(name, type); 609 } 610 611 return createOtherProperty(name, type); 612 613 } 614 615 618 protected Object createIndexedProperty(String name, Class type) { 619 620 Object indexedProperty = null; 622 623 if (type == null) { 624 625 indexedProperty = defaultIndexedProperty(name); 626 627 } else if (type.isArray()) { 628 629 indexedProperty = Array.newInstance(type.getComponentType(), 0); 630 631 } else if (List .class.isAssignableFrom(type)) { 632 if (type.isInterface()) { 633 indexedProperty = defaultIndexedProperty(name); 634 } else { 635 try { 636 indexedProperty = type.newInstance(); 637 } 638 catch (Exception ex) { 639 throw new IllegalArgumentException 640 ("Error instantiating indexed property of type '" + 641 type.getName() + "' for '" + name + "' " + ex); 642 } 643 } 644 } else { 645 646 throw new IllegalArgumentException 647 ("Non-indexed property of type '" + type.getName() + "' for '" + name + "'"); 648 } 649 650 return indexedProperty; 651 652 } 653 654 657 protected Object createMappedProperty(String name, Class type) { 658 659 Object mappedProperty = null; 661 662 if (type == null) { 663 664 mappedProperty = defaultMappedProperty(name); 665 666 } else if (type.isInterface()) { 667 668 mappedProperty = defaultMappedProperty(name); 669 670 } else if (Map .class.isAssignableFrom(type)) { 671 try { 672 mappedProperty = type.newInstance(); 673 } 674 catch (Exception ex) { 675 throw new IllegalArgumentException 676 ("Error instantiating mapped property of type '" + type.getName() + "' for '" + name + "' " + ex); 677 } 678 } else { 679 680 throw new IllegalArgumentException 681 ("Non-mapped property of type '" + type.getName() + "' for '" + name + "'"); 682 } 683 684 return mappedProperty; 685 686 } 687 688 691 protected Object createDynaBeanProperty(String name, Class type) { 692 try { 693 return type.newInstance(); 694 } 695 catch (Exception ex) { 696 if (logger.isWarnEnabled()) { 697 logger.warn("Error instantiating DynaBean property of type '" + type.getName() + "' for '" + name + "' " + ex); 698 } 699 return null; 700 } 701 } 702 703 706 protected Object createPrimitiveProperty(String name, Class type) { 707 708 if (type == Boolean.TYPE) { 709 return Boolean.FALSE; 710 } else if (type == Integer.TYPE) { 711 return Integer_ZERO; 712 } else if (type == Long.TYPE) { 713 return Long_ZERO; 714 } else if (type == Double.TYPE) { 715 return Double_ZERO; 716 } else if (type == Float.TYPE) { 717 return Float_ZERO; 718 } else if (type == Byte.TYPE) { 719 return Byte_ZERO; 720 } else if (type == Short.TYPE) { 721 return Short_ZERO; 722 } else if (type == Character.TYPE) { 723 return Character_SPACE; 724 } else { 725 return null; 726 } 727 728 } 729 730 733 protected Object createNumberProperty(String name, Class type) { 734 735 return null; 736 737 } 738 739 742 protected Object createOtherProperty(String name, Class type) { 743 744 if (type == String .class || type == Boolean .class || 745 type == Character .class || Date .class.isAssignableFrom(type)) { 746 return null; 747 } 748 749 try { 750 return type.newInstance(); 751 } 752 catch (Exception ex) { 753 if (logger.isWarnEnabled()) { 754 logger.warn("Error instantiating property of type '" + type.getName() + "' for '" + name + "' " + ex); 755 } 756 return null; 757 } 758 } 759 760 769 protected Object defaultIndexedProperty(String name) { 770 return new ArrayList (); 771 } 772 773 782 protected Map defaultMappedProperty(String name) { 783 return new HashMap (); 784 } 785 786 789 protected boolean isDynaProperty(String name) { 790 791 if (name == null) { 792 throw new IllegalArgumentException ("No property name specified"); 793 } 794 795 if (dynaClass instanceof LazyDynaClass) { 797 return ((LazyDynaClass)dynaClass).isDynaProperty(name); 798 } 799 800 return dynaClass.getDynaProperty(name) == null ? false : true; 802 803 } 804 805 811 protected boolean isAssignable(Class dest, Class source) { 812 813 if (dest.isAssignableFrom(source) || 814 ((dest == Boolean.TYPE) && (source == Boolean .class)) || 815 ((dest == Byte.TYPE) && (source == Byte .class)) || 816 ((dest == Character.TYPE) && (source == Character .class)) || 817 ((dest == Double.TYPE) && (source == Double .class)) || 818 ((dest == Float.TYPE) && (source == Float .class)) || 819 ((dest == Integer.TYPE) && (source == Integer .class)) || 820 ((dest == Long.TYPE) && (source == Long .class)) || 821 ((dest == Short.TYPE) && (source == Short .class))) { 822 return (true); 823 } else { 824 return (false); 825 } 826 827 } 828 829 832 protected Map newMap() { 833 return new HashMap (); 834 } 835 836 } 837 | Popular Tags |