1 package org.apache.commons.betwixt; 2 3 18 19 import java.beans.BeanDescriptor ; 20 import java.beans.BeanInfo ; 21 import java.beans.IntrospectionException ; 22 import java.beans.Introspector ; 23 import java.beans.PropertyDescriptor ; 24 import java.lang.reflect.Method ; 25 import java.net.URL ; 26 import java.util.ArrayList ; 27 import java.util.HashMap ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Map ; 31 32 import org.apache.commons.beanutils.DynaBean; 33 import org.apache.commons.beanutils.DynaClass; 34 import org.apache.commons.beanutils.DynaProperty; 35 import org.apache.commons.betwixt.digester.XMLBeanInfoDigester; 36 import org.apache.commons.betwixt.digester.XMLIntrospectorHelper; 37 import org.apache.commons.betwixt.expression.EmptyExpression; 38 import org.apache.commons.betwixt.expression.IteratorExpression; 39 import org.apache.commons.betwixt.expression.MapEntryAdder; 40 import org.apache.commons.betwixt.expression.MethodUpdater; 41 import org.apache.commons.betwixt.expression.StringExpression; 42 import org.apache.commons.betwixt.registry.DefaultXMLBeanInfoRegistry; 43 import org.apache.commons.betwixt.registry.XMLBeanInfoRegistry; 44 import org.apache.commons.betwixt.strategy.ClassNormalizer; 45 import org.apache.commons.betwixt.strategy.DefaultNameMapper; 46 import org.apache.commons.betwixt.strategy.DefaultPluralStemmer; 47 import org.apache.commons.betwixt.strategy.NameMapper; 48 import org.apache.commons.betwixt.strategy.PluralStemmer; 49 import org.apache.commons.betwixt.strategy.TypeBindingStrategy; 50 import org.apache.commons.logging.Log; 51 import org.apache.commons.logging.LogFactory; 52 53 72 public class XMLIntrospector { 73 77 protected Log log = LogFactory.getLog( XMLIntrospector.class ); 78 79 80 private XMLBeanInfoRegistry registry = new DefaultXMLBeanInfoRegistry(); 81 82 83 private XMLBeanInfoDigester digester; 84 85 86 private IntrospectionConfiguration configuration; 87 88 89 public XMLIntrospector() { 90 this(new IntrospectionConfiguration()); 91 } 92 93 99 public XMLIntrospector(IntrospectionConfiguration configuration) { 100 setConfiguration(configuration); 101 } 102 103 104 107 111 public Log getLog() { 112 return getConfiguration().getIntrospectionLog(); 113 } 114 115 119 public void setLog(Log log) { 120 getConfiguration().setIntrospectionLog(log); 121 } 122 123 135 public XMLBeanInfoRegistry getRegistry() { 136 return registry; 137 } 138 139 151 public void setRegistry(XMLBeanInfoRegistry registry) { 152 this.registry = registry; 153 } 154 155 163 public IntrospectionConfiguration getConfiguration() { 164 return configuration; 165 } 166 167 175 public void setConfiguration(IntrospectionConfiguration configuration) { 176 this.configuration = configuration; 177 } 178 179 180 190 public ClassNormalizer getClassNormalizer() { 191 return getConfiguration().getClassNormalizer(); 192 } 193 194 205 public void setClassNormalizer(ClassNormalizer classNormalizer) { 206 getConfiguration().setClassNormalizer(classNormalizer); 207 } 208 209 215 public boolean isCachingEnabled() { 216 return true; 217 } 218 219 225 public void setCachingEnabled(boolean cachingEnabled) { 226 } 228 229 230 235 public boolean isAttributesForPrimitives() { 236 return getConfiguration().isAttributesForPrimitives(); 237 } 238 239 245 public void setAttributesForPrimitives(boolean attributesForPrimitives) { 246 getConfiguration().setAttributesForPrimitives(attributesForPrimitives); 247 } 248 249 255 public boolean isWrapCollectionsInElement() { 256 return getConfiguration().isWrapCollectionsInElement(); 257 } 258 259 266 public void setWrapCollectionsInElement(boolean wrapCollectionsInElement) { 267 getConfiguration().setWrapCollectionsInElement(wrapCollectionsInElement); 268 } 269 270 276 public PluralStemmer getPluralStemmer() { 277 return getConfiguration().getPluralStemmer(); 278 } 279 280 286 public void setPluralStemmer(PluralStemmer pluralStemmer) { 287 getConfiguration().setPluralStemmer(pluralStemmer); 288 } 289 290 297 public NameMapper getNameMapper() { 298 return getElementNameMapper(); 299 } 300 301 307 public void setNameMapper(NameMapper nameMapper) { 308 setElementNameMapper(nameMapper); 309 } 310 311 312 319 public NameMapper getElementNameMapper() { 320 return getConfiguration().getElementNameMapper(); 321 } 322 323 328 public void setElementNameMapper(NameMapper nameMapper) { 329 getConfiguration().setElementNameMapper( nameMapper ); 330 } 331 332 333 340 public NameMapper getAttributeNameMapper() { 341 return getConfiguration().getAttributeNameMapper(); 342 } 343 344 345 350 public void setAttributeNameMapper(NameMapper nameMapper) { 351 getConfiguration().setAttributeNameMapper( nameMapper ); 352 } 353 354 361 public boolean useBeanInfoSearchPath() { 362 return getConfiguration().useBeanInfoSearchPath(); 363 } 364 365 371 public void setUseBeanInfoSearchPath(boolean useBeanInfoSearchPath) { 372 getConfiguration().setUseBeanInfoSearchPath( useBeanInfoSearchPath ); 373 } 374 375 378 383 public void flushCache() {} 384 385 386 394 public XMLBeanInfo introspect(Object bean) throws IntrospectionException { 395 if (getLog().isDebugEnabled()) { 396 getLog().debug( "Introspecting..." ); 397 getLog().debug(bean); 398 } 399 400 if ( bean instanceof DynaBean ) { 401 XMLBeanInfo xmlBeanInfo = findByXMLDescriptor( bean.getClass() ); 403 if (xmlBeanInfo != null) { 404 return xmlBeanInfo; 405 } 406 return introspect( ((DynaBean) bean).getDynaClass() ); 408 409 } else { 410 Class normalClass = getClassNormalizer().getNormalizedClass( bean ); 412 return introspect( normalClass ); 413 } 414 } 415 416 424 public XMLBeanInfo introspect(DynaClass dynaClass) { 425 426 431 XMLBeanInfo xmlInfo = createXMLBeanInfo( dynaClass ); 433 434 DynaClassBeanType beanClass = new DynaClassBeanType( dynaClass ); 436 populate( xmlInfo, beanClass ); 437 438 return xmlInfo; 439 } 440 441 449 public XMLBeanInfo introspect(Class aClass) throws IntrospectionException { 450 String [] searchPath = null; 452 if ( !getConfiguration().useBeanInfoSearchPath() ) { 453 searchPath = Introspector.getBeanInfoSearchPath(); 454 Introspector.setBeanInfoSearchPath(new String [] { }); 455 } 456 457 XMLBeanInfo xmlInfo = registry.get( aClass ); 458 459 if ( xmlInfo == null ) { 460 if ( getLog().isDebugEnabled() ) { 462 getLog().debug( "Attempting to lookup an XML descriptor for class: " + aClass ); 463 } 464 465 xmlInfo = findByXMLDescriptor( aClass ); 466 if ( xmlInfo == null ) { 467 BeanInfo info = Introspector.getBeanInfo( aClass ); 468 xmlInfo = introspect( info ); 469 } 470 471 if ( xmlInfo != null ) { 472 registry.put( aClass, xmlInfo ); 473 } 474 } else { 475 getLog().trace( "Used cached XMLBeanInfo." ); 476 } 477 478 if ( getLog().isTraceEnabled() ) { 479 getLog().trace( xmlInfo ); 480 } 481 if ( !getConfiguration().useBeanInfoSearchPath() ) { 482 Introspector.setBeanInfoSearchPath( searchPath ); 484 } 485 486 return xmlInfo; 487 } 488 489 497 public XMLBeanInfo introspect(BeanInfo beanInfo) throws IntrospectionException { 498 XMLBeanInfo xmlBeanInfo = createXMLBeanInfo( beanInfo ); 499 populate( xmlBeanInfo, new JavaBeanType( beanInfo ) ); 500 return xmlBeanInfo; 501 } 502 503 509 private void populate(XMLBeanInfo xmlBeanInfo, BeanType bean) { 510 String name = bean.getBeanName(); 511 512 ElementDescriptor elementDescriptor = new ElementDescriptor(); 513 elementDescriptor.setLocalName( 514 getElementNameMapper().mapTypeToElementName( name ) ); 515 elementDescriptor.setPropertyType( bean.getElementType() ); 516 517 if (getLog().isTraceEnabled()) { 518 getLog().trace("Populating:" + bean); 519 } 520 521 if ( bean.isPrimitiveType() ) { 523 getLog().trace("Bean is primitive"); 524 elementDescriptor.setTextExpression( StringExpression.getInstance() ); 525 526 } else if ( bean.isLoopType() ) { 527 getLog().trace("Bean is loop"); 528 ElementDescriptor loopDescriptor = new ElementDescriptor(); 529 loopDescriptor.setContextExpression( 530 new IteratorExpression( EmptyExpression.getInstance() ) 531 ); 532 if ( bean.isMapType() ) { 533 loopDescriptor.setQualifiedName( "entry" ); 534 } 535 elementDescriptor.setElementDescriptors( new ElementDescriptor[] { loopDescriptor } ); 536 537 } else { 538 getLog().trace("Bean is standard type"); 539 List elements = new ArrayList (); 540 List attributes = new ArrayList (); 541 List contents = new ArrayList (); 542 543 addProperties( bean.getProperties(), elements, attributes, contents ); 544 545 int size = elements.size(); 546 if ( size > 0 ) { 547 ElementDescriptor[] descriptors = new ElementDescriptor[size]; 548 elements.toArray( descriptors ); 549 elementDescriptor.setElementDescriptors( descriptors ); 550 } 551 size = attributes.size(); 552 if ( size > 0 ) { 553 AttributeDescriptor[] descriptors = new AttributeDescriptor[size]; 554 attributes.toArray( descriptors ); 555 elementDescriptor.setAttributeDescriptors( descriptors ); 556 } 557 size = contents.size(); 558 if ( size > 0 ) { 559 if ( size > 0 ) { 560 Descriptor[] descriptors = new Descriptor[size]; 561 contents.toArray( descriptors ); 562 elementDescriptor.setContentDescriptors( descriptors ); 563 } 564 } 565 } 566 567 xmlBeanInfo.setElementDescriptor( elementDescriptor ); 568 569 defaultAddMethods( elementDescriptor, bean.getElementType() ); 571 572 if (getLog().isTraceEnabled()) { 573 getLog().trace("Populated descriptor:"); 574 getLog().trace(elementDescriptor); 575 } 576 } 577 578 579 587 protected XMLBeanInfo createXMLBeanInfo(DynaClass dynaClass) { 588 XMLBeanInfo beanInfo = new XMLBeanInfo(dynaClass.getClass()); 590 return beanInfo; 591 } 592 593 594 595 596 607 public Descriptor createDescriptor( 608 PropertyDescriptor propertyDescriptor, 609 boolean useAttributesForPrimitives 610 ) throws IntrospectionException { 611 return createXMLDescriptor( new BeanProperty( propertyDescriptor ) ); 612 } 613 614 623 public Descriptor createXMLDescriptor( BeanProperty beanProperty ) { 624 return beanProperty.createXMLDescriptor( configuration ); 625 } 626 627 628 655 public void defaultAddMethods( 656 ElementDescriptor rootDescriptor, 657 Class beanClass ) { 658 659 if ( beanClass != null ) { 662 ArrayList singleParameterAdders = new ArrayList (); 663 ArrayList twinParameterAdders = new ArrayList (); 664 665 Method [] methods = beanClass.getMethods(); 666 for ( int i = 0, size = methods.length; i < size; i++ ) { 667 Method method = methods[i]; 668 String name = method.getName(); 669 if ( name.startsWith( "add" )) { 670 Class [] types = method.getParameterTypes(); 673 if ( types != null) { 674 if ( getLog().isTraceEnabled() ) { 675 getLog().trace("Searching for match for " + method); 676 } 677 678 switch (types.length) 679 { 680 case 1: 681 singleParameterAdders.add(method); 682 break; 683 case 2: 684 twinParameterAdders.add(method); 685 break; 686 default: 687 break; 689 } 690 } 691 } 692 } 693 694 Map elementsByPropertyName = makeElementDescriptorMap( rootDescriptor ); 695 696 for (Iterator it=singleParameterAdders.iterator();it.hasNext();) { 697 Method singleParameterAdder = (Method ) it.next(); 698 setIteratorAdder(elementsByPropertyName, singleParameterAdder); 699 } 700 701 for (Iterator it=twinParameterAdders.iterator();it.hasNext();) { 702 Method twinParameterAdder = (Method ) it.next(); 703 setMapAdder(elementsByPropertyName, twinParameterAdder); 704 } 705 } 706 } 707 708 713 private void setIteratorAdder( 714 Map elementsByPropertyName, 715 Method singleParameterAdderMethod) { 716 717 String adderName = singleParameterAdderMethod.getName(); 718 String propertyName = Introspector.decapitalize(adderName.substring(3)); 719 ElementDescriptor matchingDescriptor = getMatchForAdder(propertyName, elementsByPropertyName); 720 if (matchingDescriptor != null) { 721 723 Class singularType = singleParameterAdderMethod.getParameterTypes()[0]; 724 if (getLog().isTraceEnabled()) { 725 getLog().trace(adderName + "->" + propertyName); 726 } 727 getLog().trace("Matching collection or iteration"); 729 730 matchingDescriptor.setUpdater( new MethodUpdater( singleParameterAdderMethod ) ); 731 matchingDescriptor.setSingularPropertyType( singularType ); 732 matchingDescriptor.setHollow(!isPrimitiveType(singularType)); 733 String localName = matchingDescriptor.getLocalName(); 734 if ( localName == null || localName.length() == 0 ) { 735 matchingDescriptor.setLocalName( 736 getElementNameMapper() 737 .mapTypeToElementName( propertyName ) ); 738 } 739 740 if ( getLog().isDebugEnabled() ) { 741 getLog().debug( "!! " + singleParameterAdderMethod); 742 getLog().debug( "!! " + singularType); 743 } 744 } 745 } 746 747 752 private void setMapAdder( 753 Map elementsByPropertyName, 754 Method twinParameterAdderMethod) { 755 String adderName = twinParameterAdderMethod.getName(); 756 String propertyName = Introspector.decapitalize(adderName.substring(3)); 757 ElementDescriptor matchingDescriptor = getMatchForAdder(propertyName, elementsByPropertyName); 758 if ( matchingDescriptor != null 759 && Map .class.isAssignableFrom( matchingDescriptor.getPropertyType() )) { 760 getLog().trace("Matching map"); 762 ElementDescriptor[] children 763 = matchingDescriptor.getElementDescriptors(); 764 if ( children.length == 0 ) { 766 getLog().info( 767 "'entry' descriptor is missing for map. " 768 + "Updaters cannot be set"); 769 770 } else { 771 Class [] types = twinParameterAdderMethod.getParameterTypes(); 772 Class keyType = types[0]; 773 Class valueType = types[1]; 774 775 MapEntryAdder adder = new MapEntryAdder(twinParameterAdderMethod); 778 for ( 779 int n=0, 780 noOfGrandChildren = children.length; 781 n < noOfGrandChildren; 782 n++ ) { 783 if ( "key".equals( children[n].getLocalName() ) ) { 784 785 children[n].setUpdater( adder.getKeyUpdater() ); 786 children[n].setSingularPropertyType( keyType ); 787 if (children[n].getPropertyType() == null) { 788 children[n].setPropertyType( valueType ); 789 } 790 if ( isPrimitiveType(keyType) ) { 791 children[n].setHollow(false); 792 } 793 if ( getLog().isTraceEnabled() ) { 794 getLog().trace( "Key descriptor: " + children[n]); 795 } 796 797 } else if ( "value".equals( children[n].getLocalName() ) ) { 798 799 children[n].setUpdater( adder.getValueUpdater() ); 800 children[n].setSingularPropertyType( valueType ); 801 if (children[n].getPropertyType() == null) { 802 children[n].setPropertyType( valueType ); 803 } 804 if ( isPrimitiveType( valueType) ) { 805 children[n].setHollow(false); 806 } 807 if ( isLoopType( valueType )) { 808 ElementDescriptor loopDescriptor = new ElementDescriptor(); 812 loopDescriptor.setHollow(true); 813 loopDescriptor.setSingularPropertyType( valueType ); 814 loopDescriptor.setPropertyType( valueType ); 815 children[n].addElementDescriptor(loopDescriptor); 816 817 } 818 if ( getLog().isTraceEnabled() ) { 819 getLog().trace( "Value descriptor: " + children[n]); 820 } 821 } 822 } 823 } 824 } 825 } 826 827 833 private ElementDescriptor getMatchForAdder( 834 String propertyName, 835 Map elementsByPropertyName) { 836 ElementDescriptor matchingDescriptor = null; 837 if (propertyName.length() > 0) { 838 if ( getLog().isTraceEnabled() ) { 839 getLog().trace( "findPluralDescriptor( " + propertyName 840 + " ):root property name=" + propertyName ); 841 } 842 843 PluralStemmer stemmer = getPluralStemmer(); 844 matchingDescriptor = stemmer.findPluralDescriptor( propertyName, elementsByPropertyName ); 845 846 if ( getLog().isTraceEnabled() ) { 847 getLog().trace( 848 "findPluralDescriptor( " + propertyName 849 + " ):ElementDescriptor=" + matchingDescriptor ); 850 } 851 } 852 return matchingDescriptor; 853 } 854 855 858 859 862 private Map makeElementDescriptorMap( ElementDescriptor rootDescriptor ) { 863 Map result = new HashMap (); 864 String rootPropertyName = rootDescriptor.getPropertyName(); 865 if (rootPropertyName != null) { 866 result.put(rootPropertyName, rootDescriptor); 867 } 868 makeElementDescriptorMap( rootDescriptor, result ); 869 return result; 870 } 871 872 879 private void makeElementDescriptorMap( ElementDescriptor rootDescriptor, Map map ) { 880 ElementDescriptor[] children = rootDescriptor.getElementDescriptors(); 881 if ( children != null ) { 882 for ( int i = 0, size = children.length; i < size; i++ ) { 883 ElementDescriptor child = children[i]; 884 String propertyName = child.getPropertyName(); 885 if ( propertyName != null ) { 886 map.put( propertyName, child ); 887 } 888 makeElementDescriptorMap( child, map ); 889 } 890 } 891 } 892 893 901 protected PluralStemmer createPluralStemmer() { 902 return new DefaultPluralStemmer(); 903 } 904 905 913 protected NameMapper createNameMapper() { 914 return new DefaultNameMapper(); 915 } 916 917 926 protected synchronized XMLBeanInfo findByXMLDescriptor( Class aClass ) { 927 String name = aClass.getName(); 929 int idx = name.lastIndexOf( '.' ); 930 if ( idx >= 0 ) { 931 name = name.substring( idx + 1 ); 932 } 933 name += ".betwixt"; 934 935 URL url = aClass.getResource( name ); 936 if ( url != null ) { 937 try { 938 String urlText = url.toString(); 939 if ( getLog().isDebugEnabled( )) { 940 getLog().debug( "Parsing Betwixt XML descriptor: " + urlText ); 941 } 942 if ( digester == null ) { 945 digester = new XMLBeanInfoDigester(); 946 digester.setXMLIntrospector( this ); 947 } 948 digester.setBeanClass( aClass ); 949 return (XMLBeanInfo) digester.parse( urlText ); 950 } catch (Exception e) { 951 getLog().warn( "Caught exception trying to parse: " + name, e ); 952 } 953 } 954 955 if ( getLog().isTraceEnabled() ) { 956 getLog().trace( "Could not find betwixt file " + name ); 957 } 958 return null; 959 } 960 961 971 protected void addProperties( 972 BeanInfo beanInfo, 973 List elements, 974 List attributes, 975 List contents) 976 throws 977 IntrospectionException { 978 PropertyDescriptor [] descriptors = beanInfo.getPropertyDescriptors(); 979 if ( descriptors != null ) { 980 for ( int i = 0, size = descriptors.length; i < size; i++ ) { 981 addProperty(beanInfo, descriptors[i], elements, attributes, contents); 982 } 983 } 984 if (getLog().isTraceEnabled()) { 985 getLog().trace(elements); 986 getLog().trace(attributes); 987 getLog().trace(contents); 988 } 989 } 990 999 protected void addProperties( 1000 BeanProperty[] beanProperties, 1001 List elements, 1002 List attributes, 1003 List contents) { 1004 if ( beanProperties != null ) { 1005 if (getLog().isTraceEnabled()) { 1006 getLog().trace(beanProperties.length + " properties to be added"); 1007 } 1008 for ( int i = 0, size = beanProperties.length; i < size; i++ ) { 1009 addProperty(beanProperties[i], elements, attributes, contents); 1010 } 1011 } 1012 if (getLog().isTraceEnabled()) { 1013 getLog().trace("After properties have been added (elements, attributes, contents):"); 1014 getLog().trace(elements); 1015 getLog().trace(attributes); 1016 getLog().trace(contents); 1017 } 1018 } 1019 1020 1021 1035 protected void addProperty( 1036 BeanInfo beanInfo, 1037 PropertyDescriptor propertyDescriptor, 1038 List elements, 1039 List attributes, 1040 List contents) 1041 throws 1042 IntrospectionException { 1043 addProperty( propertyDescriptor, elements, attributes, contents); 1044 } 1045 1046 1058 protected void addProperty( 1059 PropertyDescriptor propertyDescriptor, 1060 List elements, 1061 List attributes, 1062 List contents) 1063 throws 1064 IntrospectionException { 1065 addProperty(new BeanProperty( propertyDescriptor ), elements, attributes, contents); 1066 } 1067 1068 1079 protected void addProperty( 1080 BeanProperty beanProperty, 1081 List elements, 1082 List attributes, 1083 List contents) { 1084 Descriptor nodeDescriptor = createXMLDescriptor(beanProperty); 1085 if (nodeDescriptor == null) { 1086 return; 1087 } 1088 if (nodeDescriptor instanceof ElementDescriptor) { 1089 elements.add(nodeDescriptor); 1090 } else if (nodeDescriptor instanceof AttributeDescriptor) { 1091 attributes.add(nodeDescriptor); 1092 } else { 1093 contents.add(nodeDescriptor); 1094 } 1095 } 1096 1097 1107 protected void addProperties( 1108 BeanInfo beanInfo, 1109 List elements, 1110 List attributes) 1111 throws 1112 IntrospectionException { 1113 PropertyDescriptor [] descriptors = beanInfo.getPropertyDescriptors(); 1114 if ( descriptors != null ) { 1115 for ( int i = 0, size = descriptors.length; i < size; i++ ) { 1116 addProperty(beanInfo, descriptors[i], elements, attributes); 1117 } 1118 } 1119 if (getLog().isTraceEnabled()) { 1120 getLog().trace(elements); 1121 getLog().trace(attributes); 1122 } 1123 } 1124 1125 1138 protected void addProperty( 1139 BeanInfo beanInfo, 1140 PropertyDescriptor propertyDescriptor, 1141 List elements, 1142 List attributes) 1143 throws 1144 IntrospectionException { 1145 NodeDescriptor nodeDescriptor = XMLIntrospectorHelper 1146 .createDescriptor(propertyDescriptor, 1147 isAttributesForPrimitives(), 1148 this); 1149 if (nodeDescriptor == null) { 1150 return; 1151 } 1152 if (nodeDescriptor instanceof ElementDescriptor) { 1153 elements.add(nodeDescriptor); 1154 } else { 1155 attributes.add(nodeDescriptor); 1156 } 1157 } 1158 1159 1160 1166 protected XMLBeanInfo createXMLBeanInfo( BeanInfo beanInfo ) { 1167 XMLBeanInfo xmlBeanInfo = new XMLBeanInfo( beanInfo.getBeanDescriptor().getBeanClass() ); 1168 return xmlBeanInfo; 1169 } 1170 1171 1177 public boolean isLoopType(Class type) { 1178 return XMLIntrospectorHelper.isLoopType(type); 1179 } 1180 1181 1182 1189 public boolean isPrimitiveType(Class type) { 1190 TypeBindingStrategy.BindingType bindingType 1191 = configuration.getTypeBindingStrategy().bindingType( type ) ; 1192 boolean result = (bindingType.equals(TypeBindingStrategy.BindingType.PRIMITIVE)); 1193 return result; 1194 } 1195 1196 1197 1198 private abstract class BeanType { 1199 1203 public abstract String getBeanName(); 1204 1205 1209 public abstract Class getElementType(); 1210 1211 1215 public abstract boolean isPrimitiveType(); 1216 1217 1221 public abstract boolean isMapType(); 1222 1223 1227 public abstract boolean isLoopType(); 1228 1229 1233 public abstract BeanProperty[] getProperties(); 1234 1235 1239 public String toString() { 1240 return "Bean[name=" + getBeanName() + ", type=" + getElementType(); 1241 } 1242 } 1243 1244 1245 private class JavaBeanType extends BeanType { 1246 1247 private BeanInfo beanInfo; 1248 1249 private Class beanClass; 1250 1251 private String name; 1252 1253 private BeanProperty[] properties; 1254 1255 1259 public JavaBeanType(BeanInfo beanInfo) { 1260 this.beanInfo = beanInfo; 1261 BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor(); 1262 beanClass = beanDescriptor.getBeanClass(); 1263 name = beanDescriptor.getName(); 1264 if (beanClass.isArray()) { 1266 name = "Array"; 1268 } 1269 1270 } 1271 1272 1273 public Class getElementType() { 1274 return beanClass; 1275 } 1276 1277 1278 public String getBeanName() { 1279 return name; 1280 } 1281 1282 1283 public boolean isPrimitiveType() { 1284 return XMLIntrospector.this.isPrimitiveType( beanClass ); 1285 } 1286 1287 1288 public boolean isLoopType() { 1289 return XMLIntrospectorHelper.isLoopType( beanClass ); 1290 } 1291 1292 1293 public boolean isMapType() { 1294 return Map .class.isAssignableFrom( beanClass ); 1295 } 1296 1297 1298 public BeanProperty[] getProperties() { 1299 if ( properties == null ) { 1301 ArrayList propertyDescriptors = new ArrayList (); 1302 PropertyDescriptor [] descriptors = beanInfo.getPropertyDescriptors(); 1304 if ( descriptors != null ) { 1305 for (int i=0, size=descriptors.length; i<size; i++) { 1306 propertyDescriptors.add( descriptors[i] ); 1307 } 1308 } 1309 1310 BeanInfo [] additionals = beanInfo.getAdditionalBeanInfo(); 1312 if ( additionals != null ) { 1313 for ( int i=0, outerSize=additionals.length; i<outerSize; i++ ) { 1314 BeanInfo additionalInfo = additionals[i]; 1315 descriptors = beanInfo.getPropertyDescriptors(); 1316 if ( descriptors != null ) { 1317 for (int j=0, innerSize=descriptors.length; j<innerSize; j++) { 1318 propertyDescriptors.add( descriptors[j] ); 1319 } 1320 } 1321 } 1322 } 1323 properties = new BeanProperty[ propertyDescriptors.size() ]; 1325 int count = 0; 1326 for ( Iterator it = propertyDescriptors.iterator(); it.hasNext(); count++) { 1327 PropertyDescriptor propertyDescriptor = (PropertyDescriptor ) it.next(); 1328 properties[count] = new BeanProperty( propertyDescriptor ); 1329 } 1330 } 1331 return properties; 1332 } 1333 } 1334 1335 1336 private class DynaClassBeanType extends BeanType { 1337 1338 private DynaClass dynaClass; 1339 1340 private BeanProperty[] properties; 1341 1342 1346 public DynaClassBeanType(DynaClass dynaClass) { 1347 this.dynaClass = dynaClass; 1348 DynaProperty[] dynaProperties = dynaClass.getDynaProperties(); 1349 properties = new BeanProperty[dynaProperties.length]; 1350 for (int i=0, size=dynaProperties.length; i<size; i++) { 1351 properties[i] = new BeanProperty(dynaProperties[i]); 1352 } 1353 } 1354 1355 1356 public String getBeanName() { 1357 return dynaClass.getName(); 1358 } 1359 1360 public Class getElementType() { 1361 return DynaClass.class; 1362 } 1363 1364 public boolean isPrimitiveType() { 1365 return false; 1366 } 1367 1368 public boolean isMapType() { 1369 return false; 1370 } 1371 1372 public boolean isLoopType() { 1373 return false; 1374 } 1375 1376 public BeanProperty[] getProperties() { 1377 return properties; 1378 } 1379 } 1380} 1381 | Popular Tags |