r1958 - in trunk/commons-beanutils: . branches branches/upstream
branches/upstream/current branches/upstream/current/optional
branches/upstream/current/optional/bean-collections
branches/upstream/current/optional/bean-collections/src
branches/upstream/current/optional/bean-collections/src/conf
branches/upstream/current/optional/bean-collections/src/java
branches/upstream/current/optional/bean-collections/src/java/org
branches/upstream/current/optional/bean-collections/src/java/org/apache
branches/upstream/current/optional/bean-collections/src/java/org/apache/commons
branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils
branches/upstream/current/optional/bean-collections/src/test
branches/upstream/current/optional/bean-collections/src/test/org
branches/upstream/current/optional/bean-collections/src/test/org/apache
branches/upstream/current/optional/bean-collections/src/test/org/apache/commons
branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils
branches/upstream/current/optional/bean-collections/xdocs
branches/upstream/current/src branches/upstream/current/src/conf
branches/upstream/current/src/java
branches/upstream/current/src/java/org
branches/upstream/current/src/java/org/apache
branches/upstream/current/src/java/org/apache/commons
branches/upstream/current/src/java/org/apache/commons/beanutils
branches/upstream/current/src/java/org/apache/commons/beanutils/converters
branches/upstream/current/src/java/org/apache/commons/beanutils/locale
branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters
branches/upstream/current/src/java/org/apache/commons/collections
branches/upstream/current/src/media
branches/upstream/current/src/test
branches/upstream/current/src/test/org
branches/upstream/current/src/test/org/apache
branches/upstream/current/src/test/org/apache/commons
branches/upstream/current/src/test/org/apache/commons/beanutils
branches/upstream/current/src/test/org/apache/commons/beanutils/converters
branches/upstream/current/src/test/org/apache/commons/beanutils/locale
branches/upstream/current/src/test/org/apache/commons/beanutils/locale/converters
branches/upstream/current/src/test/org/apache/commons/beanutils/priv
branches/upstream/current/src/test/org/apache/commons/collections
branches/upstream/current/src/test/org/apache/commons/collections/keyvalue
branches/upstream/current/xdocs
branches/upstream/current/xdocs/images
branches/upstream/current/xdocs/style
Arnaud Vandyck
avdyk at costa.debian.org
Thu Mar 9 22:05:12 UTC 2006
Author: avdyk
Date: 2006-03-09 22:04:21 +0000 (Thu, 09 Mar 2006)
New Revision: 1958
Added:
trunk/commons-beanutils/branches/
trunk/commons-beanutils/branches/upstream/
trunk/commons-beanutils/branches/upstream/current/
trunk/commons-beanutils/branches/upstream/current/.cvsignore
trunk/commons-beanutils/branches/upstream/current/LICENSE.txt
trunk/commons-beanutils/branches/upstream/current/NOTICE.txt
trunk/commons-beanutils/branches/upstream/current/PROPOSAL.html
trunk/commons-beanutils/branches/upstream/current/README.txt
trunk/commons-beanutils/branches/upstream/current/RELEASE-NOTES.txt
trunk/commons-beanutils/branches/upstream/current/STATUS.html
trunk/commons-beanutils/branches/upstream/current/build.properties.sample
trunk/commons-beanutils/branches/upstream/current/build.xml
trunk/commons-beanutils/branches/upstream/current/maven.xml
trunk/commons-beanutils/branches/upstream/current/optional/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/.cvsignore
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/LICENSE.txt
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/build.properties.sample
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/build.xml
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/project.xml
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/conf/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/conf/MANIFEST.MF
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanComparator.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanMap.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPredicate.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPropertyValueChangeClosure.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPropertyValueEqualsPredicate.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanToPropertyValueTransformer.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/overview.html
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/AbstractParent.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/AlphaBean.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanCollectionsTestSuite.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanComparatorTestCase.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPredicateTestCase.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPropertyValueChangeClosureTest.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPropertyValueEqualsPredicateTest.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanToPropertyValueTransformerTest.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/Child.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/TestBean.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/TestBeanMap.java
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/xdocs/
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/xdocs/index.xml
trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/xdocs/navigation.xml
trunk/commons-beanutils/branches/upstream/current/project.properties
trunk/commons-beanutils/branches/upstream/current/project.xml
trunk/commons-beanutils/branches/upstream/current/src/
trunk/commons-beanutils/branches/upstream/current/src/conf/
trunk/commons-beanutils/branches/upstream/current/src/conf/MANIFEST.MF
trunk/commons-beanutils/branches/upstream/current/src/java/
trunk/commons-beanutils/branches/upstream/current/src/java/org/
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BasicDynaBean.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BasicDynaClass.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanAccessLanguageException.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanUtils.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanUtilsBean.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConstructorUtils.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ContextClassLoaderLocal.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConversionException.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertUtils.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertUtilsBean.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/Converter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertingWrapDynaBean.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaBean.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaClass.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaProperty.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/JDBCDynaClass.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaBean.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaClass.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaMap.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MappedPropertyDescriptor.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MethodUtils.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MutableDynaClass.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/NestedNullException.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/PropertyUtils.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/PropertyUtilsBean.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ResultSetDynaClass.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ResultSetIterator.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/RowSetDynaClass.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/WrapDynaBean.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/WrapDynaClass.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/AbstractArrayConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BigDecimalConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BigIntegerConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BooleanArrayConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BooleanConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ByteArrayConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ByteConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/CharacterArrayConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/CharacterConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ClassConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/DoubleArrayConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/DoubleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FileConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FloatArrayConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FloatConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/IntegerArrayConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/IntegerConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/LongArrayConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/LongConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ShortArrayConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ShortConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlDateConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlTimeConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlTimestampConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/StringArrayConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/StringConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/URLConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/package.html
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/BaseLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleBeanUtils.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleBeanUtilsBean.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtils.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtilsBean.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/ByteLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DateLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DecimalLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DoubleLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/FloatLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/IntegerLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/LongLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/ShortLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlDateLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlTimeLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlTimestampLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/StringLocaleConverter.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/package.html
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/package.html
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/package.html
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/ArrayStack.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/Buffer.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/BufferUnderflowException.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/FastHashMap.java
trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/package.html
trunk/commons-beanutils/branches/upstream/current/src/java/overview.html
trunk/commons-beanutils/branches/upstream/current/src/media/
trunk/commons-beanutils/branches/upstream/current/src/media/logo.xcf
trunk/commons-beanutils/branches/upstream/current/src/test/
trunk/commons-beanutils/branches/upstream/current/src/test/org/
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/A.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AbstractChild.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AbstractParent.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AlphaBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BasicDynaBeanTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanUtilsBenchCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanWithInnerBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanificationTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BenchBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BetaBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/Child.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ConstructorUtilsTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ConvertUtilsTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaBeanUtilsTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaPropertyUtilsTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaResultSetTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaRowSetTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ExtendMapBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaBeanTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaClassTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaMapTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/MappedPropertyTestBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/MethodUtilsTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/NestedTestBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PassTestException.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PrimitiveBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PropertyUtilsBenchCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PropertyUtilsTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/SonOfAlphaBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBeanPackageSubclass.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBeanPublicSubclass.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestResultSet.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestResultSetMetaData.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ThrowExceptionConverter.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/WrapDynaBeanTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ByteConverterTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ConverterTestSuite.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/DoubleConverterTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/FileConverterTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/FloatConverterTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/IntegerConverterTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/LongConverterTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/NumberConverterTestBase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ShortConverterTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/StringArrayConverterTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/URLConverterTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleBeanificationTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleConvertTestSuite.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleConvertUtilsTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/converters/
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/converters/DateLocaleConverterTestCase.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PackageBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBeanFactory.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBeanSubclass.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateDirect.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateIndirect.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PublicSubBean.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/ReferenceMap.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/AbstractKeyValue.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/AbstractMapEntry.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/DefaultMapEntry.java
trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/KeyValue.java
trunk/commons-beanutils/branches/upstream/current/xdocs/
trunk/commons-beanutils/branches/upstream/current/xdocs/.cvsignore
trunk/commons-beanutils/branches/upstream/current/xdocs/images/
trunk/commons-beanutils/branches/upstream/current/xdocs/images/logo.png
trunk/commons-beanutils/branches/upstream/current/xdocs/index.xml
trunk/commons-beanutils/branches/upstream/current/xdocs/navigation.xml
trunk/commons-beanutils/branches/upstream/current/xdocs/proposal.xml
trunk/commons-beanutils/branches/upstream/current/xdocs/style/
trunk/commons-beanutils/branches/upstream/current/xdocs/style/project.css
trunk/commons-beanutils/tags/
Log:
[svn-inject] Installing original source of commons-beanutils
Added: trunk/commons-beanutils/branches/upstream/current/.cvsignore
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/.cvsignore 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/.cvsignore 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,8 @@
+build.properties
+dist
+target
+beanutils.ipr
+maven.log
+velocity.log
+.classpath
+.project
Added: trunk/commons-beanutils/branches/upstream/current/LICENSE.txt
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/LICENSE.txt 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/LICENSE.txt 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
Added: trunk/commons-beanutils/branches/upstream/current/NOTICE.txt
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/NOTICE.txt 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/NOTICE.txt 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,2 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
Added: trunk/commons-beanutils/branches/upstream/current/PROPOSAL.html
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/PROPOSAL.html 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/PROPOSAL.html 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,128 @@
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+<head>
+<title>Proposal for BeanUtils Package</title>
+</head>
+<body bgcolor="white">
+
+<div align="center">
+<h1>Proposal for <em>BeanUtils</em> Package</h1>
+</div>
+
+<h3>(0) Rationale</h3>
+
+<p>Most Java developers are used to creating Java classes that conform to the
+JavaBeans naming patterns for property getters and setters. It is natural to
+then access these methods directly, using calls to the corresponding
+<code>getXxx</code> and <code>setXxx</code> methods. However, there are some
+occasions where dynamic access to Java object properties (without compiled-in
+knowledge of the property getter and setter methods to be called) is needed.
+Example use cases include:</p>
+<ul>
+<li>Building scripting languages that interact with the Java object model
+ (such as the Bean Scripting Framework).</li>
+<li>Building template language processors for web presentation and similar
+ uses (such as JSP or Velocity).</li>
+<li>Building custom tag libraries for JSP and XSP environments (such as Jakarta
+ Taglibs, Struts, Cocoon).</li>
+<li>Consuming XML-based configuration resources (such as Ant build scripts, web
+ application deployment descriptors, Tomcat's <code>server.xml</code>
+ file).</li>
+</ul>
+
+<p>The Java language provides <em>Reflection</em> and <em>Introspection</em>
+APIs (see the <code>java.lang.reflect</code> and <code>java.beans</code>
+packages in the JDK Javadocs). However, these APIs can be quite complex to
+understand and utilize. The proposed <em>BeanUtils</em> component provides
+easy-to-use wrappers around these capabilities.</p>
+
+
+<h3>(1) Scope of the Package</h3>
+
+<p>This proposal is to create a package of Java utility methods for accessing
+and modifying the properties of arbitrary JavaBeans. No dependencies outside
+of the JDK are required, so the use of this package is very lightweight.</p>
+
+<p>In addition to wrapping the reflection and introspection APIs of the
+standard JDK, <em>BeanUtils</em> components shall support a syntax for directly
+accessing <strong>nested</strong> and <strong>indexed</strong> properties, in a
+manner that will be familar to users of scripting languages like JavaScript.
+For example, the following property accessor expressions are supported:</p>
+<ul>
+<li><strong>customer</strong> - Equivalent to <code>getCustomer()</code>.</li>
+<li><strong>customer.address</strong> - Equivalent to
+ <code>getCustomer().getAddress()</code>.</li>
+<li><strong>customer.address[2].street</strong> - Equivalent to
+ <code>getCustomer().getAddress(2).getStreet()</code> (access to indexed
+ properties also works if the underlying property is an array rather than
+ providing indexed getter and setter methods).</li>
+</ul>
+
+
+<h3>(1.5) Interaction With Other Packages</h3>
+
+<p><em>BeanUtils</em> relies only on standard JDK 1.2 (or later) APIs for
+production deployment. It utilizes the JUnit unit testing framework for
+developing and executing unit tests, but this is of interest only to
+developers of the component. BeanUtils will also be a dependency for
+several future proposed components for the Jakarta Commons subproject.</p>
+
+<p>No external configuration files are utilized.</p>
+
+
+<h3>(2) Initial Source of the Package</h3>
+
+<p>The three original Java classes (<code>BeanUtils</code>,
+<code>ConvertUtils</code>, and <code>PropertyUtils</code>) are an integral
+part of the <a href="http://jakarta.apache.org/struts">Struts Framework</a>.
+However, they have very few dependencies on other aspects of Struts, and
+those dependencies have been removed in the proposed code base.
+Once accepted and released as a Jakarta Commons component, Struts will
+be modified to use the Commons version of these classes, and its internal
+versions will be deprecated.</p>
+
+<p>The proposed package name for the new component is
+<code>org.apache.commons.beanutils</code>.</p>
+
+
+<h3>(3) Required Jakarta-Commons Resources</h3>
+
+<ul>
+<li>CVS Repository - New directory <code>beanutils</code> in the
+ <code>jakarta-commons</code> CVS repository. All initial committers
+ are already committers on <code>jakarta-commons</code>, so no
+ additional user setups are required.</li>
+<li>Mailing List - Discussions will take place on the general
+ <em>jakarta-commons at jakarta.apache.org</em> mailing list. To help
+ list subscribers identify messages of interest, it is suggested that
+ the message subject of messages about this component be prefixed with
+ [BeanUtils].</li>
+<li>Bugzilla - New component "BeanUtils" under the "Commons" product
+ category, with appropriate version identifiers as needed.</li>
+<li>Jyve FAQ - New category "commons-beanutils" (when available). </li>
+</ul>
+
+
+<h3>(4) Initial Committers</h3>
+
+<p>The initial committers on the BeanUtils component shall be Craig
+McClanahan and Geir Magnusson Jr.</p>
+
+
+
+</body>
+</html>
Property changes on: trunk/commons-beanutils/branches/upstream/current/PROPOSAL.html
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/README.txt
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/README.txt 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/README.txt 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,26 @@
+README
+======
+
+Jars
+----
+
+BeanUtils now comes packaged (into jars) in two different ways:
+
+ an all-in-one jar (commons-beanutils.jar);
+ and as modular component jars:
+ commons-beanutils-core.jar (core classes)
+ commons-beanutils-bean-collections.jar (additional dependency on commons-collections 3.0)
+
+Those who want it all should grab the all-in-one jar (and the optional dependencies)
+whereas those who need minimal dependencies should use commons-beanutils-core.jar
+plus any optional jars they plan to use.
+
+All classes that were in the last release are in commons-beanutils-core except for BeanComparator.
+
+Commons-Collections
+-------------------
+BeanUtils now ships with a small number of commons collections classes.
+This is a temporary measure intended to allow BeanUtils core to be used with
+either commons-collections 2 or commons-collections-3 without a dependency on either.
+It is intended that soon BeanUtils core will have no dependency on any commons collection
+packaged classes.
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/RELEASE-NOTES.txt
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/RELEASE-NOTES.txt 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/RELEASE-NOTES.txt 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,90 @@
+$Id: RELEASE-NOTES.txt,v 1.11.2.3 2004/08/01 20:15:19 rdonkin Exp $
+
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Commons BeanUtils Package
+ Version 1.7.0
+ Release Notes
+
+INTRODUCTION:
+============
+
+Beanutils 1.7.0 is a service release aimed at providing compatibility
+with both the commons collections 2.x series of releases
+and the commons collections 3.x series of releases
+
+CHANGES:
+========
+
+Upgraded License To Apache License 2.0
+--------------------------------------
+Beanutils is now released under the Apache License 2.0.
+See http://www.apache.org/licenses/LICENSE-2.0.
+
+Beanification
+-------------
+Creation of objects to back the static utility classes. These object are
+per-context-classloader pseudo-singletons. Each web or enterprise application
+is therefore isolated from changes made to the state of others suing the
+static facades. Greater flexibility of implementation is encourage since users
+can subclass and then set their own implementations. Calls to the static facades
+will then be passed to that implementation.
+
+Removal Of Commons Collections Dependency
+-----------------------------------------
+The commons collections dependency is in the process of being removed
+from core beanutils. This will reduce the number of dependencies for
+the core beanutils and also will allow beanutils to used with both
+collection 2.x and collection 3.x releases.
+
+Documentation Improvements
+--------------------------
+Many thanks to all those kind souls who've contributed documentation :)
+
+
+ENHANCEMENTS:
+=============
+
+BeanAccessLanguageException & NestNullException
+-----------------------------------------------
+Added new subclasses of RuntimeException so that bean access language
+exceptions can be trapped by users.
+
+BeanComparator
+--------------
+Added no-argument constructor for use in bean-centric environments.
+
+ConvertUtilsBean
+----------------
+Added a File converter and registered the File and URL converters by default
+
+
+BUG REPORTS ADDRESSED:
+=====================
+ #14848 Converted localized versions of beanutils and convert utils to use
+ delegated singletons. Now instances with the functionality in these
+ classes can be created.
+ Added public constructors for the utility objects (BeanUtilsBean,
+ PropertyUtilsBean and ConvertUtilsBean). Add public accessor properties
+ for the ConvertUtilsBean and PropertyUtilsBean instances used by a
+ BeanUtilsBean. This allows BeanUtilsBean objects to be created with
+ independent registered converters and independent caches. Also added
+ test cases.
+ #17663 Made BeanUtils.getArrayProperty conversions use ConvertUtils
+ (rather than just toString)
+ #18918 This bug prevented converters from being correctly deregistered
+ #19850 Now cloneBean will deal successfully with DynaBeans.
+
Added: trunk/commons-beanutils/branches/upstream/current/STATUS.html
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/STATUS.html 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/STATUS.html 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,131 @@
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+<head>
+<title>Status File for Jakarta Commons "BeanUtils" Component</title>
+<head>
+<body bgcolor="white">
+
+
+<div align="center">
+<h1>The Jakarta Commons <em>BeanUtils</em> Component</h1>
+$Id: STATUS.html,v 1.16 2004/02/29 21:17:51 scolebourne Exp $<br>
+<a href="#Introduction">[Introduction]</a>
+<a href="#Dependencies">[Dependencies]</a>
+<a href="#Release Info">[Release Info]</a>
+<a href="#Committers">[Committers]</a>
+<a href="#Action Items">[Action Items]</a>
+<br><br>
+</div>
+
+
+<a name="Introduction"></a>
+<h3>1. INTRODUCTION</h3>
+
+<p>The <em>BeanUtils</em> Component contains a set of Java classes that provide
+static utility methods useful in manipulating Java classes that conform to the
+JavaBeans Specification naming patterns for bean properties in a dynamic
+fashion. The following classes are included:</p>
+<ul>
+<li><strong>BeanUtils</strong> - Higher level getters and setters that deal
+ with automatic conversion of String-represented property values to the
+ corresponding data types of the underlying property setters (and vice
+ versa), using the capabilities of the ConvertUtils and PropertyUtils
+ classes.</li>
+<li><strong>ConvertUtils</strong> - Utility methods to convert String arguments
+ to native Java types (and vice versa)</li>.
+<li><strong>PropertyUtils</strong> - Low level getters and setters for bean
+ properties that perform no type conversions at all. Works on
+ <code>List</code> objects as well (Not JavaBeans standard).</li>
+</ul>
+
+<p>An innovative and unique feature of this component is the syntax for
+accessing nested and indexed bean properties. See the Javadocs
+<a href="http://jakarta.apache.org/commons/beanutils/api/">PropertyUtils</a>
+for more information about this feature.</p>
+
+
+<a name="Dependencies"></a>
+<h3>2. DEPENDENCIES</h3>
+
+<p>The <em>BeanUtils</em> component is dependent upon the following external
+components for development and use:</p>
+<ul>
+<li><a href="http://java.sun.com/j2se">Java Development Kit</a>
+ (Version 1.2 or later)</li>
+<li><a href="http://jakarta.apache.org/commons">Collections Classes</a>
+ from the Jakarta Commons Subproject</li>
+<li><a href="http://jakarta.apache.org/commons">Logging Classes</a>
+ from the Jakarta Commons Subproject</li>
+<li><a href="http://www.junit.org">JUnit Testing Framework</a>
+ (Version 3.7 or later) - for unit tests only, not required
+ for deployment</li>
+</ul>
+
+
+<a name="Release Info"></a>
+<h3>3. RELEASE INFO</h3>
+
+<p>Current Release: Version 1.6.1</p>
+
+<p>Planned Next Release: 1.7</p>
+
+
+<a name="Committers"></a>
+<h3>4. COMMITTERS</h3>
+
+<p>The following individuals are the primary developers and maintainers of this
+component. Developers who plan to use <em>BeanUtils</em> in their own
+projects are encouraged to collaborate on the future development of this
+component to ensure that it continues to meet a variety of needs.</p>
+<ul>
+<li><a href="mailto:craigmcc at apache.org">Craig McClanahan</a></li>
+<li><a href="mailto:geirm at apache.org">Geir Magnusson Jr.</a></li>
+<li><a href="mailto:sanders at apache.org">Scott Sanders</a></li>
+<li><a href="mailto:rdonkin at apache.org">Robert Burrell Donkin</a></li>
+<li><a href="mailto:dion at apache.org">dIon Gillard</a></li>
+<li><a href="mailto:jstrachan at apache.org">James Strachan</a></li>
+<li><a href="mailto:yoavs at apache.org">Yoav Shapira</a></li>
+</ul>
+
+
+<a name="Action Items"></a>
+<h3>5. ACTION ITEMS</h3>
+
+<p>The following action items need to be completed prior to the next
+release of this component:</p>
+
+<table border="1">
+
+ <tr>
+ <th width="80%">Action Item</th>
+ <th width="20%">Volunteer</th>
+ </tr>
+
+ <tr>
+ <td><strong>Finish locale-sensitive beans and converters.</strong>.
+ <td align="center">All</td>
+ </tr>
+
+ <tr>
+ <td><strong>Add test cases</strong>. Especially for i18n classes.</td>
+ <td align="center">All</td>
+ </tr>
+
+</table>
+
+</body>
+</html>
Property changes on: trunk/commons-beanutils/branches/upstream/current/STATUS.html
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/build.properties.sample
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/build.properties.sample 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/build.properties.sample 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,38 @@
+# Copyright 2001-2004 The Apache Software Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# The home directory for the Commons collection classes distribution
+commons-collections.home = ../collections/dist
+
+# The pathname of the collections classes JAR file
+commons-collections.jar = ${commons-collections.home}/commons-collections.jar
+
+# The home directory for the Commons logging classes distribution
+commons-logging.home = ../logging/dist
+
+# The pathname of the Commons Logging JAR file
+commons-logging.jar = ${commons-logging.home}/commons-logging.jar
+
+# The directory containing your binary distribution of JUnit,
+# version 3.7 or later
+junit.home = /usr/local/junit3.7
+
+# The pathname of the "junit.jar" JAR file
+junit.jar = ${junit.home}/junit.jar
+
+
+# Maven properties (for web site build)
+# Those committers using agents may like to use
+#maven.username=rdonkin
+#beanutils.cvs=lserver:rdonkin at cvs.apache.org:/home/cvs
\ No newline at end of file
Property changes on: trunk/commons-beanutils/branches/upstream/current/build.properties.sample
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/build.xml
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/build.xml 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/build.xml 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,575 @@
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project name="Bean Utilities" default="compile" basedir=".">
+
+
+<!--
+ "Bean Utilities" component of the Jakarta Commons Subproject
+ $Id: build.xml,v 1.59.2.3 2004/07/27 21:59:14 rdonkin Exp $
+-->
+
+
+<!-- ========== Initialize Properties ===================================== -->
+
+
+ <property file="build.properties"/> <!-- Component local -->
+ <property file="../build.properties"/> <!-- Commons local -->
+ <property file="${user.home}/build.properties"/> <!-- User local -->
+
+
+<!-- ========== External Dependencies ===================================== -->
+
+ <!-- The home directory for the Commons collection classes distribution -->
+ <property name="commons-logging.home" value="../logging/dist"/>
+
+ <!-- The directory containing your binary distribution of JUnit,
+ version 3.7 or later -->
+ <property name="junit.home" value="/usr/local/junit3.7"/>
+
+
+<!-- ========== Derived Values ============================================ -->
+
+ <!-- The pathname of the "junit.jar" JAR file -->
+ <property name="junit.jar" value="${junit.home}/junit.jar"/>
+
+
+<!-- ========== Component Declarations ==================================== -->
+
+
+ <!-- The name of this component -->
+ <property name="component.name" value="beanutils"/>
+
+ <!-- The primary package name of this component -->
+ <property name="component.package" value="org.apache.commons.beanutils"/>
+
+ <!-- The title of this component -->
+ <property name="component.title" value="Bean Introspection Utilities"/>
+
+ <!-- The current version number of this component -->
+ <property name="component.version" value="1.7"/>
+
+ <!-- The base directory for compilation targets -->
+ <property name="build.home" value="target"/>
+
+ <!-- The base directory for component configuration files -->
+ <property name="conf.home" value="src/conf"/>
+
+ <!-- The base directory for distribution targets -->
+ <property name="dist.home" value="dist"/>
+
+ <!-- The base directory for component sources -->
+ <property name="source.home" value="src/java"/>
+
+ <!-- The base directory for unit test sources -->
+ <property name="test.home" value="src/test"/>
+
+
+<!-- ========== Compiler Defaults ========================================= -->
+
+
+ <!-- Should Java compilations set the 'debug' compiler option? -->
+ <property name="compile.debug" value="true"/>
+
+ <!-- Should Java compilations set the 'deprecation' compiler option? -->
+ <property name="compile.deprecation" value="false"/>
+
+ <!-- Should Java compilations set the 'optimize' compiler option? -->
+ <property name="compile.optimize" value="true"/>
+
+ <!-- Construct compile classpath -->
+ <path id="compile.classpath">
+ <pathelement location="${build.home}/classes"/>
+ <pathelement location="${commons-logging.jar}"/>
+ </path>
+
+
+<!-- ========== Test Execution Defaults =================================== -->
+
+
+ <!-- Construct unit test classpath -->
+ <path id="test.classpath">
+ <pathelement location="${build.home}/classes"/>
+ <pathelement location="${build.home}/tests"/>
+ <pathelement location="${commons-logging.jar}"/>
+ <pathelement location="${junit.jar}"/>
+ </path>
+
+ <!-- Should all tests fail if one does? -->
+ <property name="test.failonerror" value="true"/>
+
+ <!-- The test runner to execute -->
+ <property name="test.runner" value="junit.textui.TestRunner"/>
+
+ <!-- The Commons Logger LogFactory implementation to use -->
+ <property name="test.factory"
+ value="org.apache.commons.logging.impl.LogFactoryImpl"/>
+
+ <!-- The Commons Logger Log implementation to use (standard factory) -->
+ <property name="test.log"
+ value="org.apache.commons.logging.impl.SimpleLog"/>
+
+ <!-- The Commons Logger SimpleLog level for testing -->
+ <property name="test.level" value="error"/>
+
+ <!-- Loop counter for microbenchmarks -->
+ <property name="bench.counter" value="100000"/>
+
+
+<!-- ========== Executable Targets ======================================== -->
+
+
+ <target name="init"
+ description="Initialize and evaluate conditionals">
+ <echo message="-------- ${component.name} ${component.version} --------"/>
+ <filter token="name" value="${component.name}"/>
+ <filter token="package" value="${component.package}"/>
+ <filter token="version" value="${component.version}"/>
+ </target>
+
+
+ <target name="prepare" depends="init"
+ description="Prepare build directory">
+ <mkdir dir="${build.home}"/>
+ <mkdir dir="${build.home}/classes"/>
+ <mkdir dir="${build.home}/conf"/>
+ <mkdir dir="${build.home}/tests"/>
+ </target>
+
+
+ <target name="static" depends="prepare"
+ description="Copy static files to build directory">
+ <tstamp/>
+ <copy todir="${build.home}/conf" filtering="on">
+ <fileset dir="${conf.home}" includes="*.MF"/>
+ </copy>
+ </target>
+
+
+ <target name="compile" depends="static"
+ description="Compile shareable components">
+ <javac srcdir="${source.home}"
+ destdir="${build.home}/classes"
+ debug="${compile.debug}"
+ deprecation="${compile.deprecation}"
+ optimize="${compile.optimize}">
+ <classpath refid="compile.classpath"/>
+ </javac>
+ <copy todir="${build.home}/classes" filtering="on">
+ <fileset dir="${source.home}" excludes="**/*.java"/>
+ </copy>
+ </target>
+
+
+ <target name="compile.tests" depends="compile"
+ description="Compile unit test cases">
+ <javac srcdir="${test.home}"
+ destdir="${build.home}/tests"
+ debug="${compile.debug}"
+ deprecation="${compile.deprecation}"
+ optimize="${compile.optimize}">
+ <classpath refid="test.classpath"/>
+ </javac>
+ <copy todir="${build.home}/tests" filtering="on">
+ <fileset dir="${test.home}" excludes="**/*.java"/>
+ </copy>
+ </target>
+
+
+ <target name="clean"
+ description="Clean build and distribution directories">
+ <delete dir="${build.home}"/>
+ <delete dir="${dist.home}"/>
+ </target>
+
+
+ <target name="all" depends="clean,compile"
+ description="Clean and compile all components"/>
+
+
+ <target name="javadoc" depends="compile"
+ description="Create component Javadoc documentation">
+ <mkdir dir="${dist.home}"/>
+ <mkdir dir="${dist.home}/docs"/>
+ <mkdir dir="${dist.home}/docs/api"/>
+ <javadoc sourcepath="${source.home}"
+ destdir="${dist.home}/docs/api"
+ packagenames="org.apache.commons.*"
+ author="true"
+ private="true"
+ version="true"
+ overview="src/java/overview.html"
+ doctitle="<h1>${component.title} (Version ${component.version})</h1>"
+ windowtitle="${component.title} (Version ${component.version})"
+ bottom="Copyright (c) 2001-2004 - Apache Software Foundation">
+ <classpath refid="compile.classpath"/>
+ </javadoc>
+ </target>
+
+
+ <target name="dist" depends="compile,javadoc"
+ description="Create binary distribution">
+ <mkdir dir="${dist.home}"/>
+ <copy file="LICENSE.txt"
+ todir="${dist.home}"/>
+ <copy file="NOTICE.txt"
+ todir="${dist.home}"/>
+ <copy file="RELEASE-NOTES.txt"
+ todir="${dist.home}"/>
+ <copy file="README.txt"
+ todir="${dist.home}"/>
+ <antcall target="jar"/>
+ <antcall target="bean-collections-dist"/>
+ </target>
+
+
+ <target name="jar" depends="compile"
+ description="Create jar">
+ <mkdir dir="${dist.home}"/>
+ <mkdir dir="${build.home}/classes/META-INF"/>
+ <copy file="LICENSE.txt"
+ tofile="${build.home}/classes/META-INF/LICENSE.txt"/>
+ <copy file="NOTICE.txt"
+ tofile="${build.home}/classes/META-INF/NOTICE.txt"/>
+ <jar jarfile="${dist.home}/commons-beanutils.jar"
+ basedir="${build.home}/classes"
+ manifest="${build.home}/conf/MANIFEST.MF"/>
+ <copy tofile='${dist.home}/commons-beanutils-core.jar' file='${dist.home}/commons-beanutils.jar'/>
+ </target>
+
+
+ <target name="install-jar" depends="jar"
+ description="--> Installs jar file in ${lib.repo}">
+ <copy todir="${lib.repo}" filtering="no">
+ <fileset dir="${dist.home}">
+ <include name="commons-${component.name}.jar"/>
+ </fileset>
+ </copy>
+ </target>
+
+<!-- ========== Sub Component Targets ===================================== -->
+
+ <target name='bean-collections-dist'>
+ <ant antfile='optional/bean-collections/build.xml' target='dist' inheritAll='false'/>
+ </target>
+
+<!-- ========== Unit Test Targets ========================================= -->
+
+
+ <target name="test" depends="compile.tests,
+ test.basic.dynabean,
+ test.wrap.dynabean,
+ test.dyna.property,
+ test.property,
+ test.dyna.bean,
+ test.bean,
+ test.convert,
+ test.method,
+ test.dyna.result,
+ test.dyna.row,
+ test.locale.convert,
+ test.converters,
+ test.beanification,
+ test.lazy.dynaclass,
+ test.lazy.dynabean,
+ test.lazy.dynamap
+ "
+ description="Run all unit test cases">
+ </target>
+
+
+ <target name="test.basic.dynabean" depends="compile.tests">
+ <echo message="Running BasicDynaBean tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.BasicDynaBeanTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.wrap.dynabean" depends="compile.tests">
+ <echo message="Running WrapDynaBean tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.WrapDynaBeanTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.dyna.property" depends="compile.tests">
+ <echo message="Running DynaBean PropertyUtils tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.DynaPropertyUtilsTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.property" depends="compile.tests">
+ <echo message="Running PropertyUtils tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.PropertyUtilsTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.dyna.bean" depends="compile.tests">
+ <echo message="Running DynaBean BeanUtils tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.DynaBeanUtilsTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.bean" depends="compile.tests">
+ <echo message="Running BeanUtils tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.BeanUtilsTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.convert" depends="compile.tests">
+ <echo message="Running ConvertUtils tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.ConvertUtilsTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.method" depends="compile.tests">
+ <echo message="Running MethodUtils tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.MethodUtilsTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.dyna.result" depends="compile.tests">
+ <echo message="Running DynaBean ResultSet tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.DynaResultSetTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.dyna.row" depends="compile.tests">
+ <echo message="Running DynaBean RowSet tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.DynaRowSetTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.locale.convert" depends="compile.tests">
+ <echo message="Running Locale converters tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.locale.LocaleConvertTestSuite"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+
+ <target name="test.converters" depends="compile.tests">
+ <echo message="Running Converters tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.converters.ConverterTestSuite"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.lazy.dynaclass" depends="compile.tests">
+ <echo message="Running LazyDynaClass tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.LazyDynaClassTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.lazy.dynabean" depends="compile.tests">
+ <echo message="Running LazyDynaBean tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.LazyDynaBeanTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.lazy.dynamap" depends="compile.tests">
+ <echo message="Running LazyDynaMap tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.LazyDynaMapTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="test.beanification" depends="compile.tests">
+ <echo message="Running Beanification tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <arg value="org.apache.commons.beanutils.BeanificationTestCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+
+ <!-- ========== Microbenchmark Cases ===================================== -->
+
+
+ <target name="bench" depends="compile.tests,
+ bench.BeanUtils,
+ bench.PropertyUtils
+ "
+ description="Execute microbenchmark cases"/>
+
+
+ <target name="bench.BeanUtils" depends="compile.tests">
+ <echo message="Running BeanUtils microbenchmarks"/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="counter"
+ value="${bench.counter}"/>
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.BeanUtilsBenchCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+ <target name="bench.PropertyUtils" depends="compile.tests">
+ <echo message="Running PropertyUtils microbenchmarks"/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="counter"
+ value="${bench.counter}"/>
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.PropertyUtilsBenchCase"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+
+
+</project>
Property changes on: trunk/commons-beanutils/branches/upstream/current/build.xml
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/maven.xml
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/maven.xml 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/maven.xml 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,19 @@
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project default="java:jar"
+ xmlns:j="jelly:core">
+
+</project>
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/.cvsignore
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/.cvsignore 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/.cvsignore 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,4 @@
+*.log
+*.properties
+target
+dist
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/LICENSE.txt
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/LICENSE.txt 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/LICENSE.txt 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/build.properties.sample
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/build.properties.sample 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/build.properties.sample 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,39 @@
+# Copyright 2001-2004 The Apache Software Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# The home directory for the Commons collection classes distribution
+commons-collections.home= ../collections/dist
+
+# The pathname of the collections classes JAR file
+commons-collections.jar = ${commons-collections.home}/commons-collections.jar
+commons-collections-testframework.jar = ${commons-collections.home}/commons-collections-testframework-3.0-dev.jar
+
+# The home directory for the Commons logging classes distribution
+commons-logging.home = ../logging/dist
+
+# The pathname of the Commons Logging JAR file
+commons-logging.jar = ${commons-logging.home}/commons-logging.jar
+
+# The directory containing your binary distribution of JUnit,
+# version 3.7 or later
+junit.home = /usr/local/junit3.7
+
+# The pathname of the "junit.jar" JAR file
+junit.jar = ${junit.home}/junit.jar
+
+
+# Maven properties (for web site build)
+# Those committers using agents may like to use
+#maven.username=rdonkin
+#beanutils.cvs=lserver:rdonkin at cvs.apache.org:/home/cvs
\ No newline at end of file
Property changes on: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/build.properties.sample
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/build.xml
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/build.xml 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/build.xml 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,301 @@
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project name="Bean Utilities Bean Collections" default="dist" basedir=".">
+
+
+<!--
+ "Bean Utilities" component of the Jakarta Commons Subproject
+ $Id: build.xml,v 1.2.2.3 2004/07/27 21:59:14 rdonkin Exp $
+-->
+
+
+<!-- ========== Initialize Properties ===================================== -->
+
+
+ <property file="build.properties"/> <!-- Component local -->
+ <property file="../build.properties"/> <!-- Commons local -->
+ <property file="${user.home}/build.properties"/> <!-- User local -->
+
+<!-- ========== External Dependencies ===================================== -->
+
+ <!-- The home directory for the Commons collection classes distribution -->
+ <property name="commons-collections.home" value="../../../collections/dist"/>
+
+ <!-- The home directory for the Commons collection classes distribution -->
+ <property name="commons-logging.home" value="../logging/dist"/>
+
+ <!-- The directory containing your binary distribution of JUnit,
+ version 3.7 or later -->
+ <property name="junit.home" value="/usr/local/junit3.7"/>
+
+ <!-- The pathname of the beanutils core JAR file -->
+ <property name="commons-beanutils-core.jar" value="../../dist/commons-beanutils.jar"/>
+
+
+<!-- ========== Derived Values ============================================ -->
+
+ <!-- The pathname of the collections classes JAR file -->
+ <property name="commons-collections.jar" value="${commons-collections.home}/commons-collections-3.0-dev.jar"/>
+
+ <!-- The pathname of the collections testframework classes JAR file -->
+ <property name="commons-collections-testframework.jar" value="${commons-collections.home}/commons-collections-testframework-3.0-dev.jar"/>
+
+
+ <!-- The pathname of the logging classes JAR file -->
+ <property name="commons-logging.jar" value="${commons-logging.home}/commons-logging.jar"/>
+
+ <!-- The pathname of the "junit.jar" JAR file -->
+ <property name="junit.jar" value="${junit.home}/junit.jar"/>
+
+
+<!-- ========== Component Declarations ==================================== -->
+
+
+ <!-- The name of this component -->
+ <property name="component.name" value="beanutils"/>
+
+ <!-- The primary package name of this component -->
+ <property name="component.package" value="org.apache.commons.beanutils"/>
+
+ <!-- The title of this component -->
+ <property name="component.title" value="Bean Utilities Bean Collections"/>
+
+ <!-- The current version number of this component -->
+ <property name="component.version" value="1.7"/>
+
+ <!-- The base directory for compilation targets -->
+ <property name="build.home" value="target"/>
+
+ <!-- The base directory for component configuration files -->
+ <property name="conf.home" value="src/conf"/>
+
+ <!-- The base directory for distribution targets -->
+ <property name="dist.home" value="dist"/>
+
+ <!-- The base directory for component sources -->
+ <property name="source.home" value="src/java"/>
+
+ <!-- The base directory for unit test sources -->
+ <property name="test.home" value="src/test"/>
+
+
+<!-- ========== Compiler Defaults ========================================= -->
+
+
+ <!-- Should Java compilations set the 'debug' compiler option? -->
+ <property name="compile.debug" value="true"/>
+
+ <!-- Should Java compilations set the 'deprecation' compiler option? -->
+ <property name="compile.deprecation" value="false"/>
+
+ <!-- Should Java compilations set the 'optimize' compiler option? -->
+ <property name="compile.optimize" value="true"/>
+
+ <!-- Construct compile classpath -->
+ <path id="compile.classpath">
+ <pathelement location="${build.home}/classes"/>
+ <pathelement location="${commons-logging.jar}"/>
+ <pathelement location="${commons-collections.jar}"/>
+ <pathelement location="${commons-beanutils-core.jar}"/>
+ </path>
+
+
+<!-- ========== Test Execution Defaults =================================== -->
+
+
+ <!-- Construct unit test classpath -->
+ <path id="test.classpath">
+ <pathelement location="${build.home}/classes"/>
+ <pathelement location="${build.home}/tests"/>
+ <pathelement location="${commons-logging.jar}"/>
+ <pathelement location="${commons-collections.jar}"/>
+ <pathelement location="${commons-collections-testframework.jar}"/>
+ <pathelement location="${commons-beanutils-core.jar}"/>
+ <pathelement location="${junit.jar}"/>
+ </path>
+
+ <!-- Should all tests fail if one does? -->
+ <property name="test.failonerror" value="true"/>
+
+ <!-- The test runner to execute -->
+ <property name="test.runner" value="junit.textui.TestRunner"/>
+
+ <!-- The Commons Logger LogFactory implementation to use -->
+ <property name="test.factory"
+ value="org.apache.commons.logging.impl.LogFactoryImpl"/>
+
+ <!-- The Commons Logger Log implementation to use (standard factory) -->
+ <property name="test.log"
+ value="org.apache.commons.logging.impl.SimpleLog"/>
+
+ <!-- The Commons Logger SimpleLog level for testing -->
+ <property name="test.level" value="error"/>
+
+ <!-- Loop counter for microbenchmarks -->
+ <property name="bench.counter" value="100000"/>
+
+
+<!-- ========== Executable Targets ======================================== -->
+
+
+ <target name="init"
+ description="Initialize and evaluate conditionals">
+ <echo message="-------- ${component.name} ${component.version} --------"/>
+ <filter token="name" value="${component.name}"/>
+ <filter token="package" value="${component.package}"/>
+ <filter token="version" value="${component.version}"/>
+ </target>
+
+
+ <target name="prepare" depends="init"
+ description="Prepare build directory">
+ <mkdir dir="${build.home}"/>
+ <mkdir dir="${build.home}/classes"/>
+ <mkdir dir="${build.home}/conf"/>
+ <mkdir dir="${build.home}/tests"/>
+ </target>
+
+
+ <target name="static" depends="prepare"
+ description="Copy static files to build directory">
+ <tstamp/>
+ <copy todir="${build.home}/conf" filtering="on">
+ <fileset dir="${conf.home}" includes="*.MF"/>
+ </copy>
+ </target>
+
+
+ <target name="compile" depends="static"
+ description="Compile shareable components">
+ <javac srcdir="${source.home}"
+ destdir="${build.home}/classes"
+ debug="${compile.debug}"
+ deprecation="${compile.deprecation}"
+ optimize="${compile.optimize}">
+ <classpath refid="compile.classpath"/>
+ </javac>
+ <copy todir="${build.home}/classes" filtering="on">
+ <fileset dir="${source.home}" excludes="**/*.java"/>
+ </copy>
+ </target>
+
+
+ <target name="compile.tests" depends="compile"
+ description="Compile unit test cases">
+ <javac srcdir="${test.home}"
+ destdir="${build.home}/tests"
+ debug="${compile.debug}"
+ deprecation="${compile.deprecation}"
+ optimize="${compile.optimize}">
+ <classpath refid="test.classpath"/>
+ </javac>
+ <copy todir="${build.home}/tests" filtering="on">
+ <fileset dir="${test.home}" excludes="**/*.java"/>
+ </copy>
+ </target>
+
+
+ <target name="clean"
+ description="Clean build and distribution directories">
+ <delete dir="${build.home}"/>
+ <delete dir="${dist.home}"/>
+ </target>
+
+
+ <target name="all" depends="clean,compile"
+ description="Clean and compile all components"/>
+
+ <target name="dist" depends="clean,compile,javadoc,jar"
+ description="Clean, compile and jar">
+ <copy todir='../../dist' file= '${dist.home}/commons-beanutils-bean-collections.jar'/>
+ </target>
+
+ <target name="jar" depends="compile"
+ description="Create jar">
+ <mkdir dir="${dist.home}"/>
+ <mkdir dir="${build.home}/classes/META-INF"/>
+ <copy file="../../LICENSE.txt"
+ tofile="${build.home}/classes/META-INF/LICENSE.txt"/>
+ <copy file="../../NOTICE.txt"
+ tofile="${build.home}/classes/META-INF/NOTICE.txt"/>
+ <jar jarfile="${dist.home}/commons-beanutils-bean-collections.jar"
+ basedir="${build.home}/classes"
+ manifest="${build.home}/conf/MANIFEST.MF"/>
+ <jar jarfile="../../dist/commons-beanutils.jar"
+ basedir="${build.home}/classes"
+ update='true'/>
+ </target>
+
+
+ <target name="javadoc" depends="compile"
+ description="Create component Javadoc documentation">
+ <mkdir dir="${dist.home}"/>
+ <mkdir dir="${dist.home}/docs"/>
+ <mkdir dir="${dist.home}/docs/api"/>
+ <mkdir dir="../../dist/docs/"/>
+ <mkdir dir="../../dist/docs/bean-collections"/>
+ <javadoc sourcepath="${source.home}"
+ destdir="${dist.home}/docs/api"
+ packagenames="org.apache.commons.*"
+ author="true"
+ private="true"
+ version="true"
+ overview="src/java/overview.html"
+ doctitle="<h1>${component.title} (Version ${component.version})</h1>"
+ windowtitle="${component.title} (Version ${component.version})"
+ bottom="Copyright (c) 2001-2004 - Apache Software Foundation">
+ <classpath refid="compile.classpath"/>
+ </javadoc>
+ <copy
+ todir='../../dist/docs/bean-collections'>
+ <fileset dir='${dist.home}/docs/api'/>
+ </copy>
+ </target>
+
+ <target name="install-jar" depends="jar"
+ description="--> Installs jar file in ${lib.repo}">
+ <copy todir="${lib.repo}" filtering="no">
+ <fileset dir="${dist.home}">
+ <include name="commons-${component.name}.jar"/>
+ </fileset>
+ </copy>
+ </target>
+
+
+<!-- ========== Unit Test Targets ========================================= -->
+
+
+ <target name="test" depends="compile.tests,
+ test.bean.collections"
+ description="Run all unit test cases">
+ </target>
+
+ <target name="test.bean.collections" depends="compile.tests">
+ <echo message="Running bean collection utilities tests ..."/>
+ <java classname="${test.runner}" fork="yes"
+ failonerror="${test.failonerror}">
+ <sysproperty key="org.apache.commons.logging.LogFactory"
+ value="${test.factory}"/>
+ <sysproperty key="org.apache.commons.logging.Log"
+ value="${test.log}"/>
+ <sysproperty key="org.apache.commons.logging.simplelog.defaultlog"
+ value="${test.level}"/>
+ <arg value="org.apache.commons.beanutils.BeanCollectionsTestSuite"/>
+ <classpath refid="test.classpath"/>
+ </java>
+ </target>
+
+</project>
Property changes on: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/build.xml
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/project.xml
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/project.xml 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/project.xml 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project>
+ <extend>../../project.xml</extend>
+ <pomVersion>3</pomVersion>
+ <id>commons-beanutils-bean-collections</id>
+ <name>BeanUtils Bean Collections</name>
+ <currentVersion>1.7</currentVersion>
+ <inceptionYear>2000</inceptionYear>
+ <shortDescription>Commons BeanUtils Bean Collections</shortDescription>
+ <description>Extensions of commons collections focussing on collections of beans</description>
+
+ <siteDirectory>/www/jakarta.apache.org/commons/beanutils/bean-collections</siteDirectory>
+
+ <dependencies>
+ <dependency>
+ <id>commons-logging</id>
+ <version>1.0.3</version>
+ </dependency>
+ <dependency>
+ <id>commons-collections</id>
+ <version>3.0</version>
+ </dependency>
+ <dependency>
+ <id>commons-beanutils</id>
+ <version>1.6</version>
+ </dependency>
+ <!-- Test Only -->
+ <dependency>
+ <artifactId>commons-collections-testframework</artifactId>
+ <groupId>commons-collections</groupId>
+ <version>SNAPSHOT</version>
+ </dependency>
+
+ </dependencies>
+</project>
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/conf/MANIFEST.MF
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/conf/MANIFEST.MF 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/conf/MANIFEST.MF 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,7 @@
+Extension-Name: org.apache.commons.beanutils-bean-collections
+Specification-Title: Jakarta Commons Beanutils
+Specification-Vendor: Apache Software Foundation
+Specification-Version: 1.6
+Implementation-Title: org.apache.commons.beanutils-bean-collections
+Implementation-Vendor: Apache Software Foundation
+Implementation-Version: 1.6
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanComparator.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanComparator.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanComparator.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.collections.comparators.ComparableComparator;
+
+/**
+ * <p>
+ * This comparator compares two beans by the specified bean property.
+ * It is also possible to compare beans based on nested, indexed,
+ * combined, mapped bean properties. Please see the {@link PropertyUtilsBean}
+ * documentation for all property name possibilities.
+ *
+ * </p><p>
+ * <strong>Note:</strong> The BeanComparator passes the values of the specified
+ * bean property to a ComparableComparator, if no comparator is
+ * specified in the constructor. If you are comparing two beans based
+ * on a property that could contain "null" values, a suitable <code>Comparator</code>
+ * or <code>ComparatorChain</code> should be supplied in the constructor.
+ * </p>
+ *
+ * @author <a href"mailto:epugh at upstate.com">Eric Pugh</a>
+ * @author Tim O'Brien
+ */
+public class BeanComparator implements Comparator, Serializable {
+
+ private String property;
+ private Comparator comparator;
+
+ /**
+ * <p>Constructs a Bean Comparator without a property set.
+ * </p><p>
+ * <strong>Note</strong> that this is intended to be used
+ * only in bean-centric environments.
+ * </p><p>
+ * Until {@link #setProperty} is called with a non-null value.
+ * this comparator will compare the Objects only.
+ * </p>
+ */
+ public BeanComparator() {
+ this( null );
+ }
+
+ /**
+ * <p>Constructs a property-based comparator for beans.
+ * This compares two beans by the property
+ * specified in the property parameter. This constructor creates
+ * a <code>BeanComparator</code> that uses a <code>ComparableComparator</code>
+ * to compare the property values.
+ * </p>
+ *
+ * <p>Passing "null" to this constructor will cause the BeanComparator
+ * to compare objects based on natural order, that is
+ * <code>java.lang.Comparable</code>.
+ * </p>
+ *
+ * @param property String Name of a bean property, which may contain the
+ * name of a simple, nested, indexed, mapped, or combined
+ * property. See {@link PropertyUtilsBean} for property query language syntax.
+ * If the property passed in is null then the actual objects will be compared
+ */
+ public BeanComparator( String property ) {
+ this( property, ComparableComparator.getInstance() );
+ }
+
+ /**
+ * Constructs a property-based comparator for beans.
+ * This constructor creates
+ * a BeanComparator that uses the supplied Comparator to compare
+ * the property values.
+ *
+ * @param property Name of a bean property, can contain the name
+ * of a simple, nested, indexed, mapped, or combined
+ * property. See {@link PropertyUtilsBean} for property query language
+ * syntax.
+ * @param comparator BeanComparator will pass the values of the
+ * specified bean property to this Comparator.
+ * If your bean property is not a comparable or
+ * contains null values, a suitable comparator
+ * may be supplied in this constructor.
+ */
+ public BeanComparator( String property, Comparator comparator ) {
+ setProperty( property );
+ this.comparator = comparator;
+ }
+
+ /**
+ * Sets the method to be called to compare two JavaBeans
+ *
+ * @param property String method name to call to compare
+ * If the property passed in is null then the actual objects will be compared
+ */
+ public void setProperty( String property ) {
+ this.property = property;
+ }
+
+
+ /**
+ * Gets the property attribute of the BeanComparator
+ *
+ * @return String method name to call to compare.
+ * A null value indicates that the actual objects will be compared
+ */
+ public String getProperty() {
+ return property;
+ }
+
+
+ /**
+ * Gets the Comparator being used to compare beans.
+ */
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+
+ /**
+ * Compare two JavaBeans by their shared property.
+ * If {@link #getProperty} is null then the actual objects will be compared.
+ *
+ * @param o1 Object The first bean to get data from to compare against
+ * @param o2 Object The second bean to get data from to compare
+ * @return int negative or positive based on order
+ */
+ public int compare( Object o1, Object o2 ) {
+
+ if ( property == null ) {
+ // compare the actual objects
+ return comparator.compare( o1, o2 );
+ }
+
+ try {
+ Object value1 = PropertyUtils.getProperty( o1, property );
+ Object value2 = PropertyUtils.getProperty( o2, property );
+ return comparator.compare( value1, value2 );
+ }
+ catch ( Exception e ) {
+ throw new ClassCastException( e.toString() );
+ }
+ }
+
+ /**
+ * Two <code>BeanComparator</code>'s are equals if and only if
+ * the wrapped comparators and the property names to be compared
+ * are equal.
+ */
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BeanComparator)) return false;
+
+ final BeanComparator beanComparator = (BeanComparator) o;
+
+ if (!comparator.equals(beanComparator.comparator)) return false;
+ if (property != null)
+ {
+ if (!property.equals(beanComparator.property)) return false;
+ }
+ else
+ {
+ return (beanComparator.property == null);
+ }
+
+ return true;
+ }
+
+ /**
+ * Hashcode compatible with equals.
+ */
+ public int hashCode() {
+ int result;
+ result = comparator.hashCode();
+ return result;
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanMap.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanMap.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanMap.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,803 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.beanutils;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.commons.collections.list.UnmodifiableList;
+import org.apache.commons.collections.keyvalue.AbstractMapEntry;
+import org.apache.commons.collections.set.UnmodifiableSet;
+import org.apache.commons.collections.Transformer;
+
+/**
+ * An implementation of Map for JavaBeans which uses introspection to
+ * get and put properties in the bean.
+ * <p>
+ * If an exception occurs during attempts to get or set a property then the
+ * property is considered non existent in the Map
+ *
+ * @version $Revision: 1.2.2.2 $ $Date: 2004/06/22 21:07:02 $
+ *
+ * @author James Strachan
+ * @author Stephen Colebourne
+ */
+public class BeanMap extends AbstractMap implements Cloneable {
+
+ private transient Object bean;
+
+ private transient HashMap readMethods = new HashMap();
+ private transient HashMap writeMethods = new HashMap();
+ private transient HashMap types = new HashMap();
+
+ /**
+ * An empty array. Used to invoke accessors via reflection.
+ */
+ public static final Object[] NULL_ARGUMENTS = {};
+
+ /**
+ * Maps primitive Class types to transformers. The transformer
+ * transform strings into the appropriate primitive wrapper.
+ */
+ public static HashMap defaultTransformers = new HashMap();
+
+ static {
+ defaultTransformers.put(
+ Boolean.TYPE,
+ new Transformer() {
+ public Object transform( Object input ) {
+ return Boolean.valueOf( input.toString() );
+ }
+ }
+ );
+ defaultTransformers.put(
+ Character.TYPE,
+ new Transformer() {
+ public Object transform( Object input ) {
+ return new Character( input.toString().charAt( 0 ) );
+ }
+ }
+ );
+ defaultTransformers.put(
+ Byte.TYPE,
+ new Transformer() {
+ public Object transform( Object input ) {
+ return Byte.valueOf( input.toString() );
+ }
+ }
+ );
+ defaultTransformers.put(
+ Short.TYPE,
+ new Transformer() {
+ public Object transform( Object input ) {
+ return Short.valueOf( input.toString() );
+ }
+ }
+ );
+ defaultTransformers.put(
+ Integer.TYPE,
+ new Transformer() {
+ public Object transform( Object input ) {
+ return Integer.valueOf( input.toString() );
+ }
+ }
+ );
+ defaultTransformers.put(
+ Long.TYPE,
+ new Transformer() {
+ public Object transform( Object input ) {
+ return Long.valueOf( input.toString() );
+ }
+ }
+ );
+ defaultTransformers.put(
+ Float.TYPE,
+ new Transformer() {
+ public Object transform( Object input ) {
+ return Float.valueOf( input.toString() );
+ }
+ }
+ );
+ defaultTransformers.put(
+ Double.TYPE,
+ new Transformer() {
+ public Object transform( Object input ) {
+ return Double.valueOf( input.toString() );
+ }
+ }
+ );
+ }
+
+
+ // Constructors
+ //-------------------------------------------------------------------------
+
+ /**
+ * Constructs a new empty <code>BeanMap</code>.
+ */
+ public BeanMap() {
+ }
+
+ /**
+ * Constructs a new <code>BeanMap</code> that operates on the
+ * specified bean. If the given bean is <code>null</code>, then
+ * this map will be empty.
+ *
+ * @param bean the bean for this map to operate on
+ */
+ public BeanMap(Object bean) {
+ this.bean = bean;
+ initialise();
+ }
+
+ // Map interface
+ //-------------------------------------------------------------------------
+
+ /**
+ * Renders a string representation of this object.
+ * @return a <code>String</code> representation of this object
+ */
+ public String toString() {
+ return "BeanMap<" + String.valueOf(bean) + ">";
+ }
+
+ /**
+ * Clone this bean map using the following process:
+ *
+ * <ul>
+ * <li>If there is no underlying bean, return a cloned BeanMap without a
+ * bean.
+ *
+ * <li>Since there is an underlying bean, try to instantiate a new bean of
+ * the same type using Class.newInstance().
+ *
+ * <li>If the instantiation fails, throw a CloneNotSupportedException
+ *
+ * <li>Clone the bean map and set the newly instantiated bean as the
+ * underlying bean for the bean map.
+ *
+ * <li>Copy each property that is both readable and writable from the
+ * existing object to a cloned bean map.
+ *
+ * <li>If anything fails along the way, throw a
+ * CloneNotSupportedException.
+ *
+ * <ul>
+ */
+ public Object clone() throws CloneNotSupportedException {
+ BeanMap newMap = (BeanMap)super.clone();
+
+ if(bean == null) {
+ // no bean, just an empty bean map at the moment. return a newly
+ // cloned and empty bean map.
+ return newMap;
+ }
+
+ Object newBean = null;
+ Class beanClass = null;
+ try {
+ beanClass = bean.getClass();
+ newBean = beanClass.newInstance();
+ } catch (Exception e) {
+ // unable to instantiate
+ throw new CloneNotSupportedException
+ ("Unable to instantiate the underlying bean \"" +
+ beanClass.getName() + "\": " + e);
+ }
+
+ try {
+ newMap.setBean(newBean);
+ } catch (Exception exception) {
+ throw new CloneNotSupportedException
+ ("Unable to set bean in the cloned bean map: " +
+ exception);
+ }
+
+ try {
+ // copy only properties that are readable and writable. If its
+ // not readable, we can't get the value from the old map. If
+ // its not writable, we can't write a value into the new map.
+ Iterator readableKeys = readMethods.keySet().iterator();
+ while(readableKeys.hasNext()) {
+ Object key = readableKeys.next();
+ if(getWriteMethod(key) != null) {
+ newMap.put(key, get(key));
+ }
+ }
+ } catch (Exception exception) {
+ throw new CloneNotSupportedException
+ ("Unable to copy bean values to cloned bean map: " +
+ exception);
+ }
+
+ return newMap;
+ }
+
+ /**
+ * Puts all of the writable properties from the given BeanMap into this
+ * BeanMap. Read-only and Write-only properties will be ignored.
+ *
+ * @param map the BeanMap whose properties to put
+ */
+ public void putAllWriteable(BeanMap map) {
+ Iterator readableKeys = map.readMethods.keySet().iterator();
+ while (readableKeys.hasNext()) {
+ Object key = readableKeys.next();
+ if (getWriteMethod(key) != null) {
+ this.put(key, map.get(key));
+ }
+ }
+ }
+
+
+ /**
+ * This method reinitializes the bean map to have default values for the
+ * bean's properties. This is accomplished by constructing a new instance
+ * of the bean which the map uses as its underlying data source. This
+ * behavior for <code>clear()</code> differs from the Map contract in that
+ * the mappings are not actually removed from the map (the mappings for a
+ * BeanMap are fixed).
+ */
+ public void clear() {
+ if(bean == null) return;
+
+ Class beanClass = null;
+ try {
+ beanClass = bean.getClass();
+ bean = beanClass.newInstance();
+ }
+ catch (Exception e) {
+ throw new UnsupportedOperationException( "Could not create new instance of class: " + beanClass );
+ }
+ }
+
+ /**
+ * Returns true if the bean defines a property with the given name.
+ * <p>
+ * The given name must be a <code>String</code>; if not, this method
+ * returns false. This method will also return false if the bean
+ * does not define a property with that name.
+ * <p>
+ * Write-only properties will not be matched as the test operates against
+ * property read methods.
+ *
+ * @param name the name of the property to check
+ * @return false if the given name is null or is not a <code>String</code>;
+ * false if the bean does not define a property with that name; or
+ * true if the bean does define a property with that name
+ */
+ public boolean containsKey(Object name) {
+ Method method = getReadMethod(name);
+ return method != null;
+ }
+
+ /**
+ * Returns true if the bean defines a property whose current value is
+ * the given object.
+ *
+ * @param value the value to check
+ * @return false true if the bean has at least one property whose
+ * current value is that object, false otherwise
+ */
+ public boolean containsValue(Object value) {
+ // use default implementation
+ return super.containsValue(value);
+ }
+
+ /**
+ * Returns the value of the bean's property with the given name.
+ * <p>
+ * The given name must be a {@link String} and must not be
+ * null; otherwise, this method returns <code>null</code>.
+ * If the bean defines a property with the given name, the value of
+ * that property is returned. Otherwise, <code>null</code> is
+ * returned.
+ * <p>
+ * Write-only properties will not be matched as the test operates against
+ * property read methods.
+ *
+ * @param name the name of the property whose value to return
+ * @return the value of the property with that name
+ */
+ public Object get(Object name) {
+ if ( bean != null ) {
+ Method method = getReadMethod( name );
+ if ( method != null ) {
+ try {
+ return method.invoke( bean, NULL_ARGUMENTS );
+ }
+ catch ( IllegalAccessException e ) {
+ logWarn( e );
+ }
+ catch ( IllegalArgumentException e ) {
+ logWarn( e );
+ }
+ catch ( InvocationTargetException e ) {
+ logWarn( e );
+ }
+ catch ( NullPointerException e ) {
+ logWarn( e );
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Sets the bean property with the given name to the given value.
+ *
+ * @param name the name of the property to set
+ * @param value the value to set that property to
+ * @return the previous value of that property
+ * @throws IllegalArgumentException if the given name is null;
+ * if the given name is not a {@link String}; if the bean doesn't
+ * define a property with that name; or if the bean property with
+ * that name is read-only
+ */
+ public Object put(Object name, Object value) throws IllegalArgumentException, ClassCastException {
+ if ( bean != null ) {
+ Object oldValue = get( name );
+ Method method = getWriteMethod( name );
+ if ( method == null ) {
+ throw new IllegalArgumentException( "The bean of type: "+ bean.getClass().getName() + " has no property called: " + name );
+ }
+ try {
+ Object[] arguments = createWriteMethodArguments( method, value );
+ method.invoke( bean, arguments );
+
+ Object newValue = get( name );
+ firePropertyChange( name, oldValue, newValue );
+ }
+ catch ( InvocationTargetException e ) {
+ logInfo( e );
+ throw new IllegalArgumentException( e.getMessage() );
+ }
+ catch ( IllegalAccessException e ) {
+ logInfo( e );
+ throw new IllegalArgumentException( e.getMessage() );
+ }
+ return oldValue;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the number of properties defined by the bean.
+ *
+ * @return the number of properties defined by the bean
+ */
+ public int size() {
+ return readMethods.size();
+ }
+
+
+ /**
+ * Get the keys for this BeanMap.
+ * <p>
+ * Write-only properties are <b>not</b> included in the returned set of
+ * property names, although it is possible to set their value and to get
+ * their type.
+ *
+ * @return BeanMap keys. The Set returned by this method is not
+ * modifiable.
+ */
+ public Set keySet() {
+ return UnmodifiableSet.decorate(readMethods.keySet());
+ }
+
+ /**
+ * Gets a Set of MapEntry objects that are the mappings for this BeanMap.
+ * <p>
+ * Each MapEntry can be set but not removed.
+ *
+ * @return the unmodifiable set of mappings
+ */
+ public Set entrySet() {
+ return UnmodifiableSet.decorate(new AbstractSet() {
+ public Iterator iterator() {
+ return entryIterator();
+ }
+ public int size() {
+ return BeanMap.this.readMethods.size();
+ }
+ });
+ }
+
+ /**
+ * Returns the values for the BeanMap.
+ *
+ * @return values for the BeanMap. The returned collection is not
+ * modifiable.
+ */
+ public Collection values() {
+ ArrayList answer = new ArrayList( readMethods.size() );
+ for ( Iterator iter = valueIterator(); iter.hasNext(); ) {
+ answer.add( iter.next() );
+ }
+ return UnmodifiableList.decorate(answer);
+ }
+
+
+ // Helper methods
+ //-------------------------------------------------------------------------
+
+ /**
+ * Returns the type of the property with the given name.
+ *
+ * @param name the name of the property
+ * @return the type of the property, or <code>null</code> if no such
+ * property exists
+ */
+ public Class getType(String name) {
+ return (Class) types.get( name );
+ }
+
+ /**
+ * Convenience method for getting an iterator over the keys.
+ * <p>
+ * Write-only properties will not be returned in the iterator.
+ *
+ * @return an iterator over the keys
+ */
+ public Iterator keyIterator() {
+ return readMethods.keySet().iterator();
+ }
+
+ /**
+ * Convenience method for getting an iterator over the values.
+ *
+ * @return an iterator over the values
+ */
+ public Iterator valueIterator() {
+ final Iterator iter = keyIterator();
+ return new Iterator() {
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+ public Object next() {
+ Object key = iter.next();
+ return get(key);
+ }
+ public void remove() {
+ throw new UnsupportedOperationException( "remove() not supported for BeanMap" );
+ }
+ };
+ }
+
+ /**
+ * Convenience method for getting an iterator over the entries.
+ *
+ * @return an iterator over the entries
+ */
+ public Iterator entryIterator() {
+ final Iterator iter = keyIterator();
+ return new Iterator() {
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+ public Object next() {
+ Object key = iter.next();
+ Object value = get(key);
+ return new Entry( BeanMap.this, key, value );
+ }
+ public void remove() {
+ throw new UnsupportedOperationException( "remove() not supported for BeanMap" );
+ }
+ };
+ }
+
+
+ // Properties
+ //-------------------------------------------------------------------------
+
+ /**
+ * Returns the bean currently being operated on. The return value may
+ * be null if this map is empty.
+ *
+ * @return the bean being operated on by this map
+ */
+ public Object getBean() {
+ return bean;
+ }
+
+ /**
+ * Sets the bean to be operated on by this map. The given value may
+ * be null, in which case this map will be empty.
+ *
+ * @param newBean the new bean to operate on
+ */
+ public void setBean( Object newBean ) {
+ bean = newBean;
+ reinitialise();
+ }
+
+ /**
+ * Returns the accessor for the property with the given name.
+ *
+ * @param name the name of the property
+ * @return the accessor method for the property, or null
+ */
+ public Method getReadMethod(String name) {
+ return (Method) readMethods.get(name);
+ }
+
+ /**
+ * Returns the mutator for the property with the given name.
+ *
+ * @param name the name of the property
+ * @return the mutator method for the property, or null
+ */
+ public Method getWriteMethod(String name) {
+ return (Method) writeMethods.get(name);
+ }
+
+
+ // Implementation methods
+ //-------------------------------------------------------------------------
+
+ /**
+ * Returns the accessor for the property with the given name.
+ *
+ * @param name the name of the property
+ * @return null if the name is null; null if the name is not a
+ * {@link String}; null if no such property exists; or the accessor
+ * method for that property
+ */
+ protected Method getReadMethod( Object name ) {
+ return (Method) readMethods.get( name );
+ }
+
+ /**
+ * Returns the mutator for the property with the given name.
+ *
+ * @param name the name of the
+ * @return null if the name is null; null if the name is not a
+ * {@link String}; null if no such property exists; null if the
+ * property is read-only; or the mutator method for that property
+ */
+ protected Method getWriteMethod( Object name ) {
+ return (Method) writeMethods.get( name );
+ }
+
+ /**
+ * Reinitializes this bean. Called during {@link #setBean(Object)}.
+ * Does introspection to find properties.
+ */
+ protected void reinitialise() {
+ readMethods.clear();
+ writeMethods.clear();
+ types.clear();
+ initialise();
+ }
+
+ private void initialise() {
+ if(getBean() == null) return;
+
+ Class beanClass = getBean().getClass();
+ try {
+ //BeanInfo beanInfo = Introspector.getBeanInfo( bean, null );
+ BeanInfo beanInfo = Introspector.getBeanInfo( beanClass );
+ PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
+ if ( propertyDescriptors != null ) {
+ for ( int i = 0; i < propertyDescriptors.length; i++ ) {
+ PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
+ if ( propertyDescriptor != null ) {
+ String name = propertyDescriptor.getName();
+ Method readMethod = propertyDescriptor.getReadMethod();
+ Method writeMethod = propertyDescriptor.getWriteMethod();
+ Class aType = propertyDescriptor.getPropertyType();
+
+ if ( readMethod != null ) {
+ readMethods.put( name, readMethod );
+ }
+ if ( writeMethods != null ) {
+ writeMethods.put( name, writeMethod );
+ }
+ types.put( name, aType );
+ }
+ }
+ }
+ }
+ catch ( IntrospectionException e ) {
+ logWarn( e );
+ }
+ }
+
+ /**
+ * Called during a successful {@link #put(Object,Object)} operation.
+ * Default implementation does nothing. Override to be notified of
+ * property changes in the bean caused by this map.
+ *
+ * @param key the name of the property that changed
+ * @param oldValue the old value for that property
+ * @param newValue the new value for that property
+ */
+ protected void firePropertyChange( Object key, Object oldValue, Object newValue ) {
+ }
+
+ // Implementation classes
+ //-------------------------------------------------------------------------
+
+ /**
+ * Map entry used by {@link BeanMap}.
+ */
+ protected static class Entry extends AbstractMapEntry {
+ private BeanMap owner;
+
+ /**
+ * Constructs a new <code>Entry</code>.
+ *
+ * @param owner the BeanMap this entry belongs to
+ * @param key the key for this entry
+ * @param value the value for this entry
+ */
+ protected Entry( BeanMap owner, Object key, Object value ) {
+ super( key, value );
+ this.owner = owner;
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value the new value for the entry
+ * @return the old value for the entry
+ */
+ public Object setValue(Object value) {
+ Object key = getKey();
+ Object oldValue = owner.get( key );
+
+ owner.put( key, value );
+ Object newValue = owner.get( key );
+ super.setValue( newValue );
+ return oldValue;
+ }
+ }
+
+ /**
+ * Creates an array of parameters to pass to the given mutator method.
+ * If the given object is not the right type to pass to the method
+ * directly, it will be converted using {@link #convertType(Class,Object)}.
+ *
+ * @param method the mutator method
+ * @param value the value to pass to the mutator method
+ * @return an array containing one object that is either the given value
+ * or a transformed value
+ * @throws IllegalAccessException if {@link #convertType(Class,Object)}
+ * raises it
+ * @throws IllegalArgumentException if any other exception is raised
+ * by {@link #convertType(Class,Object)}
+ */
+ protected Object[] createWriteMethodArguments( Method method, Object value ) throws IllegalAccessException, ClassCastException {
+ try {
+ if ( value != null ) {
+ Class[] types = method.getParameterTypes();
+ if ( types != null && types.length > 0 ) {
+ Class paramType = types[0];
+ if ( ! paramType.isAssignableFrom( value.getClass() ) ) {
+ value = convertType( paramType, value );
+ }
+ }
+ }
+ Object[] answer = { value };
+ return answer;
+ }
+ catch ( InvocationTargetException e ) {
+ logInfo( e );
+ throw new IllegalArgumentException( e.getMessage() );
+ }
+ catch ( InstantiationException e ) {
+ logInfo( e );
+ throw new IllegalArgumentException( e.getMessage() );
+ }
+ }
+
+ /**
+ * Converts the given value to the given type. First, reflection is
+ * is used to find a public constructor declared by the given class
+ * that takes one argument, which must be the precise type of the
+ * given value. If such a constructor is found, a new object is
+ * created by passing the given value to that constructor, and the
+ * newly constructed object is returned.<P>
+ *
+ * If no such constructor exists, and the given type is a primitive
+ * type, then the given value is converted to a string using its
+ * {@link Object#toString() toString()} method, and that string is
+ * parsed into the correct primitive type using, for instance,
+ * {@link Integer#valueOf(String)} to convert the string into an
+ * <code>int</code>.<P>
+ *
+ * If no special constructor exists and the given type is not a
+ * primitive type, this method returns the original value.
+ *
+ * @param newType the type to convert the value to
+ * @param value the value to convert
+ * @return the converted value
+ * @throws NumberFormatException if newType is a primitive type, and
+ * the string representation of the given value cannot be converted
+ * to that type
+ * @throws InstantiationException if the constructor found with
+ * reflection raises it
+ * @throws InvocationTargetException if the constructor found with
+ * reflection raises it
+ * @throws IllegalAccessException never
+ * @throws IllegalArgumentException never
+ */
+ protected Object convertType( Class newType, Object value )
+ throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+
+ // try call constructor
+ Class[] types = { value.getClass() };
+ try {
+ Constructor constructor = newType.getConstructor( types );
+ Object[] arguments = { value };
+ return constructor.newInstance( arguments );
+ }
+ catch ( NoSuchMethodException e ) {
+ // try using the transformers
+ Transformer transformer = getTypeTransformer( newType );
+ if ( transformer != null ) {
+ return transformer.transform( value );
+ }
+ return value;
+ }
+ }
+
+ /**
+ * Returns a transformer for the given primitive type.
+ *
+ * @param aType the primitive type whose transformer to return
+ * @return a transformer that will convert strings into that type,
+ * or null if the given type is not a primitive type
+ */
+ protected Transformer getTypeTransformer( Class aType ) {
+ return (Transformer) defaultTransformers.get( aType );
+ }
+
+ /**
+ * Logs the given exception to <code>System.out</code>. Used to display
+ * warnings while accessing/mutating the bean.
+ *
+ * @param ex the exception to log
+ */
+ protected void logInfo(Exception ex) {
+ // Deliberately do not use LOG4J or Commons Logging to avoid dependencies
+ System.out.println( "INFO: Exception: " + ex );
+ }
+
+ /**
+ * Logs the given exception to <code>System.err</code>. Used to display
+ * errors while accessing/mutating the bean.
+ *
+ * @param ex the exception to log
+ */
+ protected void logWarn(Exception ex) {
+ // Deliberately do not use LOG4J or Commons Logging to avoid dependencies
+ System.out.println( "WARN: Exception: " + ex );
+ ex.printStackTrace();
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPredicate.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPredicate.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPredicate.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import org.apache.commons.collections.Predicate;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * <p>Predicate implementation that applies the given <code>Predicate</code>
+ * to the result of calling the given property getter.
+ * </p>
+ */
+public class BeanPredicate implements Predicate {
+
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ /** Name of the property whose value will be predicated */
+ private String propertyName;
+ /** <code>Predicate</code> to be applied to the property value */
+ private Predicate predicate;
+
+ /**
+ * Constructs a <code>BeanPredicate</code> that applies the given
+ * <code>Predicate</code> to the named property value.
+ * @param propertyName the name of the property whose value is to be predicated,
+ * not null
+ * @param predicate the <code>Predicate</code> to be applied,
+ * not null
+ */
+ public BeanPredicate(String propertyName, Predicate predicate) {
+ this.propertyName = propertyName;
+ this.predicate = predicate;
+ }
+
+ /**
+ * Evaluates the given object by applying the {@link #getPredicate()}
+ * to a property value named by {@link #getPropertyName()}.
+ * @throws IllegalAccessException when the property cannot be evaluated
+ */
+ public boolean evaluate(Object object) {
+
+ boolean evaluation = false;
+
+ try {
+ Object propValue = PropertyUtils.getProperty( object, propertyName );
+ evaluation = predicate.evaluate(propValue);
+ } catch (IllegalArgumentException e) {
+ final String errorMsg = "Problem during evaluation.";
+ log.error("ERROR: " + errorMsg, e);
+ throw e;
+ } catch (IllegalAccessException e) {
+ final String errorMsg = "Unable to access the property provided.";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ } catch (InvocationTargetException e) {
+ final String errorMsg = "Exception occurred in property's getter";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ } catch (NoSuchMethodException e) {
+ final String errorMsg = "Property not found.";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ }
+
+ return evaluation;
+ }
+
+ /**
+ * Gets the name of the property whose value is to be predicated.
+ * in the evaluation.
+ * @return the property name, not null
+ */
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Sets the name of the property whose value is to be predicated.
+ * @param propertyName the name of the property whose value is to be predicated,
+ * not null
+ */
+ public void setPropertyName(String propertyName) {
+ this.propertyName = propertyName;
+ }
+
+ /**
+ * Gets the <code>Predicate</code> to be applied to the value of the named property
+ * during {@link #evaluate}.
+ * @return <code>Predicate</code>, not null
+ */
+ public Predicate getPredicate() {
+ return predicate;
+ }
+
+ /**
+ * Sets the <code>Predicate</code> to be applied to the value of the named property
+ * during {@link evaluate}.
+ * @param predicate <code>Predicate</code>, not null
+ */
+ public void setPredicate(Predicate predicate) {
+ this.predicate = predicate;
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPropertyValueChangeClosure.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPropertyValueChangeClosure.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPropertyValueChangeClosure.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import org.apache.commons.collections.Closure;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.lang.reflect.InvocationTargetException;
+
+
+/**
+ * <p><code>Closure</code> that sets a property.</p>
+ * <p>
+ * An implementation of <code>org.apache.commons.collections.Closure</code> that updates
+ * a specified property on the object provided with a specified value.
+ * The <code>BeanPropertyValueChangeClosure</code> constructor takes two parameters which determine
+ * what property will be updated and with what value.
+ * <dl>
+ * <dt>
+ * <b><code><pre>public BeanPropertyValueChangeClosure( String propertyName, Object propertyValue )</pre></code></b>
+ * </dt>
+ * <dd>
+ * Will create a <code>Closure</code> that will update an object by setting the property
+ * specified by <code>propertyName</code> to the value specified by <code>propertyValue</code>.
+ * </dd>
+ * </dl>
+ *
+ * <p/>
+ * <strong>Note:</strong> Property names can be a simple, nested, indexed, or mapped property as defined by
+ * <code>org.apache.commons.beanutils.PropertyUtils</code>. If any object in the property path
+ * specified by <code>propertyName</code> is <code>null</code> then the outcome is based on the
+ * value of the <code>ignoreNull</code> attribute.
+ *
+ * <p/>
+ * A typical usage might look like:
+ * <code><pre>
+ * // create the closure
+ * BeanPropertyValueChangeClosure closure =
+ * new BeanPropertyValueChangeClosure( "activeEmployee", Boolean.TRUE );
+ *
+ * // update the Collection
+ * CollectionUtils.forAllDo( peopleCollection, closure );
+ * </pre></code>
+ * <p/>
+ *
+ * This would take a <code>Collection</code> of person objects and update the
+ * <code>activeEmployee</code> property of each object in the <code>Collection</code> to
+ * <code>true</code>. Assuming...
+ * <ul>
+ * <li>
+ * The top level object in the <code>peopleCollection</code> is an object which represents a
+ * person.
+ * </li>
+ * <li>
+ * The person object has a <code>setActiveEmployee( boolean )</code> method which updates
+ * the value for the object's <code>activeEmployee</code> property.
+ * </li>
+ * </ul>
+ *
+ * @author Norm Deane
+ * @see org.apache.commons.beanutils.PropertyUtils
+ * @see org.apache.commons.collections.Closure
+ */
+public class BeanPropertyValueChangeClosure implements Closure {
+
+ /** For logging. */
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ /**
+ * The name of the property which will be updated when this <code>Closure</code> executes.
+ */
+ private String propertyName;
+
+ /**
+ * The value that the property specified by <code>propertyName</code>
+ * will be updated to when this <code>Closure</code> executes.
+ */
+ private Object propertyValue;
+
+ /**
+ * Determines whether <code>null</code> objects in the property path will genenerate an
+ * <code>IllegalArgumentException</code> or not. If set to <code>true</code> then if any objects
+ * in the property path leading up to the target property evaluate to <code>null</code> then the
+ * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged but
+ * not rethrown. If set to <code>false</code> then if any objects in the property path leading
+ * up to the target property evaluate to <code>null</code> then the
+ * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged and
+ * rethrown.
+ */
+ private boolean ignoreNull;
+
+ /**
+ * Constructor which takes the name of the property to be changed, the new value to set
+ * the property to, and assumes <code>ignoreNull</code> to be <code>false</code>.
+ *
+ * @param propertyName The name of the property that will be updated with the value specified by
+ * <code>propertyValue</code>.
+ * @param propertyValue The value that <code>propertyName</code> will be set to on the target
+ * object.
+ * @throws IllegalArgumentException If the propertyName provided is null or empty.
+ */
+ public BeanPropertyValueChangeClosure(String propertyName, Object propertyValue) {
+ this(propertyName, propertyValue, false);
+ }
+
+ /**
+ * Constructor which takes the name of the property to be changed, the new value to set
+ * the property to and a boolean which determines whether <code>null</code> objects in the
+ * property path will genenerate an <code>IllegalArgumentException</code> or not.
+ *
+ * @param propertyName The name of the property that will be updated with the value specified by
+ * <code>propertyValue</code>.
+ * @param propertyValue The value that <code>propertyName</code> will be set to on the target
+ * object.
+ * @param ignoreNull Determines whether <code>null</code> objects in the property path will
+ * genenerate an <code>IllegalArgumentException</code> or not.
+ * @throws IllegalArgumentException If the propertyName provided is null or empty.
+ */
+ public BeanPropertyValueChangeClosure(String propertyName, Object propertyValue, boolean ignoreNull) {
+ super();
+
+ if ((propertyName != null) && (propertyName.length() > 0)) {
+ this.propertyName = propertyName;
+ this.propertyValue = propertyValue;
+ this.ignoreNull = ignoreNull;
+ } else {
+ throw new IllegalArgumentException("propertyName cannot be null or empty");
+ }
+ }
+
+ /**
+ * Updates the target object provided using the property update criteria provided when this
+ * <code>BeanPropertyValueChangeClosure</code> was constructed. If any object in the property
+ * path leading up to the target property is <code>null</code> then the outcome will be based on
+ * the value of the <code>ignoreNull</code> attribute. By default, <code>ignoreNull</code> is
+ * <code>false</code> and would result in an <code>IllegalArgumentException</code> if an object
+ * in the property path leading up to the target property is <code>null</code>.
+ *
+ * @param object The object to be updated.
+ * @throws IllegalArgumentException If an IllegalAccessException, InvocationTargetException, or
+ * NoSuchMethodException is thrown when trying to access the property specified on the object
+ * provided. Or if an object in the property path provided is <code>null</code> and
+ * <code>ignoreNull</code> is set to <code>false</code>.
+ */
+ public void execute(Object object) {
+
+ try {
+ PropertyUtils.setProperty(object, propertyName, propertyValue);
+ } catch (IllegalArgumentException e) {
+ final String errorMsg = "Unable to execute Closure. Null value encountered in property path...";
+
+ if (ignoreNull) {
+ log.warn("WARNING: " + errorMsg, e);
+ } else {
+ log.error("ERROR: " + errorMsg, e);
+ throw e;
+ }
+ } catch (IllegalAccessException e) {
+ final String errorMsg = "Unable to access the property provided.";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ } catch (InvocationTargetException e) {
+ final String errorMsg = "Exception occurred in property's getter";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ } catch (NoSuchMethodException e) {
+ final String errorMsg = "Property not found";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ }
+ }
+
+ /**
+ * Returns the name of the property which will be updated when this <code>Closure</code> executes.
+ *
+ * @return The name of the property which will be updated when this <code>Closure</code> executes.
+ */
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Returns the value that the property specified by <code>propertyName</code>
+ * will be updated to when this <code>Closure</code> executes.
+ *
+ * @return The value that the property specified by <code>propertyName</code>
+ * will be updated to when this <code>Closure</code> executes.
+ */
+ public Object getPropertyValue() {
+ return propertyValue;
+ }
+
+ /**
+ * Returns the flag that determines whether <code>null</code> objects in the property path will
+ * genenerate an <code>IllegalArgumentException</code> or not. If set to <code>true</code> then
+ * if any objects in the property path leading up to the target property evaluate to
+ * <code>null</code> then the <code>IllegalArgumentException</code> throw by
+ * <code>PropertyUtils</code> will be logged but not rethrown. If set to <code>false</code> then
+ * if any objects in the property path leading up to the target property evaluate to
+ * <code>null</code> then the <code>IllegalArgumentException</code> throw by
+ * <code>PropertyUtils</code> will be logged and rethrown.
+ *
+ * @return The flag that determines whether <code>null</code> objects in the property path will
+ * genenerate an <code>IllegalArgumentException</code> or not.
+ */
+ public boolean isIgnoreNull() {
+ return ignoreNull;
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPropertyValueEqualsPredicate.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPropertyValueEqualsPredicate.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanPropertyValueEqualsPredicate.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import org.apache.commons.collections.Predicate;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.lang.reflect.InvocationTargetException;
+
+
+/**
+ * <p><code>Predicate</code> that evaluates a property value against a specified value.</p>
+ * <p>
+ * An implementation of <code>org.apache.commons.collections.Predicate</code> that evaluates a
+ * property value on the object provided against a specified value and returns <code>true</code>
+ * if equal; <code>false</code> otherwise.
+ * The <code>BeanPropertyValueEqualsPredicate</code> constructor takes two parameters which
+ * determine what property will be evaluated on the target object and what its expected value should
+ * be.
+ * <dl>
+ * <dt>
+ * <strong><code><pre>public BeanPropertyValueEqualsPredicate( String propertyName, Object propertyValue )</pre></code></strong>
+ * </dt>
+ * <dd>
+ * Will create a <code>Predicate</code> that will evaluate the target object and return
+ * <code>true</code> if the property specified by <code>propertyName</code> has a value which
+ * is equal to the the value specified by <code>propertyValue</code>. Or return
+ * <code>false</code> otherwise.
+ * </dd>
+ * </dl>
+ * </p>
+ * <p>
+ * <strong>Note:</strong> Property names can be a simple, nested, indexed, or mapped property as defined by
+ * <code>org.apache.commons.beanutils.PropertyUtils</code>. If any object in the property path
+ * specified by <code>propertyName</code> is <code>null</code> then the outcome is based on the
+ * value of the <code>ignoreNull</code> attribute.
+ * </p>
+ * <p>
+ * A typical usage might look like:
+ * <code><pre>
+ * // create the closure
+ * BeanPropertyValueEqualsPredicate predicate =
+ * new BeanPropertyValueEqualsPredicate( "activeEmployee", Boolean.FALSE );
+ *
+ * // filter the Collection
+ * CollectionUtils.filter( peopleCollection, predicate );
+ * </pre></code>
+ * </p>
+ * <p>
+ * This would take a <code>Collection</code> of person objects and filter out any people whose
+ * <code>activeEmployee</code> property is <code>false</code>. Assuming...
+ * <ul>
+ * <li>
+ * The top level object in the <code>peeopleCollection</code> is an object which represents a
+ * person.
+ * </li>
+ * <li>
+ * The person object has a <code>getActiveEmployee()</code> method which returns
+ * the boolean value for the object's <code>activeEmployee</code> property.
+ * </li>
+ * </ul>
+ * </p>
+ * <p>
+ * Another typical usage might look like:
+ * <code><pre>
+ * // create the closure
+ * BeanPropertyValueEqualsPredicate predicate =
+ * new BeanPropertyValueEqualsPredicate( "personId", "456-12-1234" );
+ *
+ * // search the Collection
+ * CollectionUtils.find( peopleCollection, predicate );
+ * </pre><code>
+ * </p>
+ * <p>
+ * This would search a <code>Collection</code> of person objects and return the first object whose
+ * <code>personId</code> property value equals <code>456-12-1234</code>. Assuming...
+ * <ul>
+ * <li>
+ * The top level object in the <code>peeopleCollection</code> is an object which represents a
+ * person.
+ * </li>
+ * <li>
+ * The person object has a <code>getPersonId()</code> method which returns
+ * the value for the object's <code>personId</code> property.
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @author Norm Deane
+ * @see org.apache.commons.beanutils.PropertyUtils
+ * @see org.apache.commons.collections.Predicate
+ */
+public class BeanPropertyValueEqualsPredicate implements Predicate {
+
+ /** For logging. */
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ /**
+ * The name of the property which will be evaluated when this <code>Predicate</code> is executed.
+ */
+ private String propertyName;
+
+ /**
+ * The value that the property specified by <code>propertyName</code>
+ * will be compared to when this <code>Predicate</code> executes.
+ */
+ private Object propertyValue;
+
+ /**
+ * <p>Should <code>null</code> objects in the property path be ignored?</p>
+ * <p>
+ * Determines whether <code>null</code> objects in the property path will genenerate an
+ * <code>IllegalArgumentException</code> or not. If set to <code>true</code> then if any objects
+ * in the property path evaluate to <code>null</code> then the
+ * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged but
+ * not rethrown and <code>false</code> will be returned. If set to <code>false</code> then if
+ * any objects in the property path evaluate to <code>null</code> then the
+ * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged and
+ * rethrown.
+ * </p>
+ */
+ private boolean ignoreNull;
+
+ /**
+ * Constructor which takes the name of the property, its expected value to be used in evaluation,
+ * and assumes <code>ignoreNull</code> to be <code>false</code>.
+ *
+ * @param propertyName The name of the property that will be evaluated against the expected value.
+ * @param propertyValue The value to use in object evaluation.
+ * @throws IllegalArgumentException If the property name provided is null or empty.
+ */
+ public BeanPropertyValueEqualsPredicate(String propertyName, Object propertyValue) {
+ this(propertyName, propertyValue, false);
+ }
+
+ /**
+ * Constructor which takes the name of the property, its expected value
+ * to be used in evaluation, and a boolean which determines whether <code>null</code> objects in
+ * the property path will genenerate an <code>IllegalArgumentException</code> or not.
+ *
+ * @param propertyName The name of the property that will be evaluated against the expected value.
+ * @param propertyValue The value to use in object evaluation.
+ * @param ignoreNull Determines whether <code>null</code> objects in the property path will
+ * genenerate an <code>IllegalArgumentException</code> or not.
+ * @throws IllegalArgumentException If the property name provided is null or empty.
+ */
+ public BeanPropertyValueEqualsPredicate(String propertyName, Object propertyValue, boolean ignoreNull) {
+ super();
+
+ if ((propertyName != null) && (propertyName.length() > 0)) {
+ this.propertyName = propertyName;
+ this.propertyValue = propertyValue;
+ this.ignoreNull = ignoreNull;
+ } else {
+ throw new IllegalArgumentException("propertyName cannot be null or empty");
+ }
+ }
+
+ /**
+ * Evaulates the object provided against the criteria specified when this
+ * <code>BeanPropertyValueEqualsPredicate</code> was constructed. Equality is based on
+ * either reference or logical equality as defined by the property object's equals method. If
+ * any object in the property path leading up to the target property is <code>null</code> then
+ * the outcome will be based on the value of the <code>ignoreNull</code> attribute. By default,
+ * <code>ignoreNull</code> is <code>false</code> and would result in an
+ * <code>IllegalArgumentException</code> if an object in the property path leading up to the
+ * target property is <code>null</code>.
+ *
+ * @param object The object to be evaluated.
+ * @return True if the object provided meets all the criteria for this <code>Predicate</code>;
+ * false otherwise.
+ * @throws IllegalArgumentException If an IllegalAccessException, InvocationTargetException, or
+ * NoSuchMethodException is thrown when trying to access the property specified on the object
+ * provided. Or if an object in the property path provided is <code>null</code> and
+ * <code>ignoreNull</code> is set to <code>false</code>.
+ */
+ public boolean evaluate(Object object) {
+
+ boolean evaluation = false;
+
+ try {
+ evaluation = evaluateValue(propertyValue,
+ PropertyUtils.getProperty(object, propertyName));
+ } catch (IllegalArgumentException e) {
+ final String errorMsg = "Problem during evaluation. Null value encountered in property path...";
+
+ if (ignoreNull) {
+ log.warn("WARNING: " + errorMsg, e);
+ } else {
+ log.error("ERROR: " + errorMsg, e);
+ throw e;
+ }
+ } catch (IllegalAccessException e) {
+ final String errorMsg = "Unable to access the property provided.";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ } catch (InvocationTargetException e) {
+ final String errorMsg = "Exception occurred in property's getter";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ } catch (NoSuchMethodException e) {
+ final String errorMsg = "Property not found.";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ }
+
+ return evaluation;
+ }
+
+ /**
+ * Utility method which evaluates whether the actual property value equals the expected property
+ * value.
+ *
+ * @param expected The expected value.
+ * @param actual The actual value.
+ * @return True if they are equal; false otherwise.
+ */
+ private boolean evaluateValue(Object expected, Object actual) {
+ return (expected == actual) || ((expected != null) && expected.equals(actual));
+ }
+
+ /**
+ * Returns the name of the property which will be evaluated when this <code>Predicate</code> is
+ * executed.
+ *
+ * @return The name of the property which will be evaluated when this <code>Predicate</code> is
+ * executed.
+ */
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Returns the value that the property specified by <code>propertyName</code> will be compared to
+ * when this <code>Predicate</code> executes.
+ *
+ * @return The value that the property specified by <code>propertyName</code> will be compared to
+ * when this <code>Predicate</code> executes.
+ */
+ public Object getPropertyValue() {
+ return propertyValue;
+ }
+
+ /**
+ * Returns the flag which determines whether <code>null</code> objects in the property path will
+ * genenerate an <code>IllegalArgumentException</code> or not. If set to <code>true</code> then
+ * if any objects in the property path evaluate to <code>null</code> then the
+ * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged but
+ * not rethrown and <code>false</code> will be returned. If set to <code>false</code> then if
+ * any objects in the property path evaluate to <code>null</code> then the
+ * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged and
+ * rethrown.
+ *
+ * @return The flag which determines whether <code>null</code> objects in the property path will
+ * genenerate an <code>IllegalArgumentException</code> or not.
+ */
+ public boolean isIgnoreNull() {
+ return ignoreNull;
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanToPropertyValueTransformer.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanToPropertyValueTransformer.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/org/apache/commons/beanutils/BeanToPropertyValueTransformer.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import org.apache.commons.collections.Transformer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.lang.reflect.InvocationTargetException;
+
+
+/**
+ * <p><code>Transformer</code> that outputs a property value.</p>
+ *
+ * <p>An implementation of <code>org.apache.commons.collections.Transformer</code> that transforms
+ * the object provided by returning the value of a specified property of the object. The
+ * constructor for <code>BeanToPropertyValueTransformer</code> requires the name of the property
+ * that will be used in the transformation. The property can be a simple, nested, indexed, or
+ * mapped property as defined by <code>org.apache.commons.beanutils.PropertyUtils</code>. If any
+ * object in the property path specified by <code>propertyName</code> is <code>null</code> then the
+ * outcome is based on the value of the <code>ignoreNull</code> attribute.
+ * </p>
+ *
+ * <p>
+ * A typical usage might look like:
+ * <code><pre>
+ * // create the transformer
+ * BeanToPropertyValueTransformer transformer = new BeanToPropertyValueTransformer( "person.address.city" );
+ *
+ * // transform the Collection
+ * Collection peoplesCities = CollectionUtils.collect( peopleCollection, transformer );
+ * </pre></code>
+ * </p>
+ *
+ * <p>
+ * This would take a <code>Collection</code> of person objects and return a <code>Collection</code>
+ * of objects which represents the cities in which each person lived. Assuming...
+ * <ul>
+ * <li>
+ * The top level object in the <code>peeopleCollection</code> is an object which represents a
+ * person.
+ * </li>
+ * <li>
+ * The person object has a <code>getAddress()</code> method which returns an object which
+ * represents a person's address.
+ * </li>
+ * <li>
+ * The address object has a <code>getCity()</code> method which returns an object which
+ * represents the city in which a person lives.
+ * </li>
+ * </ul>
+ *
+ * @author Norm Deane
+ * @see org.apache.commons.beanutils.PropertyUtils
+ * @see org.apache.commons.collections.Transformer
+ */
+public class BeanToPropertyValueTransformer implements Transformer {
+
+ /** For logging. */
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ /** The name of the property that will be used in the transformation of the object. */
+ private String propertyName;
+
+ /**
+ * <p>Should null objects on the property path throw an <code>IllegalArgumentException</code>?</p>
+ * <p>
+ * Determines whether <code>null</code> objects in the property path will genenerate an
+ * <code>IllegalArgumentException</code> or not. If set to <code>true</code> then if any objects
+ * in the property path evaluate to <code>null</code> then the
+ * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged but
+ * not rethrown and <code>null</code> will be returned. If set to <code>false</code> then if any
+ * objects in the property path evaluate to <code>null</code> then the
+ * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged and
+ * rethrown.
+ * </p>
+ */
+ private boolean ignoreNull;
+
+ /**
+ * Constructs a Transformer which does not ignore nulls.
+ * Constructor which takes the name of the property that will be used in the transformation and
+ * assumes <code>ignoreNull</code> to be <code>false</code>.
+ *
+ * @param propertyName The name of the property that will be used in the transformation.
+ * @throws IllegalArgumentException If the <code>propertyName</code> is <code>null</code> or
+ * empty.
+ */
+ public BeanToPropertyValueTransformer(String propertyName) {
+ this(propertyName, false);
+ }
+
+ /**
+ * Constructs a Transformer and sets ignoreNull.
+ * Constructor which takes the name of the property that will be used in the transformation and
+ * a boolean which determines whether <code>null</code> objects in the property path will
+ * genenerate an <code>IllegalArgumentException</code> or not.
+ *
+ * @param propertyName The name of the property that will be used in the transformation.
+ * @param ignoreNull Determines whether <code>null</code> objects in the property path will
+ * genenerate an <code>IllegalArgumentException</code> or not.
+ * @throws IllegalArgumentException If the <code>propertyName</code> is <code>null</code> or
+ * empty.
+ */
+ public BeanToPropertyValueTransformer(String propertyName, boolean ignoreNull) {
+ super();
+
+ if ((propertyName != null) && (propertyName.length() > 0)) {
+ this.propertyName = propertyName;
+ this.ignoreNull = ignoreNull;
+ } else {
+ throw new IllegalArgumentException(
+ "propertyName cannot be null or empty");
+ }
+ }
+
+ /**
+ * Returns the value of the property named in the transformer's constructor for
+ * the object provided. If any object in the property path leading up to the target property is
+ * <code>null</code> then the outcome will be based on the value of the <code>ignoreNull</code>
+ * attribute. By default, <code>ignoreNull</code> is <code>false</code> and would result in an
+ * <code>IllegalArgumentException</code> if an object in the property path leading up to the
+ * target property is <code>null</code>.
+ *
+ * @param object The object to be transformed.
+ * @return The value of the property named in the transformer's constructor for the object
+ * provided.
+ * @throws IllegalArgumentException If an IllegalAccessException, InvocationTargetException, or
+ * NoSuchMethodException is thrown when trying to access the property specified on the object
+ * provided. Or if an object in the property path provided is <code>null</code> and
+ * <code>ignoreNull</code> is set to <code>false</code>.
+ */
+ public Object transform(Object object) {
+
+ Object propertyValue = null;
+
+ try {
+ propertyValue = PropertyUtils.getProperty(object, propertyName);
+ } catch (IllegalArgumentException e) {
+ final String errorMsg = "Problem during transformation. Null value encountered in property path...";
+
+ if (ignoreNull) {
+ log.warn("WARNING: " + errorMsg, e);
+ } else {
+ log.error("ERROR: " + errorMsg, e);
+ throw e;
+ }
+ } catch (IllegalAccessException e) {
+ final String errorMsg = "Unable to access the property provided.";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ } catch (InvocationTargetException e) {
+ final String errorMsg = "Exception occurred in property's getter";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ } catch (NoSuchMethodException e) {
+ final String errorMsg = "No property found for name [" +
+ propertyName + "]";
+ log.error(errorMsg, e);
+ throw new IllegalArgumentException(errorMsg);
+ }
+
+ return propertyValue;
+ }
+
+ /**
+ * Returns the name of the property that will be used in the transformation of the bean.
+ *
+ * @return The name of the property that will be used in the transformation of the bean.
+ */
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Returns the flag which determines whether <code>null</code> objects in the property path will
+ * genenerate an <code>IllegalArgumentException</code> or not. If set to <code>true</code> then
+ * if any objects in the property path evaluate to <code>null</code> then the
+ * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged but
+ * not rethrown and <code>null</code> will be returned. If set to <code>false</code> then if any
+ * objects in the property path evaluate to <code>null</code> then the
+ * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged and
+ * rethrown.
+ *
+ * @return The flag which determines whether <code>null</code> objects in the property path will
+ * genenerate an <code>IllegalArgumentException</code> or not.
+ */
+ public boolean isIgnoreNull() {
+ return ignoreNull;
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/overview.html
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/overview.html 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/java/overview.html 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<title>Overview Documentation for COMMONS-BEANUTILS BEAN COLLECTIONS</title>
+</head>
+<body bgcolor="white">
+<p>The <em>Bean Introspection Utilities</em> component of the Jakarta Commons
+subproject offers low-level utility classes that assist in getting and setting
+property values on Java classes that follow the naming design patterns outlined
+in the JavaBeans Specification, as well as mechanisms for dynamically defining
+and accessing bean properties.</p>
+<p>
+The Bean-Collections optional distribution contains objects which apply these
+techniques to collections. They rely on commons-collections 3.0 (or higher).
+</p>
+
+<p>The documentation for this optional package is included with the core Beanutils
+documentation.</p>
+</body>
+</html>
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/AbstractParent.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/AbstractParent.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/AbstractParent.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+public abstract class AbstractParent {
+
+ private Child child;
+
+ public Child getChild()
+ {
+ return child;
+ }
+
+ /**
+ * Method which matches signature but which has wrong parameters
+ */
+ public String testAddChild(String badParameter) {
+ return null;
+ }
+
+ /**
+ * Method which matches signature but which has wrong parameters
+ */
+ public String testAddChild2(String ignore, String badParameter) {
+ return null;
+ }
+
+ public String testAddChild(Child child) {
+ this.child = child;
+ return child.getName();
+ }
+
+
+ public String testAddChild2(String ignore, Child child) {
+ this.child = child;
+ return child.getName();
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/AlphaBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/AlphaBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/AlphaBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+public class AlphaBean extends AbstractParent implements Child {
+
+ private String name;
+
+ public AlphaBean() {}
+
+ public AlphaBean(String name) {
+ setName(name);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Used for testing that correct exception is thrown.
+ */
+ public void bogus(String badParameter){}
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanCollectionsTestSuite.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanCollectionsTestSuite.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanCollectionsTestSuite.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * <p>Test suite which runs all the test cases application to beans in collections.
+ *
+ * @author <a href="mailto:epugh at upstate.com">Eric Pugh</a>
+ * @version $Revision: 1.2 $
+ */
+
+public class BeanCollectionsTestSuite extends TestCase {
+
+ public BeanCollectionsTestSuite(java.lang.String testName) {
+ super(testName);
+ }
+
+ public static void main(java.lang.String[] args) {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static junit.framework.Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTestSuite(BeanComparatorTestCase.class);
+ suite.addTestSuite(BeanToPropertyValueTransformerTest.class);
+ suite.addTestSuite(BeanPropertyValueEqualsPredicateTest.class);
+ suite.addTestSuite(BeanPropertyValueChangeClosureTest.class);
+ suite.addTestSuite(TestBeanMap.class);
+
+ return suite;
+ }
+}
+
+
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanComparatorTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanComparatorTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanComparatorTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * <p>
+ * Test Case for the BeanComparator class.
+ *
+ * @author <a href="mailto:epugh at upstate.com">Eric Pugh</a>
+ * @version $Revision: 1.1 $
+ */
+
+public class BeanComparatorTestCase extends TestCase {
+
+ // ---------------------------------------------------- Instance Variables
+
+ /**
+ * The test beans for each test.
+ */
+ protected TestBean bean = null;
+ protected AlphaBean alphaBean1 = null;
+ protected AlphaBean alphaBean2 = null;
+
+ // The test BeanComparator
+ protected BeanComparator beanComparator = null;
+
+
+
+
+
+ // ---------------------------------------------------------- Constructors
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public BeanComparatorTestCase(String name) {
+ super(name);
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+ bean = new TestBean();
+ alphaBean1 = new AlphaBean("alphaBean1");
+ alphaBean2 = new AlphaBean("alphaBean2");
+
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(BeanComparatorTestCase.class));
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ bean = null;
+ alphaBean1 = null;
+ alphaBean2 = null;
+ beanComparator = null;
+ }
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ /**
+ * tests comparing two beans via their name using the default Comparator
+ */
+ public void testSimpleCompare() {
+ try {
+ beanComparator = new BeanComparator("name");
+ int result = beanComparator.compare(alphaBean1, alphaBean2);
+ assertTrue("Comparator did not sort properly. Result:" + result,result==-1);
+
+ }
+ catch (Exception e) {
+ fail("Exception");
+ }
+ }
+
+ /**
+ * tests comparing two beans via their name using the default Comparator, but the inverse
+ */
+ public void testSimpleCompareInverse() {
+ try {
+ beanComparator = new BeanComparator("name");
+ int result = beanComparator.compare(alphaBean2, alphaBean1);
+ assertTrue("Comparator did not sort properly. Result:" + result,result==1);
+
+ }
+ catch (Exception e) {
+ fail("Exception" + e);
+ }
+ }
+
+ /**
+ * tests comparing two beans via their name using the default Comparator where they have the same value.
+ */
+ public void testCompareIdentical() {
+ try {
+ alphaBean1 = new AlphaBean("alphabean");
+ alphaBean2 = new AlphaBean("alphabean");
+ beanComparator = new BeanComparator("name");
+ int result = beanComparator.compare(alphaBean1, alphaBean2);
+ assertTrue("Comparator did not sort properly. Result:" + result,result==0);
+
+ }
+ catch (Exception e) {
+ fail("Exception");
+ }
+ }
+
+ /**
+ * tests comparing one bean against itself.
+ */
+ public void testCompareBeanAgainstSelf() {
+ try {
+ beanComparator = new BeanComparator("name");
+ int result = beanComparator.compare(alphaBean1, alphaBean1);
+ assertTrue("Comparator did not sort properly. Result:" + result,result==0);
+
+ }
+ catch (Exception e) {
+ fail("Exception");
+ }
+ }
+
+ /**
+ * tests comparing two beans via their name using the default Comparator, but with one of the beans
+ * being null.
+ */
+ public void testCompareWithNulls() {
+ try {
+ beanComparator = new BeanComparator("name");
+ beanComparator.compare(alphaBean2, null);
+
+ // DEP not sure if this is the best way to test an exception?
+ fail("Should not be able to compare a null value.");
+
+ }
+ catch (Exception e) {
+
+ }
+ }
+
+ /**
+ * tests comparing two beans who don't have a property
+ */
+ public void testCompareOnMissingProperty() {
+ try {
+ beanComparator = new BeanComparator("bogusName");
+ beanComparator.compare(alphaBean2, alphaBean1);
+ fail("should not be able to compare");
+
+
+ }
+ catch (ClassCastException cce){
+ assertTrue("Wrong exception was thrown.",cce.toString().indexOf("Unknown property") > -1);
+ }
+ catch (Exception e) {
+ fail("Exception" + e);
+ }
+ }
+
+ /**
+ * tests comparing two beans on a boolean property, which is not possible.
+ */
+ public void testCompareOnBooleanProperty() {
+ try {
+ TestBean testBeanA = new TestBean();
+ TestBean testBeanB = new TestBean();
+
+ testBeanA.setBooleanProperty(true);
+ testBeanB.setBooleanProperty(false);
+
+ beanComparator = new BeanComparator("booleanProperty");
+ beanComparator.compare(testBeanA, testBeanB);
+
+ fail("BeanComparator should throw an exception when comparing two booleans.");
+
+ }
+ catch (ClassCastException cce){
+ ; // Expected result
+ }
+ catch (Exception e) {
+ fail("Exception" + e);
+ }
+ }
+
+ /**
+ * tests comparing two beans on a boolean property, then changing the property and testing
+ */
+ public void testSetProperty() {
+ try {
+ TestBean testBeanA = new TestBean();
+ TestBean testBeanB = new TestBean();
+
+ testBeanA.setDoubleProperty(5.5);
+ testBeanB.setDoubleProperty(1.0);
+
+ beanComparator = new BeanComparator("doubleProperty");
+ int result = beanComparator.compare(testBeanA, testBeanB);
+
+ assertTrue("Comparator did not sort properly. Result:" + result,result==1);
+
+ testBeanA.setStringProperty("string 1");
+ testBeanB.setStringProperty("string 2");
+
+ beanComparator.setProperty("stringProperty");
+
+ result = beanComparator.compare(testBeanA, testBeanB);
+
+ assertTrue("Comparator did not sort properly. Result:" + result,result==-1);
+
+ }
+ catch (ClassCastException cce){
+ fail("ClassCaseException " + cce.toString());
+ }
+ catch (Exception e) {
+ fail("Exception" + e);
+ }
+ }
+}
+
+
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPredicateTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPredicateTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPredicateTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.collections.functors.EqualPredicate;
+import org.apache.commons.collections.functors.InstanceofPredicate;
+import org.apache.commons.collections.functors.NotPredicate;
+import org.apache.commons.collections.functors.NullPredicate;
+
+public class BeanPredicateTestCase extends TestCase {
+
+ public BeanPredicateTestCase(String name) {
+ super(name);
+ }
+
+ public void testEqual() {
+ BeanPredicate predicate =
+ new BeanPredicate("stringProperty",new EqualPredicate("foo"));
+ assertTrue(predicate.evaluate(new TestBean("foo")));
+ assertTrue(!predicate.evaluate(new TestBean("bar")));
+ }
+
+ public void testNotEqual() {
+ BeanPredicate predicate =
+ new BeanPredicate("stringProperty",new NotPredicate( new EqualPredicate("foo")));
+ assertTrue(!predicate.evaluate(new TestBean("foo")));
+ assertTrue(predicate.evaluate(new TestBean("bar")));
+ }
+
+ public void testInstanceOf() {
+ BeanPredicate predicate =
+ new BeanPredicate("stringProperty",new InstanceofPredicate( String.class ));
+ assertTrue(predicate.evaluate(new TestBean("foo")));
+ assertTrue(predicate.evaluate(new TestBean("bar")));
+ }
+
+ public void testNull() {
+ BeanPredicate predicate =
+ new BeanPredicate("stringProperty", NullPredicate.INSTANCE);
+ String nullString = null;
+ assertTrue(predicate.evaluate(new TestBean(nullString)));
+ assertTrue(!predicate.evaluate(new TestBean("bar")));
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPropertyValueChangeClosureTest.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPropertyValueChangeClosureTest.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPropertyValueChangeClosureTest.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Test cases for <code>BeanPropertyValueChangeClosure</code>.
+ *
+ * @author Norm Deane
+ */
+public class BeanPropertyValueChangeClosureTest extends TestCase {
+
+ private static final Integer expectedIntegerValue = new Integer(123);
+ private static final Float expectedFloatValue = new Float(123.123f);
+ private static final Double expectedDoubleValue = new Double(567879.12344d);
+ private static final Boolean expectedBooleanValue = Boolean.TRUE;
+ private static final Byte expectedByteValue = new Byte("12");
+
+ /**
+ * Constructor for BeanPropertyValueChangeClosureTest.
+ *
+ * @param name Name of this test case.
+ */
+ public BeanPropertyValueChangeClosureTest(String name) {
+ super(name);
+ }
+
+ /**
+ * Test execute with simple float property and Float value.
+ */
+ public void testExecuteWithSimpleFloatPropertyAndFloatValue() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("floatProperty", expectedFloatValue).execute(testBean);
+ assertTrue(expectedFloatValue.floatValue() == testBean.getFloatProperty());
+ }
+
+ /**
+ * Test execute with simple float property and String value.
+ */
+ public void testExecuteWithSimpleFloatPropertyAndStringValue() {
+ try {
+ new BeanPropertyValueChangeClosure("floatProperty", "123").execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with simple float property and Double value.
+ */
+ public void testExecuteWithSimpleFloatPropertyAndDoubleValue() {
+ try {
+ new BeanPropertyValueChangeClosure("floatProperty", expectedDoubleValue).execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with simple float property and Integer value.
+ */
+ public void testExecuteWithSimpleFloatPropertyAndIntegerValue() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("floatProperty", expectedIntegerValue).execute(testBean);
+ assertTrue(expectedIntegerValue.floatValue() == testBean.getFloatProperty());
+ }
+
+ /**
+ * Test execute with simple double property and Double value.
+ */
+ public void testExecuteWithSimpleDoublePropertyAndDoubleValue() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("doubleProperty", expectedDoubleValue).execute(testBean);
+ assertTrue(expectedDoubleValue.doubleValue() == testBean.getDoubleProperty());
+ }
+
+ /**
+ * Test execute with simple double property and String value.
+ */
+ public void testExecuteWithSimpleDoublePropertyAndStringValue() {
+ try {
+ new BeanPropertyValueChangeClosure("doubleProperty", "123").execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with simple double property and Float value.
+ */
+ public void testExecuteWithSimpleDoublePropertyAndFloatValue() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("doubleProperty", expectedFloatValue).execute(testBean);
+ assertTrue(expectedFloatValue.doubleValue() == testBean.getDoubleProperty());
+ }
+
+ /**
+ * Test execute with simple double property and Integer value.
+ */
+ public void testExecuteWithSimpleDoublePropertyAndIntegerValue() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("doubleProperty", expectedIntegerValue).execute(testBean);
+ assertTrue(expectedIntegerValue.doubleValue() == testBean.getDoubleProperty());
+ }
+
+ /**
+ * Test execute with simple int property and Double value.
+ */
+ public void testExecuteWithSimpleIntPropertyAndDoubleValue() {
+ try {
+ new BeanPropertyValueChangeClosure("intProperty", expectedDoubleValue).execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with simple int property and String value.
+ */
+ public void testExecuteWithSimpleIntPropertyAndStringValue() {
+ try {
+ new BeanPropertyValueChangeClosure("intProperty", "123").execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with simple int property and Float value.
+ */
+ public void testExecuteWithSimpleIntPropertyAndFloatValue() {
+ try {
+ new BeanPropertyValueChangeClosure("intProperty", expectedFloatValue).execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with simple int property and Integer value.
+ */
+ public void testExecuteWithSimpleIntPropertyAndIntegerValue() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("intProperty", expectedIntegerValue).execute(testBean);
+ assertTrue(expectedIntegerValue.intValue() == testBean.getIntProperty());
+ }
+
+ /**
+ * Test execute with simple boolean property and Boolean value.
+ */
+ public void testExecuteWithSimpleBooleanPropertyAndBooleanValue() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("booleanProperty", expectedBooleanValue).execute(testBean);
+ assertTrue(expectedBooleanValue.booleanValue() == testBean.getBooleanProperty());
+ }
+
+ /**
+ * Test execute with simple boolean property and String value.
+ */
+ public void testExecuteWithSimpleBooleanPropertyAndStringValue() {
+ try {
+ new BeanPropertyValueChangeClosure("booleanProperty", "true").execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with simple byte property and Byte value.
+ */
+ public void testExecuteWithSimpleBytePropertyAndByteValue() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("byteProperty", expectedByteValue).execute(testBean);
+ assertTrue(expectedByteValue.byteValue() == testBean.getByteProperty());
+ }
+
+ /**
+ * Test execute with simple boolean property and String value.
+ */
+ public void testExecuteWithSimpleBytePropertyAndStringValue() {
+ try {
+ new BeanPropertyValueChangeClosure("byteProperty", "foo").execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with simple primitive property and null value.
+ */
+ public void testExecuteWithSimplePrimitivePropertyAndNullValue() {
+ try {
+ new BeanPropertyValueChangeClosure("intProperty", null).execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (NullPointerException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with read only property.
+ */
+ public void testExecuteWithReadOnlyProperty() {
+ try {
+ new BeanPropertyValueChangeClosure("readOnlyProperty", "foo").execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with write only property.
+ */
+ public void testExecuteWithWriteOnlyProperty() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("writeOnlyProperty", "foo").execute(testBean);
+ assertEquals("foo", testBean.getWriteOnlyPropertyValue());
+ }
+
+ /**
+ * Test execute with a nested property.
+ */
+ public void testExecuteWithNestedProperty() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("nested.stringProperty", "bar").execute(testBean);
+ assertEquals("bar", testBean.getNested().getStringProperty());
+ }
+
+ /**
+ * Test execute with a nested property and null in the property path.
+ */
+ public void testExecuteWithNullInPropertyPath() {
+ try {
+ new BeanPropertyValueChangeClosure("anotherNested.stringProperty", "foo").execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+
+ /**
+ * Test execute with a nested property and null in the property path and ignoreNull = true.
+ */
+ public void testExecuteWithNullInPropertyPathAngIgnoreTrue() {
+ TestBean testBean = new TestBean();
+
+ // create a closure that will attempt to set a property on the null bean in the path
+ BeanPropertyValueChangeClosure closure = new BeanPropertyValueChangeClosure("anotherNested.stringProperty",
+ "Should ignore exception", true);
+
+ try {
+ closure.execute(testBean);
+ } catch (IllegalArgumentException e) {
+ fail("Should have ignored the exception.");
+ }
+ }
+
+ /**
+ * Test execute with indexed property.
+ */
+ public void testExecuteWithIndexedProperty() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("intIndexed[0]", expectedIntegerValue).execute(testBean);
+ assertTrue(expectedIntegerValue.intValue() == testBean.getIntIndexed(0));
+ }
+
+ /**
+ * Test execute with mapped property.
+ */
+ public void testExecuteWithMappedProperty() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("mappedProperty(fred)", "barney").execute(testBean);
+ assertEquals("barney", testBean.getMappedProperty("fred"));
+ }
+
+ /**
+ * Test execute with a simple String property.
+ */
+ public void testExecuteWithSimpleStringProperty() {
+ TestBean testBean = new TestBean();
+ new BeanPropertyValueChangeClosure("stringProperty", "barney").execute(testBean);
+ assertEquals("barney", testBean.getStringProperty());
+ }
+
+ /**
+ * Test execute with an invalid property name.
+ */
+ public void testExecuteWithInvalidPropertyName() {
+ try {
+ new BeanPropertyValueChangeClosure("bogusProperty", "foo").execute(new TestBean());
+ fail("Should have thrown an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* this is what we expect */
+ }
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPropertyValueEqualsPredicateTest.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPropertyValueEqualsPredicateTest.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanPropertyValueEqualsPredicateTest.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Test cases for <code>BeanPropertyValueEqualsPredicateTest</code>.
+ *
+ * @author Norm Deane
+ */
+public class BeanPropertyValueEqualsPredicateTest extends TestCase {
+
+ private static final Integer expectedIntegerValue = new Integer(123);
+ private static final Float expectedFloatValue = new Float(123.123f);
+ private static final Double expectedDoubleValue = new Double(567879.12344d);
+ private static final Boolean expectedBooleanValue = Boolean.TRUE;
+ private static final Byte expectedByteValue = new Byte("12");
+
+ /**
+ * Constructor for BeanPropertyValueEqualsPredicateTest.
+ *
+ * @param name Name of this test case.
+ */
+ public BeanPropertyValueEqualsPredicateTest(String name) {
+ super(name);
+ }
+
+ /**
+ * Test evaluate with simple String property.
+ */
+ public void testEvaluateWithSimpleStringProperty() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("stringProperty","foo");
+ assertTrue(predicate.evaluate(new TestBean("foo")));
+ assertTrue(!predicate.evaluate(new TestBean("bar")));
+ }
+
+ /**
+ * Test evaluate with simple String property and null values.
+ */
+ public void testEvaluateWithSimpleStringPropertyWithNullValues() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("stringProperty",null);
+ assertTrue(predicate.evaluate(new TestBean((String) null)));
+ assertTrue(!predicate.evaluate(new TestBean("bar")));
+ }
+
+ /**
+ * Test evaluate with nested property.
+ */
+ public void testEvaluateWithNestedProperty() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("anotherNested.stringProperty","match");
+ TestBean testBean = new TestBean();
+ TestBean nestedBean = new TestBean("match");
+ testBean.setAnotherNested(nestedBean);
+ assertTrue(predicate.evaluate(testBean));
+ testBean.setAnotherNested(new TestBean("no-match"));
+ assertTrue(!predicate.evaluate(testBean));
+ }
+
+ /**
+ * Test evaluate with null in property path and ignore=false.
+ */
+ public void testEvaluateWithNullInPath() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("anotherNested.stringProperty","foo");
+ try {
+ // try to evaluate the predicate
+ predicate.evaluate(new TestBean());
+ fail("Should have throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* ignore this is what should happen */
+ }
+ }
+
+ /**
+ * Test evaluate with null in property path and ignore=true.
+ */
+ public void testEvaluateWithNullInPathAndIgnoreTrue() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("anotherNested.stringProperty","foo", true);
+ try {
+ assertTrue(!predicate.evaluate(new TestBean()));
+ } catch (IllegalArgumentException e) {
+ fail("Should not have throw IllegalArgumentException");
+ }
+ }
+
+ /**
+ * Test evaluate with int property.
+ */
+ public void testEvaluateWithIntProperty() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("intProperty",expectedIntegerValue);
+ assertTrue(predicate.evaluate(new TestBean(expectedIntegerValue.intValue())));
+ assertTrue(!predicate.evaluate(new TestBean(expectedIntegerValue.intValue() - 1)));
+ }
+
+ /**
+ * Test evaluate with float property.
+ */
+ public void testEvaluateWithFloatProperty() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("floatProperty",expectedFloatValue);
+ assertTrue(predicate.evaluate(new TestBean(expectedFloatValue.floatValue())));
+ assertTrue(!predicate.evaluate(new TestBean(expectedFloatValue.floatValue() - 1)));
+ }
+
+ /**
+ * Test evaluate with double property.
+ */
+ public void testEvaluateWithDoubleProperty() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("doubleProperty",expectedDoubleValue);
+ assertTrue(predicate.evaluate(new TestBean(expectedDoubleValue.doubleValue())));
+ assertTrue(!predicate.evaluate(new TestBean(expectedDoubleValue.doubleValue() - 1)));
+ }
+
+ /**
+ * Test evaluate with boolean property.
+ */
+ public void testEvaluateWithBooleanProperty() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("booleanProperty",expectedBooleanValue);
+ assertTrue(predicate.evaluate(new TestBean(expectedBooleanValue.booleanValue())));
+ assertTrue(!predicate.evaluate(new TestBean(!expectedBooleanValue.booleanValue())));
+ }
+
+ /**
+ * Test evaluate with byte property.
+ */
+ public void testEvaluateWithByteProperty() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("byteProperty",expectedByteValue);
+ TestBean testBean = new TestBean();
+ testBean.setByteProperty(expectedByteValue.byteValue());
+ assertTrue(predicate.evaluate(testBean));
+ testBean.setByteProperty((byte) (expectedByteValue.byteValue() - 1));
+ assertTrue(!predicate.evaluate(testBean));
+ }
+
+ /**
+ * Test evaluate with mapped property.
+ */
+ public void testEvaluateWithMappedProperty() {
+ // try a key that is in the map
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("mappedProperty(test-key)","match");
+ TestBean testBean = new TestBean();
+ testBean.setMappedProperty("test-key", "match");
+ assertTrue(predicate.evaluate(testBean));
+ testBean.setMappedProperty("test-key", "no-match");
+ assertTrue(!predicate.evaluate(testBean));
+
+ // try a key that isn't in the map
+ predicate = new BeanPropertyValueEqualsPredicate("mappedProperty(invalid-key)", "match");
+ assertTrue(!predicate.evaluate(testBean));
+ }
+
+ /**
+ * Test evaluate with indexed property.
+ */
+ public void testEvaluateWithIndexedProperty() {
+ // try a valid index
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("intIndexed[0]",expectedIntegerValue);
+ TestBean testBean = new TestBean();
+ testBean.setIntIndexed(0, expectedIntegerValue.intValue());
+ assertTrue(predicate.evaluate(testBean));
+ testBean.setIntIndexed(0, expectedIntegerValue.intValue() - 1);
+ assertTrue(!predicate.evaluate(testBean));
+
+ // try an invalid index
+ predicate = new BeanPropertyValueEqualsPredicate("intIndexed[999]", "exception-ahead");
+
+ try {
+ assertTrue(!predicate.evaluate(testBean));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ /* this is what should happen */
+ }
+ }
+
+ /**
+ * Test evaluate with primitive property and null value.
+ */
+ public void testEvaluateWithPrimitiveAndNull() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("intProperty",null);
+ assertTrue(!predicate.evaluate(new TestBean(0)));
+
+ predicate = new BeanPropertyValueEqualsPredicate("booleanProperty", null);
+ assertTrue(!predicate.evaluate(new TestBean(true)));
+
+ predicate = new BeanPropertyValueEqualsPredicate("floatProperty", null);
+ assertTrue(!predicate.evaluate(new TestBean(expectedFloatValue.floatValue())));
+ }
+
+ /**
+ * Test evaluate with nested mapped property.
+ */
+ public void testEvaluateWithNestedMappedProperty() {
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("anotherNested.mappedProperty(test-key)","match");
+ TestBean testBean = new TestBean();
+ TestBean nestedBean = new TestBean();
+ nestedBean.setMappedProperty("test-key", "match");
+ testBean.setAnotherNested(nestedBean);
+ assertTrue(predicate.evaluate(testBean));
+ nestedBean.setMappedProperty("test-key", "no-match");
+ assertTrue(!predicate.evaluate(testBean));
+ }
+
+ /**
+ * Test evaluate with write only property.
+ */
+ public void testEvaluateWithWriteOnlyProperty() {
+ try {
+ new BeanPropertyValueEqualsPredicate("writeOnlyProperty", null).evaluate(new TestBean());
+ } catch (IllegalArgumentException e) {
+ /* This is what should happen */
+ }
+ }
+
+ /**
+ * Test evaluate with read only property.
+ */
+ public void testEvaluateWithReadOnlyProperty() {
+ TestBean testBean = new TestBean();
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate("readOnlyProperty",testBean.getReadOnlyProperty());
+ assertTrue(predicate.evaluate(new TestBean()));
+ }
+
+ /**
+ * Test evaluate with an invalid property name.
+ */
+ public void testEvaluateWithInvalidPropertyName() {
+ try {
+ new BeanPropertyValueEqualsPredicate("bogusProperty", null).evaluate(new TestBean());
+ } catch (IllegalArgumentException e) {
+ /* This is what should happen */
+ }
+ }
+}
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanToPropertyValueTransformerTest.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanToPropertyValueTransformerTest.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/BeanToPropertyValueTransformerTest.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Test cases for <code>BeanToPropertyValueTransformer</code>.
+ *
+ * @author Norm Deane
+ */
+public class BeanToPropertyValueTransformerTest extends TestCase {
+
+ private static final Integer expectedIntegerValue = new Integer(123);
+ private static final Long expectedLongValue = new Long(123);
+ private static final Float expectedFloatValue = new Float(123.123f);
+ private static final Double expectedDoubleValue = new Double(567879.12344d);
+ private static final Boolean expectedBooleanValue = Boolean.TRUE;
+ private static final Byte expectedByteValue = new Byte("12");
+
+ /**
+ * Constructor for BeanToPropertyValueTransformerTest.
+ *
+ * @param name Name of this test case.
+ */
+ public BeanToPropertyValueTransformerTest(String name) {
+ super(name);
+ }
+
+ /**
+ * Test transform with simple String property.
+ */
+ public void testTransformWithSimpleStringProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("stringProperty");
+ TestBean testBean = new TestBean("foo");
+ assertEquals("foo", transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with simple String property and null value.
+ *
+ */
+ public void testTransformWithSimpleStringPropertyAndNullValue() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("stringProperty");
+ TestBean testBean = new TestBean((String) null);
+ assertNull(transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with simple int property.
+ */
+ public void testTransformWithSimpleIntProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("intProperty");
+ TestBean testBean = new TestBean(expectedIntegerValue.intValue());
+ assertEquals(expectedIntegerValue, transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with simple long property.
+ */
+ public void testTransformWithSimpleLongProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("longProperty");
+ TestBean testBean = new TestBean();
+ testBean.setLongProperty(expectedLongValue.longValue());
+ assertEquals(expectedLongValue, transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with simple float property.
+ */
+ public void testTransformWithSimpleFloatProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("floatProperty");
+ TestBean testBean = new TestBean(expectedFloatValue.floatValue());
+ assertEquals(expectedFloatValue, transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with simple double property.
+ */
+ public void testTransformWithSimpleDoubleProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("doubleProperty");
+ TestBean testBean = new TestBean(expectedDoubleValue.doubleValue());
+ assertEquals(expectedDoubleValue, transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with simple byte property.
+ */
+ public void testTransformWithSimpleByteProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("byteProperty");
+ TestBean testBean = new TestBean();
+ testBean.setByteProperty(expectedByteValue.byteValue());
+ assertEquals(expectedByteValue, transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with simple boolean property.
+ */
+ public void testTransformWithSimpleBooleanProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("booleanProperty");
+ TestBean testBean = new TestBean(expectedBooleanValue.booleanValue());
+ assertEquals(expectedBooleanValue, transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with write only property.
+ */
+ public void testTransformWithWriteOnlyProperty() {
+ try {
+ new BeanToPropertyValueTransformer("writeOnlyProperty").transform(new TestBean());
+ } catch (IllegalArgumentException e) {
+ /* This is what should happen */
+ }
+ }
+
+ /**
+ * Test transform with read only property.
+ */
+ public void testTransformWithReadOnlyProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("readOnlyProperty");
+ TestBean testBean = new TestBean();
+ assertEquals(testBean.getReadOnlyProperty(), transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with invalid property.
+ */
+ public void testTransformWithInvalidProperty() {
+ try {
+ new BeanToPropertyValueTransformer("bogusProperty").transform(new TestBean());
+ } catch (IllegalArgumentException e) {
+ /* This is what should happen */
+ }
+ }
+
+ /**
+ * Test transform with nested property.
+ */
+ public void testTransformWithNestedProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("anotherNested.stringProperty");
+ TestBean testBean = new TestBean();
+ TestBean nestedBean = new TestBean("foo");
+ testBean.setAnotherNested(nestedBean);
+ assertEquals("foo", transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with mapped property.
+ */
+ public void testTransformWithMappedProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("mappedProperty(test-key)");
+ TestBean testBean = new TestBean();
+
+ // try a valid key
+ testBean.setMappedProperty("test-key", "test-value");
+ assertEquals("test-value", transformer.transform(testBean));
+
+ // now try an invalid key
+ transformer = new BeanToPropertyValueTransformer("mappedProperty(bogus-key)");
+ assertEquals(null, transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with indexed property.
+ */
+ public void testTransformWithIndexedProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("intIndexed[0]");
+ TestBean testBean = new TestBean();
+ testBean.setIntIndexed(0, expectedIntegerValue.intValue());
+ assertEquals(expectedIntegerValue, transformer.transform(testBean));
+
+ // test index out of range
+ transformer = new BeanToPropertyValueTransformer("intIndexed[9999]");
+
+ try {
+ transformer.transform(testBean);
+ fail("Should have thrown an ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException e) {
+ /* this is what should happen */
+ }
+ }
+
+ /**
+ * Test transform with nested indexed property.
+ */
+ public void testTransformWithNestedIndexedProperty() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("anotherNested.intIndexed[0]");
+ TestBean testBean = new TestBean();
+ TestBean nestedBean = new TestBean();
+ nestedBean.setIntIndexed(0, expectedIntegerValue.intValue());
+ testBean.setAnotherNested(nestedBean);
+ assertEquals(expectedIntegerValue, transformer.transform(testBean));
+ }
+
+ /**
+ * Test transform with null in property path.
+ */
+ public void testTransformWithNullInPath() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("anotherNested.stringProperty");
+
+ try {
+ transformer.transform(new TestBean());
+ fail("Should have throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ /* ignore this is what should happen */
+ }
+ }
+
+ /**
+ * Test transform with null in property path and ignore = true.
+ */
+ public void testTransformWithNullInPathAndIgnoreTrue() {
+ BeanToPropertyValueTransformer transformer =
+ new BeanToPropertyValueTransformer("anotherNested.stringProperty",true);
+ assertEquals(null, transformer.transform(new TestBean()));
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/Child.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/Child.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/Child.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+public interface Child {
+
+ public String getName();
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/TestBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/TestBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/TestBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,572 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * General purpose test bean for JUnit tests for the "beanutils" component.
+ *
+ * @author Craig R. McClanahan
+ * @author Rodney Waldhoff
+ * @version $Revision: 1.1 $ $Date: 2004/05/10 20:01:16 $
+ */
+
+public class TestBean {
+
+ // ----------------------------------------------------------- Constructors
+
+ public TestBean() {
+ }
+
+ public TestBean(String stringProperty) {
+ setStringProperty(stringProperty);
+ }
+
+ public TestBean(float floatProperty) {
+ setFloatProperty(floatProperty);
+ }
+
+ public TestBean(boolean booleanProperty) {
+ setBooleanProperty(booleanProperty);
+ }
+
+ public TestBean(Boolean booleanSecond) {
+ setBooleanSecond(booleanSecond.booleanValue());
+ }
+
+ public TestBean(float floatProperty, String stringProperty) {
+ setFloatProperty(floatProperty);
+ setStringProperty(stringProperty);
+ }
+
+ public TestBean(boolean booleanProperty, String stringProperty) {
+ setBooleanProperty(booleanProperty);
+ setStringProperty(stringProperty);
+ }
+
+ public TestBean(Boolean booleanSecond, String stringProperty) {
+ setBooleanSecond(booleanSecond.booleanValue());
+ setStringProperty(stringProperty);
+ }
+
+ public TestBean(Integer intProperty) {
+ setIntProperty(intProperty.intValue());
+ }
+
+ public TestBean(double doubleProperty) {
+ setDoubleProperty(doubleProperty);
+ }
+
+ TestBean(int intProperty) {
+ setIntProperty(intProperty);
+ }
+
+ protected TestBean(boolean booleanProperty, boolean booleanSecond, String stringProperty) {
+ setBooleanProperty(booleanProperty);
+ setBooleanSecond(booleanSecond);
+ setStringProperty(stringProperty);
+ }
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A boolean property.
+ */
+ private boolean booleanProperty = true;
+
+ public boolean getBooleanProperty() {
+ return (booleanProperty);
+ }
+
+ public void setBooleanProperty(boolean booleanProperty) {
+ this.booleanProperty = booleanProperty;
+ }
+
+
+ /**
+ * A boolean property that uses an "is" method for the getter.
+ */
+ private boolean booleanSecond = true;
+
+ public boolean isBooleanSecond() {
+ return (booleanSecond);
+ }
+
+ public void setBooleanSecond(boolean booleanSecond) {
+ this.booleanSecond = booleanSecond;
+ }
+
+
+ /**
+ * A byte property.
+ */
+ private byte byteProperty = (byte) 121;
+
+ public byte getByteProperty() {
+ return (this.byteProperty);
+ }
+
+ public void setByteProperty(byte byteProperty) {
+ this.byteProperty = byteProperty;
+ }
+
+
+ /**
+ * A double property.
+ */
+ private double doubleProperty = 321.0;
+
+ public double getDoubleProperty() {
+ return (this.doubleProperty);
+ }
+
+ public void setDoubleProperty(double doubleProperty) {
+ this.doubleProperty = doubleProperty;
+ }
+
+
+ /**
+ * An "indexed property" accessible via both array and subscript
+ * based getters and setters.
+ */
+ private String dupProperty[] =
+ { "Dup 0", "Dup 1", "Dup 2", "Dup 3", "Dup 4" };
+
+ public String[] getDupProperty() {
+ return (this.dupProperty);
+ }
+
+ public String getDupProperty(int index) {
+ return (this.dupProperty[index]);
+ }
+
+ public void setDupProperty(int index, String value) {
+ this.dupProperty[index] = value;
+ }
+
+ public void setDupProperty(String dupProperty[]) {
+ this.dupProperty = dupProperty;
+ }
+
+
+ /**
+ * A float property.
+ */
+ private float floatProperty = (float) 123.0;
+
+ public float getFloatProperty() {
+ return (this.floatProperty);
+ }
+
+ public void setFloatProperty(float floatProperty) {
+ this.floatProperty = floatProperty;
+ }
+
+
+ /**
+ * An integer array property accessed as an array.
+ */
+ private int intArray[] = { 0, 10, 20, 30, 40 };
+
+ public int[] getIntArray() {
+ return (this.intArray);
+ }
+
+ public void setIntArray(int intArray[]) {
+ this.intArray = intArray;
+ }
+
+
+ /**
+ * An integer array property accessed as an indexed property.
+ */
+ private int intIndexed[] = { 0, 10, 20, 30, 40 };
+
+ public int getIntIndexed(int index) {
+ return (intIndexed[index]);
+ }
+
+ public void setIntIndexed(int index, int value) {
+ intIndexed[index] = value;
+ }
+
+
+ /**
+ * An integer property.
+ */
+ private int intProperty = 123;
+
+ public int getIntProperty() {
+ return (this.intProperty);
+ }
+
+ public void setIntProperty(int intProperty) {
+ this.intProperty = intProperty;
+ }
+
+
+ /**
+ * A List property accessed as an indexed property.
+ */
+ private static List listIndexed = new ArrayList();
+
+ static {
+ listIndexed.add("String 0");
+ listIndexed.add("String 1");
+ listIndexed.add("String 2");
+ listIndexed.add("String 3");
+ listIndexed.add("String 4");
+ }
+
+ public List getListIndexed() {
+ return (listIndexed);
+ }
+
+
+ /**
+ * A long property.
+ */
+ private long longProperty = 321;
+
+ public long getLongProperty() {
+ return (this.longProperty);
+ }
+
+ public void setLongProperty(long longProperty) {
+ this.longProperty = longProperty;
+ }
+
+
+ /**
+ * A mapped property with only a getter and setter for a Map.
+ */
+ private Map mapProperty = null;
+
+ public Map getMapProperty() {
+ // Create the map the very first time
+ if (mapProperty == null) {
+ mapProperty = new HashMap();
+ mapProperty.put("First Key", "First Value");
+ mapProperty.put("Second Key", "Second Value");
+ }
+ return (mapProperty);
+ }
+
+ public void setMapProperty(Map mapProperty) {
+ // Create the map the very first time
+ if (mapProperty == null) {
+ mapProperty = new HashMap();
+ mapProperty.put("First Key", "First Value");
+ mapProperty.put("Second Key", "Second Value");
+ }
+ this.mapProperty = mapProperty;
+ }
+
+
+ /**
+ * A mapped property that has String keys and Object values.
+ */
+ private HashMap mappedObjects = null;
+
+ public Object getMappedObjects(String key) {
+ // Create the map the very first time
+ if (mappedObjects == null) {
+ mappedObjects = new HashMap();
+ mappedObjects.put("First Key", "First Value");
+ mappedObjects.put("Second Key", "Second Value");
+ }
+ return (mappedObjects.get(key));
+ }
+
+ public void setMappedObjects(String key, Object value) {
+ // Create the map the very first time
+ if (mappedObjects == null) {
+ mappedObjects = new HashMap();
+ mappedObjects.put("First Key", "First Value");
+ mappedObjects.put("Second Key", "Second Value");
+ }
+ mappedObjects.put(key, value);
+ }
+
+
+ /**
+ * A mapped property that has String keys and String values.
+ */
+ private HashMap mappedProperty = null;
+
+ public String getMappedProperty(String key) {
+ // Create the map the very first time
+ if (mappedProperty == null) {
+ mappedProperty = new HashMap();
+ mappedProperty.put("First Key", "First Value");
+ mappedProperty.put("Second Key", "Second Value");
+ }
+ return ((String) mappedProperty.get(key));
+ }
+
+ public void setMappedProperty(String key, String value) {
+ // Create the map the very first time
+ if (mappedProperty == null) {
+ mappedProperty = new HashMap();
+ mappedProperty.put("First Key", "First Value");
+ mappedProperty.put("Second Key", "Second Value");
+ }
+ mappedProperty.put(key, value);
+ }
+
+
+ /**
+ * A mapped property that has String keys and int values.
+ */
+ private HashMap mappedIntProperty = null;
+
+ public int getMappedIntProperty(String key) {
+ // Create the map the very first time
+ if (mappedProperty == null) {
+ mappedProperty = new HashMap();
+ mappedProperty.put("One", new Integer(1));
+ mappedProperty.put("Two", new Integer(2));
+ }
+ Integer x = (Integer) mappedIntProperty.get(key);
+ return ((x == null) ? 0 : x.intValue());
+ }
+
+ public void setMappedIntProperty(String key, int value) {
+ mappedIntProperty.put(key, new Integer(value));
+ }
+
+
+ /**
+ * A nested reference to another test bean (populated as needed).
+ */
+ private TestBean nested = null;
+
+ public TestBean getNested() {
+ if (nested == null)
+ nested = new TestBean();
+ return (nested);
+ }
+
+ /**
+ * Another nested reference to another test bean,
+ */
+ private TestBean anotherNested = null;
+
+ public TestBean getAnotherNested() {
+ return anotherNested;
+ }
+
+ public void setAnotherNested( TestBean anotherNested ) {
+ this.anotherNested = anotherNested;
+ }
+
+ /*
+ * Another nested reference to a bean containing mapp properties
+ */
+ class MappedTestBean {
+ public void setValue(String key,String val) { }
+ public String getValue(String key) { return "Mapped Value"; }
+ }
+
+ private MappedTestBean mappedNested = null;
+
+ public MappedTestBean getMappedNested() {
+ if (mappedNested == null)
+ {
+ mappedNested = new MappedTestBean();
+ }
+ return mappedNested;
+ }
+
+ /**
+ * A String property with an initial value of null.
+ */
+ private String nullProperty = null;
+
+ public String getNullProperty() {
+ return (this.nullProperty);
+ }
+
+ public void setNullProperty(String nullProperty) {
+ this.nullProperty = nullProperty;
+ }
+
+
+ /**
+ * A read-only String property.
+ */
+ private String readOnlyProperty = "Read Only String Property";
+
+ public String getReadOnlyProperty() {
+ return (this.readOnlyProperty);
+ }
+
+
+ /**
+ * A short property.
+ */
+ private short shortProperty = (short) 987;
+
+ public short getShortProperty() {
+ return (this.shortProperty);
+ }
+
+ public void setShortProperty(short shortProperty) {
+ this.shortProperty = shortProperty;
+ }
+
+
+ /**
+ * A String array property accessed as a String.
+ */
+ private String stringArray[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+
+ public String[] getStringArray() {
+ return (this.stringArray);
+ }
+
+ public void setStringArray(String stringArray[]) {
+ this.stringArray = stringArray;
+ }
+
+
+ /**
+ * A String array property accessed as an indexed property.
+ */
+ private String stringIndexed[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+
+ public String getStringIndexed(int index) {
+ return (stringIndexed[index]);
+ }
+
+ public void setStringIndexed(int index, String value) {
+ stringIndexed[index] = value;
+ }
+
+
+ /**
+ * A String property.
+ */
+ private String stringProperty = "This is a string";
+
+ public String getStringProperty() {
+ return (this.stringProperty);
+ }
+
+ public void setStringProperty(String stringProperty) {
+ this.stringProperty = stringProperty;
+ }
+
+
+ /**
+ * A write-only String property.
+ */
+ private String writeOnlyProperty = "Write Only String Property";
+
+ public String getWriteOnlyPropertyValue() {
+ return (this.writeOnlyProperty);
+ }
+
+ public void setWriteOnlyProperty(String writeOnlyProperty) {
+ this.writeOnlyProperty = writeOnlyProperty;
+ }
+
+
+ // ------------------------------------------------------ Invalid Properties
+
+
+ /**
+ * <p>An invalid property that has two boolean getters (getInvalidBoolean
+ * and isInvalidBoolean) plus a String setter (setInvalidBoolean). By the
+ * rules described in the JavaBeans Specification, this will be considered
+ * a read-only boolean property, using isInvalidBoolean() as the getter.</p>
+ */
+ private boolean invalidBoolean = false;
+
+ public boolean getInvalidBoolean() {
+ return (this.invalidBoolean);
+ }
+
+ public boolean isInvalidBoolean() {
+ return (this.invalidBoolean);
+ }
+
+ public void setInvalidBoolean(String invalidBoolean) {
+ if ("true".equalsIgnoreCase(invalidBoolean) ||
+ "yes".equalsIgnoreCase(invalidBoolean) ||
+ "1".equalsIgnoreCase(invalidBoolean)) {
+ this.invalidBoolean = true;
+ } else {
+ this.invalidBoolean = false;
+ }
+ }
+
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * A static variable that is accessed and updated via static methods
+ * for MethodUtils testing.
+ */
+ private static int counter = 0;
+
+
+ /**
+ * Return the current value of the counter.
+ */
+ public static int currentCounter() {
+
+ return (counter);
+
+ }
+
+
+ /**
+ * Increment the current value of the counter by 1.
+ */
+ public static void incrementCounter() {
+
+ incrementCounter(1);
+
+ }
+
+
+ /**
+ * Increment the current value of the counter by the specified amount.
+ *
+ * @param amount Amount to be added to the current counter
+ */
+ public static void incrementCounter(int amount) {
+
+ counter += amount;
+
+ }
+
+
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/TestBean.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/TestBeanMap.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/TestBeanMap.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/src/test/org/apache/commons/beanutils/TestBeanMap.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.beanutils;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.textui.TestRunner;
+
+import org.apache.commons.collections.map.AbstractTestMap;
+import org.apache.commons.collections.BulkTest;
+
+/**
+ * Test cases for BeanMap
+ *
+ * @version $Revision: 1.1 $ $Date: 2004/05/11 22:46:26 $
+ *
+ * @author Morgan Delagrange
+ * @author Stephen Colebourne
+ */
+public class TestBeanMap extends AbstractTestMap {
+
+ public TestBeanMap(String testName) {
+ super(testName);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return BulkTest.makeSuite(TestBeanMap.class);
+ }
+
+/*
+ note to self. The getter and setter methods were generated by copying the
+ field declarations and using the following regular expression search and
+ replace:
+
+ From:
+ private \(.*\) some\(.*\);
+ To:
+ public \1 getSome\2Value() {
+ return some\2;
+ }
+ public void setSome\2Value(\1 value) {
+ some\2 = value;
+ }
+
+ Also note: The sample keys and mappings were generated manually.
+*/
+
+
+ public static class BeanWithProperties implements Serializable {
+ private int someInt;
+ private long someLong;
+ private double someDouble;
+ private float someFloat;
+ private short someShort;
+ private byte someByte;
+ private char someChar;
+ private Integer someInteger;
+ private String someString;
+ private Object someObject;
+
+ public int getSomeIntValue() {
+ return someInt;
+ }
+ public void setSomeIntValue(int value) {
+ someInt = value;
+ }
+
+ public long getSomeLongValue() {
+ return someLong;
+ }
+ public void setSomeLongValue(long value) {
+ someLong = value;
+ }
+
+ public double getSomeDoubleValue() {
+ return someDouble;
+ }
+ public void setSomeDoubleValue(double value) {
+ someDouble = value;
+ }
+
+ public float getSomeFloatValue() {
+ return someFloat;
+ }
+ public void setSomeFloatValue(float value) {
+ someFloat = value;
+ }
+
+ public short getSomeShortValue() {
+ return someShort;
+ }
+ public void setSomeShortValue(short value) {
+ someShort = value;
+ }
+
+ public byte getSomeByteValue() {
+ return someByte;
+ }
+ public void setSomeByteValue(byte value) {
+ someByte = value;
+ }
+
+ public char getSomeCharValue() {
+ return someChar;
+ }
+ public void setSomeCharValue(char value) {
+ someChar = value;
+ }
+
+ public String getSomeStringValue() {
+ return someString;
+ }
+ public void setSomeStringValue(String value) {
+ someString = value;
+ }
+
+ public Integer getSomeIntegerValue() {
+ return someInteger;
+ }
+ public void setSomeIntegerValue(Integer value) {
+ someInteger = value;
+ }
+
+ public Object getSomeObjectValue() {
+ return someObject;
+ }
+ public void setSomeObjectValue(Object value) {
+ someObject = value;
+ }
+ }
+
+ // note to self. The Sample keys were generated by copying the field
+ // declarations and using the following regular expression search and replace:
+ //
+ // From:
+ // private \(.*\) some\(.*\);
+ // To:
+ // "some\2Value",
+ //
+ // Then, I manually added the "class" key, which is a property that exists for
+ // all beans (and all objects for that matter.
+ public Object[] getSampleKeys() {
+ Object[] keys = new Object[] {
+ "someIntValue",
+ "someLongValue",
+ "someDoubleValue",
+ "someFloatValue",
+ "someShortValue",
+ "someByteValue",
+ "someCharValue",
+ "someIntegerValue",
+ "someStringValue",
+ "someObjectValue",
+ "class",
+ };
+ return keys;
+ }
+
+ /**
+ * An object value that will be stored in the bean map as a value. Need
+ * to save this externally so that we can make sure the object instances
+ * are equivalent since getSampleValues() would otherwise construct a new
+ * and different Object each time.
+ **/
+ private Object objectInFullMap = new Object();
+
+ // note to self: the sample values were created manually
+ public Object[] getSampleValues() {
+ Object[] values = new Object[] {
+ new Integer(1234),
+ new Long(1298341928234L),
+ new Double(123423.34),
+ new Float(1213332.12f),
+ new Short((short)134),
+ new Byte((byte)10),
+ new Character('a'),
+ new Integer(1432),
+ "SomeStringValue",
+ objectInFullMap,
+ BeanWithProperties.class,
+ };
+ return values;
+ }
+
+ public Object[] getNewSampleValues() {
+ Object[] values = new Object[] {
+ new Integer(223),
+ new Long(23341928234L),
+ new Double(23423.34),
+ new Float(213332.12f),
+ new Short((short)234),
+ new Byte((byte)20),
+ new Character('b'),
+ new Integer(232),
+ "SomeNewStringValue",
+ new Object(),
+ null,
+ };
+ return values;
+ }
+
+ /**
+ * Values is a dead copy in BeanMap, so refresh each time.
+ */
+ public void verifyValues() {
+ values = map.values();
+ super.verifyValues();
+ }
+
+ /**
+ * The mappings in a BeanMap are fixed on the properties the underlying
+ * bean has. Adding and removing mappings is not possible, thus this
+ * method is overridden to return false.
+ */
+ public boolean isPutAddSupported() {
+ return false;
+ }
+
+ /**
+ * The mappings in a BeanMap are fixed on the properties the underlying
+ * bean has. Adding and removing mappings is not possible, thus this
+ * method is overridden to return false.
+ */
+ public boolean isRemoveSupported() {
+ return false;
+ }
+
+ public Map makeFullMap() {
+ // note: These values must match (i.e. .equals() must return true)
+ // those returned from getSampleValues().
+ BeanWithProperties bean = new BeanWithProperties();
+ bean.setSomeIntValue(1234);
+ bean.setSomeLongValue(1298341928234L);
+ bean.setSomeDoubleValue(123423.34);
+ bean.setSomeFloatValue(1213332.12f);
+ bean.setSomeShortValue((short)134);
+ bean.setSomeByteValue((byte)10);
+ bean.setSomeCharValue('a');
+ bean.setSomeIntegerValue(new Integer(1432));
+ bean.setSomeStringValue("SomeStringValue");
+ bean.setSomeObjectValue(objectInFullMap);
+ return new BeanMap(bean);
+ }
+
+ public Map makeEmptyMap() {
+ return new BeanMap();
+ }
+
+ public String[] ignoredTests() {
+ // Ignore the serialization tests on collection views.
+ return new String[] {
+ "TestBeanMap.bulkTestMapEntrySet.testCanonicalEmptyCollectionExists",
+ "TestBeanMap.bulkTestMapEntrySet.testCanonicalFullCollectionExists",
+ "TestBeanMap.bulkTestMapKeySet.testCanonicalEmptyCollectionExists",
+ "TestBeanMap.bulkTestMapKeySet.testCanonicalFullCollectionExists",
+ "TestBeanMap.bulkTestMapValues.testCanonicalEmptyCollectionExists",
+ "TestBeanMap.bulkTestMapValues.testCanonicalFullCollectionExists",
+ "TestBeanMap.bulkTestMapEntrySet.testSimpleSerialization",
+ "TestBeanMap.bulkTestMapKeySet.testSimpleSerialization",
+ "TestBeanMap.bulkTestMapEntrySet.testSerializeDeserializeThenCompare",
+ "TestBeanMap.bulkTestMapKeySet.testSerializeDeserializeThenCompare"
+ };
+ }
+
+ /**
+ * Need to override this method because the "clear()" method on the bean
+ * map just returns the bean properties to their default states. It does
+ * not actually remove the mappings as per the map contract. The default
+ * testClear() methods checks that the clear method throws an
+ * UnsupportedOperationException since this class is not add/remove
+ * modifiable. In our case though, we do not always throw that exception.
+ */
+ public void testMapClear() {
+ //TODO: make sure a call to BeanMap.clear returns the bean to its
+ //default initialization values.
+ }
+
+ /**
+ * Need to override this method because the "put()" method on the bean
+ * doesn't work for this type of Map.
+ */
+ public void testMapPut() {
+ // see testBeanMapPutAllWriteable
+ }
+
+ public void testBeanMapClone() {
+ BeanMap map = (BeanMap)makeFullMap();
+ try {
+ BeanMap map2 = (BeanMap)((BeanMap)map).clone();
+
+ // make sure containsKey is working to verify the bean was cloned
+ // ok, and the read methods were properly initialized
+ Object[] keys = getSampleKeys();
+ for(int i = 0; i < keys.length; i++) {
+ assertTrue("Cloned BeanMap should contain the same keys",
+ map2.containsKey(keys[i]));
+ }
+ } catch (CloneNotSupportedException exception) {
+ fail("BeanMap.clone() should not throw a " +
+ "CloneNotSupportedException when clone should succeed.");
+ }
+ }
+
+ public void testBeanMapPutAllWriteable() {
+ BeanMap map1 = (BeanMap)makeFullMap();
+ BeanMap map2 = (BeanMap)makeFullMap();
+ map2.put("someIntValue", new Integer(0));
+ map1.putAllWriteable(map2);
+ assertEquals(map1.get("someIntValue"), new Integer(0));
+ }
+
+ public void testMethodAccessor() throws Exception {
+ BeanMap map = (BeanMap) makeFullMap();
+ Method method = BeanWithProperties.class.getDeclaredMethod("getSomeIntegerValue", null);
+ assertEquals(method, map.getReadMethod("someIntegerValue"));
+ }
+
+ public void testMethodMutator() throws Exception {
+ BeanMap map = (BeanMap) makeFullMap();
+ Method method = BeanWithProperties.class.getDeclaredMethod("setSomeIntegerValue", new Class[] {Integer.class});
+ assertEquals(method, map.getWriteMethod("someIntegerValue"));
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/xdocs/index.xml
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/xdocs/index.xml 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/xdocs/index.xml 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<document>
+
+ <properties>
+ <title>Commons</title>
+ <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+ </properties>
+
+ <body>
+
+<section name="Commons BeanUtils Bean Collections">
+
+<p>
+Dealing with collections of beans is a common feature of development in Java.
+A lot of time is spent creating bean-specific implementations
+for standard collection manipulators such as functors and comparators.
+</p>
+
+<p>
+<code>BeanUtils Bean collections</code> is a library intended to
+improve developer productivity by using sophisticated bean introspection
+(from <code>BeanUtils</code>)
+to allow general library classes to be used (rather than creating bean specific
+implementation classes).
+</p>
+
+<p>
+But won't this be slower? Yes, reflection is slower than direct references
+but in real life applications, this is typically insignificant. So why not use
+these classes to speed development and then substitute faster implementations only
+where the profiler indicates there is a problem :)
+</p>
+ <subsection name='Quick-Quick Guide To Functors'>
+ <p>
+Many of the classes in <code>bean-collections</code> are functor implementations
+specialized for bean properties. This is a very quick guide (aimed to let java developer
+know why functors make for elegant code).
+ </p>
+ <p>
+The word <code>functor</code> is mathematical in origin but comes into object oriented
+development from functional and logic coding. In Java terms, a functor
+is a function that is encapsulated as an object (and so can be manipulated as an object).
+This allows elegant, concise and powerful techniques to be used. For example,
+<a href='http://jakarta.apache.org/commons/collections'>Commons Collections</a>
+contains utilities that allow functions (as functors) to be easily applied to
+Collections.
+ </p>
+ <p>
+This is actually pretty useful when it comes to collections of beans. It's a common
+problem to want to extract information from a collection of beans or to change all properties
+to a particular value. Functors can be a particularly elegant way to do this. So try them!
+You might just like them!
+ </p>
+ <p>
+For more information about functors, please read the introduction to the
+<a href='http://jakarta.apache.org/commons/sandbox/functor/'>Commons Functor component</a>.
+ </p>
+ </subsection>
+</section>
+<section name='Releases'>
+ <p>
+BeanUtils Bean-Collections is distributed as an optional jar within the main
+beanutils distribution. For details, see the
+<a href='http://jakarta.apache.org/commons/beanutils/index.html'>main BeanUtils website</a>
+ </p>
+</section>
+
+</body>
+</document>
Added: trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/xdocs/navigation.xml
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/xdocs/navigation.xml 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/optional/bean-collections/xdocs/navigation.xml 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!DOCTYPE org.apache.commons.menus SYSTEM '../../../../commons-build/menus/menus.dtd'>
+<project name="BeanUtils Bean Collections">
+
+ <title>BeanUtils Bean Collections</title>
+ <organizationLogo href="/images/jakarta-logo-blue.gif">
+ Jakarta
+ </organizationLogo>
+
+ <body>
+ <links>
+ <item name="BeanUtils Core"
+ href="http://jakarta.apache.org/commons/beanutils"/>
+ <item name="Jakarta Commons"
+ href="http://jakarta.apache.org/commons/"/>
+ </links>
+
+ <menu name="Commons BeanUtils Bean Collections">
+ <item name="Overview" href="/index.html"/>
+ </menu>
+
+ &common-menus;
+
+ </body>
+</project>
Added: trunk/commons-beanutils/branches/upstream/current/project.properties
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/project.properties 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/project.properties 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,23 @@
+# Copyright 2001-2004 The Apache Software Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# documentation properties
+maven.xdoc.jsl=../commons-build/commons-site.jsl
+maven.xdoc.date=left
+maven.xdoc.version=${pom.currentVersion}
+maven.xdoc.developmentProcessUrl=http://jakarta.apache.org/commons/charter.html
+maven.xdoc.poweredby.image=maven-feather.png
+
+
+beanutils.cvs=pserver:anoncvs at cvs.apache.org:/home/cvspublic
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/project.xml
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/project.xml 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/project.xml 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project>
+ <pomVersion>3</pomVersion>
+ <id>commons-beanutils</id>
+ <name>BeanUtils</name>
+ <currentVersion>1.7</currentVersion>
+ <inceptionYear>2000</inceptionYear>
+ <shortDescription>Commons BeanUtils</shortDescription>
+ <description>BeanUtils provides an easy-to-use but flexible wrapper around reflection and introspection.</description>
+ <logo>/images/logo.png</logo>
+
+ <package>org.apache.commons.beanutils.*</package>
+ <url>http://jakarta.apache.org/commons/beanutils/index.html</url>
+
+ <organization>
+ <name>The Apache Software Foundation</name>
+ <url>http://jakarta.apache.org</url>
+ <logo>http://jakarta.apache.org/images/original-jakarta-logo.gif</logo>
+ </organization>
+
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>/LICENSE.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <gumpRepositoryId>jakarta</gumpRepositoryId>
+ <issueTrackingUrl>http://issues.apache.org/bugzilla/</issueTrackingUrl>
+ <siteAddress>jakarta.apache.org</siteAddress>
+ <siteDirectory>/www/jakarta.apache.org/commons/${pom.artifactId.substring(8)}/</siteDirectory>
+ <distributionDirectory>/www/jakarta.apache.org/builds/jakarta-commons/${pom.artifactId.substring(8)}/</distributionDirectory>
+
+ <repository>
+ <connection>scm:cvs:pserver:anoncvs at cvs.apache.org:/home/cvspublic:jakarta-commons/${pom.artifactId.substring(8)}</connection>
+ <url>http://cvs.apache.org/viewcvs/jakarta-commons/${pom.artifactId.substring(8)}/</url>
+ </repository>
+
+ <mailingLists>
+ <mailingList>
+ <name>Commons Dev List</name>
+ <subscribe>commons-dev-subscribe at jakarta.apache.org</subscribe>
+ <unsubscribe>commons-dev-unsubscribe at jakarta.apache.org</unsubscribe>
+ <archive>http://nagoya.apache.org/eyebrowse/SummarizeList?listName=commons-dev@jakarta.apache.org</archive>
+ </mailingList>
+ <mailingList>
+ <name>Commons User List</name>
+ <subscribe>commons-user-subscribe at jakarta.apache.org</subscribe>
+ <unsubscribe>commons-user-unsubscribe at jakarta.apache.org</unsubscribe>
+ <archive>http://nagoya.apache.org/eyebrowse/SummarizeList?listName=commons-user@jakarta.apache.org</archive>
+ </mailingList>
+ </mailingLists>
+
+ <developers>
+ <developer>
+ <name>Robert Burrell Donkin</name>
+ <id>rdonkin</id>
+ <email>rdonkin at apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ <developer>
+ <name>dIon Gillard</name>
+ <id>dion</id>
+ <email>dion at apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ <developer>
+ <name>Craig McClanahan</name>
+ <id>craigmcc</id>
+ <email>craigmcc at apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ <developer>
+ <name>Geir Magnusson Jr.</name>
+ <id>geirm</id>
+ <email>geirm at apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ <developer>
+ <name>Scott Sanders</name>
+ <id>sanders</id>
+ <email>sanders at apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ <developer>
+ <name>James Strachan</name>
+ <id>jstrachan</id>
+ <email>jstrachan at apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ <developer>
+ <name>Rodney Waldhoff</name>
+ <id>rwaldhoff</id>
+ <email>rwaldhoff at apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ <developer>
+ <name>Martin van den Bemt</name>
+ <id>mvdb</id>
+ <email>mvdb at apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ <developer>
+ <name>Yoav Shapira</name>
+ <id>yoavs</id>
+ <email>yoavs at apache.org</email>
+ <organization>Apache Software Foundation</organization>
+ </developer>
+ </developers>
+
+ <contributors>
+ <contributor>
+ <name>Paul Jack</name>
+ <email></email>
+ </contributor>
+ <contributor>
+ <name>Stephen Colebourne</name>
+ <email></email>
+ </contributor>
+ <contributor>
+ <name>Berin Loritsch</name>
+ <email></email>
+ </contributor>
+ </contributors>
+
+ <dependencies>
+ <dependency>
+ <id>commons-logging</id>
+ <version>1.0.3</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <nagEmailAddress>commons-dev at jakarta.apache.org</nagEmailAddress>
+ <sourceDirectory>src/java</sourceDirectory>
+ <unitTestSourceDirectory>src/test</unitTestSourceDirectory>
+ <integrationUnitTestSourceDirectory/>
+ <aspectSourceDirectory/>
+
+ <!-- Unit test classes -->
+ <unitTest>
+ <includes>
+ <include>**/*TestCase.java</include>
+ </includes>
+ <resources>
+ <resource>
+ <directory>${pom.build.unitTestSourceDirectory}</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+ </resource>
+ </resources>
+ </unitTest>
+
+ <!-- Integration unit test classes -->
+ <integrationUnitTestPatterns></integrationUnitTestPatterns>
+
+ <resources>
+ <includes>
+ <include>**/*.properties</include>
+ </includes>
+ </resources>
+ <jars/>
+ </build>
+
+ <reports>
+ <report>maven-changelog-plugin</report>
+ <report>maven-changes-plugin</report>
+ <report>maven-developer-activity-plugin</report>
+ <report>maven-file-activity-plugin</report>
+ <report>maven-javadoc-plugin</report>
+ <report>maven-jdepend-plugin</report>
+ <report>maven-junit-report-plugin</report>
+ <report>maven-jxr-plugin</report>
+ <report>maven-license-plugin</report>
+ <report>maven-tasklist-plugin</report>
+ </reports>
+</project>
Added: trunk/commons-beanutils/branches/upstream/current/src/conf/MANIFEST.MF
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/conf/MANIFEST.MF 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/conf/MANIFEST.MF 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,7 @@
+Extension-Name: org.apache.commons.beanutils
+Specification-Title: Jakarta Commons Beanutils
+Specification-Vendor: Apache Software Foundation
+Specification-Version: 1.6
+Implementation-Title: org.apache.commons.beanutils
+Implementation-Vendor: Apache Software Foundation
+Implementation-Version: 1.6
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BasicDynaBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BasicDynaBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BasicDynaBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,402 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * <p>Minimal implementation of the <code>DynaBean</code> interface. Can be
+ * used as a convenience base class for more sophisticated implementations.</p>
+ *
+ * <p><strong>IMPLEMENTATION NOTE</strong> - Instances of this class that are
+ * accessed from multiple threads simultaneously need to be synchronized.</p>
+ *
+ * <p><strong>IMPLEMENTATION NOTE</strong> - Instances of this class can be
+ * successfully serialized and deserialized <strong>ONLY</strong> if all
+ * property values are <code>Serializable</code>.</p>
+ *
+ * @author Craig McClanahan
+ * @version $Revision: 1.11 $ $Date: 2004/02/28 13:18:33 $
+ */
+
+public class BasicDynaBean implements DynaBean, Serializable {
+
+
+ // ---------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new <code>DynaBean</code> associated with the specified
+ * <code>DynaClass</code> instance.
+ *
+ * @param dynaClass The DynaClass we are associated with
+ */
+ public BasicDynaBean(DynaClass dynaClass) {
+
+ super();
+ this.dynaClass = dynaClass;
+
+ }
+
+
+ // ---------------------------------------------------- Instance Variables
+
+
+ /**
+ * The <code>DynaClass</code> "base class" that this DynaBean
+ * is associated with.
+ */
+ protected DynaClass dynaClass = null;
+
+
+ /**
+ * The set of property values for this DynaBean, keyed by property name.
+ */
+ protected HashMap values = new HashMap();
+
+
+ // ------------------------------------------------------ DynaBean Methods
+
+
+ /**
+ * Does the specified mapped property contain a value for the specified
+ * key value?
+ *
+ * @param name Name of the property to check
+ * @param key Name of the key to check
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public boolean contains(String name, String key) {
+
+ Object value = values.get(name);
+ if (value == null) {
+ throw new NullPointerException
+ ("No mapped value for '" + name + "(" + key + ")'");
+ } else if (value instanceof Map) {
+ return (((Map) value).containsKey(key));
+ } else {
+ throw new IllegalArgumentException
+ ("Non-mapped property for '" + name + "(" + key + ")'");
+ }
+
+ }
+
+
+ /**
+ * Return the value of a simple property with the specified name.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public Object get(String name) {
+
+ // Return any non-null value for the specified property
+ Object value = values.get(name);
+ if (value != null) {
+ return (value);
+ }
+
+ // Return a null value for a non-primitive property
+ Class type = getDynaProperty(name).getType();
+ if (!type.isPrimitive()) {
+ return (value);
+ }
+
+ // Manufacture default values for primitive properties
+ if (type == Boolean.TYPE) {
+ return (Boolean.FALSE);
+ } else if (type == Byte.TYPE) {
+ return (new Byte((byte) 0));
+ } else if (type == Character.TYPE) {
+ return (new Character((char) 0));
+ } else if (type == Double.TYPE) {
+ return (new Double((double) 0.0));
+ } else if (type == Float.TYPE) {
+ return (new Float((float) 0.0));
+ } else if (type == Integer.TYPE) {
+ return (new Integer((int) 0));
+ } else if (type == Long.TYPE) {
+ return (new Long((int) 0));
+ } else if (type == Short.TYPE) {
+ return (new Short((short) 0));
+ } else {
+ return (null);
+ }
+
+ }
+
+
+ /**
+ * Return the value of an indexed property with the specified name.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ * @param index Index of the value to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not indexed
+ * @exception IndexOutOfBoundsException if the specified index
+ * is outside the range of the underlying property
+ * @exception NullPointerException if no array or List has been
+ * initialized for this property
+ */
+ public Object get(String name, int index) {
+
+ Object value = values.get(name);
+ if (value == null) {
+ throw new NullPointerException
+ ("No indexed value for '" + name + "[" + index + "]'");
+ } else if (value.getClass().isArray()) {
+ return (Array.get(value, index));
+ } else if (value instanceof List) {
+ return ((List) value).get(index);
+ } else {
+ throw new IllegalArgumentException
+ ("Non-indexed property for '" + name + "[" + index + "]'");
+ }
+
+ }
+
+
+ /**
+ * Return the value of a mapped property with the specified name,
+ * or <code>null</code> if there is no value for the specified key.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ * @param key Key of the value to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not mapped
+ */
+ public Object get(String name, String key) {
+
+ Object value = values.get(name);
+ if (value == null) {
+ throw new NullPointerException
+ ("No mapped value for '" + name + "(" + key + ")'");
+ } else if (value instanceof Map) {
+ return (((Map) value).get(key));
+ } else {
+ throw new IllegalArgumentException
+ ("Non-mapped property for '" + name + "(" + key + ")'");
+ }
+
+ }
+
+
+ /**
+ * Return the <code>DynaClass</code> instance that describes the set of
+ * properties available for this DynaBean.
+ */
+ public DynaClass getDynaClass() {
+
+ return (this.dynaClass);
+
+ }
+
+
+ /**
+ * Remove any existing value for the specified key on the
+ * specified mapped property.
+ *
+ * @param name Name of the property for which a value is to
+ * be removed
+ * @param key Key of the value to be removed
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public void remove(String name, String key) {
+
+ Object value = values.get(name);
+ if (value == null) {
+ throw new NullPointerException
+ ("No mapped value for '" + name + "(" + key + ")'");
+ } else if (value instanceof Map) {
+ ((Map) value).remove(key);
+ } else {
+ throw new IllegalArgumentException
+ ("Non-mapped property for '" + name + "(" + key + ")'");
+ }
+
+ }
+
+
+ /**
+ * Set the value of a simple property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception NullPointerException if an attempt is made to set a
+ * primitive property to null
+ */
+ public void set(String name, Object value) {
+
+ DynaProperty descriptor = getDynaProperty(name);
+ if (value == null) {
+ if (descriptor.getType().isPrimitive()) {
+ throw new NullPointerException
+ ("Primitive value for '" + name + "'");
+ }
+ } else if (!isAssignable(descriptor.getType(), value.getClass())) {
+ throw new ConversionException
+ ("Cannot assign value of type '" +
+ value.getClass().getName() +
+ "' to property '" + name + "' of type '" +
+ descriptor.getType().getName() + "'");
+ }
+ values.put(name, value);
+
+ }
+
+
+ /**
+ * Set the value of an indexed property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param index Index of the property to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not indexed
+ * @exception IndexOutOfBoundsException if the specified index
+ * is outside the range of the underlying property
+ */
+ public void set(String name, int index, Object value) {
+
+ Object prop = values.get(name);
+ if (prop == null) {
+ throw new NullPointerException
+ ("No indexed value for '" + name + "[" + index + "]'");
+ } else if (prop.getClass().isArray()) {
+ Array.set(prop, index, value);
+ } else if (prop instanceof List) {
+ try {
+ ((List) prop).set(index, value);
+ } catch (ClassCastException e) {
+ throw new ConversionException(e.getMessage());
+ }
+ } else {
+ throw new IllegalArgumentException
+ ("Non-indexed property for '" + name + "[" + index + "]'");
+ }
+
+ }
+
+
+ /**
+ * Set the value of a mapped property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param key Key of the property to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not mapped
+ */
+ public void set(String name, String key, Object value) {
+
+ Object prop = values.get(name);
+ if (prop == null) {
+ throw new NullPointerException
+ ("No mapped value for '" + name + "(" + key + ")'");
+ } else if (prop instanceof Map) {
+ ((Map) prop).put(key, value);
+ } else {
+ throw new IllegalArgumentException
+ ("Non-mapped property for '" + name + "(" + key + ")'");
+ }
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Return the property descriptor for the specified property name.
+ *
+ * @param name Name of the property for which to retrieve the descriptor
+ *
+ * @exception IllegalArgumentException if this is not a valid property
+ * name for our DynaClass
+ */
+ protected DynaProperty getDynaProperty(String name) {
+
+ DynaProperty descriptor = getDynaClass().getDynaProperty(name);
+ if (descriptor == null) {
+ throw new IllegalArgumentException
+ ("Invalid property name '" + name + "'");
+ }
+ return (descriptor);
+
+ }
+
+
+ /**
+ * Is an object of the source class assignable to the destination class?
+ *
+ * @param dest Destination class
+ * @param source Source class
+ */
+ protected boolean isAssignable(Class dest, Class source) {
+
+ if (dest.isAssignableFrom(source) ||
+ ((dest == Boolean.TYPE) && (source == Boolean.class)) ||
+ ((dest == Byte.TYPE) && (source == Byte.class)) ||
+ ((dest == Character.TYPE) && (source == Character.class)) ||
+ ((dest == Double.TYPE) && (source == Double.class)) ||
+ ((dest == Float.TYPE) && (source == Float.class)) ||
+ ((dest == Integer.TYPE) && (source == Integer.class)) ||
+ ((dest == Long.TYPE) && (source == Long.class)) ||
+ ((dest == Short.TYPE) && (source == Short.class))) {
+ return (true);
+ } else {
+ return (false);
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BasicDynaClass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BasicDynaClass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BasicDynaClass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+
+
+/**
+ * <p>Minimal implementation of the <code>DynaClass</code> interface. Can be
+ * used as a convenience base class for more sophisticated implementations.</p> *
+ * <p><strong>IMPLEMENTATION NOTE</strong> - The <code>DynaBean</code>
+ * implementation class supplied to our constructor MUST have a one-argument
+ * constructor of its own that accepts a <code>DynaClass</code>. This is
+ * used to associate the DynaBean instance with this DynaClass.</p>
+ *
+ * @author Craig McClanahan
+ * @version $Revision: 1.11 $ $Date: 2004/02/28 13:18:33 $
+ */
+
+public class BasicDynaClass implements DynaClass, Serializable {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new BasicDynaClass with default parameters.
+ */
+ public BasicDynaClass() {
+
+ this(null, null, null);
+
+ }
+
+
+ /**
+ * Construct a new BasicDynaClass with the specified parameters.
+ *
+ * @param name Name of this DynaBean class
+ * @param dynaBeanClass The implementation class for new instances
+ */
+ public BasicDynaClass(String name, Class dynaBeanClass) {
+
+ this(name, dynaBeanClass, null);
+
+ }
+
+
+ /**
+ * Construct a new BasicDynaClass with the specified parameters.
+ *
+ * @param name Name of this DynaBean class
+ * @param dynaBeanClass The implementation class for new intances
+ * @param properties Property descriptors for the supported properties
+ */
+ public BasicDynaClass(String name, Class dynaBeanClass,
+ DynaProperty properties[]) {
+
+ super();
+ if (name != null)
+ this.name = name;
+ if (dynaBeanClass == null)
+ dynaBeanClass = BasicDynaBean.class;
+ setDynaBeanClass(dynaBeanClass);
+ if (properties != null)
+ setProperties(properties);
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The constructor of the <code>dynaBeanClass</code> that we will use
+ * for creating new instances.
+ */
+ protected transient Constructor constructor = null;
+
+
+ /**
+ * The method signature of the constructor we will use to create
+ * new DynaBean instances.
+ */
+ protected static Class constructorTypes[] = { DynaClass.class };
+
+
+ /**
+ * The argument values to be passed to the constructore we will use
+ * to create new DynaBean instances.
+ */
+ protected Object constructorValues[] = { this };
+
+
+ /**
+ * The <code>DynaBean</code> implementation class we will use for
+ * creating new instances.
+ */
+ protected Class dynaBeanClass = BasicDynaBean.class;
+
+
+ /**
+ * The "name" of this DynaBean class.
+ */
+ protected String name = this.getClass().getName();
+
+
+ /**
+ * The set of dynamic properties that are part of this DynaClass.
+ */
+ protected DynaProperty properties[] = new DynaProperty[0];
+
+
+ /**
+ * The set of dynamic properties that are part of this DynaClass,
+ * keyed by the property name. Individual descriptor instances will
+ * be the same instances as those in the <code>properties</code> list.
+ */
+ protected HashMap propertiesMap = new HashMap();
+
+
+ // ------------------------------------------------------ DynaClass Methods
+
+
+ /**
+ * Return the name of this DynaClass (analogous to the
+ * <code>getName()</code> method of <code>java.lang.Class</code), which
+ * allows the same <code>DynaClass</code> implementation class to support
+ * different dynamic classes, with different sets of properties.
+ */
+ public String getName() {
+
+ return (this.name);
+
+ }
+
+
+ /**
+ * Return a property descriptor for the specified property, if it exists;
+ * otherwise, return <code>null</code>.
+ *
+ * @param name Name of the dynamic property for which a descriptor
+ * is requested
+ *
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ public DynaProperty getDynaProperty(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException
+ ("No property name specified");
+ }
+ return ((DynaProperty) propertiesMap.get(name));
+
+ }
+
+
+ /**
+ * <p>Return an array of <code>ProperyDescriptors</code> for the properties
+ * currently defined in this DynaClass. If no properties are defined, a
+ * zero-length array will be returned.</p>
+ *
+ * <p><strong>FIXME</strong> - Should we really be implementing
+ * <code>getBeanInfo()</code> instead, which returns property descriptors
+ * and a bunch of other stuff?</p>
+ */
+ public DynaProperty[] getDynaProperties() {
+
+ return (properties);
+
+ }
+
+
+ /**
+ * Instantiate and return a new DynaBean instance, associated
+ * with this DynaClass.
+ *
+ * @exception IllegalAccessException if the Class or the appropriate
+ * constructor is not accessible
+ * @exception InstantiationException if this Class represents an abstract
+ * class, an array class, a primitive type, or void; or if instantiation
+ * fails for some other reason
+ */
+ public DynaBean newInstance()
+ throws IllegalAccessException, InstantiationException {
+
+ try {
+ // Refind the constructor after a deserialization (if needed)
+ if (constructor == null) {
+ setDynaBeanClass(this.dynaBeanClass);
+ }
+ // Invoke the constructor to create a new bean instance
+ return ((DynaBean) constructor.newInstance(constructorValues));
+ } catch (InvocationTargetException e) {
+ throw new InstantiationException
+ (e.getTargetException().getMessage());
+ }
+
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Return the Class object we will use to create new instances in the
+ * <code>newInstance()</code> method. This Class <strong>MUST</strong>
+ * implement the <code>DynaBean</code> interface.
+ */
+ public Class getDynaBeanClass() {
+
+ return (this.dynaBeanClass);
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Set the Class object we will use to create new instances in the
+ * <code>newInstance()</code> method. This Class <strong>MUST</strong>
+ * implement the <code>DynaBean</code> interface.
+ *
+ * @param dynaBeanClass The new Class object
+ *
+ * @exception IllegalArgumentException if the specified Class does not
+ * implement the <code>DynaBean</code> interface
+ */
+ protected void setDynaBeanClass(Class dynaBeanClass) {
+
+ // Validate the argument type specified
+ if (dynaBeanClass.isInterface())
+ throw new IllegalArgumentException
+ ("Class " + dynaBeanClass.getName() +
+ " is an interface, not a class");
+ if (!DynaBean.class.isAssignableFrom(dynaBeanClass))
+ throw new IllegalArgumentException
+ ("Class " + dynaBeanClass.getName() +
+ " does not implement DynaBean");
+
+ // Identify the Constructor we will use in newInstance()
+ try {
+ this.constructor = dynaBeanClass.getConstructor(constructorTypes);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException
+ ("Class " + dynaBeanClass.getName() +
+ " does not have an appropriate constructor");
+ }
+ this.dynaBeanClass = dynaBeanClass;
+
+ }
+
+
+ /**
+ * Set the list of dynamic properties supported by this DynaClass.
+ *
+ * @param properties List of dynamic properties to be supported
+ */
+ protected void setProperties(DynaProperty properties[]) {
+
+ this.properties = properties;
+ propertiesMap.clear();
+ for (int i = 0; i < properties.length; i++) {
+ propertiesMap.put(properties[i].getName(), properties[i]);
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanAccessLanguageException.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanAccessLanguageException.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanAccessLanguageException.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+/**
+ * Thrown to indicate that the <em>Bean Access Language</em> cannot execute query
+ * against given bean. This is a runtime exception and access langauges are encouraged
+ * to subclass to create custom exceptions whenever appropriate.
+ *
+ * @author Robert Burrell Donkin
+ * @since 1.7
+ */
+
+public class BeanAccessLanguageException extends IllegalArgumentException {
+
+ // --------------------------------------------------------- Constuctors
+
+ /**
+ * Constructs a <code>BeanAccessLanguageException</code> without a detail message.
+ */
+ public BeanAccessLanguageException() {
+ super();
+ }
+
+ /**
+ * Constructs a <code>BeanAccessLanguageException</code> without a detail message.
+ *
+ * @param message the detail message explaining this exception
+ */
+ public BeanAccessLanguageException(String message) {
+ super(message);
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanUtils.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanUtils.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanUtils.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+
+import org.apache.commons.collections.FastHashMap;
+
+
+/**
+ * <p>Utility methods for populating JavaBeans properties via reflection.</p>
+ *
+ * <p>The implementations are provided by {@link BeanUtilsBean}.
+ * These static utility methods use the default instance.
+ * More sophisticated behaviour can be provided by using a <code>BeanUtilsBean</code> instance.</p>
+ *
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author Rey François
+ * @author Gregor Raýman
+ * @version $Revision: 1.40 $ $Date: 2004/02/28 13:18:33 $
+ * @see BeanUtilsBean
+ */
+
+public class BeanUtils {
+
+
+ // ------------------------------------------------------ Private Variables
+
+
+ /**
+ * Dummy collection from the Commons Collections API, to force a
+ * ClassNotFoundException if commons-collections.jar is not present in the
+ * runtime classpath, and this class is the first one referenced.
+ * Otherwise, the ClassNotFoundException thrown by ConvertUtils or
+ * PropertyUtils can get masked.
+ */
+ private static FastHashMap dummy = new FastHashMap();
+
+ /**
+ * The debugging detail level for this component.
+ * @deprecated BeanUtils now uses commons-logging for all log messages.
+ * Use your favorite logging tool to configure logging for
+ * this class.
+ */
+ private static int debug = 0;
+
+ /**
+ * @deprecated BeanUtils now uses commons-logging for all log messages.
+ * Use your favorite logging tool to configure logging for
+ * this class.
+ */
+ public static int getDebug() {
+ return (debug);
+ }
+
+ /**
+ * @deprecated BeanUtils now uses commons-logging for all log messages.
+ * Use your favorite logging tool to configure logging for
+ * this class.
+ */
+ public static void setDebug(int newDebug) {
+ debug = newDebug;
+ }
+
+ // --------------------------------------------------------- Class Methods
+
+
+ /**
+ * <p>Clone a bean based on the available property getters and setters,
+ * even if the bean class itself does not implement Cloneable.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#cloneBean
+ */
+ public static Object cloneBean(Object bean)
+ throws IllegalAccessException, InstantiationException,
+ InvocationTargetException, NoSuchMethodException {
+
+ return BeanUtilsBean.getInstance().cloneBean(bean);
+
+ }
+
+
+ /**
+ * <p>Copy property values from the origin bean to the destination bean
+ * for all cases where the property names are the same.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#copyProperties
+ */
+ public static void copyProperties(Object dest, Object orig)
+ throws IllegalAccessException, InvocationTargetException {
+
+ BeanUtilsBean.getInstance().copyProperties(dest, orig);
+ }
+
+
+ /**
+ * <p>Copy the specified property value to the specified destination bean,
+ * performing any type conversion that is required.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#copyProperty
+ */
+ public static void copyProperty(Object bean, String name, Object value)
+ throws IllegalAccessException, InvocationTargetException {
+
+ BeanUtilsBean.getInstance().copyProperty(bean, name, value);
+ }
+
+
+ /**
+ * <p>Return the entire set of properties for which the specified bean
+ * provides a read method.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#describe
+ */
+ public static Map describe(Object bean)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return BeanUtilsBean.getInstance().describe(bean);
+ }
+
+
+ /**
+ * <p>Return the value of the specified array property of the specified
+ * bean, as a String array.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#getArrayProperty
+ */
+ public static String[] getArrayProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return BeanUtilsBean.getInstance().getArrayProperty(bean, name);
+ }
+
+
+ /**
+ * <p>Return the value of the specified indexed property of the specified
+ * bean, as a String.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#getIndexedProperty(Object, String)
+ */
+ public static String getIndexedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return BeanUtilsBean.getInstance().getIndexedProperty(bean, name);
+
+ }
+
+
+ /**
+ * Return the value of the specified indexed property of the specified
+ * bean, as a String. The index is specified as a method parameter and
+ * must *not* be included in the property name expression
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#getIndexedProperty(Object, String, int)
+ */
+ public static String getIndexedProperty(Object bean,
+ String name, int index)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return BeanUtilsBean.getInstance().getIndexedProperty(bean, name, index);
+
+ }
+
+
+ /**
+ * </p>Return the value of the specified indexed property of the specified
+ * bean, as a String.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#getMappedProperty(Object, String)
+ */
+ public static String getMappedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return BeanUtilsBean.getInstance().getMappedProperty(bean, name);
+
+ }
+
+
+ /**
+ * </p>Return the value of the specified mapped property of the specified
+ * bean, as a String.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#getMappedProperty(Object, String, String)
+ */
+ public static String getMappedProperty(Object bean,
+ String name, String key)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return BeanUtilsBean.getInstance().getMappedProperty(bean, name, key);
+
+ }
+
+
+ /**
+ * <p>Return the value of the (possibly nested) property of the specified
+ * name, for the specified bean, as a String.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#getNestedProperty
+ */
+ public static String getNestedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return BeanUtilsBean.getInstance().getNestedProperty(bean, name);
+
+ }
+
+
+ /**
+ * <p>Return the value of the specified property of the specified bean,
+ * no matter which property reference format is used, as a String.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#getProperty
+ */
+ public static String getProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return BeanUtilsBean.getInstance().getProperty(bean, name);
+
+ }
+
+
+ /**
+ * <p>Return the value of the specified simple property of the specified
+ * bean, converted to a String.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#getSimpleProperty
+ */
+ public static String getSimpleProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return BeanUtilsBean.getInstance().getSimpleProperty(bean, name);
+
+ }
+
+
+ /**
+ * <p>Populate the JavaBeans properties of the specified bean, based on
+ * the specified name/value pairs.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#populate
+ */
+ public static void populate(Object bean, Map properties)
+ throws IllegalAccessException, InvocationTargetException {
+
+ BeanUtilsBean.getInstance().populate(bean, properties);
+ }
+
+
+ /**
+ * <p>Set the specified property value, performing type conversions as
+ * required to conform to the type of the destination property.</p>
+ *
+ * <p>For more details see <code>BeanUtilsBean</code>.</p>
+ *
+ * @see BeanUtilsBean#setProperty
+ */
+ public static void setProperty(Object bean, String name, Object value)
+ throws IllegalAccessException, InvocationTargetException {
+
+ BeanUtilsBean.getInstance().setProperty(bean, name, value);
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanUtilsBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanUtilsBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/BeanUtilsBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,1075 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.apache.commons.collections.FastHashMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * <p>JavaBean property population methods.</p>
+ *
+ * <p>This class provides implementations for the utility methods in
+ * {@link BeanUtils}.
+ * Different instances can be used to isolate caches between classloaders
+ * and to vary the value converters registered.</p>
+ *
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author Rey François
+ * @author Gregor Raýman
+ * @version $Revision: 1.16 $ $Date: 2004/02/28 13:18:33 $
+ * @see BeanUtils
+ * @since 1.7
+ */
+
+public class BeanUtilsBean {
+
+
+ // ------------------------------------------------------ Private Class Variables
+
+ /**
+ * Contains <code>BeanUtilsBean</code> instances indexed by context classloader.
+ */
+ private static final ContextClassLoaderLocal
+ beansByClassLoader = new ContextClassLoaderLocal() {
+ // Creates the default instance used when the context classloader is unavailable
+ protected Object initialValue() {
+ return new BeanUtilsBean();
+ }
+ };
+
+ /**
+ * Gets the instance which provides the functionality for {@link BeanUtils}.
+ * This is a pseudo-singleton - an single instance is provided per (thread) context classloader.
+ * This mechanism provides isolation for web apps deployed in the same container.
+ */
+ public synchronized static BeanUtilsBean getInstance() {
+ return (BeanUtilsBean) beansByClassLoader.get();
+ }
+
+ /**
+ * Sets the instance which provides the functionality for {@link BeanUtils}.
+ * This is a pseudo-singleton - an single instance is provided per (thread) context classloader.
+ * This mechanism provides isolation for web apps deployed in the same container.
+ */
+ public synchronized static void setInstance(BeanUtilsBean newInstance) {
+ beansByClassLoader.set(newInstance);
+ }
+
+ // --------------------------------------------------------- Attributes
+
+ /**
+ * Logging for this instance
+ */
+ private Log log = LogFactory.getLog(BeanUtils.class);
+
+ /** Used to perform conversions between object types when setting properties */
+ private ConvertUtilsBean convertUtilsBean;
+
+ /** Used to access properties*/
+ private PropertyUtilsBean propertyUtilsBean;
+
+ // --------------------------------------------------------- Constuctors
+
+ /**
+ * <p>Constructs an instance using new property
+ * and conversion instances.</p>
+ */
+ public BeanUtilsBean() {
+ this(new ConvertUtilsBean(), new PropertyUtilsBean());
+ }
+
+ /**
+ * <p>Constructs an instance using given property and conversion instances.</p>
+ *
+ * @param convertUtilsBean use this <code>ConvertUtilsBean</code>
+ * to perform conversions from one object to another
+ * @param propertyUtilsBean use this <code>PropertyUtilsBean</code>
+ * to access properties
+ */
+ public BeanUtilsBean(
+ ConvertUtilsBean convertUtilsBean,
+ PropertyUtilsBean propertyUtilsBean) {
+
+ this.convertUtilsBean = convertUtilsBean;
+ this.propertyUtilsBean = propertyUtilsBean;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * <p>Clone a bean based on the available property getters and setters,
+ * even if the bean class itself does not implement Cloneable.</p>
+ *
+ * <p>
+ * <strong>Note:</strong> this method creates a <strong>shallow</strong> clone.
+ * In other words, any objects referred to by the bean are shared with the clone
+ * rather than being cloned in turn.
+ * </p>
+ *
+ * @param bean Bean to be cloned
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InstantiationException if a new instance of the bean's
+ * class cannot be instantiated
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * property cannot be found
+ */
+ public Object cloneBean(Object bean)
+ throws IllegalAccessException, InstantiationException,
+ InvocationTargetException, NoSuchMethodException {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Cloning bean: " + bean.getClass().getName());
+ }
+ Class clazz = bean.getClass();
+ Object newBean = null;
+ if (bean instanceof DynaBean) {
+ newBean = ((DynaBean) bean).getDynaClass().newInstance();
+ } else {
+ newBean = bean.getClass().newInstance();
+ }
+ getPropertyUtils().copyProperties(newBean, bean);
+ return (newBean);
+
+ }
+
+
+ /**
+ * <p>Copy property values from the origin bean to the destination bean
+ * for all cases where the property names are the same. For each
+ * property, a conversion is attempted as necessary. All combinations of
+ * standard JavaBeans and DynaBeans as origin and destination are
+ * supported. Properties that exist in the origin bean, but do not exist
+ * in the destination bean (or are read-only in the destination bean) are
+ * silently ignored.</p>
+ *
+ * <p>If the origin "bean" is actually a <code>Map</code>, it is assumed
+ * to contain String-valued <strong>simple</strong> property names as the keys, pointing at
+ * the corresponding property values that will be converted (if necessary)
+ * and set in the destination bean. <strong>Note</strong> that this method
+ * is intended to perform a "shallow copy" of the properties and so complex
+ * properties (for example, nested ones) will not be copied.</p>
+ *
+ * <p>This method differs from <code>populate()</code>, which
+ * was primarily designed for populating JavaBeans from the map of request
+ * parameters retrieved on an HTTP request, is that no scalar->indexed
+ * or indexed->scalar manipulations are performed. If the origin property
+ * is indexed, the destination property must be also.</p>
+ *
+ * <p>If you know that no type conversions are required, the
+ * <code>copyProperties()</code> method in {@link PropertyUtils} will
+ * execute faster than this method.</p>
+ *
+ * <p><strong>FIXME</strong> - Indexed and mapped properties that do not
+ * have getter and setter methods for the underlying array or Map are not
+ * copied by this method.</p>
+ *
+ * @param dest Destination bean whose properties are modified
+ * @param orig Origin bean whose properties are retrieved
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if the <code>dest</code> or
+ * <code>orig</code> argument is null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ */
+ public void copyProperties(Object dest, Object orig)
+ throws IllegalAccessException, InvocationTargetException {
+
+ // Validate existence of the specified beans
+ if (dest == null) {
+ throw new IllegalArgumentException
+ ("No destination bean specified");
+ }
+ if (orig == null) {
+ throw new IllegalArgumentException("No origin bean specified");
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("BeanUtils.copyProperties(" + dest + ", " +
+ orig + ")");
+ }
+
+ // Copy the properties, converting as necessary
+ if (orig instanceof DynaBean) {
+ DynaProperty origDescriptors[] =
+ ((DynaBean) orig).getDynaClass().getDynaProperties();
+ for (int i = 0; i < origDescriptors.length; i++) {
+ String name = origDescriptors[i].getName();
+ if (getPropertyUtils().isWriteable(dest, name)) {
+ Object value = ((DynaBean) orig).get(name);
+ copyProperty(dest, name, value);
+ }
+ }
+ } else if (orig instanceof Map) {
+ Iterator names = ((Map) orig).keySet().iterator();
+ while (names.hasNext()) {
+ String name = (String) names.next();
+ if (getPropertyUtils().isWriteable(dest, name)) {
+ Object value = ((Map) orig).get(name);
+ copyProperty(dest, name, value);
+ }
+ }
+ } else /* if (orig is a standard JavaBean) */ {
+ PropertyDescriptor origDescriptors[] =
+ getPropertyUtils().getPropertyDescriptors(orig);
+ for (int i = 0; i < origDescriptors.length; i++) {
+ String name = origDescriptors[i].getName();
+ if ("class".equals(name)) {
+ continue; // No point in trying to set an object's class
+ }
+ if (getPropertyUtils().isReadable(orig, name) &&
+ getPropertyUtils().isWriteable(dest, name)) {
+ try {
+ Object value =
+ getPropertyUtils().getSimpleProperty(orig, name);
+ copyProperty(dest, name, value);
+ } catch (NoSuchMethodException e) {
+ ; // Should not happen
+ }
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * <p>Copy the specified property value to the specified destination bean,
+ * performing any type conversion that is required. If the specified
+ * bean does not have a property of the specified name, or the property
+ * is read only on the destination bean, return without
+ * doing anything. If you have custom destination property types, register
+ * {@link Converter}s for them by calling the <code>register()</code>
+ * method of {@link ConvertUtils}.</p>
+ *
+ * <p><strong>IMPLEMENTATION RESTRICTIONS</strong>:</p>
+ * <ul>
+ * <li>Does not support destination properties that are indexed,
+ * but only an indexed setter (as opposed to an array setter)
+ * is available.</li>
+ * <li>Does not support destination properties that are mapped,
+ * but only a keyed setter (as opposed to a Map setter)
+ * is available.</li>
+ * <li>The desired property type of a mapped setter cannot be
+ * determined (since Maps support any data type), so no conversion
+ * will be performed.</li>
+ * </ul>
+ *
+ * @param bean Bean on which setting is to be performed
+ * @param name Property name (can be nested/indexed/mapped/combo)
+ * @param value Value to be set
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ */
+ public void copyProperty(Object bean, String name, Object value)
+ throws IllegalAccessException, InvocationTargetException {
+
+ // Trace logging (if enabled)
+ if (log.isTraceEnabled()) {
+ StringBuffer sb = new StringBuffer(" copyProperty(");
+ sb.append(bean);
+ sb.append(", ");
+ sb.append(name);
+ sb.append(", ");
+ if (value == null) {
+ sb.append("<NULL>");
+ } else if (value instanceof String) {
+ sb.append((String) value);
+ } else if (value instanceof String[]) {
+ String values[] = (String[]) value;
+ sb.append('[');
+ for (int i = 0; i < values.length; i++) {
+ if (i > 0) {
+ sb.append(',');
+ }
+ sb.append(values[i]);
+ }
+ sb.append(']');
+ } else {
+ sb.append(value.toString());
+ }
+ sb.append(')');
+ log.trace(sb.toString());
+ }
+
+ // Resolve any nested expression to get the actual target bean
+ Object target = bean;
+ int delim = name.lastIndexOf(PropertyUtils.NESTED_DELIM);
+ if (delim >= 0) {
+ try {
+ target =
+ getPropertyUtils().getProperty(bean, name.substring(0, delim));
+ } catch (NoSuchMethodException e) {
+ return; // Skip this property setter
+ }
+ name = name.substring(delim + 1);
+ if (log.isTraceEnabled()) {
+ log.trace(" Target bean = " + target);
+ log.trace(" Target name = " + name);
+ }
+ }
+
+ // Declare local variables we will require
+ String propName = null; // Simple name of target property
+ Class type = null; // Java type of target property
+ int index = -1; // Indexed subscript value (if any)
+ String key = null; // Mapped key value (if any)
+
+ // Calculate the target property name, index, and key values
+ propName = name;
+ int i = propName.indexOf(PropertyUtils.INDEXED_DELIM);
+ if (i >= 0) {
+ int k = propName.indexOf(PropertyUtils.INDEXED_DELIM2);
+ try {
+ index =
+ Integer.parseInt(propName.substring(i + 1, k));
+ } catch (NumberFormatException e) {
+ ;
+ }
+ propName = propName.substring(0, i);
+ }
+ int j = propName.indexOf(PropertyUtils.MAPPED_DELIM);
+ if (j >= 0) {
+ int k = propName.indexOf(PropertyUtils.MAPPED_DELIM2);
+ try {
+ key = propName.substring(j + 1, k);
+ } catch (IndexOutOfBoundsException e) {
+ ;
+ }
+ propName = propName.substring(0, j);
+ }
+
+ // Calculate the target property type
+ if (target instanceof DynaBean) {
+ DynaClass dynaClass = ((DynaBean) target).getDynaClass();
+ DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
+ if (dynaProperty == null) {
+ return; // Skip this property setter
+ }
+ type = dynaProperty.getType();
+ } else {
+ PropertyDescriptor descriptor = null;
+ try {
+ descriptor =
+ getPropertyUtils().getPropertyDescriptor(target, name);
+ if (descriptor == null) {
+ return; // Skip this property setter
+ }
+ } catch (NoSuchMethodException e) {
+ return; // Skip this property setter
+ }
+ type = descriptor.getPropertyType();
+ if (type == null) {
+ // Most likely an indexed setter on a POJB only
+ if (log.isTraceEnabled()) {
+ log.trace(" target type for property '" +
+ propName + "' is null, so skipping ths setter");
+ }
+ return;
+ }
+ }
+ if (log.isTraceEnabled()) {
+ log.trace(" target propName=" + propName + ", type=" +
+ type + ", index=" + index + ", key=" + key);
+ }
+
+ // Convert the specified value to the required type and store it
+ if (index >= 0) { // Destination must be indexed
+ Converter converter = getConvertUtils().lookup(type.getComponentType());
+ if (converter != null) {
+ log.trace(" USING CONVERTER " + converter);
+ value = converter.convert(type, value);
+ }
+ try {
+ getPropertyUtils().setIndexedProperty(target, propName,
+ index, value);
+ } catch (NoSuchMethodException e) {
+ throw new InvocationTargetException
+ (e, "Cannot set " + propName);
+ }
+ } else if (key != null) { // Destination must be mapped
+ // Maps do not know what the preferred data type is,
+ // so perform no conversions at all
+ // FIXME - should we create or support a TypedMap?
+ try {
+ getPropertyUtils().setMappedProperty(target, propName,
+ key, value);
+ } catch (NoSuchMethodException e) {
+ throw new InvocationTargetException
+ (e, "Cannot set " + propName);
+ }
+ } else { // Destination must be simple
+ Converter converter = getConvertUtils().lookup(type);
+ if (converter != null) {
+ log.trace(" USING CONVERTER " + converter);
+ value = converter.convert(type, value);
+ }
+ try {
+ getPropertyUtils().setSimpleProperty(target, propName, value);
+ } catch (NoSuchMethodException e) {
+ throw new InvocationTargetException
+ (e, "Cannot set " + propName);
+ }
+ }
+
+ }
+
+
+ /**
+ * <p>Return the entire set of properties for which the specified bean
+ * provides a read method. This map contains the to <code>String</code>
+ * converted property values for all properties for which a read method
+ * is provided (i.e. where the getReadMethod() returns non-null).</p>
+ *
+ * <p>This map can be fed back to a call to
+ * <code>BeanUtils.populate()</code> to reconsitute the same set of
+ * properties, modulo differences for read-only and write-only
+ * properties, but only if there are no indexed properties.</p>
+ *
+ * @param bean Bean whose properties are to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * property cannot be found
+ */
+ public Map describe(Object bean)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ // return (Collections.EMPTY_MAP);
+ return (new java.util.HashMap());
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("Describing bean: " + bean.getClass().getName());
+ }
+
+ Map description = new HashMap();
+ if (bean instanceof DynaBean) {
+ DynaProperty descriptors[] =
+ ((DynaBean) bean).getDynaClass().getDynaProperties();
+ for (int i = 0; i < descriptors.length; i++) {
+ String name = descriptors[i].getName();
+ description.put(name, getProperty(bean, name));
+ }
+ } else {
+ PropertyDescriptor descriptors[] =
+ getPropertyUtils().getPropertyDescriptors(bean);
+ for (int i = 0; i < descriptors.length; i++) {
+ String name = descriptors[i].getName();
+ if (descriptors[i].getReadMethod() != null)
+ description.put(name, getProperty(bean, name));
+ }
+ }
+ return (description);
+
+ }
+
+
+ /**
+ * Return the value of the specified array property of the specified
+ * bean, as a String array.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Name of the property to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * property cannot be found
+ */
+ public String[] getArrayProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getProperty(bean, name);
+ if (value == null) {
+ return (null);
+ } else if (value instanceof Collection) {
+ ArrayList values = new ArrayList();
+ Iterator items = ((Collection) value).iterator();
+ while (items.hasNext()) {
+ Object item = items.next();
+ if (item == null) {
+ values.add((String) null);
+ } else {
+ // convert to string using convert utils
+ values.add(getConvertUtils().convert(item));
+ }
+ }
+ return ((String[]) values.toArray(new String[values.size()]));
+ } else if (value.getClass().isArray()) {
+ int n = Array.getLength(value);
+ String results[] = new String[n];
+ for (int i = 0; i < n; i++) {
+ Object item = Array.get(value, i);
+ if (item == null) {
+ results[i] = null;
+ } else {
+ // convert to string using convert utils
+ results[i] = getConvertUtils().convert(item);
+ }
+ }
+ return (results);
+ } else {
+ String results[] = new String[1];
+ results[0] = value.toString();
+ return (results);
+ }
+
+ }
+
+
+ /**
+ * Return the value of the specified indexed property of the specified
+ * bean, as a String. The zero-relative index of the
+ * required value must be included (in square brackets) as a suffix to
+ * the property name, or <code>IllegalArgumentException</code> will be
+ * thrown.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name <code>propertyname[index]</code> of the property value
+ * to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * property cannot be found
+ */
+ public String getIndexedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getIndexedProperty(bean, name);
+ return (getConvertUtils().convert(value));
+
+ }
+
+
+ /**
+ * Return the value of the specified indexed property of the specified
+ * bean, as a String. The index is specified as a method parameter and
+ * must *not* be included in the property name expression
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Simple property name of the property value to be extracted
+ * @param index Index of the property value to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * property cannot be found
+ */
+ public String getIndexedProperty(Object bean,
+ String name, int index)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getIndexedProperty(bean, name, index);
+ return (getConvertUtils().convert(value));
+
+ }
+
+
+ /**
+ * Return the value of the specified indexed property of the specified
+ * bean, as a String. The String-valued key of the required value
+ * must be included (in parentheses) as a suffix to
+ * the property name, or <code>IllegalArgumentException</code> will be
+ * thrown.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name <code>propertyname(index)</code> of the property value
+ * to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * property cannot be found
+ */
+ public String getMappedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getMappedProperty(bean, name);
+ return (getConvertUtils().convert(value));
+
+ }
+
+
+ /**
+ * Return the value of the specified mapped property of the specified
+ * bean, as a String. The key is specified as a method parameter and
+ * must *not* be included in the property name expression
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Simple property name of the property value to be extracted
+ * @param key Lookup key of the property value to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * property cannot be found
+ */
+ public String getMappedProperty(Object bean,
+ String name, String key)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getMappedProperty(bean, name, key);
+ return (getConvertUtils().convert(value));
+
+ }
+
+
+ /**
+ * Return the value of the (possibly nested) property of the specified
+ * name, for the specified bean, as a String.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Possibly nested name of the property to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if a nested reference to a
+ * property returns null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * property cannot be found
+ */
+ public String getNestedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getNestedProperty(bean, name);
+ return (getConvertUtils().convert(value));
+
+ }
+
+
+ /**
+ * Return the value of the specified property of the specified bean,
+ * no matter which property reference format is used, as a String.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Possibly indexed and/or nested name of the property
+ * to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * property cannot be found
+ */
+ public String getProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return (getNestedProperty(bean, name));
+
+ }
+
+
+ /**
+ * Return the value of the specified simple property of the specified
+ * bean, converted to a String.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Name of the property to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * property cannot be found
+ */
+ public String getSimpleProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getSimpleProperty(bean, name);
+ return (getConvertUtils().convert(value));
+
+ }
+
+
+ /**
+ * <p>Populate the JavaBeans properties of the specified bean, based on
+ * the specified name/value pairs. This method uses Java reflection APIs
+ * to identify corresponding "property setter" method names, and deals
+ * with setter arguments of type <code>String</code>, <code>boolean</code>,
+ * <code>int</code>, <code>long</code>, <code>float</code>, and
+ * <code>double</code>. In addition, array setters for these types (or the
+ * corresponding primitive types) can also be identified.</p>
+ *
+ * <p>The particular setter method to be called for each property is
+ * determined using the usual JavaBeans introspection mechanisms. Thus,
+ * you may identify custom setter methods using a BeanInfo class that is
+ * associated with the class of the bean itself. If no such BeanInfo
+ * class is available, the standard method name conversion ("set" plus
+ * the capitalized name of the property in question) is used.</p>
+ *
+ * <p><strong>NOTE</strong>: It is contrary to the JavaBeans Specification
+ * to have more than one setter method (with different argument
+ * signatures) for the same property.</p>
+ *
+ * <p><strong>WARNING</strong> - The logic of this method is customized
+ * for extracting String-based request parameters from an HTTP request.
+ * It is probably not what you want for general property copying with
+ * type conversion. For that purpose, check out the
+ * <code>copyProperties()</code> method instead.</p>
+ *
+ * @param bean JavaBean whose properties are being populated
+ * @param properties Map keyed by property name, with the
+ * corresponding (String or String[]) value(s) to be set
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ */
+ public void populate(Object bean, Map properties)
+ throws IllegalAccessException, InvocationTargetException {
+
+ // Do nothing unless both arguments have been specified
+ if ((bean == null) || (properties == null)) {
+ return;
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("BeanUtils.populate(" + bean + ", " +
+ properties + ")");
+ }
+
+ // Loop through the property name/value pairs to be set
+ Iterator names = properties.keySet().iterator();
+ while (names.hasNext()) {
+
+ // Identify the property name and value(s) to be assigned
+ String name = (String) names.next();
+ if (name == null) {
+ continue;
+ }
+ Object value = properties.get(name);
+
+ // Perform the assignment for this property
+ setProperty(bean, name, value);
+
+ }
+
+ }
+
+
+ /**
+ * <p>Set the specified property value, performing type conversions as
+ * required to conform to the type of the destination property.</p>
+ *
+ * <p>If the property is read only then the method returns
+ * without throwing an exception.</p>
+ *
+ * <p>If <code>null</code> is passed into a property expecting a primitive value,
+ * then this will be converted as if it were a <code>null</code> string.</p>
+ *
+ * <p><strong>WARNING</strong> - The logic of this method is customized
+ * to meet the needs of <code>populate()</code>, and is probably not what
+ * you want for general property copying with type conversion. For that
+ * purpose, check out the <code>copyProperty()</code> method instead.</p>
+ *
+ * <p><strong>WARNING</strong> - PLEASE do not modify the behavior of this
+ * method without consulting with the Struts developer community. There
+ * are some subtleties to its functionality that are not documented in the
+ * Javadoc description above, yet are vital to the way that Struts utilizes
+ * this method.</p>
+ *
+ * @param bean Bean on which setting is to be performed
+ * @param name Property name (can be nested/indexed/mapped/combo)
+ * @param value Value to be set
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ */
+ public void setProperty(Object bean, String name, Object value)
+ throws IllegalAccessException, InvocationTargetException {
+
+ // Trace logging (if enabled)
+ if (log.isTraceEnabled()) {
+ StringBuffer sb = new StringBuffer(" setProperty(");
+ sb.append(bean);
+ sb.append(", ");
+ sb.append(name);
+ sb.append(", ");
+ if (value == null) {
+ sb.append("<NULL>");
+ } else if (value instanceof String) {
+ sb.append((String) value);
+ } else if (value instanceof String[]) {
+ String values[] = (String[]) value;
+ sb.append('[');
+ for (int i = 0; i < values.length; i++) {
+ if (i > 0) {
+ sb.append(',');
+ }
+ sb.append(values[i]);
+ }
+ sb.append(']');
+ } else {
+ sb.append(value.toString());
+ }
+ sb.append(')');
+ log.trace(sb.toString());
+ }
+
+ // Resolve any nested expression to get the actual target bean
+ Object target = bean;
+ int delim = findLastNestedIndex(name);
+ if (delim >= 0) {
+ try {
+ target =
+ getPropertyUtils().getProperty(bean, name.substring(0, delim));
+ } catch (NoSuchMethodException e) {
+ return; // Skip this property setter
+ }
+ name = name.substring(delim + 1);
+ if (log.isTraceEnabled()) {
+ log.trace(" Target bean = " + target);
+ log.trace(" Target name = " + name);
+ }
+ }
+
+ // Declare local variables we will require
+ String propName = null; // Simple name of target property
+ Class type = null; // Java type of target property
+ int index = -1; // Indexed subscript value (if any)
+ String key = null; // Mapped key value (if any)
+
+ // Calculate the property name, index, and key values
+ propName = name;
+ int i = propName.indexOf(PropertyUtils.INDEXED_DELIM);
+ if (i >= 0) {
+ int k = propName.indexOf(PropertyUtils.INDEXED_DELIM2);
+ try {
+ index =
+ Integer.parseInt(propName.substring(i + 1, k));
+ } catch (NumberFormatException e) {
+ ;
+ }
+ propName = propName.substring(0, i);
+ }
+ int j = propName.indexOf(PropertyUtils.MAPPED_DELIM);
+ if (j >= 0) {
+ int k = propName.indexOf(PropertyUtils.MAPPED_DELIM2);
+ try {
+ key = propName.substring(j + 1, k);
+ } catch (IndexOutOfBoundsException e) {
+ ;
+ }
+ propName = propName.substring(0, j);
+ }
+
+ // Calculate the property type
+ if (target instanceof DynaBean) {
+ DynaClass dynaClass = ((DynaBean) target).getDynaClass();
+ DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
+ if (dynaProperty == null) {
+ return; // Skip this property setter
+ }
+ type = dynaProperty.getType();
+ } else {
+ PropertyDescriptor descriptor = null;
+ try {
+ descriptor =
+ getPropertyUtils().getPropertyDescriptor(target, name);
+ if (descriptor == null) {
+ return; // Skip this property setter
+ }
+ } catch (NoSuchMethodException e) {
+ return; // Skip this property setter
+ }
+ if (descriptor instanceof MappedPropertyDescriptor) {
+ if (((MappedPropertyDescriptor) descriptor).getMappedWriteMethod() == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping read-only property");
+ }
+ return; // Read-only, skip this property setter
+ }
+ type = ((MappedPropertyDescriptor) descriptor).
+ getMappedPropertyType();
+ } else if (descriptor instanceof IndexedPropertyDescriptor) {
+ if (((IndexedPropertyDescriptor) descriptor).getIndexedWriteMethod() == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping read-only property");
+ }
+ return; // Read-only, skip this property setter
+ }
+ type = ((IndexedPropertyDescriptor) descriptor).
+ getIndexedPropertyType();
+ } else {
+ if (descriptor.getWriteMethod() == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping read-only property");
+ }
+ return; // Read-only, skip this property setter
+ }
+ type = descriptor.getPropertyType();
+ }
+ }
+
+ // Convert the specified value to the required type
+ Object newValue = null;
+ if (type.isArray() && (index < 0)) { // Scalar value into array
+ if (value == null) {
+ String values[] = new String[1];
+ values[0] = (String) value;
+ newValue = getConvertUtils().convert((String[]) values, type);
+ } else if (value instanceof String) {
+ String values[] = new String[1];
+ values[0] = (String) value;
+ newValue = getConvertUtils().convert((String[]) values, type);
+ } else if (value instanceof String[]) {
+ newValue = getConvertUtils().convert((String[]) value, type);
+ } else {
+ newValue = value;
+ }
+ } else if (type.isArray()) { // Indexed value into array
+ if (value instanceof String) {
+ newValue = getConvertUtils().convert((String) value,
+ type.getComponentType());
+ } else if (value instanceof String[]) {
+ newValue = getConvertUtils().convert(((String[]) value)[0],
+ type.getComponentType());
+ } else {
+ newValue = value;
+ }
+ } else { // Value into scalar
+ if ((value instanceof String) || (value == null)) {
+ newValue = getConvertUtils().convert((String) value, type);
+ } else if (value instanceof String[]) {
+ newValue = getConvertUtils().convert(((String[]) value)[0],
+ type);
+ } else if (getConvertUtils().lookup(value.getClass()) != null) {
+ newValue = getConvertUtils().convert(value.toString(), type);
+ } else {
+ newValue = value;
+ }
+ }
+
+ // Invoke the setter method
+ try {
+ if (index >= 0) {
+ getPropertyUtils().setIndexedProperty(target, propName,
+ index, newValue);
+ } else if (key != null) {
+ getPropertyUtils().setMappedProperty(target, propName,
+ key, newValue);
+ } else {
+ getPropertyUtils().setProperty(target, propName, newValue);
+ }
+ } catch (NoSuchMethodException e) {
+ throw new InvocationTargetException
+ (e, "Cannot set " + propName);
+ }
+
+ }
+
+ private int findLastNestedIndex(String expression)
+ {
+ // walk back from the end to the start
+ // and find the first index that
+ int bracketCount = 0;
+ for (int i = expression.length() - 1; i>=0 ; i--) {
+ char at = expression.charAt(i);
+ switch (at) {
+ case PropertyUtils.NESTED_DELIM:
+ if (bracketCount < 1) {
+ return i;
+ }
+ break;
+
+ case PropertyUtils.MAPPED_DELIM:
+ case PropertyUtils.INDEXED_DELIM:
+ // not bothered which
+ --bracketCount;
+ break;
+
+ case PropertyUtils.MAPPED_DELIM2:
+ case PropertyUtils.INDEXED_DELIM2:
+ // not bothered which
+ ++bracketCount;
+ break;
+ }
+ }
+ // can't find any
+ return -1;
+ }
+
+ /**
+ * Gets the <code>ConvertUtilsBean</code> instance used to perform the conversions.
+ */
+ public ConvertUtilsBean getConvertUtils() {
+ return convertUtilsBean;
+ }
+
+ /**
+ * Gets the <code>PropertyUtilsBean</code> instance used to access properties.
+ */
+ public PropertyUtilsBean getPropertyUtils() {
+ return propertyUtilsBean;
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConstructorUtils.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConstructorUtils.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConstructorUtils.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+
+/**
+ * <p> Utility reflection methods focussed on constructors, modelled after {@link MethodUtils}. </p>
+ *
+ * <h3>Known Limitations</h3>
+ * <h4>Accessing Public Constructors In A Default Access Superclass</h4>
+ * <p>There is an issue when invoking public constructors contained in a default access superclass.
+ * Reflection locates these constructors fine and correctly assigns them as public.
+ * However, an <code>IllegalAccessException</code> is thrown if the constructors is invoked.</p>
+ *
+ * <p><code>ConstructorUtils</code> contains a workaround for this situation.
+ * It will attempt to call <code>setAccessible</code> on this constructor.
+ * If this call succeeds, then the method can be invoked as normal.
+ * This call will only succeed when the application has sufficient security privilages.
+ * If this call fails then a warning will be logged and the method may fail.</p>
+ *
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author Rey François
+ * @author Gregor Raýman
+ * @author Jan Sorensen
+ * @author Robert Burrell Donkin
+ * @author Rodney Waldhoff
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:33 $
+ */
+public class ConstructorUtils {
+
+ // --------------------------------------------------------- Private Members
+ /** An empty class array */
+ private static final Class[] emptyClassArray = new Class[0];
+ /** An empty object array */
+ private static final Object[] emptyObjectArray = new Object[0];
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * <p>Convenience method returning new instance of <code>klazz</code> using a single argument constructor.
+ * The formal parameter type is inferred from the actual values of <code>arg</code>.
+ * See {@link #invokeExactConstructor(Class, Object[], Class[])} for more details.</p>
+ *
+ * <p>The signatures should be assignment compatible.</p>
+ *
+ * @param klass the class to be constructed.
+ * @param arg the actual argument
+ * @return new instance of <code>klazz</code>
+ *
+ * @see #invokeConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
+ */
+ public static Object invokeConstructor(Class klass, Object arg)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException,
+ InstantiationException {
+
+ Object[] args = { arg };
+ return invokeConstructor(klass, args);
+
+ }
+
+ /**
+ * <p>Returns new instance of <code>klazz</code> created using the actual arguments <code>args</code>.
+ * The formal parameter types are inferred from the actual values of <code>args</code>.
+ * See {@link #invokeExactConstructor(Class, Object[], Class[])} for more details.</p>
+ *
+ * <p>The signatures should be assignment compatible.</p>
+ *
+ * @param klass the class to be constructed.
+ * @param args actual argument array
+ * @return new instance of <code>klazz</code>
+ *
+ * @see #invokeConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
+ */
+ public static Object invokeConstructor(Class klass, Object[] args)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException,
+ InstantiationException {
+
+ if (null == args) {
+ args = emptyObjectArray;
+ }
+ int arguments = args.length;
+ Class parameterTypes[] = new Class[arguments];
+ for (int i = 0; i < arguments; i++) {
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeConstructor(klass, args, parameterTypes);
+
+ }
+
+ /**
+ * <p>Returns new instance of <code>klazz</code> created using constructor
+ * with signature <code>parameterTypes</code> and actual arguments <code>args</code>.</p>
+ *
+ * <p>The signatures should be assignment compatible.</p>
+ *
+ * @param klass the class to be constructed.
+ * @param args actual argument array
+ * @param parameterTypes parameter types array
+ * @return new instance of <code>klazz</code>
+ *
+ * @throws NoSuchMethodException if matching constructor cannot be found
+ * @throws IllegalAccessException thrown on the constructor's invocation
+ * @throws InvocationTargetException thrown on the constructor's invocation
+ * @throws InstantiationException thrown on the constructor's invocation
+ * @see Constructor#newInstance
+ */
+ public static Object invokeConstructor(
+ Class klass,
+ Object[] args,
+ Class[] parameterTypes)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException,
+ InstantiationException {
+
+ if (parameterTypes == null) {
+ parameterTypes = emptyClassArray;
+ }
+ if (args == null) {
+ args = emptyObjectArray;
+ }
+
+ Constructor ctor =
+ getMatchingAccessibleConstructor(klass, parameterTypes);
+ if (null == ctor) {
+ throw new NoSuchMethodException(
+ "No such accessible constructor on object: " + klass.getName());
+ }
+ return ctor.newInstance(args);
+ }
+
+
+ /**
+ * <p>Convenience method returning new instance of <code>klazz</code> using a single argument constructor.
+ * The formal parameter type is inferred from the actual values of <code>arg</code>.
+ * See {@link #invokeExactConstructor(Class, Object[], Class[])} for more details.</p>
+ *
+ * <p>The signatures should match exactly.</p>
+ *
+ * @param klass the class to be constructed.
+ * @param arg the actual argument
+ * @return new instance of <code>klazz</code>
+ *
+ * @see #invokeExactConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
+ */
+ public static Object invokeExactConstructor(Class klass, Object arg)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException,
+ InstantiationException {
+
+ Object[] args = { arg };
+ return invokeExactConstructor(klass, args);
+
+ }
+
+ /**
+ * <p>Returns new instance of <code>klazz</code> created using the actual arguments <code>args</code>.
+ * The formal parameter types are inferred from the actual values of <code>args</code>.
+ * See {@link #invokeExactConstructor(Class, Object[], Class[])} for more details.</p>
+ *
+ * <p>The signatures should match exactly.</p>
+ *
+ * @param klass the class to be constructed.
+ * @param args actual argument array
+ * @return new instance of <code>klazz</code>
+ *
+ * @see #invokeExactConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
+ */
+ public static Object invokeExactConstructor(Class klass, Object[] args)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException,
+ InstantiationException {
+ if (null == args) {
+ args = emptyObjectArray;
+ }
+ int arguments = args.length;
+ Class parameterTypes[] = new Class[arguments];
+ for (int i = 0; i < arguments; i++) {
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeExactConstructor(klass, args, parameterTypes);
+
+ }
+
+ /**
+ * <p>Returns new instance of <code>klazz</code> created using constructor
+ * with signature <code>parameterTypes</code> and actual arguments
+ * <code>args</code>.</p>
+ *
+ * <p>The signatures should match exactly.</p>
+ *
+ * @param klass the class to be constructed.
+ * @param args actual argument array
+ * @param parameterTypes parameter types array
+ * @return new instance of <code>klazz</code>
+ *
+ * @throws NoSuchMethodException if matching constructor cannot be found
+ * @throws IllegalAccessException thrown on the constructor's invocation
+ * @throws InvocationTargetException thrown on the constructor's invocation
+ * @throws InstantiationException thrown on the constructor's invocation
+ * @see Constructor#newInstance
+ */
+ public static Object invokeExactConstructor(
+ Class klass,
+ Object[] args,
+ Class[] parameterTypes)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException,
+ InstantiationException {
+
+ if (args == null) {
+ args = emptyObjectArray;
+ }
+
+ if (parameterTypes == null) {
+ parameterTypes = emptyClassArray;
+ }
+
+ Constructor ctor = getAccessibleConstructor(klass, parameterTypes);
+ if (null == ctor) {
+ throw new NoSuchMethodException(
+ "No such accessible constructor on object: " + klass.getName());
+ }
+ return ctor.newInstance(args);
+
+ }
+
+ /**
+ * Returns a constructor with single argument.
+ * @param klass the class to be constructed
+ * @return null if matching accessible constructor can not be found.
+ * @see Class#getConstructor
+ * @see #getAccessibleConstructor(java.lang.reflect.Constructor)
+ */
+ public static Constructor getAccessibleConstructor(
+ Class klass,
+ Class parameterType) {
+
+ Class[] parameterTypes = { parameterType };
+ return getAccessibleConstructor(klass, parameterTypes);
+
+ }
+
+ /**
+ * Returns a constructor given a class and signature.
+ * @param klass the class to be constructed
+ * @param parameterTypes the parameter array
+ * @return null if matching accessible constructor can not be found
+ * @see Class#getConstructor
+ * @see #getAccessibleConstructor(java.lang.reflect.Constructor)
+ */
+ public static Constructor getAccessibleConstructor(
+ Class klass,
+ Class[] parameterTypes) {
+
+ try {
+ return getAccessibleConstructor(
+ klass.getConstructor(parameterTypes));
+ } catch (NoSuchMethodException e) {
+ return (null);
+ }
+
+ }
+
+ /**
+ * Returns accessible version of the given constructor.
+ * @param ctor prototype constructor object.
+ * @return <code>null</code> if accessible constructor can not be found.
+ * @see java.lang.SecurityManager
+ */
+ public static Constructor getAccessibleConstructor(Constructor ctor) {
+
+ // Make sure we have a method to check
+ if (ctor == null) {
+ return (null);
+ }
+
+ // If the requested method is not public we cannot call it
+ if (!Modifier.isPublic(ctor.getModifiers())) {
+ return (null);
+ }
+
+ // If the declaring class is public, we are done
+ Class clazz = ctor.getDeclaringClass();
+ if (Modifier.isPublic(clazz.getModifiers())) {
+ return (ctor);
+ }
+
+ // what else can we do?
+ return null;
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+ /**
+ * <p>Find an accessible constructor with compatible parameters.
+ * Compatible parameters mean that every method parameter is assignable from
+ * the given parameters. In other words, it finds constructor that will take
+ * the parameters given.</p>
+ *
+ * <p>First it checks if there is constructor matching the exact signature.
+ * If no such, all the constructors of the class are tested if their signatures
+ * are assignment compatible with the parameter types.
+ * The first matching constructor is returned.</p>
+ *
+ * @param clazz find constructor for this class
+ * @param parameterTypes find method with compatible parameters
+ * @return a valid Constructor object. If there's no matching constructor, returns <code>null</code>.
+ */
+ private static Constructor getMatchingAccessibleConstructor(
+ Class clazz,
+ Class[] parameterTypes) {
+ // see if we can find the method directly
+ // most of the time this works and it's much faster
+ try {
+ Constructor ctor = clazz.getConstructor(parameterTypes);
+ try {
+ //
+ // XXX Default access superclass workaround
+ //
+ // When a public class has a default access superclass
+ // with public methods, these methods are accessible.
+ // Calling them from compiled code works fine.
+ //
+ // Unfortunately, using reflection to invoke these methods
+ // seems to (wrongly) to prevent access even when the method
+ // modifer is public.
+ //
+ // The following workaround solves the problem but will only
+ // work from sufficiently privilages code.
+ //
+ // Better workarounds would be greatfully accepted.
+ //
+ ctor.setAccessible(true);
+ } catch (SecurityException se) {}
+ return ctor;
+
+ } catch (NoSuchMethodException e) { /* SWALLOW */
+ }
+
+ // search through all methods
+ int paramSize = parameterTypes.length;
+ Constructor[] ctors = clazz.getConstructors();
+ for (int i = 0, size = ctors.length; i < size; i++) {
+ // compare parameters
+ Class[] ctorParams = ctors[i].getParameterTypes();
+ int ctorParamSize = ctorParams.length;
+ if (ctorParamSize == paramSize) {
+ boolean match = true;
+ for (int n = 0; n < ctorParamSize; n++) {
+ if (!MethodUtils
+ .isAssignmentCompatible(
+ ctorParams[n],
+ parameterTypes[n])) {
+ match = false;
+ break;
+ }
+ }
+
+ if (match) {
+ // get accessible version of method
+ Constructor ctor = getAccessibleConstructor(ctors[i]);
+ if (ctor != null) {
+ try {
+ ctor.setAccessible(true);
+ } catch (SecurityException se) {}
+ return ctor;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ContextClassLoaderLocal.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ContextClassLoaderLocal.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ContextClassLoaderLocal.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * A value that is provided per (thread) context classloader.
+ * Patterned after ThreadLocal.
+ * There is a separate value used when Thread.getContextClassLoader() is null.
+ * This mechanism provides isolation for web apps deployed in the same container.
+ * <strong>Note:</strong> A WeakHashMap bug in several 1.3 JVMs results in a memory leak
+ * for those JVMs.
+ *
+ * @see java.lang.Thread#getContextClassLoader
+ * @author Eric Pabst
+ */
+public class ContextClassLoaderLocal {
+ private Map valueByClassLoader = new WeakHashMap();
+ private boolean globalValueInitialized = false;
+ private Object globalValue;
+
+ public ContextClassLoaderLocal() {
+ super();
+ }
+
+ /**
+ * Returns the initial value for this ContextClassLoaderLocal
+ * variable. This method will be called once per Context ClassLoader for
+ * each ContextClassLoaderLocal, the first time it is accessed
+ * with get or set. If the programmer desires ContextClassLoaderLocal variables
+ * to be initialized to some value other than null, ContextClassLoaderLocal must
+ * be subclassed, and this method overridden. Typically, an anonymous
+ * inner class will be used. Typical implementations of initialValue
+ * will call an appropriate constructor and return the newly constructed
+ * object.
+ *
+ * @return a new Object to be used as an initial value for this ContextClassLoaderLocal
+ */
+ protected Object initialValue() {
+ return null;
+ }
+
+ /**
+ * Gets the instance which provides the functionality for {@link BeanUtils}.
+ * This is a pseudo-singleton - an single instance is provided per (thread) context classloader.
+ * This mechanism provides isolation for web apps deployed in the same container.
+ * @return the object currently associated with the
+ */
+ public synchronized Object get() {
+ // synchronizing the whole method is a bit slower
+ // but guarentees no subtle threading problems, and there's no
+ // need to synchronize valueByClassLoader
+
+ // make sure that the map is given a change to purge itself
+ valueByClassLoader.isEmpty();
+ try {
+
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ if (contextClassLoader != null) {
+
+ Object value = valueByClassLoader.get(contextClassLoader);
+ if ((value == null)
+ && !valueByClassLoader.containsKey(contextClassLoader)) {
+ value = initialValue();
+ valueByClassLoader.put(contextClassLoader, value);
+ }
+ return value;
+
+ }
+
+ } catch (SecurityException e) { /* SWALLOW - should we log this? */ }
+
+ // if none or exception, return the globalValue
+ if (!globalValueInitialized) {
+ globalValue = initialValue();
+ globalValueInitialized = true;
+ }//else already set
+ return globalValue;
+ }
+
+ /**
+ * Sets the value - a value is provided per (thread) context classloader.
+ * This mechanism provides isolation for web apps deployed in the same container.
+ *
+ * @param value the object to be associated with the entrant thread's context classloader
+ */
+ public synchronized void set(Object value) {
+ // synchronizing the whole method is a bit slower
+ // but guarentees no subtle threading problems
+
+ // make sure that the map is given a change to purge itself
+ valueByClassLoader.isEmpty();
+ try {
+
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ if (contextClassLoader != null) {
+ valueByClassLoader.put(contextClassLoader, value);
+ return;
+ }
+
+ } catch (SecurityException e) { /* SWALLOW - should we log this? */ }
+
+ // if in doubt, set the global value
+ globalValue = value;
+ globalValueInitialized = true;
+ }
+
+ /**
+ * Unsets the value associated with the current thread's context classloader
+ */
+ public synchronized void unset() {
+ try {
+
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ unset(contextClassLoader);
+
+ } catch (SecurityException e) { /* SWALLOW - should we log this? */ }
+ }
+
+ /**
+ * Unsets the value associated with the given classloader
+ */
+ public synchronized void unset(ClassLoader classLoader) {
+ valueByClassLoader.remove(classLoader);
+ }
+}
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConversionException.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConversionException.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConversionException.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+/**
+ * <p>A <strong>ConversionException</strong> indicates that a call to
+ * <code>Converter.convert()</code> has failed to complete successfully.
+ *
+ * @author Craig McClanahan
+ * @author Paulo Gaspar
+ * @since 1.3
+ */
+
+public class ConversionException extends RuntimeException {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new exception with the specified message.
+ *
+ * @param message The message describing this exception
+ */
+ public ConversionException(String message) {
+
+ super(message);
+
+ }
+
+
+ /**
+ * Construct a new exception with the specified message and root cause.
+ *
+ * @param message The message describing this exception
+ * @param cause The root cause of this exception
+ */
+ public ConversionException(String message, Throwable cause) {
+
+ super(message);
+ this.cause = cause;
+
+ }
+
+
+ /**
+ * Construct a new exception with the specified root cause.
+ *
+ * @param cause The root cause of this exception
+ */
+ public ConversionException(Throwable cause) {
+
+ super(cause.getMessage());
+ this.cause = cause;
+
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * The root cause of this <code>ConversionException</code>, compatible with
+ * JDK 1.4's extensions to <code>java.lang.Throwable</code>.
+ */
+ protected Throwable cause = null;
+
+ public Throwable getCause() {
+ return (this.cause);
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertUtils.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertUtils.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertUtils.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+/**
+ * <p>Utility methods for converting String scalar values to objects of the
+ * specified Class, String arrays to arrays of the specified Class.</p>
+ *
+ * <p>For more details, see <code>ConvertUtilsBean</code> which provides the
+ * implementations for these methods.</p>
+ *
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @version $Revision: 1.17 $ $Date: 2004/02/28 13:18:33 $
+ * @see ConvertUtilsBean
+ */
+
+public class ConvertUtils {
+
+
+ // ------------------------------------------------------ Static Properties
+
+ /**
+ * Gets the default value for Boolean conversions.
+ * @deprecated Register replacement converters for Boolean.TYPE and
+ * Boolean.class instead
+ */
+ public static boolean getDefaultBoolean() {
+ return (ConvertUtilsBean.getInstance().getDefaultBoolean());
+ }
+
+ /**
+ * Sets the default value for Boolean conversions.
+ * @deprecated Register replacement converters for Boolean.TYPE and
+ * Boolean.class instead
+ */
+ public static void setDefaultBoolean(boolean newDefaultBoolean) {
+ ConvertUtilsBean.getInstance().setDefaultBoolean(newDefaultBoolean);
+ }
+
+
+ /**
+ * Gets the default value for Byte conversions.
+ * @deprecated Register replacement converters for Byte.TYPE and
+ * Byte.class instead
+ */
+ public static byte getDefaultByte() {
+ return ConvertUtilsBean.getInstance().getDefaultByte();
+ }
+
+ /**
+ * Sets the default value for Byte conversions.
+ * @deprecated Register replacement converters for Byte.TYPE and
+ * Byte.class instead
+ */
+ public static void setDefaultByte(byte newDefaultByte) {
+ ConvertUtilsBean.getInstance().setDefaultByte(newDefaultByte);
+ }
+
+
+ /**
+ * Gets the default value for Character conversions.
+ * @deprecated Register replacement converters for Character.TYPE and
+ * Character.class instead
+ */
+ public static char getDefaultCharacter() {
+ return ConvertUtilsBean.getInstance().getDefaultCharacter();
+ }
+
+ /**
+ * Sets the default value for Character conversions.
+ * @deprecated Register replacement converters for Character.TYPE and
+ * Character.class instead
+ */
+ public static void setDefaultCharacter(char newDefaultCharacter) {
+ ConvertUtilsBean.getInstance().setDefaultCharacter(newDefaultCharacter);
+ }
+
+
+ /**
+ * Gets the default value for Double conversions.
+ * @deprecated Register replacement converters for Double.TYPE and
+ * Double.class instead
+ */
+ public static double getDefaultDouble() {
+ return ConvertUtilsBean.getInstance().getDefaultDouble();
+ }
+
+ /**
+ * Sets the default value for Double conversions.
+ * @deprecated Register replacement converters for Double.TYPE and
+ * Double.class instead
+ */
+ public static void setDefaultDouble(double newDefaultDouble) {
+ ConvertUtilsBean.getInstance().setDefaultDouble(newDefaultDouble);
+ }
+
+
+ /**
+ * Get the default value for Float conversions.
+ * @deprecated Register replacement converters for Float.TYPE and
+ * Float.class instead
+ */
+ public static float getDefaultFloat() {
+ return ConvertUtilsBean.getInstance().getDefaultFloat();
+ }
+
+ /**
+ * Sets the default value for Float conversions.
+ * @deprecated Register replacement converters for Float.TYPE and
+ * Float.class instead
+ */
+ public static void setDefaultFloat(float newDefaultFloat) {
+ ConvertUtilsBean.getInstance().setDefaultFloat(newDefaultFloat);
+ }
+
+
+ /**
+ * Gets the default value for Integer conversions.
+ * @deprecated Register replacement converters for Integer.TYPE and
+ * Integer.class instead
+ */
+ public static int getDefaultInteger() {
+ return ConvertUtilsBean.getInstance().getDefaultInteger();
+ }
+
+ /**
+ * Sets the default value for Integer conversions.
+ * @deprecated Register replacement converters for Integer.TYPE and
+ * Integer.class instead
+ */
+ public static void setDefaultInteger(int newDefaultInteger) {
+ ConvertUtilsBean.getInstance().setDefaultInteger(newDefaultInteger);
+ }
+
+
+ /**
+ * Gets the default value for Long conversions.
+ * @deprecated Register replacement converters for Long.TYPE and
+ * Long.class instead
+ */
+ public static long getDefaultLong() {
+ return (ConvertUtilsBean.getInstance().getDefaultLong());
+ }
+
+ /**
+ * Sets the default value for Long conversions.
+ * @deprecated Register replacement converters for Long.TYPE and
+ * Long.class instead
+ */
+ public static void setDefaultLong(long newDefaultLong) {
+ ConvertUtilsBean.getInstance().setDefaultLong(newDefaultLong);
+ }
+
+
+ /**
+ * Gets the default value for Short conversions.
+ * @deprecated Register replacement converters for Short.TYPE and
+ * Short.class instead
+ */
+ public static short getDefaultShort() {
+ return ConvertUtilsBean.getInstance().getDefaultShort();
+ }
+
+ /**
+ * Sets the default value for Short conversions.
+ * @deprecated Register replacement converters for Short.TYPE and
+ * Short.class instead
+ */
+ public static void setDefaultShort(short newDefaultShort) {
+ ConvertUtilsBean.getInstance().setDefaultShort(newDefaultShort);
+ }
+
+ // --------------------------------------------------------- Public Classes
+
+
+ /**
+ * <p>Convert the specified value into a String.</p>
+ *
+ * <p>For more details see <code>ConvertUtilsBean</code>.</p>
+ *
+ * @see ConvertUtilsBean#convert(Object)
+ */
+ public static String convert(Object value) {
+
+ return ConvertUtilsBean.getInstance().convert(value);
+
+ }
+
+
+ /**
+ * <p>Convert the specified value to an object of the specified class (if
+ * possible). Otherwise, return a String representation of the value.</p>
+ *
+ * <p>For more details see <code>ConvertUtilsBean</code>.</p>
+ *
+ * @see ConvertUtilsBean#convert(String, Class)
+ */
+ public static Object convert(String value, Class clazz) {
+
+ return ConvertUtilsBean.getInstance().convert(value, clazz);
+
+ }
+
+
+ /**
+ * <p>Convert an array of specified values to an array of objects of the
+ * specified class (if possible).</p>
+ *
+ * <p>For more details see <code>ConvertUtilsBean</code>.</p>
+ *
+ * @see ConvertUtilsBean#convert(String[], Class)
+ */
+ public static Object convert(String values[], Class clazz) {
+
+ return ConvertUtilsBean.getInstance().convert(values, clazz);
+
+ }
+
+
+ /**
+ * <p>Remove all registered {@link Converter}s, and re-establish the
+ * standard Converters.</p>
+ *
+ * <p>For more details see <code>ConvertUtilsBean</code>.</p>
+ *
+ * @see ConvertUtilsBean#deregister()
+ */
+ public static void deregister() {
+
+ ConvertUtilsBean.getInstance().deregister();
+
+ }
+
+
+ /**
+ * <p>Remove any registered {@link Converter} for the specified destination
+ * <code>Class</code>.</p>
+ *
+ * <p>For more details see <code>ConvertUtilsBean</code>.</p>
+ *
+ * @see ConvertUtilsBean#deregister(Class)
+ */
+ public static void deregister(Class clazz) {
+
+ ConvertUtilsBean.getInstance().deregister(clazz);
+
+ }
+
+
+ /**
+ * <p>Look up and return any registered {@link Converter} for the specified
+ * destination class; if there is no registered Converter, return
+ * <code>null</code>.</p>
+ *
+ * <p>For more details see <code>ConvertUtilsBean</code>.</p>
+ *
+ * @see ConvertUtilsBean#lookup(Class)
+ */
+ public static Converter lookup(Class clazz) {
+
+ return ConvertUtilsBean.getInstance().lookup(clazz);
+
+ }
+
+
+ /**
+ * <p>Register a custom {@link Converter} for the specified destination
+ * <code>Class</code>, replacing any previously registered Converter.</p>
+ *
+ * <p>For more details see <code>ConvertUtilsBean</code>.</p>
+ *
+ * @see ConvertUtilsBean#register(Converter, Class)
+ */
+ public static void register(Converter converter, Class clazz) {
+
+ ConvertUtilsBean.getInstance().register(converter, clazz);
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertUtilsBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertUtilsBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertUtilsBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,581 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.io.File;
+import java.lang.reflect.Array;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URL;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import org.apache.commons.beanutils.converters.BigDecimalConverter;
+import org.apache.commons.beanutils.converters.BigIntegerConverter;
+import org.apache.commons.beanutils.converters.BooleanConverter;
+import org.apache.commons.beanutils.converters.BooleanArrayConverter;
+import org.apache.commons.beanutils.converters.ByteConverter;
+import org.apache.commons.beanutils.converters.ByteArrayConverter;
+import org.apache.commons.beanutils.converters.CharacterConverter;
+import org.apache.commons.beanutils.converters.CharacterArrayConverter;
+import org.apache.commons.beanutils.converters.ClassConverter;
+import org.apache.commons.beanutils.converters.DoubleConverter;
+import org.apache.commons.beanutils.converters.DoubleArrayConverter;
+import org.apache.commons.beanutils.converters.FileConverter;
+import org.apache.commons.beanutils.converters.FloatConverter;
+import org.apache.commons.beanutils.converters.FloatArrayConverter;
+import org.apache.commons.beanutils.converters.IntegerConverter;
+import org.apache.commons.beanutils.converters.IntegerArrayConverter;
+import org.apache.commons.beanutils.converters.LongConverter;
+import org.apache.commons.beanutils.converters.LongArrayConverter;
+import org.apache.commons.beanutils.converters.ShortConverter;
+import org.apache.commons.beanutils.converters.ShortArrayConverter;
+import org.apache.commons.beanutils.converters.SqlDateConverter;
+import org.apache.commons.beanutils.converters.SqlTimeConverter;
+import org.apache.commons.beanutils.converters.SqlTimestampConverter;
+import org.apache.commons.beanutils.converters.StringConverter;
+import org.apache.commons.beanutils.converters.StringArrayConverter;
+import org.apache.commons.beanutils.converters.URLConverter;
+import org.apache.commons.collections.FastHashMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * <p>Utility methods for converting String scalar values to objects of the
+ * specified Class, String arrays to arrays of the specified Class. The
+ * actual {@link Converter} instance to be used can be registered for each
+ * possible destination Class. Unless you override them, standard
+ * {@link Converter} instances are provided for all of the following
+ * destination Classes:</p>
+ * <ul>
+ * <li>java.lang.BigDecimal</li>
+ * <li>java.lang.BigInteger</li>
+ * <li>boolean and java.lang.Boolean</li>
+ * <li>byte and java.lang.Byte</li>
+ * <li>char and java.lang.Character</li>
+ * <li>java.lang.Class</li>
+ * <li>double and java.lang.Double</li>
+ * <li>float and java.lang.Float</li>
+ * <li>int and java.lang.Integer</li>
+ * <li>long and java.lang.Long</li>
+ * <li>short and java.lang.Short</li>
+ * <li>java.lang.String</li>
+ * <li>java.io.File</li>
+ * <li>java.net.URL</li>
+ * <li>java.sql.Date</li>
+ * <li>java.sql.Time</li>
+ * <li>java.sql.Timestamp</li>
+ * </ul>
+ *
+ * <p>For backwards compatibility, the standard Converters for primitive
+ * types (and the corresponding wrapper classes) return a defined
+ * default value when a conversion error occurs. If you prefer to have a
+ * {@link ConversionException} thrown instead, replace the standard Converter
+ * instances with instances created with the zero-arguments constructor. For
+ * example, to cause the Converters for integers to throw an exception on
+ * conversion errors, you could do this:</p>
+ * <pre>
+ * // No-args constructor gets the version that throws exceptions
+ * Converter myConverter =
+ * new org.apache.commons.beanutils.converter.IntegerConverter();
+ * ConvertUtils.register(myConverter, Integer.TYPE); // Native type
+ * ConvertUtils.register(myConverter, Integer.class); // Wrapper class
+ * </pre>
+ *
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author James Strachan
+ * @version $Revision: 1.12.2.1 $ $Date: 2004/07/27 21:44:26 $
+ * @since 1.7
+ */
+
+public class ConvertUtilsBean {
+
+ // ------------------------------------------------------- Class Methods
+ /** Get singleton instance */
+ protected static ConvertUtilsBean getInstance() {
+ return BeanUtilsBean.getInstance().getConvertUtils();
+ }
+
+ // ------------------------------------------------------- Variables
+
+
+ /**
+ * The set of {@link Converter}s that can be used to convert Strings
+ * into objects of a specified Class, keyed by the destination Class.
+ */
+ private FastHashMap converters = new FastHashMap();
+
+ /**
+ * The <code>Log</code> instance for this class.
+ */
+ private Log log = LogFactory.getLog(ConvertUtils.class);
+
+ // ------------------------------------------------------- Constructors
+
+ /** Construct a bean with standard converters registered */
+ public ConvertUtilsBean() {
+ converters.setFast(false);
+ deregister();
+ converters.setFast(true);
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+ // ------------------------------------------------------ Static Properties
+
+
+ /**
+ * The default value for Boolean conversions.
+ * @deprecated Register replacement converters for Boolean.TYPE and
+ * Boolean.class instead
+ */
+ private Boolean defaultBoolean = Boolean.FALSE;
+
+ /**
+ * Gets the default value for Boolean conversions.
+ * @deprecated Register replacement converters for Boolean.TYPE and
+ * Boolean.class instead
+ */
+ public boolean getDefaultBoolean() {
+ return (defaultBoolean.booleanValue());
+ }
+
+ /**
+ * Sets the default value for Boolean conversions.
+ * @deprecated Register replacement converters for Boolean.TYPE and
+ * Boolean.class instead
+ */
+ public void setDefaultBoolean(boolean newDefaultBoolean) {
+ defaultBoolean = new Boolean(newDefaultBoolean);
+ register(new BooleanConverter(defaultBoolean), Boolean.TYPE);
+ register(new BooleanConverter(defaultBoolean), Boolean.class);
+ }
+
+
+ /**
+ * The default value for Byte conversions.
+ * @deprecated Register replacement converters for Byte.TYPE and
+ * Byte.class instead
+ */
+ private Byte defaultByte = new Byte((byte) 0);
+
+ /**
+ * Gets the default value for Byte conversions.
+ * @deprecated Register replacement converters for Byte.TYPE and
+ * Byte.class instead
+ */
+ public byte getDefaultByte() {
+ return (defaultByte.byteValue());
+ }
+
+ /**
+ * Sets the default value for Byte conversions.
+ * @deprecated Register replacement converters for Byte.TYPE and
+ * Byte.class instead
+ */
+ public void setDefaultByte(byte newDefaultByte) {
+ defaultByte = new Byte(newDefaultByte);
+ register(new ByteConverter(defaultByte), Byte.TYPE);
+ register(new ByteConverter(defaultByte), Byte.class);
+ }
+
+
+ /**
+ * The default value for Character conversions.
+ * @deprecated Register replacement converters for Character.TYPE and
+ * Character.class instead
+ */
+ private Character defaultCharacter = new Character(' ');
+
+ /**
+ * Gets the default value for Character conversions.
+ * @deprecated Register replacement converters for Character.TYPE and
+ * Character.class instead
+ */
+ public char getDefaultCharacter() {
+ return (defaultCharacter.charValue());
+ }
+
+ /**
+ * Sets the default value for Character conversions.
+ * @deprecated Register replacement converters for Character.TYPE and
+ * Character.class instead
+ */
+ public void setDefaultCharacter(char newDefaultCharacter) {
+ defaultCharacter = new Character(newDefaultCharacter);
+ register(new CharacterConverter(defaultCharacter),
+ Character.TYPE);
+ register(new CharacterConverter(defaultCharacter),
+ Character.class);
+ }
+
+
+ /**
+ * The default value for Double conversions.
+ * @deprecated Register replacement converters for Double.TYPE and
+ * Double.class instead
+ */
+ private Double defaultDouble = new Double((double) 0.0);
+
+ /**
+ * Gets the default value for Double conversions.
+ * @deprecated Register replacement converters for Double.TYPE and
+ * Double.class instead
+ */
+ public double getDefaultDouble() {
+ return (defaultDouble.doubleValue());
+ }
+
+ /**
+ * Sets the default value for Double conversions.
+ * @deprecated Register replacement converters for Double.TYPE and
+ * Double.class instead
+ */
+ public void setDefaultDouble(double newDefaultDouble) {
+ defaultDouble = new Double(newDefaultDouble);
+ register(new DoubleConverter(defaultDouble), Double.TYPE);
+ register(new DoubleConverter(defaultDouble), Double.class);
+ }
+
+
+ /**
+ * The default value for Float conversions.
+ * @deprecated Register replacement converters for Float.TYPE and
+ * Float.class instead
+ */
+ private Float defaultFloat = new Float((float) 0.0);
+
+ /**
+ * Gets the default value for Float conversions.
+ * @deprecated Register replacement converters for Float.TYPE and
+ * Float.class instead
+ */
+ public float getDefaultFloat() {
+ return (defaultFloat.floatValue());
+ }
+
+ /**
+ * Sets the default value for Float conversions.
+ * @deprecated Register replacement converters for Float.TYPE and
+ * Float.class instead
+ */
+ public void setDefaultFloat(float newDefaultFloat) {
+ defaultFloat = new Float(newDefaultFloat);
+ register(new FloatConverter(defaultFloat), Float.TYPE);
+ register(new FloatConverter(defaultFloat), Float.class);
+ }
+
+
+ /**
+ * The default value for Integer conversions.
+ * @deprecated Register replacement converters for Integer.TYPE and
+ * Integer.class instead
+ */
+ private Integer defaultInteger = new Integer(0);
+
+ /**
+ * Gets the default value for Integer conversions.
+ * @deprecated Register replacement converters for Integer.TYPE and
+ * Integer.class instead
+ */
+ public int getDefaultInteger() {
+ return (defaultInteger.intValue());
+ }
+
+ /**
+ * Sets the default value for Integer conversions.
+ * @deprecated Register replacement converters for Integer.TYPE and
+ * Integer.class instead
+ */
+ public void setDefaultInteger(int newDefaultInteger) {
+ defaultInteger = new Integer(newDefaultInteger);
+ register(new IntegerConverter(defaultInteger), Integer.TYPE);
+ register(new IntegerConverter(defaultInteger), Integer.class);
+ }
+
+
+ /**
+ * The default value for Long conversions.
+ * @deprecated Register replacement converters for Long.TYPE and
+ * Long.class instead
+ */
+ private Long defaultLong = new Long((long) 0);
+
+ /**
+ * Gets the default value for Long conversions.
+ * @deprecated Register replacement converters for Long.TYPE and
+ * Long.class instead
+ */
+ public long getDefaultLong() {
+ return (defaultLong.longValue());
+ }
+
+ /**
+ * Sets the default value for Long conversions.
+ * @deprecated Register replacement converters for Long.TYPE and
+ * Long.class instead
+ */
+ public void setDefaultLong(long newDefaultLong) {
+ defaultLong = new Long(newDefaultLong);
+ register(new LongConverter(defaultLong), Long.TYPE);
+ register(new LongConverter(defaultLong), Long.class);
+ }
+
+
+ /**
+ * The default value for Short conversions.
+ * @deprecated Register replacement converters for Short.TYPE and
+ * Short.class instead
+ */
+ private static Short defaultShort = new Short((short) 0);
+
+ /**
+ * Gets the default value for Short conversions.
+ * @deprecated Register replacement converters for Short.TYPE and
+ * Short.class instead
+ */
+ public short getDefaultShort() {
+ return (defaultShort.shortValue());
+ }
+
+ /**
+ * Sets the default value for Short conversions.
+ * @deprecated Register replacement converters for Short.TYPE and
+ * Short.class instead
+ */
+ public void setDefaultShort(short newDefaultShort) {
+ defaultShort = new Short(newDefaultShort);
+ register(new ShortConverter(defaultShort), Short.TYPE);
+ register(new ShortConverter(defaultShort), Short.class);
+ }
+
+
+
+ /**
+ * Convert the specified value into a String. If the specified value
+ * is an array, the first element (converted to a String) will be
+ * returned. The registered {@link Converter} for the
+ * <code>java.lang.String</code> class will be used, which allows
+ * applications to customize Object->String conversions (the default
+ * implementation simply uses toString()).
+ *
+ * @param value Value to be converted (may be null)
+ */
+ public String convert(Object value) {
+
+ if (value == null) {
+ return ((String) null);
+ } else if (value.getClass().isArray()) {
+ if (Array.getLength(value) < 1) {
+ return (null);
+ }
+ value = Array.get(value, 0);
+ if (value == null) {
+ return ((String) null);
+ } else {
+ Converter converter = lookup(String.class);
+ return ((String) converter.convert(String.class, value));
+ }
+ } else {
+ Converter converter = lookup(String.class);
+ return ((String) converter.convert(String.class, value));
+ }
+
+ }
+
+
+ /**
+ * Convert the specified value to an object of the specified class (if
+ * possible). Otherwise, return a String representation of the value.
+ *
+ * @param value Value to be converted (may be null)
+ * @param clazz Java class to be converted to
+ *
+ * @exception ConversionException if thrown by an underlying Converter
+ */
+ public Object convert(String value, Class clazz) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Convert string '" + value + "' to class '" +
+ clazz.getName() + "'");
+ }
+ Converter converter = lookup(clazz);
+ if (converter == null) {
+ converter = lookup(String.class);
+ }
+ if (log.isTraceEnabled()) {
+ log.trace(" Using converter " + converter);
+ }
+ return (converter.convert(clazz, value));
+
+ }
+
+
+ /**
+ * Convert an array of specified values to an array of objects of the
+ * specified class (if possible). If the specified Java class is itself
+ * an array class, this class will be the type of the returned value.
+ * Otherwise, an array will be constructed whose component type is the
+ * specified class.
+ *
+ * @param values Values to be converted (may be null)
+ * @param clazz Java array or element class to be converted to
+ *
+ * @exception ConversionException if thrown by an underlying Converter
+ */
+ public Object convert(String values[], Class clazz) {
+
+ Class type = clazz;
+ if (clazz.isArray()) {
+ type = clazz.getComponentType();
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Convert String[" + values.length + "] to class '" +
+ type.getName() + "[]'");
+ }
+ Converter converter = lookup(type);
+ if (converter == null) {
+ converter = lookup(String.class);
+ }
+ if (log.isTraceEnabled()) {
+ log.trace(" Using converter " + converter);
+ }
+ Object array = Array.newInstance(type, values.length);
+ for (int i = 0; i < values.length; i++) {
+ Array.set(array, i, converter.convert(type, values[i]));
+ }
+ return (array);
+
+ }
+
+
+ /**
+ * Remove all registered {@link Converter}s, and re-establish the
+ * standard Converters.
+ */
+ public void deregister() {
+
+ boolean booleanArray[] = new boolean[0];
+ byte byteArray[] = new byte[0];
+ char charArray[] = new char[0];
+ double doubleArray[] = new double[0];
+ float floatArray[] = new float[0];
+ int intArray[] = new int[0];
+ long longArray[] = new long[0];
+ short shortArray[] = new short[0];
+ String stringArray[] = new String[0];
+
+ converters.clear();
+ register(BigDecimal.class, new BigDecimalConverter());
+ register(BigInteger.class, new BigIntegerConverter());
+ register(Boolean.TYPE, new BooleanConverter(defaultBoolean));
+ register(Boolean.class, new BooleanConverter(defaultBoolean));
+ register(booleanArray.getClass(),
+ new BooleanArrayConverter(booleanArray));
+ register(Byte.TYPE, new ByteConverter(defaultByte));
+ register(Byte.class, new ByteConverter(defaultByte));
+ register(byteArray.getClass(),
+ new ByteArrayConverter(byteArray));
+ register(Character.TYPE,
+ new CharacterConverter(defaultCharacter));
+ register(Character.class,
+ new CharacterConverter(defaultCharacter));
+ register(charArray.getClass(),
+ new CharacterArrayConverter(charArray));
+ register(Class.class, new ClassConverter());
+ register(Double.TYPE, new DoubleConverter(defaultDouble));
+ register(Double.class, new DoubleConverter(defaultDouble));
+ register(doubleArray.getClass(),
+ new DoubleArrayConverter(doubleArray));
+ register(Float.TYPE, new FloatConverter(defaultFloat));
+ register(Float.class, new FloatConverter(defaultFloat));
+ register(floatArray.getClass(),
+ new FloatArrayConverter(floatArray));
+ register(Integer.TYPE, new IntegerConverter(defaultInteger));
+ register(Integer.class, new IntegerConverter(defaultInteger));
+ register(intArray.getClass(),
+ new IntegerArrayConverter(intArray));
+ register(Long.TYPE, new LongConverter(defaultLong));
+ register(Long.class, new LongConverter(defaultLong));
+ register(longArray.getClass(),
+ new LongArrayConverter(longArray));
+ register(Short.TYPE, new ShortConverter(defaultShort));
+ register(Short.class, new ShortConverter(defaultShort));
+ register(shortArray.getClass(),
+ new ShortArrayConverter(shortArray));
+ register(String.class, new StringConverter());
+ register(stringArray.getClass(),
+ new StringArrayConverter(stringArray));
+ register(Date.class, new SqlDateConverter());
+ register(Time.class, new SqlTimeConverter());
+ register(Timestamp.class, new SqlTimestampConverter());
+ register(File.class, new FileConverter());
+ register(URL.class, new URLConverter());
+
+ }
+
+ /** strictly for convenience since it has same parameter order as Map.put */
+ private void register(Class clazz, Converter converter) {
+ register(converter, clazz);
+ }
+
+ /**
+ * Remove any registered {@link Converter} for the specified destination
+ * <code>Class</code>.
+ *
+ * @param clazz Class for which to remove a registered Converter
+ */
+ public void deregister(Class clazz) {
+
+ converters.remove(clazz);
+
+ }
+
+
+ /**
+ * Look up and return any registered {@link Converter} for the specified
+ * destination class; if there is no registered Converter, return
+ * <code>null</code>.
+ *
+ * @param clazz Class for which to return a registered Converter
+ */
+ public Converter lookup(Class clazz) {
+
+ return ((Converter) converters.get(clazz));
+
+ }
+
+
+ /**
+ * Register a custom {@link Converter} for the specified destination
+ * <code>Class</code>, replacing any previously registered Converter.
+ *
+ * @param converter Converter to be registered
+ * @param clazz Destination class for conversions performed by this
+ * Converter
+ */
+ public void register(Converter converter, Class clazz) {
+
+ converters.put(clazz, converter);
+
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/Converter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/Converter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/Converter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+/**
+ * <p>General purpose data type converter that can be registered and used
+ * within the BeanUtils package to manage the conversion of objects from
+ * one type to another.
+ *
+ * @author Craig McClanahan
+ * @author Paulo Gaspar
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:33 $
+ * @since 1.3
+ */
+
+public interface Converter {
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value);
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertingWrapDynaBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertingWrapDynaBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ConvertingWrapDynaBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+/**
+ * <p>Implementation of <code>DynaBean</code> that wraps a standard JavaBean
+ * instance, so that DynaBean APIs can be used to access its properties,
+ * though this implementation allows type conversion to occur when properties are set.
+ * This means that (say) Strings can be passed in as values in setter methods and
+ * this DynaBean will convert them to the correct primitive data types.</p>
+ *
+ * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does not
+ * support the <code>contains()</code> and <code>remove()</code> methods.</p>
+ *
+ * @author James Strachan
+ * @version $Revision: 1.3 $ $Date: 2002/01/23 22:35:58 $
+ */
+
+public class ConvertingWrapDynaBean extends WrapDynaBean {
+
+
+
+ /**
+ * Construct a new <code>DynaBean</code> associated with the specified
+ * JavaBean instance.
+ *
+ * @param instance JavaBean instance to be wrapped
+ */
+ public ConvertingWrapDynaBean(Object instance) {
+
+ super(instance);
+
+ }
+
+
+ /**
+ * Set the value of the property with the specified name
+ * performing any type conversions if necessary. So this method
+ * can accept String values for primitive numeric data types for example.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception NullPointerException if an attempt is made to set a
+ * primitive property to null
+ */
+ public void set(String name, Object value) {
+
+ try {
+ BeanUtils.copyProperty(instance, name, value);
+ } catch (Throwable t) {
+ throw new IllegalArgumentException
+ ("Property '" + name + "' has no write method");
+ }
+
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+/**
+ * <p>A <strong>DynaBean</strong> is a Java object that supports properties
+ * whose names and data types, as well as values, may be dynamically modified.
+ * To the maximum degree feasible, other components of the BeanUtils package
+ * will recognize such beans and treat them as standard JavaBeans for the
+ * purpose of retrieving and setting property values.</p>
+ *
+ * @author Craig McClanahan
+ * @author Paulo Gaspar
+ * @version $Revision: 1.9 $ $Date: 2004/02/28 13:18:33 $
+ */
+
+public interface DynaBean {
+
+
+ /**
+ * Does the specified mapped property contain a value for the specified
+ * key value?
+ *
+ * @param name Name of the property to check
+ * @param key Name of the key to check
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public boolean contains(String name, String key);
+
+
+ /**
+ * Return the value of a simple property with the specified name.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public Object get(String name);
+
+
+ /**
+ * Return the value of an indexed property with the specified name.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ * @param index Index of the value to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not indexed
+ * @exception IndexOutOfBoundsException if the specified index
+ * is outside the range of the underlying property
+ * @exception NullPointerException if no array or List has been
+ * initialized for this property
+ */
+ public Object get(String name, int index);
+
+
+ /**
+ * Return the value of a mapped property with the specified name,
+ * or <code>null</code> if there is no value for the specified key.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ * @param key Key of the value to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not mapped
+ */
+ public Object get(String name, String key);
+
+
+ /**
+ * Return the <code>DynaClass</code> instance that describes the set of
+ * properties available for this DynaBean.
+ */
+ public DynaClass getDynaClass();
+
+
+ /**
+ * Remove any existing value for the specified key on the
+ * specified mapped property.
+ *
+ * @param name Name of the property for which a value is to
+ * be removed
+ * @param key Key of the value to be removed
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public void remove(String name, String key);
+
+
+ /**
+ * Set the value of a simple property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception NullPointerException if an attempt is made to set a
+ * primitive property to null
+ */
+ public void set(String name, Object value);
+
+
+ /**
+ * Set the value of an indexed property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param index Index of the property to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not indexed
+ * @exception IndexOutOfBoundsException if the specified index
+ * is outside the range of the underlying property
+ */
+ public void set(String name, int index, Object value);
+
+
+ /**
+ * Set the value of a mapped property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param key Key of the property to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not mapped
+ */
+ public void set(String name, String key, Object value);
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaClass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaClass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaClass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+
+
+
+/**
+ * <p>A <strong>DynaClass</strong> is a simulation of the functionality of
+ * <code>java.lang.Class</code> for classes implementing the
+ * <code>DynaBean</code> interface. DynaBean instances that share the same
+ * DynaClass all have the same set of available properties, along with any
+ * associated data types, read-only states, and write-only states.</p>
+ *
+ * @author Craig McClanahan
+ * @author Michael Smith
+ * @author Paulo Gaspar
+ * @version $Revision: 1.12 $ $Date: 2004/02/28 13:18:33 $
+ */
+
+public interface DynaClass {
+
+
+ /**
+ * Return the name of this DynaClass (analogous to the
+ * <code>getName()</code> method of <code>java.lang.Class</code), which
+ * allows the same <code>DynaClass</code> implementation class to support
+ * different dynamic classes, with different sets of properties.
+ */
+ public String getName();
+
+
+ /**
+ * Return a property descriptor for the specified property, if it exists;
+ * otherwise, return <code>null</code>.
+ *
+ * @param name Name of the dynamic property for which a descriptor
+ * is requested
+ *
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ public DynaProperty getDynaProperty(String name);
+
+
+ /**
+ * <p>Return an array of <code>ProperyDescriptors</code> for the properties
+ * currently defined in this DynaClass. If no properties are defined, a
+ * zero-length array will be returned.</p>
+ *
+ * <p><strong>FIXME</strong> - Should we really be implementing
+ * <code>getBeanInfo()</code> instead, which returns property descriptors
+ * and a bunch of other stuff?</p>
+ */
+ public DynaProperty[] getDynaProperties();
+
+
+ /**
+ * Instantiate and return a new DynaBean instance, associated
+ * with this DynaClass.
+ *
+ * @exception IllegalAccessException if the Class or the appropriate
+ * constructor is not accessible
+ * @exception InstantiationException if this Class represents an abstract
+ * class, an array class, a primitive type, or void; or if instantiation
+ * fails for some other reason
+ */
+ public DynaBean newInstance()
+ throws IllegalAccessException, InstantiationException;
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaProperty.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaProperty.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/DynaProperty.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.StreamCorruptedException;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * <p>The metadata describing an individual property of a DynaBean.</p>
+ *
+ * <p>The meta contains an <em>optional</em> content type property ({@link #getContentType})
+ * for use by mapped and iterated properties.
+ * A mapped or iterated property may choose to indicate the type it expects.
+ * The DynaBean implementation may choose to enforce this type on its entries.
+ * Alternatively, an implementatin may choose to ignore this property.
+ * All keys for maps must be of type String so no meta data is needed for map keys.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.13 $ $Date: 2004/02/28 13:18:33 $
+ */
+
+public class DynaProperty implements Serializable {
+
+ // ----------------------------------------------------------- Constants
+
+ /*
+ * There are issues with serializing primitive class types on certain JVM versions
+ * (including java 1.3).
+ * This class uses a custom serialization implementation that writes an integer
+ * for these primitive class.
+ * This list of constants are the ones used in serialization.
+ * If these values are changed, then older versions will no longer be read correctly
+ */
+ private static final int BOOLEAN_TYPE = 1;
+ private static final int BYTE_TYPE = 2;
+ private static final int CHAR_TYPE = 3;
+ private static final int DOUBLE_TYPE = 4;
+ private static final int FLOAT_TYPE = 5;
+ private static final int INT_TYPE = 6;
+ private static final int LONG_TYPE = 7;
+ private static final int SHORT_TYPE = 8;
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a property that accepts any data type.
+ *
+ * @param name Name of the property being described
+ */
+ public DynaProperty(String name) {
+
+ this(name, Object.class);
+
+ }
+
+
+ /**
+ * Construct a property of the specified data type.
+ *
+ * @param name Name of the property being described
+ * @param type Java class representing the property data type
+ */
+ public DynaProperty(String name, Class type) {
+
+ super();
+ this.name = name;
+ this.type = type;
+
+ }
+
+ /**
+ * Construct an indexed or mapped <code>DynaProperty</code> that supports (pseudo)-introspection
+ * of the content type.
+ *
+ * @param name Name of the property being described
+ * @param type Java class representing the property data type
+ * @param contentType Class that all indexed or mapped elements are instances of
+ */
+ public DynaProperty(String name, Class type, Class contentType) {
+
+ super();
+ this.name = name;
+ this.type = type;
+ this.contentType = contentType;
+
+ }
+
+ // ------------------------------------------------------------- Properties
+
+ /** Property name */
+ protected String name = null;
+ /**
+ * Get the name of this property.
+ */
+ public String getName() {
+ return (this.name);
+ }
+
+ /** Property type */
+ protected transient Class type = null;
+ /**
+ * <p>Gets the Java class representing the data type of the underlying property
+ * values.</p>
+ *
+ * <p>There are issues with serializing primitive class types on certain JVM versions
+ * (including java 1.3).
+ * Therefore, this field <strong>must not be serialized using the standard methods</strong>.</p>
+ *
+ * <p><strong>Please leave this field as <code>transient</code></strong></p>
+ */
+ public Class getType() {
+ return (this.type);
+ }
+
+
+ /** The <em>(optional)</em> type of content elements for indexed <code>DynaProperty</code> */
+ protected transient Class contentType;
+ /**
+ * Gets the <em>(optional)</em> type of the indexed content for <code>DynaProperty</code>'s
+ * that support this feature.
+ *
+ * <p>There are issues with serializing primitive class types on certain JVM versions
+ * (including java 1.3).
+ * Therefore, this field <strong>must not be serialized using the standard methods</strong>.</p>
+ *
+ * @return the Class for the content type if this is an indexed <code>DynaProperty</code>
+ * and this feature is supported. Otherwise null.
+ */
+ public Class getContentType() {
+ return contentType;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Does this property represent an indexed value (ie an array or List)?
+ */
+ public boolean isIndexed() {
+
+ if (type == null) {
+ return (false);
+ } else if (type.isArray()) {
+ return (true);
+ } else if (List.class.isAssignableFrom(type)) {
+ return (true);
+ } else {
+ return (false);
+ }
+
+ }
+
+
+ /**
+ * Does this property represent a mapped value (ie a Map)?
+ */
+ public boolean isMapped() {
+
+ if (type == null) {
+ return (false);
+ } else {
+ return (Map.class.isAssignableFrom(type));
+ }
+
+ }
+
+
+ /**
+ * Return a String representation of this Object.
+ */
+ public String toString() {
+
+ StringBuffer sb = new StringBuffer("DynaProperty[name=");
+ sb.append(this.name);
+ sb.append(",type=");
+ sb.append(this.type);
+ if (isMapped() || isIndexed()) {
+ sb.append(" <").append(this.contentType).append(">");
+ }
+ sb.append("]");
+ return (sb.toString());
+
+ }
+
+ // --------------------------------------------------------- Serialization helper methods
+
+ /**
+ * Writes this object safely.
+ * There are issues with serializing primitive class types on certain JVM versions
+ * (including java 1.3).
+ * This method provides a workaround.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+
+ writeAnyClass(this.type,out);
+
+ if (isMapped() || isIndexed()) {
+ writeAnyClass(this.contentType,out);
+ }
+
+ // write out other values
+ out.defaultWriteObject();
+ }
+
+ /**
+ * Write a class using safe encoding to workaround java 1.3 serialization bug.
+ */
+ private void writeAnyClass(Class clazz, ObjectOutputStream out) throws IOException {
+ // safely write out any class
+ int primitiveType = 0;
+ if (Boolean.TYPE.equals(clazz)) {
+ primitiveType = BOOLEAN_TYPE;
+ } else if (Byte.TYPE.equals(clazz)) {
+ primitiveType = BYTE_TYPE;
+ } else if (Character.TYPE.equals(clazz)) {
+ primitiveType = CHAR_TYPE;
+ } else if (Double.TYPE.equals(clazz)) {
+ primitiveType = DOUBLE_TYPE;
+ } else if (Float.TYPE.equals(clazz)) {
+ primitiveType = FLOAT_TYPE;
+ } else if (Integer.TYPE.equals(clazz)) {
+ primitiveType = INT_TYPE;
+ } else if (Long.TYPE.equals(clazz)) {
+ primitiveType = LONG_TYPE;
+ } else if (Short.TYPE.equals(clazz)) {
+ primitiveType = SHORT_TYPE;
+ }
+
+ if (primitiveType == 0) {
+ // then it's not a primitive type
+ out.writeBoolean(false);
+ out.writeObject(clazz);
+ } else {
+ // we'll write out a constant instead
+ out.writeBoolean(true);
+ out.writeInt(primitiveType);
+ }
+ }
+
+ /**
+ * Reads field values for this object safely.
+ * There are issues with serializing primitive class types on certain JVM versions
+ * (including java 1.3).
+ * This method provides a workaround.
+ *
+ * @throws StreamCorruptedException when the stream data values are outside expected range
+ */
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+
+ this.type = readAnyClass(in);
+
+ if (isMapped() || isIndexed()) {
+ this.contentType = readAnyClass(in);
+ }
+
+ // read other values
+ in.defaultReadObject();
+ }
+
+
+ /**
+ * Reads a class using safe encoding to workaround java 1.3 serialization bug.
+ */
+ private Class readAnyClass(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ // read back type class safely
+ if (in.readBoolean()) {
+ // it's a type constant
+ switch (in.readInt()) {
+
+ case BOOLEAN_TYPE: return Boolean.TYPE;
+ case BYTE_TYPE: return Byte.TYPE;
+ case CHAR_TYPE: return Character.TYPE;
+ case DOUBLE_TYPE: return Double.TYPE;
+ case FLOAT_TYPE: return Float.TYPE;
+ case INT_TYPE: return Integer.TYPE;
+ case LONG_TYPE: return Long.TYPE;
+ case SHORT_TYPE: return Short.TYPE;
+ default:
+ // something's gone wrong
+ throw new StreamCorruptedException(
+ "Invalid primitive type. "
+ + "Check version of beanutils used to serialize is compatible.");
+
+ }
+
+ } else {
+ // it's another class
+ return ((Class) in.readObject());
+ }
+ }
+}
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/JDBCDynaClass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/JDBCDynaClass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/JDBCDynaClass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import java.io.Serializable;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>Provides common logic for JDBC implementations of {@link DynaClass}.</p>
+ *
+ * @author Craig R. McClanahan
+ * @author George Franciscus
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:33 $
+ */
+
+abstract class JDBCDynaClass implements DynaClass, Serializable {
+
+ // ----------------------------------------------------- Instance Variables
+
+ /**
+ * <p>Flag defining whether column names should be lower cased when
+ * converted to property names.</p>
+ */
+ protected boolean lowerCase = true;
+
+ /**
+ * <p>The set of dynamic properties that are part of this
+ * {@link DynaClass}.</p>
+ */
+ protected DynaProperty properties[] = null;
+
+ /**
+ * <p>The set of dynamic properties that are part of this
+ * {@link DynaClass}, keyed by the property name. Individual descriptor
+ * instances will be the same instances as those in the
+ * <code>properties</code> list.</p>
+ */
+ protected Map propertiesMap = new HashMap();
+
+ // ------------------------------------------------------ DynaClass Methods
+
+ /**
+ * <p>Return the name of this DynaClass (analogous to the
+ * <code>getName()</code> method of <code>java.lang.Class</code), which
+ * allows the same <code>DynaClass</code> implementation class to support
+ * different dynamic classes, with different sets of properties.</p>
+ */
+ public String getName() {
+
+ return (this.getClass().getName());
+
+ }
+
+ /**
+ * <p>Return a property descriptor for the specified property, if it
+ * exists; otherwise, return <code>null</code>.</p>
+ *
+ * @param name Name of the dynamic property for which a descriptor
+ * is requested
+ *
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ public DynaProperty getDynaProperty(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("No property name specified");
+ }
+ return ((DynaProperty) propertiesMap.get(name));
+
+ }
+
+ /**
+ * <p>Return an array of <code>ProperyDescriptors</code> for the properties
+ * currently defined in this DynaClass. If no properties are defined, a
+ * zero-length array will be returned.</p>
+ */
+ public DynaProperty[] getDynaProperties() {
+
+ return (properties);
+
+ }
+
+ /**
+ * <p>Instantiate and return a new DynaBean instance, associated
+ * with this DynaClass. <strong>NOTE</strong> - This operation is not
+ * supported, and throws an exception.</p>
+ *
+ * @exception IllegalAccessException if the Class or the appropriate
+ * constructor is not accessible
+ * @exception InstantiationException if this Class represents an abstract
+ * class, an array class, a primitive type, or void; or if instantiation
+ * fails for some other reason
+ */
+ public DynaBean newInstance()
+ throws IllegalAccessException, InstantiationException {
+
+ throw new UnsupportedOperationException("newInstance() not supported");
+
+ }
+
+ /**
+ * <p>Loads and returns the <code>Class</code> of the given name.
+ * By default, a load from the thread context class loader is attempted.
+ * If there is no such class loader, the class loader used to load this
+ * class will be utilized.</p>
+ *
+ * @exception SQLException if an exception was thrown trying to load
+ * the specified class
+ */
+ protected Class loadClass(String className) throws SQLException {
+
+ try {
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ if (cl == null) {
+ cl = this.getClass().getClassLoader();
+ }
+ return (cl.loadClass(className));
+ } catch (Exception e) {
+ throw new SQLException(
+ "Cannot load column class '" + className + "': " + e);
+ }
+
+ }
+
+ /**
+ * <p>Factory method to create a new DynaProperty for the given index
+ * into the result set metadata.</p>
+ *
+ * @param metadata is the result set metadata
+ * @param i is the column index in the metadata
+ * @return the newly created DynaProperty instance
+ */
+ protected DynaProperty createDynaProperty(
+ ResultSetMetaData metadata,
+ int i)
+ throws SQLException {
+
+ String name = null;
+ if (lowerCase) {
+ name = metadata.getColumnName(i).toLowerCase();
+ } else {
+ name = metadata.getColumnName(i);
+ }
+ String className = null;
+ try {
+ className = metadata.getColumnClassName(i);
+ } catch (SQLException e) {
+ // this is a patch for HsqlDb to ignore exceptions
+ // thrown by its metadata implementation
+ }
+
+ // Default to Object type if no class name could be retrieved
+ // from the metadata
+ Class clazz = Object.class;
+ if (className != null) {
+ clazz = loadClass(className);
+ }
+ return new DynaProperty(name, clazz);
+
+ }
+
+ /**
+ * <p>Introspect the metadata associated with our result set, and populate
+ * the <code>properties</code> and <code>propertiesMap</code> instance
+ * variables.</p>
+ *
+ * @param resultSet The <code>resultSet</code> whose metadata is to
+ * be introspected
+ *
+ * @exception SQLException if an error is encountered processing the
+ * result set metadata
+ */
+ protected void introspect(ResultSet resultSet) throws SQLException {
+
+ // Accumulate an ordered list of DynaProperties
+ ArrayList list = new ArrayList();
+ ResultSetMetaData metadata = resultSet.getMetaData();
+ int n = metadata.getColumnCount();
+ for (int i = 1; i <= n; i++) { // JDBC is one-relative!
+ DynaProperty dynaProperty = createDynaProperty(metadata, i);
+ if (dynaProperty != null) {
+ list.add(dynaProperty);
+ }
+ }
+
+ // Convert this list into the internal data structures we need
+ properties =
+ (DynaProperty[]) list.toArray(new DynaProperty[list.size()]);
+ for (int i = 0; i < properties.length; i++) {
+ propertiesMap.put(properties[i].getName(), properties[i]);
+ }
+
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,836 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.beanutils;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Date;
+import java.lang.reflect.Array;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.io.Serializable;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * <p>DynaBean which automatically adds properties to the <code>DynaClass</code>
+ * and provides <i>Lazy List</i> and <i>Lazy Map</i> features.</p>
+ *
+ * <p>DynaBeans deal with three types of properties - <i>simple</i>, <i>indexed</i> and <i>mapped</i> and
+ * have the following <code>get()</code> and <code>set()</code> methods for
+ * each of these types:</p>
+ * <ul>
+ * <li><i>Simple</i> property methods - <code>get(name)</code> and <code>set(name, value)</code></li>
+ * <li><i>Indexed</i> property methods - <code>get(name, index)</code> and <code>set(name, index, value)</code></li>
+ * <li><i>Mapped</i> property methods - <code>get(name, key)</code> and <code>set(name, key, value)</code></li>
+ * </ul>
+ *
+ * <p><b><u>Getting Property Values</u></b></p>
+ * <p>Calling any of the <code>get()</code> methods, for a property which
+ * doesn't exist, returns <code>null</code> in this implementation.</p>
+ *
+ * <p><b><u>Setting Simple Properties</u></b></p>
+ * <p>The <code>LazyDynaBean</code> will automatically add a property to the <code>DynaClass</code>
+ * if it doesn't exist when the <code>set(name, value)</code> method is called.</p>
+ *
+ * <code>DynaBean myBean = new LazyDynaBean();</code></br>
+ * <code>myBean.set("myProperty", "myValue");</code></br>
+ *
+ * <p><b><u>Setting Indexed Properties</u></b></p>
+ * <p>If the property <b>doesn't</b> exist, the <code>LazyDynaBean</code> will automatically add
+ * a property with an <code>ArrayList</code> type to the <code>DynaClass</code> when
+ * the <code>set(name, index, value)</code> method is called.
+ * It will also instantiate a new <code>ArrayList</code> and automatically <i>grow</i>
+ * the <code>List</code> so that it is big enough to accomodate the index being set.
+ * <code>ArrayList</code> is the default indexed property that LazyDynaBean uses but
+ * this can be easily changed by overriding the <code>newIndexedProperty(name)</code>
+ * method.</p>
+ *
+ * <code>DynaBean myBean = new LazyDynaBean();</code></br>
+ * <code>myBean.set("myIndexedProperty", 0, "myValue1");</code></br>
+ * <code>myBean.set("myIndexedProperty", 1, "myValue2");</code></br>
+ *
+ * <p>If the indexed property <b>does</b> exist in the <code>DynaClass</code> but is set to
+ * <code>null</code> in the <code>LazyDynaBean</code>, then it will instantiate a
+ * new <code>List</code> or <code>Array</code> as specified by the property's type
+ * in the <code>DynaClass</code> and automatically <i>grow</i> the <code>List</code>
+ * or <code>Array</code> so that it is big enough to accomodate the index being set.</p>
+ *
+ * <code>DynaBean myBean = new LazyDynaBean();</code></br>
+ * <code>MutableDynaClass myClass = (MutableDynaClass)myBean.getDynaClass();</code></br>
+ * <code>myClass.add("myIndexedProperty", int[].class);</code></br>
+ * <code>myBean.set("myIndexedProperty", 0, new Integer(10));</code></br>
+ * <code>myBean.set("myIndexedProperty", 1, new Integer(20));</code></br>
+ *
+ * <p><b><u>Setting Mapped Properties</u></b></p>
+ * <p>If the property <b>doesn't</b> exist, the <code>LazyDynaBean</code> will automatically add
+ * a property with a <code>HashMap</code> type to the <code>DynaClass</code> and
+ * instantiate a new <code>HashMap</code> in the DynaBean when the
+ * <code>set(name, key, value)</code> method is called. <code>HashMap</code> is the default
+ * mapped property that LazyDynaBean uses but this can be easily changed by overriding
+ * the <code>newMappedProperty(name)</code> method.</p>
+ *
+ * <code>DynaBean myBean = new LazyDynaBean();</code></br>
+ * <code>myBean.set("myMappedProperty", "myKey", "myValue");</code></br>
+ *
+ * <p>If the mapped property <b>does</b> exist in the <code>DynaClass</code> but is set to
+ * <code>null</code> in the <code>LazyDynaBean</code>, then it will instantiate a
+ * new <code>Map</code> as specified by the property's type in the <code>DynaClass</code>.</p>
+ *
+ * <code>DynaBean myBean = new LazyDynaBean();</code></br>
+ * <code>MutableDynaClass myClass = (MutableDynaClass)myBean.getDynaClass();</code></br>
+ * <code>myClass.add("myMappedProperty", TreeMap.class);</code></br>
+ * <code>myBean.set("myMappedProperty", "myKey", "myValue");</code></br>
+ *
+ * <p><b><u><i>Restricted</i> DynaClass</u></b></p>
+ * <p><code>MutableDynaClass</code> have a facility to <i>restrict</i> the <code>DynaClass</code>
+ * so that its properties cannot be modified. If the <code>MutableDynaClass</code> is
+ * restricted then calling any of the <code>set()</code> methods for a property which
+ * doesn't exist will result in a <code>IllegalArgumentException</code> being thrown.</p>
+ *
+ * @see LazyDynaClass
+ * @author Niall Pemberton
+ */
+public class LazyDynaBean implements DynaBean, Serializable {
+
+
+ /**
+ * Commons Logging
+ */
+ private static Log logger = LogFactory.getLog(LazyDynaBean.class);
+
+ protected static final BigInteger BigInteger_ZERO = new BigInteger("0");
+ protected static final BigDecimal BigDecimal_ZERO = new BigDecimal("0");
+ protected static final Character Character_SPACE = new Character(' ');
+ protected static final Byte Byte_ZERO = new Byte((byte)0);
+ protected static final Short Short_ZERO = new Short((short)0);
+ protected static final Integer Integer_ZERO = new Integer(0);
+ protected static final Long Long_ZERO = new Long((long)0);
+ protected static final Float Float_ZERO = new Float((byte)0);
+ protected static final Double Double_ZERO = new Double((byte)0);
+
+ /**
+ * The <code>MutableDynaClass</code> "base class" that this DynaBean
+ * is associated with.
+ */
+ protected Map values;
+
+ /**
+ * The <code>MutableDynaClass</code> "base class" that this DynaBean
+ * is associated with.
+ */
+ protected MutableDynaClass dynaClass;
+
+
+ // ------------------- Constructors ----------------------------------
+
+ /**
+ * Construct a new <code>LazyDynaBean</code> with a <code>LazyDynaClass</code> instance.
+ */
+ public LazyDynaBean() {
+ this(new LazyDynaClass());
+ }
+
+ /**
+ * Construct a new <code>LazyDynaBean</code> with a <code>LazyDynaClass</code> instance.
+ *
+ * @param name Name of this DynaBean class
+ */
+ public LazyDynaBean(String name) {
+ this(new LazyDynaClass(name));
+ }
+
+ /**
+ * Construct a new <code>DynaBean</code> associated with the specified
+ * <code>DynaClass</code> instance - if its not a <code>MutableDynaClass</code>
+ * then a new <code>LazyDynaClass</code> is created and the properties copied.
+ *
+ * @param dynaClass The DynaClass we are associated with
+ */
+ public LazyDynaBean(DynaClass dynaClass) {
+
+ values = newMap();
+
+ if (dynaClass instanceof MutableDynaClass) {
+ this.dynaClass = (MutableDynaClass)dynaClass;
+ } else {
+ this.dynaClass = new LazyDynaClass(dynaClass.getName(), dynaClass.getDynaProperties());
+ }
+
+ }
+
+
+ // ------------------- Public Methods ----------------------------------
+
+ /**
+ * Return the Map backing this <code>DynaBean</code>
+ */
+ public Map getMap() {
+ return values;
+ }
+
+ /**
+ * <p>Return the size of an indexed or mapped property.</p>
+ *
+ * @param name Name of the property
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ public int size(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("No property name specified");
+ }
+
+ Object value = values.get(name);
+ if (value == null) {
+ return 0;
+ }
+
+ if (value instanceof Map) {
+ return ((Map)value).size();
+ }
+
+ if (value instanceof List) {
+ return ((List)value).size();
+ }
+
+ if ((value.getClass().isArray())) {
+ return Array.getLength(value);
+ }
+
+ return 0;
+
+ }
+
+ // ------------------- DynaBean Methods ----------------------------------
+
+ /**
+ * Does the specified mapped property contain a value for the specified
+ * key value?
+ *
+ * @param name Name of the property to check
+ * @param key Name of the key to check
+ *
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ public boolean contains(String name, String key) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("No property name specified");
+ }
+
+ Object value = values.get(name);
+ if (value == null) {
+ return false;
+ }
+
+ if (value instanceof Map) {
+ return (((Map) value).containsKey(key));
+ }
+
+ return false;
+
+ }
+
+ /**
+ * <p>Return the value of a simple property with the specified name.</p>
+ *
+ * <p><strong>N.B.</strong> Returns <code>null</code> if there is no property
+ * of the specified name.</p>
+ *
+ * @param name Name of the property whose value is to be retrieved.
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ public Object get(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("No property name specified");
+ }
+
+ // Value found
+ Object value = values.get(name);
+ if (value != null) {
+ return value;
+ }
+
+ // Property doesn't exist
+ if (!isDynaProperty(name)) {
+ return null;
+ }
+
+ // Property doesn't exist
+ value = createProperty(name, dynaClass.getDynaProperty(name).getType());
+
+ if (value != null) {
+ set(name, value);
+ }
+
+ return value;
+
+ }
+
+ /**
+ * <p>Return the value of an indexed property with the specified name.</p>
+ *
+ * <p><strong>N.B.</strong> Returns <code>null</code> if there is no 'indexed'
+ * property of the specified name.</p>
+ *
+ * @param name Name of the property whose value is to be retrieved
+ * @param index Index of the value to be retrieved
+ *
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not indexed
+ * @exception IndexOutOfBoundsException if the specified index
+ * is outside the range of the underlying property
+ */
+ public Object get(String name, int index) {
+
+ // If its not a property, then create default indexed property
+ if (!isDynaProperty(name)) {
+ set(name, defaultIndexedProperty(name));
+ }
+
+ // Get the indexed property
+ Object indexedProperty = get(name);
+
+ // Check that the property is indexed
+ if (!dynaClass.getDynaProperty(name).isIndexed()) {
+ throw new IllegalArgumentException
+ ("Non-indexed property for '" + name + "[" + index + "]' "
+ + dynaClass.getDynaProperty(name).getName());
+ }
+
+ // Grow indexed property to appropriate size
+ indexedProperty = growIndexedProperty(name, indexedProperty, index);
+
+ // Return the indexed value
+ if (indexedProperty.getClass().isArray()) {
+ return Array.get(indexedProperty, index);
+ } else if (indexedProperty instanceof List) {
+ return ((List)indexedProperty).get(index);
+ } else {
+ throw new IllegalArgumentException
+ ("Non-indexed property for '" + name + "[" + index + "]' "
+ + indexedProperty.getClass().getName());
+ }
+
+ }
+
+ /**
+ * <p>Return the value of a mapped property with the specified name.</p>
+ *
+ * <p><strong>N.B.</strong> Returns <code>null</code> if there is no 'mapped'
+ * property of the specified name.</p>
+ *
+ * @param name Name of the property whose value is to be retrieved
+ * @param key Key of the value to be retrieved
+ *
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not mapped
+ */
+ public Object get(String name, String key) {
+
+ // If its not a property, then create default mapped property
+ if (!isDynaProperty(name)) {
+ set(name, defaultMappedProperty(name));
+ }
+
+ // Get the mapped property
+ Object mappedProperty = get(name);
+
+ // Check that the property is mapped
+ if (!dynaClass.getDynaProperty(name).isMapped()) {
+ throw new IllegalArgumentException
+ ("Non-mapped property for '" + name + "(" + key + ")' "
+ + dynaClass.getDynaProperty(name).getType().getName());
+ }
+
+ // Get the value from the Map
+ if (mappedProperty instanceof Map) {
+ return (((Map) mappedProperty).get(key));
+ } else {
+ throw new IllegalArgumentException
+ ("Non-mapped property for '" + name + "(" + key + ")'"
+ + mappedProperty.getClass().getName());
+ }
+
+ }
+
+
+ /**
+ * Return the <code>DynaClass</code> instance that describes the set of
+ * properties available for this DynaBean.
+ */
+ public DynaClass getDynaClass() {
+ return (DynaClass)dynaClass;
+ }
+
+ /**
+ * Remove any existing value for the specified key on the
+ * specified mapped property.
+ *
+ * @param name Name of the property for which a value is to
+ * be removed
+ * @param key Key of the value to be removed
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public void remove(String name, String key) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("No property name specified");
+ }
+
+ Object value = values.get(name);
+ if (value == null) {
+ return;
+ }
+
+ if (value instanceof Map) {
+ ((Map) value).remove(key);
+ } else {
+ throw new IllegalArgumentException
+ ("Non-mapped property for '" + name + "(" + key + ")'"
+ + value.getClass().getName());
+ }
+
+ }
+
+ /**
+ * Set the value of a simple property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception IllegalArgumentException if this is not an existing property
+ * name for our DynaClass and the MutableDynaClass is restricted
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception NullPointerException if an attempt is made to set a
+ * primitive property to null
+ */
+ public void set(String name, Object value) {
+
+ // If the property doesn't exist, then add it
+ if (!isDynaProperty(name)) {
+
+ if (dynaClass.isRestricted()) {
+ throw new IllegalArgumentException
+ ("Invalid property name '" + name + "' (DynaClass is restricted)");
+ }
+ if (value == null) {
+ dynaClass.add(name);
+ } else {
+ dynaClass.add(name, value.getClass());
+ }
+
+ }
+
+ DynaProperty descriptor = dynaClass.getDynaProperty(name);
+
+ if (value == null) {
+ if (descriptor.getType().isPrimitive()) {
+ throw new NullPointerException
+ ("Primitive value for '" + name + "'");
+ }
+ } else if (!isAssignable(descriptor.getType(), value.getClass())) {
+ throw new ConversionException
+ ("Cannot assign value of type '" +
+ value.getClass().getName() +
+ "' to property '" + name + "' of type '" +
+ descriptor.getType().getName() + "'");
+ }
+
+ // Set the property's value
+ values.put(name, value);
+
+ }
+
+ /**
+ * Set the value of an indexed property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param index Index of the property to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not indexed
+ * @exception IndexOutOfBoundsException if the specified index
+ * is outside the range of the underlying property
+ */
+ public void set(String name, int index, Object value) {
+
+ // If its not a property, then create default indexed property
+ if (!isDynaProperty(name)) {
+ set(name, defaultIndexedProperty(name));
+ }
+
+ // Get the indexed property
+ Object indexedProperty = get(name);
+
+ // Check that the property is indexed
+ if (!dynaClass.getDynaProperty(name).isIndexed()) {
+ throw new IllegalArgumentException
+ ("Non-indexed property for '" + name + "[" + index + "]'"
+ + dynaClass.getDynaProperty(name).getType().getName());
+ }
+
+ // Grow indexed property to appropriate size
+ indexedProperty = growIndexedProperty(name, indexedProperty, index);
+
+ // Set the value in an array
+ if (indexedProperty.getClass().isArray()) {
+ Array.set(indexedProperty, index, value);
+ } else if (indexedProperty instanceof List) {
+ ((List)indexedProperty).set(index, value);
+ } else {
+ throw new IllegalArgumentException
+ ("Non-indexed property for '" + name + "[" + index + "]' "
+ + indexedProperty.getClass().getName());
+ }
+
+ }
+
+ /**
+ * Set the value of a mapped property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param key Key of the property to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not mapped
+ */
+ public void set(String name, String key, Object value) {
+
+ // If the 'mapped' property doesn't exist, then add it
+ if (!isDynaProperty(name)) {
+ set(name, defaultMappedProperty(name));
+ }
+
+ // Get the mapped property
+ Object mappedProperty = get(name);
+
+ // Check that the property is mapped
+ if (!dynaClass.getDynaProperty(name).isMapped()) {
+ throw new IllegalArgumentException
+ ("Non-mapped property for '" + name + "(" + key + ")'"
+ + dynaClass.getDynaProperty(name).getType().getName());
+ }
+
+ // Set the value in the Map
+ ((Map)mappedProperty).put(key, value);
+
+ }
+
+ // ------------------- protected Methods ----------------------------------
+
+ protected Object growIndexedProperty(String name, Object indexedProperty, int index) {
+
+ // Grow a List to the appropriate size
+ if (indexedProperty instanceof List) {
+
+ List list = (List)indexedProperty;
+ while (index >= list.size()) {
+ list.add(null);
+ }
+
+ }
+
+ // Grow an Array to the appropriate size
+ if ((indexedProperty.getClass().isArray())) {
+
+ int length = Array.getLength(indexedProperty);
+ if (index >= length) {
+ Class componentType = indexedProperty.getClass().getComponentType();
+ Object newArray = Array.newInstance(componentType, (index + 1));
+ System.arraycopy(indexedProperty, 0, newArray, 0, length);
+ indexedProperty = newArray;
+ set(name, indexedProperty);
+ int newLength = Array.getLength(indexedProperty);
+ for (int i = length; i < newLength; i++) {
+ Array.set(indexedProperty, i, createProperty(name+"["+i+"]", componentType));
+ }
+ }
+ }
+
+ return indexedProperty;
+
+ }
+
+ /**
+ * Create a new Instance of a Property
+ */
+ protected Object createProperty(String name, Class type) {
+
+ // Create Lists, arrays or DynaBeans
+ if (type.isArray() || List.class.isAssignableFrom(type)) {
+ return createIndexedProperty(name, type);
+ }
+
+ if (Map.class.isAssignableFrom(type)) {
+ return createMappedProperty(name, type);
+ }
+
+ if (DynaBean.class.isAssignableFrom(type)) {
+ return createDynaBeanProperty(name, type);
+ }
+
+ if (type.isPrimitive()) {
+ return createPrimitiveProperty(name, type);
+ }
+
+ if (Number.class.isAssignableFrom(type)) {
+ return createNumberProperty(name, type);
+ }
+
+ return createOtherProperty(name, type);
+
+ }
+
+ /**
+ * Create a new Instance of an 'Indexed' Property
+ */
+ protected Object createIndexedProperty(String name, Class type) {
+
+ // Create the indexed object
+ Object indexedProperty = null;
+
+ if (type == null) {
+
+ indexedProperty = defaultIndexedProperty(name);
+
+ } else if (type.isArray()) {
+
+ indexedProperty = Array.newInstance(type.getComponentType(), 0);
+
+ } else if (List.class.isAssignableFrom(type)) {
+ if (type.isInterface()) {
+ indexedProperty = defaultIndexedProperty(name);
+ } else {
+ try {
+ indexedProperty = type.newInstance();
+ }
+ catch (Exception ex) {
+ throw new IllegalArgumentException
+ ("Error instantiating indexed property of type '" +
+ type.getName() + "' for '" + name + "' " + ex);
+ }
+ }
+ } else {
+
+ throw new IllegalArgumentException
+ ("Non-indexed property of type '" + type.getName() + "' for '" + name + "'");
+ }
+
+ return indexedProperty;
+
+ }
+
+ /**
+ * Create a new Instance of a 'Mapped' Property
+ */
+ protected Object createMappedProperty(String name, Class type) {
+
+ // Create the mapped object
+ Object mappedProperty = null;
+
+ if (type == null) {
+
+ mappedProperty = defaultMappedProperty(name);
+
+ } else if (type.isInterface()) {
+
+ mappedProperty = defaultMappedProperty(name);
+
+ } else if (Map.class.isAssignableFrom(type)) {
+ try {
+ mappedProperty = type.newInstance();
+ }
+ catch (Exception ex) {
+ throw new IllegalArgumentException
+ ("Error instantiating mapped property of type '" + type.getName() + "' for '" + name + "' " + ex);
+ }
+ } else {
+
+ throw new IllegalArgumentException
+ ("Non-mapped property of type '" + type.getName() + "' for '" + name + "'");
+ }
+
+ return mappedProperty;
+
+ }
+
+ /**
+ * Create a new Instance of a 'Mapped' Property
+ */
+ protected Object createDynaBeanProperty(String name, Class type) {
+ try {
+ return type.newInstance();
+ }
+ catch (Exception ex) {
+ if (logger.isWarnEnabled()) {
+ logger.warn("Error instantiating DynaBean property of type '" + type.getName() + "' for '" + name + "' " + ex);
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Create a new Instance of a 'Primitive' Property
+ */
+ protected Object createPrimitiveProperty(String name, Class type) {
+
+ if (type == Boolean.TYPE) {
+ return Boolean.FALSE;
+ } else if (type == Integer.TYPE) {
+ return Integer_ZERO;
+ } else if (type == Long.TYPE) {
+ return Long_ZERO;
+ } else if (type == Double.TYPE) {
+ return Double_ZERO;
+ } else if (type == Float.TYPE) {
+ return Float_ZERO;
+ } else if (type == Byte.TYPE) {
+ return Byte_ZERO;
+ } else if (type == Short.TYPE) {
+ return Short_ZERO;
+ } else if (type == Character.TYPE) {
+ return Character_SPACE;
+ } else {
+ return null;
+ }
+
+ }
+
+ /**
+ * Create a new Instance of a 'Primitive' Property
+ */
+ protected Object createNumberProperty(String name, Class type) {
+
+ return null;
+
+ }
+
+ /**
+ * Create a new Instance of a 'Mapped' Property
+ */
+ protected Object createOtherProperty(String name, Class type) {
+
+ if (type == String.class || type == Boolean.class ||
+ type == Character.class || Date.class.isAssignableFrom(type)) {
+ return null;
+ }
+
+ try {
+ return type.newInstance();
+ }
+ catch (Exception ex) {
+ if (logger.isWarnEnabled()) {
+ logger.warn("Error instantiating property of type '" + type.getName() + "' for '" + name + "' " + ex);
+ }
+ return null;
+ }
+ }
+
+ /**
+ * <p>Creates a new <code>ArrayList</code> for an 'indexed' property
+ * which doesn't exist.</p>
+ *
+ * <p>This method shouls be overriden if an alternative <code>List</code>
+ * or <code>Array</code> implementation is required for 'indexed' properties.</p>
+ *
+ * @param name Name of the 'indexed property.
+ */
+ protected Object defaultIndexedProperty(String name) {
+ return new ArrayList();
+ }
+
+ /**
+ * <p>Creates a new <code>HashMap</code> for a 'mapped' property
+ * which doesn't exist.</p>
+ *
+ * <p>This method can be overriden if an alternative <code>Map</code>
+ * implementation is required for 'mapped' properties.</p>
+ *
+ * @param name Name of the 'mapped property.
+ */
+ protected Map defaultMappedProperty(String name) {
+ return new HashMap();
+ }
+
+ /**
+ * Indicates if there is a property with the specified name.
+ */
+ protected boolean isDynaProperty(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("No property name specified");
+ }
+
+ // Handle LazyDynaClasses
+ if (dynaClass instanceof LazyDynaClass) {
+ return ((LazyDynaClass)dynaClass).isDynaProperty(name);
+ }
+
+ // Handle other MutableDynaClass
+ return dynaClass.getDynaProperty(name) == null ? false : true;
+
+ }
+
+ /**
+ * Is an object of the source class assignable to the destination class?
+ *
+ * @param dest Destination class
+ * @param source Source class
+ */
+ protected boolean isAssignable(Class dest, Class source) {
+
+ if (dest.isAssignableFrom(source) ||
+ ((dest == Boolean.TYPE) && (source == Boolean.class)) ||
+ ((dest == Byte.TYPE) && (source == Byte.class)) ||
+ ((dest == Character.TYPE) && (source == Character.class)) ||
+ ((dest == Double.TYPE) && (source == Double.class)) ||
+ ((dest == Float.TYPE) && (source == Float.class)) ||
+ ((dest == Integer.TYPE) && (source == Integer.class)) ||
+ ((dest == Long.TYPE) && (source == Long.class)) ||
+ ((dest == Short.TYPE) && (source == Short.class))) {
+ return (true);
+ } else {
+ return (false);
+ }
+
+ }
+
+ /**
+ * <p>Creates a new instance of the <code>Map</code>.</p>
+ */
+ protected Map newMap() {
+ return new HashMap();
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaClass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaClass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaClass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,337 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.beanutils;
+
+/**
+ * <p>DynaClass which implements the <code>MutableDynaClass</code> interface.</p>
+ *
+ * <p>A <code>MutableDynaClass</code> is a specialized extension to <code>DynaClass</code>
+ * that allows properties to be added or removed dynamically.</p>
+ *
+ * <p>This implementation has one slightly unusual default behaviour - calling
+ * the <code>getDynaProperty(name)</code> method for a property which doesn't
+ * exist returns a <code>DynaProperty</code> rather than <code>null</code>. The
+ * reason for this is that <code>BeanUtils</code> calls this method to check if
+ * a property exists before trying to set the value. This would defeat the object
+ * of the <code>LazyDynaBean</code> which automatically adds missing properties
+ * when any of its <code>set()</code> methods are called. For this reason the
+ * <code>isDynaProperty(name)</code> method has been added to this implementation
+ * in order to determine if a property actually exists. If the more <i>normal</i>
+ * behaviour of returning <code>null</code> is required, then this can be achieved
+ * by calling the <code>setReturnNull(true)</code>.</p>
+ *
+ * <p>The <code>add(name, type, readable, writable)</code> method is not implemented
+ * and always throws an <code>UnsupportedOperationException</code>. I believe
+ * this attributes need to be added to the <code>DynaProperty</code> class
+ * in order to control read/write facilities.</p>
+ *
+ * @see LazyDynaBean
+ * @author Niall Pemberton
+ */
+public class LazyDynaClass extends BasicDynaClass implements MutableDynaClass {
+
+ /**
+ * Controls whether changes to this DynaClass's properties are allowed.
+ */
+ protected boolean restricted;
+
+ /**
+ * <p>Controls whether the <code>getDynaProperty()</code> method returns
+ * null if a property doesn't exist - or creates a new one.</p>
+ *
+ * <p>Default is <code>false</code>.
+ */
+ protected boolean returnNull = false;
+
+ /**
+ * Construct a new LazyDynaClass with default parameters.
+ */
+ public LazyDynaClass() {
+ this(null, (DynaProperty[])null);
+ }
+
+ /**
+ * Construct a new LazyDynaClass with the specified name.
+ *
+ * @param name Name of this DynaBean class
+ */
+ public LazyDynaClass(String name) {
+ this(name, (DynaProperty[])null);
+ }
+
+ /**
+ * Construct a new LazyDynaClass with the specified name and DynaBean class.
+ *
+ * @param name Name of this DynaBean class
+ * @param dynaBeanClass The implementation class for new instances
+ */
+ public LazyDynaClass(String name, Class dynaBeanClass) {
+ this(name, dynaBeanClass, null);
+ }
+
+ /**
+ * Construct a new LazyDynaClass with the specified name and properties.
+ *
+ * @param name Name of this DynaBean class
+ * @param properties Property descriptors for the supported properties
+ */
+ public LazyDynaClass(String name, DynaProperty[] properties) {
+ this(name, LazyDynaBean.class, properties);
+ }
+
+ /**
+ * Construct a new LazyDynaClass with the specified name, DynaBean class and properties.
+ *
+ * @param name Name of this DynaBean class
+ * @param dynaBeanClass The implementation class for new intances
+ * @param properties Property descriptors for the supported properties
+ */
+ public LazyDynaClass(String name, Class dynaBeanClass, DynaProperty properties[]) {
+ super(name, dynaBeanClass, properties);
+ }
+
+ /**
+ * <p>Is this DynaClass currently restricted.</p>
+ * <p>If restricted, no changes to the existing registration of
+ * property names, data types, readability, or writeability are allowed.</p>
+ */
+ public boolean isRestricted() {
+ return restricted;
+ }
+
+ /**
+ * <p>Set whether this DynaClass is currently restricted.</p>
+ * <p>If restricted, no changes to the existing registration of
+ * property names, data types, readability, or writeability are allowed.</p>
+ */
+ public void setRestricted(boolean restricted) {
+ this.restricted = restricted;
+ }
+
+ /**
+ * Should this DynaClass return a <code>null</code> from
+ * the <code>getDynaProperty(name)</code> method if the property
+ * doesn't exist.
+ */
+ public boolean isReturnNull() {
+ return returnNull;
+ }
+
+ /**
+ * Set whether this DynaClass should return a <code>null</code> from
+ * the <code>getDynaProperty(name)</code> method if the property
+ * doesn't exist.
+ */
+ public void setReturnNull(boolean returnNull) {
+ this.returnNull = returnNull;
+ }
+
+ /**
+ * Add a new dynamic property with no restrictions on data type,
+ * readability, or writeability.
+ *
+ * @param name Name of the new dynamic property
+ *
+ * @exception IllegalArgumentException if name is null
+ * @exception IllegalStateException if this DynaClass is currently
+ * restricted, so no new properties can be added
+ */
+ public void add(String name) {
+ add(new DynaProperty(name));
+ }
+
+ /**
+ * Add a new dynamic property with the specified data type, but with
+ * no restrictions on readability or writeability.
+ *
+ * @param name Name of the new dynamic property
+ * @param type Data type of the new dynamic property (null for no
+ * restrictions)
+ *
+ * @exception IllegalArgumentException if name is null
+ * @exception IllegalStateException if this DynaClass is currently
+ * restricted, so no new properties can be added
+ */
+ public void add(String name, Class type) {
+ add(new DynaProperty(name, type));
+ }
+
+ /**
+ * <p>Add a new dynamic property with the specified data type, readability,
+ * and writeability.</p>
+ *
+ * <p><strong>N.B.</strong>Support for readable/writeable properties has not been implemented
+ * and this method always throws a <code>UnsupportedOperationException</code>.</p>
+ *
+ * <p>I'm not sure the intention of the original authors for this method, but it seems to
+ * me that readable/writable should be attributes of the <code>DynaProperty</code> class
+ * (which they are not) and is the reason this method has not been implemented.</p>
+ *
+ * @param name Name of the new dynamic property
+ * @param type Data type of the new dynamic property (null for no
+ * restrictions)
+ * @param readable Set to <code>true</code> if this property value
+ * should be readable
+ * @param writeable Set to <code>true</code> if this property value
+ * should be writeable
+ *
+ * @exception UnsupportedOperationException anytime this method is called
+ */
+ public void add(String name, Class type, boolean readable, boolean writeable) {
+ throw new java.lang.UnsupportedOperationException("readable/writable properties not supported");
+ }
+
+ /**
+ * Add a new dynamic property.
+ *
+ * @param property Property the new dynamic property to add.
+ *
+ * @exception IllegalArgumentException if name is null
+ * @exception IllegalStateException if this DynaClass is currently
+ * restricted, so no new properties can be added
+ */
+ protected void add(DynaProperty property) {
+
+ if (property.getName() == null) {
+ throw new IllegalArgumentException("Property name is missing.");
+ }
+
+ if (isRestricted()) {
+ throw new IllegalStateException("DynaClass is currently restricted. No new properties can be added.");
+ }
+
+ // Check if property already exists
+ if (propertiesMap.get(property.getName()) != null) {
+ return;
+ }
+
+ // Create a new property array with the specified property
+ DynaProperty[] oldProperties = getDynaProperties();
+ DynaProperty[] newProperties = new DynaProperty[oldProperties.length+1];
+ System.arraycopy(oldProperties, 0, newProperties, 0, oldProperties.length);
+ newProperties[oldProperties.length] = property;
+
+ // Update the properties
+ setProperties(newProperties);
+
+ }
+
+ /**
+ * Remove the specified dynamic property, and any associated data type,
+ * readability, and writeability, from this dynamic class.
+ * <strong>NOTE</strong> - This does <strong>NOT</strong> cause any
+ * corresponding property values to be removed from DynaBean instances
+ * associated with this DynaClass.
+ *
+ * @param name Name of the dynamic property to remove
+ *
+ * @exception IllegalArgumentException if name is null
+ * @exception IllegalStateException if this DynaClass is currently
+ * restricted, so no properties can be removed
+ */
+ public void remove(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("Property name is missing.");
+ }
+
+ if (isRestricted()) {
+ throw new IllegalStateException("DynaClass is currently restricted. No properties can be removed.");
+ }
+
+ // Ignore if property doesn't exist
+ if (propertiesMap.get(name) == null) {
+ return;
+ }
+
+
+ // Create a new property array of without the specified property
+ DynaProperty[] oldProperties = getDynaProperties();
+ DynaProperty[] newProperties = new DynaProperty[oldProperties.length-1];
+ int j = 0;
+ for (int i = 0; i < oldProperties.length; i++) {
+ if (!(name.equals(oldProperties[i].getName()))) {
+ newProperties[j] = oldProperties[i];
+ j++;
+ }
+ }
+
+ // Update the properties
+ setProperties(newProperties);
+
+ }
+
+ /**
+ * <p>Return a property descriptor for the specified property.</p>
+ *
+ * <p>If the property is not found and the <code>returnNull</code> indicator is
+ * <code>true</code>, this method always returns <code>null</code>.</p>
+ *
+ * <p>If the property is not found and the <code>returnNull</code> indicator is
+ * <code>false</code> a new property descriptor is created and returned (although
+ * its not actually added to the DynaClass's properties). This is the default
+ * beahviour.</p>
+ *
+ * <p>The reason for not returning a <code>null</code> property descriptor is that
+ * <code>BeanUtils</code> uses this method to check if a property exists
+ * before trying to set it - since these <i>Lazy</i> implementations automatically
+ * add any new properties when they are set, returning <code>null</code> from
+ * this method would defeat their purpose.</p>
+ *
+ * @param name Name of the dynamic property for which a descriptor
+ * is requested
+ *
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ public DynaProperty getDynaProperty(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("Property name is missing.");
+ }
+
+ DynaProperty dynaProperty = (DynaProperty)propertiesMap.get(name);
+
+ // If it doesn't exist and returnNull is false
+ // create a new DynaProperty
+ if (dynaProperty == null && !isReturnNull() && !isRestricted()) {
+ dynaProperty = new DynaProperty(name);
+ }
+
+ return dynaProperty;
+
+ }
+
+ /**
+ * <p>Indicate whether a property actually exists.</p>
+ *
+ * <p><strong>N.B.</strong> Using <code>getDynaProperty(name) == null</code>
+ * doesn't work in this implementation because that method might
+ * return a DynaProperty if it doesn't exist (depending on the
+ * <code>returnNull</code> indicator).</p>
+ *
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ public boolean isDynaProperty(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("Property name is missing.");
+ }
+
+ return propertiesMap.get(name) == null ? false : true;
+
+ }
+
+}
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaMap.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaMap.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/LazyDynaMap.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.beanutils;
+
+import java.util.Map;
+import java.util.Iterator;
+
+/**
+ * <p>Provides a <i>light weight</i> <code>DynaBean</code> facade to a <code>Map</code> with <i>lazy</i> map/list processing.</p>
+ *
+ * <p>Its a <i>light weight</i> <code>DynaBean</code> implementation because there is no
+ * actual <code>DynaClass</code> associated with this <code>DynaBean</code> - in fact
+ * it implements the <code>DynaClass</code> interface itself providing <i>pseudo</i> DynaClass
+ * behaviour from the actual values stored in the <code>Map</code>.</p>
+ *
+ * <p>As well providing rhe standard <code>DynaBean</code> access to the <code>Map</code>'s properties
+ * this class also provides the usual <i>Lazy</i> behaviour:</p>
+ * <ul>
+ * <li>Properties don't need to be pre-defined in a <code>DynaClass</code></li>
+ * <li>Indexed properties (<code>Lists</code> or <code>Arrays</code>) are automatically instantiated
+ * and <i>grown</i> so that they are large enough to cater for the index being set.</li>
+ * <li>Mapped properties are automatically instantiated.</li>
+ * </ul>
+ *
+ * <p><b><u><i>Restricted</i> DynaClass</u></b></p>
+ * <p>This class implements the <code>MutableDynaClass</code> interface.
+ * <code>MutableDynaClass</code> have a facility to <i>restrict</i> the <code>DynaClass</code>
+ * so that its properties cannot be modified. If the <code>MutableDynaClass</code> is
+ * restricted then calling any of the <code>set()</code> methods for a property which
+ * doesn't exist will result in a <code>IllegalArgumentException</code> being thrown.</p>
+ *
+ * @author Niall Pemberton
+ */
+public class LazyDynaMap extends LazyDynaBean implements MutableDynaClass {
+
+ /**
+ * The name of this DynaClass (analogous to the
+ * <code>getName()</code> method of <code>java.lang.Class</code>).
+ */
+ protected String name;
+
+ /**
+ * Controls whether changes to this DynaClass's properties are allowed.
+ */
+ protected boolean restricted;
+
+ /**
+ * <p>Controls whether the <code>getDynaProperty()</code> method returns
+ * null if a property doesn't exist - or creates a new one.</p>
+ *
+ * <p>Default is <code>false</code>.
+ */
+ protected boolean returnNull = false;
+
+
+ // ------------------- Constructors ----------------------------------
+
+ /**
+ * Default Constructor.
+ */
+ public LazyDynaMap() {
+ this(null, (Map)null);
+ }
+
+ /**
+ * Construct a new <code>LazyDynaMap</code> with the specified name.
+ *
+ * @param name Name of this DynaBean class
+ */
+ public LazyDynaMap(String name) {
+ this(name, (Map)null);
+ }
+
+ /**
+ * Construct a new <code>LazyDynaMap</code> with the specified <code>Map</code>.
+ *
+ * @param values The Map backing this <code>LazyDynaMap</code>
+ */
+ public LazyDynaMap(Map values) {
+ this(null, values);
+ }
+
+ /**
+ * Construct a new <code>LazyDynaMap</code> with the specified name and <code>Map</code>.
+ *
+ * @param name Name of this DynaBean class
+ * @param values The Map backing this <code>LazyDynaMap</code>
+ */
+ public LazyDynaMap(String name, Map values) {
+ this.name = name == null ? "LazyDynaMap" : name;
+ this.values = values == null ? newMap() : values;
+ this.dynaClass = this;
+ }
+
+ /**
+ * Construct a new <code>LazyDynaMap</code> with the specified properties.
+ *
+ * @param properties Property descriptors for the supported properties
+ */
+ public LazyDynaMap(DynaProperty[] properties) {
+ this(null, properties);
+ }
+
+ /**
+ * Construct a new <code>LazyDynaMap</code> with the specified name and properties.
+ *
+ * @param name Name of this DynaBean class
+ * @param properties Property descriptors for the supported properties
+ */
+ public LazyDynaMap(String name, DynaProperty[] properties) {
+ this(name, (Map)null);
+ if (properties != null) {
+ for (int i = 0; i < properties.length; i++) {
+ add(properties[i]);
+ }
+ }
+ }
+
+ /**
+ * Construct a new <code>LazyDynaMap</code> based on an exisiting DynaClass
+ *
+ * @param dynaClass DynaClass to copy the name and properties from
+ */
+ public LazyDynaMap(DynaClass dynaClass) {
+ this(dynaClass.getName(), dynaClass.getDynaProperties());
+ }
+
+ // ------------------- Public Methods ----------------------------------
+
+ /**
+ * Set the Map backing this <code>DynaBean</code>
+ */
+ public void setMap(Map values) {
+ this.values = values;
+ }
+
+ // ------------------- DynaBean Methods ----------------------------------
+
+ /**
+ * Set the value of a simple property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param value Value to which this property is to be set
+ */
+ public void set(String name, Object value) {
+
+ if (isRestricted() && !values.containsKey(name)) {
+ throw new IllegalArgumentException
+ ("Invalid property name '" + name + "' (DynaClass is restricted)");
+ }
+
+ values.put(name, value);
+
+ }
+
+ // ------------------- DynaClass Methods ----------------------------------
+
+ /**
+ * Return the name of this DynaClass (analogous to the
+ * <code>getName()</code> method of <code>java.lang.Class</code)
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * <p>Return a property descriptor for the specified property.</p>
+ *
+ * <p>If the property is not found and the <code>returnNull</code> indicator is
+ * <code>true</code>, this method always returns <code>null</code>.</p>
+ *
+ * <p>If the property is not found and the <code>returnNull</code> indicator is
+ * <code>false</code> a new property descriptor is created and returned (although
+ * its not actually added to the DynaClass's properties). This is the default
+ * beahviour.</p>
+ *
+ * <p>The reason for not returning a <code>null</code> property descriptor is that
+ * <code>BeanUtils</code> uses this method to check if a property exists
+ * before trying to set it - since these <i>Map</i> implementations automatically
+ * add any new properties when they are set, returning <code>null</code> from
+ * this method would defeat their purpose.</p>
+ *
+ * @param name Name of the dynamic property for which a descriptor
+ * is requested
+ *
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ public DynaProperty getDynaProperty(String name) {
+
+ if (name == null)
+ throw new IllegalArgumentException("Property name is missing.");
+
+ // If it doesn't exist and returnNull is false
+ // create a new DynaProperty
+ if (!values.containsKey(name) && isReturnNull()) {
+ return null;
+ }
+
+ Object value = values.get(name);
+
+ if (value == null) {
+ return new DynaProperty(name);
+ } else {
+ return new DynaProperty(name, value.getClass());
+ }
+
+ }
+
+ /**
+ * <p>Return an array of <code>ProperyDescriptors</code> for the properties
+ * currently defined in this DynaClass. If no properties are defined, a
+ * zero-length array will be returned.</p>
+ *
+ * <p><strong>FIXME</strong> - Should we really be implementing
+ * <code>getBeanInfo()</code> instead, which returns property descriptors
+ * and a bunch of other stuff?</p>
+ */
+ public DynaProperty[] getDynaProperties() {
+
+ int i = 0;
+ DynaProperty[] properties = new DynaProperty[values.size()];
+ Iterator iterator = values.keySet().iterator();
+
+ while (iterator.hasNext()) {
+ String name = (String)iterator.next();
+ Object value = values.get(name);
+ properties[i++] = new DynaProperty(name, value == null ? null : value.getClass());
+ }
+
+ return properties;
+
+ }
+
+ /**
+ * Instantiate and return a new DynaBean instance, associated
+ * with this DynaClass.
+ */
+ public DynaBean newInstance() {
+ return new LazyDynaMap(this);
+ }
+
+
+ // ------------------- MutableDynaClass Methods ----------------------------------
+
+ /**
+ * <p>Is this DynaClass currently restricted.</p>
+ * <p>If restricted, no changes to the existing registration of
+ * property names, data types, readability, or writeability are allowed.</p>
+ */
+ public boolean isRestricted() {
+ return restricted;
+ }
+
+ /**
+ * <p>Set whether this DynaClass is currently restricted.</p>
+ * <p>If restricted, no changes to the existing registration of
+ * property names, data types, readability, or writeability are allowed.</p>
+ */
+ public void setRestricted(boolean restricted) {
+ this.restricted = restricted;
+ }
+
+ /**
+ * Add a new dynamic property with no restrictions on data type,
+ * readability, or writeability.
+ *
+ * @param name Name of the new dynamic property
+ *
+ * @exception IllegalArgumentException if name is null
+ */
+ public void add(String name) {
+ add(name, null);
+ }
+
+ /**
+ * Add a new dynamic property with the specified data type, but with
+ * no restrictions on readability or writeability.
+ *
+ * @param name Name of the new dynamic property
+ * @param type Data type of the new dynamic property (null for no
+ * restrictions)
+ *
+ * @exception IllegalArgumentException if name is null
+ * @exception IllegalStateException if this DynaClass is currently
+ * restricted, so no new properties can be added
+ */
+ public void add(String name, Class type) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("Property name is missing.");
+ }
+
+ if (isRestricted())
+ throw new IllegalStateException("DynaClass is currently restricted. No new properties can be added.");
+
+ Object value = values.get(name);
+
+ // Check if the property already exists
+ if (value == null) {
+ values.put(name, type == null ? null : createProperty(name, type));
+ }
+
+ }
+
+ /**
+ * <p>Add a new dynamic property with the specified data type, readability,
+ * and writeability.</p>
+ *
+ * <p><strong>N.B.</strong>Support for readable/writeable properties has not been implemented
+ * and this method always throws a <code>UnsupportedOperationException</code>.</p>
+ *
+ * <p>I'm not sure the intention of the original authors for this method, but it seems to
+ * me that readable/writable should be attributes of the <code>DynaProperty</code> class
+ * (which they are not) and is the reason this method has not been implemented.</p>
+ *
+ * @param name Name of the new dynamic property
+ * @param type Data type of the new dynamic property (null for no
+ * restrictions)
+ * @param readable Set to <code>true</code> if this property value
+ * should be readable
+ * @param writeable Set to <code>true</code> if this property value
+ * should be writeable
+ *
+ * @exception UnsupportedOperationException anytime this method is called
+ */
+ public void add(String name, Class type, boolean readable, boolean writeable) {
+ throw new java.lang.UnsupportedOperationException("readable/writable properties not supported");
+ }
+
+ /**
+ * Add a new dynamic property.
+ *
+ * @param property Property the new dynamic property to add.
+ *
+ * @exception IllegalArgumentException if name is null
+ */
+ protected void add(DynaProperty property) {
+ add(property.getName(), property.getType());
+ }
+
+ /**
+ * Remove the specified dynamic property, and any associated data type,
+ * readability, and writeability, from this dynamic class.
+ * <strong>NOTE</strong> - This does <strong>NOT</strong> cause any
+ * corresponding property values to be removed from DynaBean instances
+ * associated with this DynaClass.
+ *
+ * @param name Name of the dynamic property to remove
+ *
+ * @exception IllegalArgumentException if name is null
+ * @exception IllegalStateException if this DynaClass is currently
+ * restricted, so no properties can be removed
+ */
+ public void remove(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("Property name is missing.");
+ }
+
+ if (isRestricted()) {
+ throw new IllegalStateException("DynaClass is currently restricted. No properties can be removed.");
+ }
+
+ // Remove, if property doesn't exist
+ if (values.containsKey(name)) {
+ values.remove(name);
+ }
+
+ }
+
+
+ // ------------------- Additional Public Methods ----------------------------------
+
+ /**
+ * Should this DynaClass return a <code>null</code> from
+ * the <code>getDynaProperty(name)</code> method if the property
+ * doesn't exist.
+ */
+ public boolean isReturnNull() {
+ return returnNull;
+ }
+
+ /**
+ * Set whether this DynaClass should return a <code>null</code> from
+ * the <code>getDynaProperty(name)</code> method if the property
+ * doesn't exist.
+ */
+ public void setReturnNull(boolean returnNull) {
+ this.returnNull = returnNull;
+ }
+
+
+ // ------------------- Protected Methods ----------------------------------
+
+ /**
+ * <p>Indicate whether a property actually exists.</p>
+ *
+ * <p><strong>N.B.</strong> Using <code>getDynaProperty(name) == null</code>
+ * doesn't work in this implementation because that method might
+ * return a DynaProperty if it doesn't exist (depending on the
+ * <code>returnNull</code> indicator).</p>
+ *
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ protected boolean isDynaProperty(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException("Property name is missing.");
+ }
+
+ return values.containsKey(name);
+
+ }
+
+}
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MappedPropertyDescriptor.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MappedPropertyDescriptor.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MappedPropertyDescriptor.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+
+/**
+ * A MappedPropertyDescriptor describes one mapped property.
+ * Mapped properties are multivalued properties like indexed properties
+ * but that are accessed with a String key instead of an index.
+ * Such property values are typically stored in a Map collection.
+ * For this class to work properly, a mapped value must have
+ * getter and setter methods of the form
+ * <p><code>get<strong>Property</strong>(String key)<code> and
+ * <p><code>set<Property>(String key, Object value)<code>,
+ * <p>where <code><strong>Property</strong></code> must be replaced
+ * by the name of the property.
+ * @see java.beans.PropertyDescriptor
+ *
+ * @author Rey François
+ * @author Gregor Raýman
+ * @version $Revision: 1.18.2.1 $ $Date: 2004/07/27 21:44:26 $
+ */
+
+
+public class MappedPropertyDescriptor extends PropertyDescriptor {
+ // ----------------------------------------------------- Instance Variables
+
+ /**
+ * The underlying data type of the property we are describing.
+ */
+ private Class mappedPropertyType;
+
+ /**
+ * The reader method for this property (if any).
+ */
+ private Method mappedReadMethod;
+
+ /**
+ * The writer method for this property (if any).
+ */
+ private Method mappedWriteMethod;
+
+ /**
+ * The parameter types array for the reader method signature.
+ */
+ private static final Class[] stringClassArray = new Class[]{String.class};
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Constructs a MappedPropertyDescriptor for a property that follows
+ * the standard Java convention by having getFoo and setFoo
+ * accessor methods, with the addition of a String parameter (the key).
+ * Thus if the argument name is "fred", it will
+ * assume that the writer method is "setFred" and the reader method
+ * is "getFred". Note that the property name should start with a lower
+ * case character, which will be capitalized in the method names.
+ *
+ * @param propertyName The programmatic name of the property.
+ * @param beanClass The Class object for the target bean. For
+ * example sun.beans.OurButton.class.
+ *
+ * @exception IntrospectionException if an exception occurs during
+ * introspection.
+ */
+ public MappedPropertyDescriptor(String propertyName, Class beanClass)
+ throws IntrospectionException {
+
+ super(propertyName, null, null);
+
+ if (propertyName == null || propertyName.length() == 0) {
+ throw new IntrospectionException("bad property name: " +
+ propertyName + " on class: " + beanClass.getClass().getName());
+ }
+
+ setName(propertyName);
+ String base = capitalizePropertyName(propertyName);
+
+ // Look for mapped read method and matching write method
+ try {
+ mappedReadMethod = findMethod(beanClass, "get" + base, 1,
+ stringClassArray);
+ Class params[] = { String.class, mappedReadMethod.getReturnType() };
+ mappedWriteMethod = findMethod(beanClass, "set" + base, 2, params);
+ } catch (IntrospectionException e) {
+ ;
+ }
+
+ // If there's no read method, then look for just a write method
+ if (mappedReadMethod == null) {
+ mappedWriteMethod = findMethod(beanClass, "set" + base, 2);
+ }
+
+ if ((mappedReadMethod == null) && (mappedWriteMethod == null)) {
+ throw new IntrospectionException("Property '" + propertyName +
+ "' not found on " +
+ beanClass.getName());
+ }
+
+ findMappedPropertyType();
+ }
+
+
+ /**
+ * This constructor takes the name of a mapped property, and method
+ * names for reading and writing the property.
+ *
+ * @param propertyName The programmatic name of the property.
+ * @param beanClass The Class object for the target bean. For
+ * example sun.beans.OurButton.class.
+ * @param mappedGetterName The name of the method used for
+ * reading one of the property values. May be null if the
+ * property is write-only.
+ * @param mappedSetterName The name of the method used for writing
+ * one of the property values. May be null if the property is
+ * read-only.
+ *
+ * @exception IntrospectionException if an exception occurs during
+ * introspection.
+ */
+ public MappedPropertyDescriptor(String propertyName, Class beanClass,
+ String mappedGetterName, String mappedSetterName)
+ throws IntrospectionException {
+
+ super(propertyName, null, null);
+
+ if (propertyName == null || propertyName.length() == 0) {
+ throw new IntrospectionException("bad property name: " +
+ propertyName);
+ }
+ setName(propertyName);
+
+ // search the mapped get and set methods
+ mappedReadMethod =
+ findMethod(beanClass, mappedGetterName, 1, stringClassArray);
+
+ if (mappedReadMethod != null) {
+ Class params[] = { String.class, mappedReadMethod.getReturnType() };
+ mappedWriteMethod =
+ findMethod(beanClass, mappedSetterName, 2, params);
+ } else {
+ mappedWriteMethod =
+ findMethod(beanClass, mappedSetterName, 2);
+ }
+
+ findMappedPropertyType();
+ }
+
+ /**
+ * This constructor takes the name of a mapped property, and Method
+ * objects for reading and writing the property.
+ *
+ * @param propertyName The programmatic name of the property.
+ * @param mappedGetter The method used for reading one of
+ * the property values. May be be null if the property
+ * is write-only.
+ * @param mappedSetter The method used for writing one the
+ * property values. May be null if the property is read-only.
+ *
+ * @exception IntrospectionException if an exception occurs during
+ * introspection.
+ */
+ public MappedPropertyDescriptor(String propertyName,
+ Method mappedGetter, Method mappedSetter)
+ throws IntrospectionException {
+
+ super(propertyName, mappedGetter, mappedSetter);
+
+ if (propertyName == null || propertyName.length() == 0) {
+ throw new IntrospectionException("bad property name: " +
+ propertyName);
+ }
+
+ setName(propertyName);
+ mappedReadMethod = mappedGetter;
+ mappedWriteMethod = mappedSetter;
+ findMappedPropertyType();
+ }
+
+ // -------------------------------------------------------- Public Methods
+
+ /**
+ * Gets the Class object for the property values.
+ *
+ * @return The Java type info for the property values. Note that
+ * the "Class" object may describe a built-in Java type such as "int".
+ * The result may be "null" if this is a mapped property that
+ * does not support non-keyed access.
+ * <p>
+ * This is the type that will be returned by the mappedReadMethod.
+ */
+ public Class getMappedPropertyType() {
+ return mappedPropertyType;
+ }
+
+ /**
+ * Gets the method that should be used to read one of the property value.
+ *
+ * @return The method that should be used to read the property value.
+ * May return null if the property can't be read.
+ */
+ public Method getMappedReadMethod() {
+ return mappedReadMethod;
+ }
+
+ /**
+ * Sets the method that should be used to read one of the property value.
+ *
+ * @param mappedGetter The new getter method.
+ */
+ public void setMappedReadMethod(Method mappedGetter)
+ throws IntrospectionException {
+ mappedReadMethod = mappedGetter;
+ findMappedPropertyType();
+ }
+
+ /**
+ * Gets the method that should be used to write one of the property value.
+ *
+ * @return The method that should be used to write one of the property value.
+ * May return null if the property can't be written.
+ */
+ public Method getMappedWriteMethod() {
+ return mappedWriteMethod;
+ }
+
+ /**
+ * Sets the method that should be used to write the property value.
+ *
+ * @param mappedSetter The new setter method.
+ */
+ public void setMappedWriteMethod(Method mappedSetter)
+ throws IntrospectionException {
+ mappedWriteMethod = mappedSetter;
+ findMappedPropertyType();
+ }
+
+ // ------------------------------------------------------- Private Methods
+
+ /**
+ * Introspect our bean class to identify the corresponding getter
+ * and setter methods.
+ */
+ private void findMappedPropertyType() throws IntrospectionException {
+ try {
+ mappedPropertyType = null;
+ if (mappedReadMethod != null) {
+ if (mappedReadMethod.getParameterTypes().length != 1) {
+ throw new IntrospectionException
+ ("bad mapped read method arg count");
+ }
+ mappedPropertyType = mappedReadMethod.getReturnType();
+ if (mappedPropertyType == Void.TYPE) {
+ throw new IntrospectionException
+ ("mapped read method " +
+ mappedReadMethod.getName() + " returns void");
+ }
+ }
+
+ if (mappedWriteMethod != null) {
+ Class params[] = mappedWriteMethod.getParameterTypes();
+ if (params.length != 2) {
+ throw new IntrospectionException
+ ("bad mapped write method arg count");
+ }
+ if (mappedPropertyType != null &&
+ mappedPropertyType != params[1]) {
+ throw new IntrospectionException
+ ("type mismatch between mapped read and write methods");
+ }
+ mappedPropertyType = params[1];
+ }
+ } catch (IntrospectionException ex) {
+ throw ex;
+ }
+ }
+
+
+ /**
+ * Return a capitalized version of the specified property name.
+ *
+ * @param s The property name
+ */
+ private static String capitalizePropertyName(String s) {
+ if (s.length() == 0) {
+ return s;
+ }
+
+ char chars[] = s.toCharArray();
+ chars[0] = Character.toUpperCase(chars[0]);
+ return new String(chars);
+ }
+
+ //======================================================================
+ // Package private support methods (copied from java.beans.Introspector).
+ //======================================================================
+
+ // Cache of Class.getDeclaredMethods:
+ private static java.util.Hashtable
+ declaredMethodCache = new java.util.Hashtable();
+
+ /*
+ * Internal method to return *public* methods within a class.
+ */
+ private static synchronized Method[] getPublicDeclaredMethods(Class clz) {
+ // Looking up Class.getDeclaredMethods is relatively expensive,
+ // so we cache the results.
+ final Class fclz = clz;
+ Method[] result = (Method[]) declaredMethodCache.get(fclz);
+ if (result != null) {
+ return result;
+ }
+
+ // We have to raise privilege for getDeclaredMethods
+ result = (Method[])
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ try{
+
+ return fclz.getDeclaredMethods();
+
+ } catch (SecurityException ex) {
+ // this means we're in a limited security environment
+ // so let's try going through the public methods
+ // and null those those that are not from the declaring
+ // class
+ Method[] methods = fclz.getMethods();
+ for (int i = 0, size = methods.length; i < size; i++) {
+ Method method = methods[i];
+ if (!(fclz.equals(method.getDeclaringClass()))) {
+ methods[i] = null;
+ }
+ }
+ return methods;
+ }
+ }
+ });
+
+ // Null out any non-public methods.
+ for (int i = 0; i < result.length; i++) {
+ Method method = result[i];
+ if (method != null) {
+ int mods = method.getModifiers();
+ if (!Modifier.isPublic(mods)) {
+ result[i] = null;
+ }
+ }
+ }
+
+ // Add it to the cache.
+ declaredMethodCache.put(clz, result);
+ return result;
+ }
+
+ /**
+ * Internal support for finding a target methodName on a given class.
+ */
+ private static Method internalFindMethod(Class start, String methodName,
+ int argCount) {
+ // For overridden methods we need to find the most derived version.
+ // So we start with the given class and walk up the superclass chain.
+ for (Class cl = start; cl != null; cl = cl.getSuperclass()) {
+ Method methods[] = getPublicDeclaredMethods(cl);
+ for (int i = 0; i < methods.length; i++) {
+ Method method = methods[i];
+ if (method == null) {
+ continue;
+ }
+ // skip static methods.
+ int mods = method.getModifiers();
+ if (Modifier.isStatic(mods)) {
+ continue;
+ }
+ if (method.getName().equals(methodName) &&
+ method.getParameterTypes().length == argCount) {
+ return method;
+ }
+ }
+ }
+
+ // Now check any inherited interfaces. This is necessary both when
+ // the argument class is itself an interface, and when the argument
+ // class is an abstract class.
+ Class ifcs[] = start.getInterfaces();
+ for (int i = 0; i < ifcs.length; i++) {
+ Method m = internalFindMethod(ifcs[i], methodName, argCount);
+ if (m != null) {
+ return m;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Internal support for finding a target methodName with a given
+ * parameter list on a given class.
+ */
+ private static Method internalFindMethod(Class start, String methodName,
+ int argCount, Class args[]) {
+ // For overriden methods we need to find the most derived version.
+ // So we start with the given class and walk up the superclass chain.
+ for (Class cl = start; cl != null; cl = cl.getSuperclass()) {
+ Method methods[] = getPublicDeclaredMethods(cl);
+ for (int i = 0; i < methods.length; i++) {
+ Method method = methods[i];
+ if (method == null) {
+ continue;
+ }
+ // skip static methods.
+ int mods = method.getModifiers();
+ if (Modifier.isStatic(mods)) {
+ continue;
+ }
+ // make sure method signature matches.
+ Class params[] = method.getParameterTypes();
+ if (method.getName().equals(methodName) &&
+ params.length == argCount) {
+ boolean different = false;
+ if (argCount > 0) {
+ for (int j = 0; j < argCount; j++) {
+ if (params[j] != args[j]) {
+ different = true;
+ continue;
+ }
+ }
+ if (different) {
+ continue;
+ }
+ }
+ return method;
+ }
+ }
+ }
+
+ // Now check any inherited interfaces. This is necessary both when
+ // the argument class is itself an interface, and when the argument
+ // class is an abstract class.
+ Class ifcs[] = start.getInterfaces();
+ for (int i = 0; i < ifcs.length; i++) {
+ Method m = internalFindMethod(ifcs[i], methodName, argCount);
+ if (m != null) {
+ return m;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Find a target methodName on a given class.
+ */
+ static Method findMethod(Class cls, String methodName, int argCount)
+ throws IntrospectionException {
+ if (methodName == null) {
+ return null;
+ }
+
+ Method m = internalFindMethod(cls, methodName, argCount);
+ if (m != null) {
+ return m;
+ }
+
+ // We failed to find a suitable method
+ throw new IntrospectionException("No method \"" + methodName +
+ "\" with " + argCount + " arg(s)");
+ }
+
+ /**
+ * Find a target methodName with specific parameter list on a given class.
+ */
+ static Method findMethod(Class cls, String methodName, int argCount,
+ Class args[]) throws IntrospectionException {
+ if (methodName == null) {
+ return null;
+ }
+
+ Method m = internalFindMethod(cls, methodName, argCount, args);
+ if (m != null) {
+ return m;
+ }
+
+ // We failed to find a suitable method
+ throw new IntrospectionException("No method \"" + methodName +
+ "\" with " + argCount + " arg(s) of matching types.");
+ }
+
+ /**
+ * Return true if class a is either equivalent to class b, or
+ * if class a is a subclass of class b, ie if a either "extends"
+ * or "implements" b.
+ * Note tht either or both "Class" objects may represent interfaces.
+ */
+ static boolean isSubclass(Class a, Class b) {
+ // We rely on the fact that for any given java class or
+ // primtitive type there is a unqiue Class object, so
+ // we can use object equivalence in the comparisons.
+ if (a == b) {
+ return true;
+ }
+
+ if (a == null || b == null) {
+ return false;
+ }
+
+ for (Class x = a; x != null; x = x.getSuperclass()) {
+ if (x == b) {
+ return true;
+ }
+
+ if (b.isInterface()) {
+ Class interfaces[] = x.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ if (isSubclass(interfaces[i], b)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Return true iff the given method throws the given exception.
+ */
+
+ private boolean throwsException(Method method, Class exception) {
+
+ Class exs[] = method.getExceptionTypes();
+ for (int i = 0; i < exs.length; i++) {
+ if (exs[i] == exception) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MethodUtils.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MethodUtils.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MethodUtils.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,851 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import java.util.WeakHashMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+
+/**
+ * <p> Utility reflection methods focussed on methods in general rather than properties in particular. </p>
+ *
+ * <h3>Known Limitations</h3>
+ * <h4>Accessing Public Methods In A Default Access Superclass</h4>
+ * <p>There is an issue when invoking public methods contained in a default access superclass.
+ * Reflection locates these methods fine and correctly assigns them as public.
+ * However, an <code>IllegalAccessException</code> is thrown if the method is invoked.</p>
+ *
+ * <p><code>MethodUtils</code> contains a workaround for this situation.
+ * It will attempt to call <code>setAccessible</code> on this method.
+ * If this call succeeds, then the method can be invoked as normal.
+ * This call will only succeed when the application has sufficient security privilages.
+ * If this call fails then a warning will be logged and the method may fail.</p>
+ *
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author Rey François
+ * @author Gregor Raýman
+ * @author Jan Sorensen
+ * @author Robert Burrell Donkin
+ */
+
+public class MethodUtils {
+
+ // --------------------------------------------------------- Private Methods
+
+ /**
+ * All logging goes through this logger
+ */
+ private static Log log = LogFactory.getLog(MethodUtils.class);
+ /** Only log warning about accessibility work around once */
+ private static boolean loggedAccessibleWarning = false;
+
+ /** An empty class array */
+ private static final Class[] emptyClassArray = new Class[0];
+ /** An empty object array */
+ private static final Object[] emptyObjectArray = new Object[0];
+
+ /**
+ * Stores a cache of Methods against MethodDescriptors, in a WeakHashMap.
+ */
+ private static WeakHashMap cache = new WeakHashMap();
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * <p>Invoke a named method whose parameter type matches the object type.</p>
+ *
+ * <p>The behaviour of this method is less deterministic
+ * than {@link #invokeExactMethod}.
+ * It loops through all methods with names that match
+ * and then executes the first it finds with compatable parameters.</p>
+ *
+ * <p>This method supports calls to methods taking primitive parameters
+ * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
+ * would match a <code>boolean</code> primitive.</p>
+ *
+ * <p> This is a convenient wrapper for
+ * {@link #invokeMethod(Object object,String methodName,Object [] args)}.
+ * </p>
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param arg use this argument
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeMethod(
+ Object object,
+ String methodName,
+ Object arg)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException {
+
+ Object[] args = {arg};
+ return invokeMethod(object, methodName, args);
+
+ }
+
+
+ /**
+ * <p>Invoke a named method whose parameter type matches the object type.</p>
+ *
+ * <p>The behaviour of this method is less deterministic
+ * than {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
+ * It loops through all methods with names that match
+ * and then executes the first it finds with compatable parameters.</p>
+ *
+ * <p>This method supports calls to methods taking primitive parameters
+ * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
+ * would match a <code>boolean</code> primitive.</p>
+ *
+ * <p> This is a convenient wrapper for
+ * {@link #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
+ * </p>
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeMethod(
+ Object object,
+ String methodName,
+ Object[] args)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException {
+
+ if (args == null) {
+ args = emptyObjectArray;
+ }
+ int arguments = args.length;
+ Class parameterTypes [] = new Class[arguments];
+ for (int i = 0; i < arguments; i++) {
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeMethod(object, methodName, args, parameterTypes);
+
+ }
+
+
+ /**
+ * <p>Invoke a named method whose parameter type matches the object type.</p>
+ *
+ * <p>The behaviour of this method is less deterministic
+ * than {@link
+ * #invokeExactMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
+ * It loops through all methods with names that match
+ * and then executes the first it finds with compatable parameters.</p>
+ *
+ * <p>This method supports calls to methods taking primitive parameters
+ * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
+ * would match a <code>boolean</code> primitive.</p>
+ *
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ * @param parameterTypes match these parameters - treat null as empty array
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeMethod(
+ Object object,
+ String methodName,
+ Object[] args,
+ Class[] parameterTypes)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException {
+
+ if (parameterTypes == null) {
+ parameterTypes = emptyClassArray;
+ }
+ if (args == null) {
+ args = emptyObjectArray;
+ }
+
+ Method method = getMatchingAccessibleMethod(
+ object.getClass(),
+ methodName,
+ parameterTypes);
+ if (method == null)
+ throw new NoSuchMethodException("No such accessible method: " +
+ methodName + "() on object: " + object.getClass().getName());
+ return method.invoke(object, args);
+ }
+
+
+ /**
+ * <p>Invoke a method whose parameter type matches exactly the object
+ * type.</p>
+ *
+ * <p> This is a convenient wrapper for
+ * {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
+ * </p>
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param arg use this argument
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeExactMethod(
+ Object object,
+ String methodName,
+ Object arg)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException {
+
+ Object[] args = {arg};
+ return invokeExactMethod(object, methodName, args);
+
+ }
+
+
+ /**
+ * <p>Invoke a method whose parameter types match exactly the object
+ * types.</p>
+ *
+ * <p> This uses reflection to invoke the method obtained from a call to
+ * {@link #getAccessibleMethod}.</p>
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeExactMethod(
+ Object object,
+ String methodName,
+ Object[] args)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException {
+ if (args == null) {
+ args = emptyObjectArray;
+ }
+ int arguments = args.length;
+ Class parameterTypes [] = new Class[arguments];
+ for (int i = 0; i < arguments; i++) {
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeExactMethod(object, methodName, args, parameterTypes);
+
+ }
+
+
+ /**
+ * <p>Invoke a method whose parameter types match exactly the parameter
+ * types given.</p>
+ *
+ * <p>This uses reflection to invoke the method obtained from a call to
+ * {@link #getAccessibleMethod}.</p>
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ * @param parameterTypes match these parameters - treat null as empty array
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeExactMethod(
+ Object object,
+ String methodName,
+ Object[] args,
+ Class[] parameterTypes)
+ throws
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException {
+
+ if (args == null) {
+ args = emptyObjectArray;
+ }
+
+ if (parameterTypes == null) {
+ parameterTypes = emptyClassArray;
+ }
+
+ Method method = getAccessibleMethod(
+ object.getClass(),
+ methodName,
+ parameterTypes);
+ if (method == null)
+ throw new NoSuchMethodException("No such accessible method: " +
+ methodName + "() on object: " + object.getClass().getName());
+ return method.invoke(object, args);
+
+ }
+
+
+ /**
+ * <p>Return an accessible method (that is, one that can be invoked via
+ * reflection) with given name and a single parameter. If no such method
+ * can be found, return <code>null</code>.
+ * Basically, a convenience wrapper that constructs a <code>Class</code>
+ * array for you.</p>
+ *
+ * @param clazz get method from this class
+ * @param methodName get method with this name
+ * @param parameterType taking this type of parameter
+ */
+ public static Method getAccessibleMethod(
+ Class clazz,
+ String methodName,
+ Class parameterType) {
+
+ Class[] parameterTypes = {parameterType};
+ return getAccessibleMethod(clazz, methodName, parameterTypes);
+
+ }
+
+
+ /**
+ * <p>Return an accessible method (that is, one that can be invoked via
+ * reflection) with given name and parameters. If no such method
+ * can be found, return <code>null</code>.
+ * This is just a convenient wrapper for
+ * {@link #getAccessibleMethod(Method method)}.</p>
+ *
+ * @param clazz get method from this class
+ * @param methodName get method with this name
+ * @param parameterTypes with these parameters types
+ */
+ public static Method getAccessibleMethod(
+ Class clazz,
+ String methodName,
+ Class[] parameterTypes) {
+
+ try {
+ MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, true);
+ // Check the cache first
+ Method method = (Method)cache.get(md);
+ if (method != null) {
+ return method;
+ }
+
+ method = getAccessibleMethod
+ (clazz.getMethod(methodName, parameterTypes));
+ cache.put(md, method);
+ return method;
+ } catch (NoSuchMethodException e) {
+ return (null);
+ }
+
+ }
+
+
+ /**
+ * <p>Return an accessible method (that is, one that can be invoked via
+ * reflection) that implements the specified Method. If no such method
+ * can be found, return <code>null</code>.</p>
+ *
+ * @param method The method that we wish to call
+ */
+ public static Method getAccessibleMethod(Method method) {
+
+ // Make sure we have a method to check
+ if (method == null) {
+ return (null);
+ }
+
+ // If the requested method is not public we cannot call it
+ if (!Modifier.isPublic(method.getModifiers())) {
+ return (null);
+ }
+
+ // If the declaring class is public, we are done
+ Class clazz = method.getDeclaringClass();
+ if (Modifier.isPublic(clazz.getModifiers())) {
+ return (method);
+ }
+
+ // Check the implemented interfaces and subinterfaces
+ method =
+ getAccessibleMethodFromInterfaceNest(clazz,
+ method.getName(),
+ method.getParameterTypes());
+ return (method);
+
+ }
+
+
+ // -------------------------------------------------------- Private Methods
+
+ /**
+ * <p>Return an accessible method (that is, one that can be invoked via
+ * reflection) that implements the specified method, by scanning through
+ * all implemented interfaces and subinterfaces. If no such method
+ * can be found, return <code>null</code>.</p>
+ *
+ * <p> There isn't any good reason why this method must be private.
+ * It is because there doesn't seem any reason why other classes should
+ * call this rather than the higher level methods.</p>
+ *
+ * @param clazz Parent class for the interfaces to be checked
+ * @param methodName Method name of the method we wish to call
+ * @param parameterTypes The parameter type signatures
+ */
+ private static Method getAccessibleMethodFromInterfaceNest
+ (Class clazz, String methodName, Class parameterTypes[]) {
+
+ Method method = null;
+
+ // Search up the superclass chain
+ for (; clazz != null; clazz = clazz.getSuperclass()) {
+
+ // Check the implemented interfaces of the parent class
+ Class interfaces[] = clazz.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+
+ // Is this interface public?
+ if (!Modifier.isPublic(interfaces[i].getModifiers()))
+ continue;
+
+ // Does the method exist on this interface?
+ try {
+ method = interfaces[i].getDeclaredMethod(methodName,
+ parameterTypes);
+ } catch (NoSuchMethodException e) {
+ ;
+ }
+ if (method != null)
+ break;
+
+ // Recursively check our parent interfaces
+ method =
+ getAccessibleMethodFromInterfaceNest(interfaces[i],
+ methodName,
+ parameterTypes);
+ if (method != null)
+ break;
+
+ }
+
+ }
+
+ // If we found a method return it
+ if (method != null)
+ return (method);
+
+ // We did not find anything
+ return (null);
+
+ }
+
+ /**
+ * <p>Find an accessible method that matches the given name and has compatible parameters.
+ * Compatible parameters mean that every method parameter is assignable from
+ * the given parameters.
+ * In other words, it finds a method with the given name
+ * that will take the parameters given.<p>
+ *
+ * <p>This method is slightly undeterminstic since it loops
+ * through methods names and return the first matching method.</p>
+ *
+ * <p>This method is used by
+ * {@link
+ * #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
+ *
+ * <p>This method can match primitive parameter by passing in wrapper classes.
+ * For example, a <code>Boolean</code> will match a primitive <code>boolean</code>
+ * parameter.
+ *
+ * @param clazz find method in this class
+ * @param methodName find method with this name
+ * @param parameterTypes find method with compatible parameters
+ */
+ public static Method getMatchingAccessibleMethod(
+ Class clazz,
+ String methodName,
+ Class[] parameterTypes) {
+ // trace logging
+ if (log.isTraceEnabled()) {
+ log.trace("Matching name=" + methodName + " on " + clazz);
+ }
+ MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, false);
+
+ // see if we can find the method directly
+ // most of the time this works and it's much faster
+ try {
+ // Check the cache first
+ Method method = (Method)cache.get(md);
+ if (method != null) {
+ return method;
+ }
+
+ method = clazz.getMethod(methodName, parameterTypes);
+ if (log.isTraceEnabled()) {
+ log.trace("Found straight match: " + method);
+ log.trace("isPublic:" + Modifier.isPublic(method.getModifiers()));
+ }
+
+ try {
+ //
+ // XXX Default access superclass workaround
+ //
+ // When a public class has a default access superclass
+ // with public methods, these methods are accessible.
+ // Calling them from compiled code works fine.
+ //
+ // Unfortunately, using reflection to invoke these methods
+ // seems to (wrongly) to prevent access even when the method
+ // modifer is public.
+ //
+ // The following workaround solves the problem but will only
+ // work from sufficiently privilages code.
+ //
+ // Better workarounds would be greatfully accepted.
+ //
+ method.setAccessible(true);
+
+ } catch (SecurityException se) {
+ // log but continue just in case the method.invoke works anyway
+ if (!loggedAccessibleWarning) {
+ boolean vunerableJVM = false;
+ try {
+ String specVersion = System.getProperty("java.specification.version");
+ if (specVersion.charAt(0) == '1' &&
+ (specVersion.charAt(0) == '0' ||
+ specVersion.charAt(0) == '1' ||
+ specVersion.charAt(0) == '2' ||
+ specVersion.charAt(0) == '3')) {
+
+ vunerableJVM = true;
+ }
+ } catch (SecurityException e) {
+ // don't know - so display warning
+ vunerableJVM = true;
+ }
+ if (vunerableJVM) {
+ log.warn(
+ "Current Security Manager restricts use of workarounds for reflection bugs "
+ + " in pre-1.4 JVMs.");
+ }
+ loggedAccessibleWarning = true;
+ }
+ log.debug(
+ "Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.",
+ se);
+ }
+ cache.put(md, method);
+ return method;
+
+ } catch (NoSuchMethodException e) { /* SWALLOW */ }
+
+ // search through all methods
+ int paramSize = parameterTypes.length;
+ Method[] methods = clazz.getMethods();
+ for (int i = 0, size = methods.length; i < size ; i++) {
+ if (methods[i].getName().equals(methodName)) {
+ // log some trace information
+ if (log.isTraceEnabled()) {
+ log.trace("Found matching name:");
+ log.trace(methods[i]);
+ }
+
+ // compare parameters
+ Class[] methodsParams = methods[i].getParameterTypes();
+ int methodParamSize = methodsParams.length;
+ if (methodParamSize == paramSize) {
+ boolean match = true;
+ for (int n = 0 ; n < methodParamSize; n++) {
+ if (log.isTraceEnabled()) {
+ log.trace("Param=" + parameterTypes[n].getName());
+ log.trace("Method=" + methodsParams[n].getName());
+ }
+ if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n])) {
+ if (log.isTraceEnabled()) {
+ log.trace(methodsParams[n] + " is not assignable from "
+ + parameterTypes[n]);
+ }
+ match = false;
+ break;
+ }
+ }
+
+ if (match) {
+ // get accessible version of method
+ Method method = getAccessibleMethod(methods[i]);
+ if (method != null) {
+ if (log.isTraceEnabled()) {
+ log.trace(method + " accessible version of "
+ + methods[i]);
+ }
+ try {
+ //
+ // XXX Default access superclass workaround
+ // (See above for more details.)
+ //
+ method.setAccessible(true);
+
+ } catch (SecurityException se) {
+ // log but continue just in case the method.invoke works anyway
+ if (!loggedAccessibleWarning) {
+ log.warn(
+ "Cannot use JVM pre-1.4 access bug workaround due to restrictive security manager.");
+ loggedAccessibleWarning = true;
+ }
+ log.debug(
+ "Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.",
+ se);
+ }
+ cache.put(md, method);
+ return method;
+ }
+
+ log.trace("Couldn't find accessible method.");
+ }
+ }
+ }
+ }
+
+ // didn't find a match
+ log.trace("No match found.");
+ return null;
+ }
+
+ /**
+ * <p>Determine whether a type can be used as a parameter in a method invocation.
+ * This method handles primitive conversions correctly.</p>
+ *
+ * <p>In order words, it will match a <code>Boolean</code> to a <code>boolean</code>,
+ * a <code>Long</code> to a <code>long</code>,
+ * a <code>Float</code> to a <code>float</code>,
+ * a <code>Integer</code> to a <code>int</code>,
+ * and a <code>Double</code> to a <code>double</code>.
+ * Now logic widening matches are allowed.
+ * For example, a <code>Long</code> will not match a <code>int</code>.
+ *
+ * @param parameterType the type of parameter accepted by the method
+ * @param parameterization the type of parameter being tested
+ *
+ * @return true if the assignement is compatible.
+ */
+ public static final boolean isAssignmentCompatible(Class parameterType, Class parameterization) {
+ // try plain assignment
+ if (parameterType.isAssignableFrom(parameterization)) {
+ return true;
+ }
+
+ if (parameterType.isPrimitive()) {
+ // this method does *not* do widening - you must specify exactly
+ // is this the right behaviour?
+ Class parameterWrapperClazz = getPrimitiveWrapper(parameterType);
+ if (parameterWrapperClazz != null) {
+ return parameterWrapperClazz.equals(parameterization);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Gets the wrapper object class for the given primitive type class.
+ * For example, passing <code>boolean.class</code> returns <code>Boolean.class</code>
+ * @param primitiveType the primitive type class for which a match is to be found
+ * @return the wrapper type associated with the given primitive
+ * or null if no match is found
+ */
+ public static Class getPrimitiveWrapper(Class primitiveType) {
+ // does anyone know a better strategy than comparing names?
+ if (boolean.class.equals(primitiveType)) {
+ return Boolean.class;
+ } else if (float.class.equals(primitiveType)) {
+ return Float.class;
+ } else if (long.class.equals(primitiveType)) {
+ return Long.class;
+ } else if (int.class.equals(primitiveType)) {
+ return Integer.class;
+ } else if (short.class.equals(primitiveType)) {
+ return Short.class;
+ } else if (byte.class.equals(primitiveType)) {
+ return Byte.class;
+ } else if (double.class.equals(primitiveType)) {
+ return Double.class;
+ } else if (char.class.equals(primitiveType)) {
+ return Character.class;
+ } else {
+
+ return null;
+ }
+ }
+
+ /**
+ * Gets the class for the primitive type corresponding to the primitive wrapper class given.
+ * For example, an instance of <code>Boolean.class</code> returns a <code>boolean.class</code>.
+ * @param wrapperType the
+ * @return the primitive type class corresponding to the given wrapper class,
+ * null if no match is found
+ */
+ public static Class getPrimitiveType(Class wrapperType) {
+ // does anyone know a better strategy than comparing names?
+ if (Boolean.class.equals(wrapperType)) {
+ return boolean.class;
+ } else if (Float.class.equals(wrapperType)) {
+ return float.class;
+ } else if (Long.class.equals(wrapperType)) {
+ return long.class;
+ } else if (Integer.class.equals(wrapperType)) {
+ return int.class;
+ } else if (Short.class.equals(wrapperType)) {
+ return short.class;
+ } else if (Byte.class.equals(wrapperType)) {
+ return byte.class;
+ } else if (Double.class.equals(wrapperType)) {
+ return double.class;
+ } else if (Character.class.equals(wrapperType)) {
+ return char.class;
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("Not a known primitive wrapper class: " + wrapperType);
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Find a non primitive representation for given primitive class.
+ *
+ * @param clazz the class to find a representation for, not null
+ * @return the original class if it not a primitive. Otherwise the wrapper class. Not null
+ */
+ public static Class toNonPrimitiveClass(Class clazz) {
+ if (clazz.isPrimitive()) {
+ Class primitiveClazz = MethodUtils.getPrimitiveWrapper(clazz);
+ // the above method returns
+ if (primitiveClazz != null) {
+ return primitiveClazz;
+ } else {
+ return clazz;
+ }
+ } else {
+ return clazz;
+ }
+ }
+
+
+ /**
+ * Represents the key to looking up a Method by reflection.
+ */
+ private static class MethodDescriptor {
+ private Class cls;
+ private String methodName;
+ private Class[] paramTypes;
+ private boolean exact;
+ private int hashCode;
+
+ /**
+ * The sole constructor.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param methodName the method name to obtain
+ * @param paramTypes the array of classes representing the paramater types
+ * @param exact whether the match has to be exact.
+ */
+ public MethodDescriptor(Class cls, String methodName, Class[] paramTypes, boolean exact) {
+ if (cls == null) {
+ throw new IllegalArgumentException("Class cannot be null");
+ }
+ if (methodName == null) {
+ throw new IllegalArgumentException("Method Name cannot be null");
+ }
+ if (paramTypes == null) {
+ paramTypes = emptyClassArray;
+ }
+
+ this.cls = cls;
+ this.methodName = methodName;
+ this.paramTypes = paramTypes;
+ this.exact= exact;
+
+ this.hashCode = methodName.length();
+ }
+ /**
+ * Checks for equality.
+ * @param obj object to be tested for equality
+ * @return true, if the object describes the same Method.
+ */
+ public boolean equals(Object obj) {
+ if (!(obj instanceof MethodDescriptor)) {
+ return false;
+ }
+ MethodDescriptor md = (MethodDescriptor)obj;
+
+ return (
+ exact == md.exact &&
+ methodName.equals(md.methodName) &&
+ cls.equals(md.cls) &&
+ java.util.Arrays.equals(paramTypes, md.paramTypes)
+ );
+ }
+ /**
+ * Returns the string length of method name. I.e. if the
+ * hashcodes are different, the objects are different. If the
+ * hashcodes are the same, need to use the equals method to
+ * determine equality.
+ * @return the string length of method name.
+ */
+ public int hashCode() {
+ return hashCode;
+ }
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MutableDynaClass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MutableDynaClass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/MutableDynaClass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+
+
+
+/**
+ * <p>A specialized extension to <code>DynaClass</code> that allows properties
+ * to be added or removed dynamically.</p>
+ *
+ * <p><strong>WARNING</strong> - No guarantees that this will be in the final
+ * APIs ... it's here primarily to preserve some concepts that were in the
+ * original proposal for further discussion.</p>
+ *
+ * @author Craig McClanahan
+ * @author Michael Smith
+ * @author Paulo Gaspar
+ * @version $Revision: 1.8 $ $Date: 2004/02/28 13:18:33 $
+ */
+
+public interface MutableDynaClass extends DynaClass {
+
+
+ /**
+ * Add a new dynamic property with no restrictions on data type,
+ * readability, or writeability.
+ *
+ * @param name Name of the new dynamic property
+ *
+ * @exception IllegalArgumentException if name is null
+ * @exception IllegalStateException if this DynaClass is currently
+ * restricted, so no new properties can be added
+ */
+ public void add(String name);
+
+
+ /**
+ * Add a new dynamic property with the specified data type, but with
+ * no restrictions on readability or writeability.
+ *
+ * @param name Name of the new dynamic property
+ * @param type Data type of the new dynamic property (null for no
+ * restrictions)
+ *
+ * @exception IllegalArgumentException if name is null
+ * @exception IllegalStateException if this DynaClass is currently
+ * restricted, so no new properties can be added
+ */
+ public void add(String name, Class type);
+
+
+ /**
+ * Add a new dynamic property with the specified data type, readability,
+ * and writeability.
+ *
+ * @param name Name of the new dynamic property
+ * @param type Data type of the new dynamic property (null for no
+ * restrictions)
+ * @param readable Set to <code>true</code> if this property value
+ * should be readable
+ * @param writeable Set to <code>true</code> if this property value
+ * should be writeable
+ *
+ * @exception IllegalArgumentException if name is null
+ * @exception IllegalStateException if this DynaClass is currently
+ * restricted, so no new properties can be added
+ */
+ public void add(String name, Class type, boolean readable,
+ boolean writeable);
+
+
+ /**
+ * Is this DynaClass currently restricted, if so, no changes to the
+ * existing registration of property names, data types, readability, or
+ * writeability are allowed.
+ */
+ public boolean isRestricted();
+
+
+ /**
+ * Remove the specified dynamic property, and any associated data type,
+ * readability, and writeability, from this dynamic class.
+ * <strong>NOTE</strong> - This does <strong>NOT</strong> cause any
+ * corresponding property values to be removed from DynaBean instances
+ * associated with this DynaClass.
+ *
+ * @param name Name of the dynamic property to remove
+ *
+ * @exception IllegalArgumentException if name is null
+ * @exception IllegalStateException if this DynaClass is currently
+ * restricted, so no properties can be removed
+ */
+ public void remove(String name);
+
+
+ /**
+ * Set the restricted state of this DynaClass to the specified value.
+ *
+ * @param restricted The new restricted state
+ */
+ public void setRestricted(boolean restricted);
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/NestedNullException.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/NestedNullException.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/NestedNullException.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+/**
+ * Thrown to indicate that the <em>Bean Access Language</em> cannot execute query
+ * against given bean since a nested bean referenced is null.
+ *
+ * @author Robert Burrell Donkin
+ * @since 1.7
+ */
+
+public class NestedNullException extends BeanAccessLanguageException {
+
+ // --------------------------------------------------------- Constuctors
+
+ /**
+ * Constructs a <code>NestedNullException</code> without a detail message.
+ */
+ public NestedNullException() {
+ super();
+ }
+
+ /**
+ * Constructs a <code>NestedNullException</code> without a detail message.
+ *
+ * @param message the detail message explaining this exception
+ */
+ public NestedNullException(String message) {
+ super(message);
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/PropertyUtils.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/PropertyUtils.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/PropertyUtils.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,581 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import org.apache.commons.collections.FastHashMap;
+
+
+/**
+ * <p>Utility methods for using Java Reflection APIs to facilitate generic
+ * property getter and setter operations on Java objects.</p>
+ *
+ * <p>The implementations for these methods are provided by <code>PropertyUtilsBean</code>.
+ * For more details see {@link PropertyUtilsBean}.</p>
+ *
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author Rey François
+ * @author Gregor Raýman
+ * @author Jan Sorensen
+ * @author Scott Sanders
+ * @version $Revision: 1.42.2.1 $ $Date: 2004/07/27 21:31:00 $
+ * @see PropertyUtilsBean
+ */
+
+public class PropertyUtils {
+
+
+ // ----------------------------------------------------- Manifest Constants
+
+
+ /**
+ * The delimiter that preceeds the zero-relative subscript for an
+ * indexed reference.
+ */
+ public static final char INDEXED_DELIM = '[';
+
+
+ /**
+ * The delimiter that follows the zero-relative subscript for an
+ * indexed reference.
+ */
+ public static final char INDEXED_DELIM2 = ']';
+
+
+ /**
+ * The delimiter that preceeds the key of a mapped property.
+ */
+ public static final char MAPPED_DELIM = '(';
+
+
+ /**
+ * The delimiter that follows the key of a mapped property.
+ */
+ public static final char MAPPED_DELIM2 = ')';
+
+
+ /**
+ * The delimiter that separates the components of a nested reference.
+ */
+ public static final char NESTED_DELIM = '.';
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * The debugging detail level for this component.
+ * @deprecated The <code>debug</code> static property is no longer used
+ */
+ private static int debug = 0;
+
+ /**
+ * @deprecated The <code>debug</code> static property is no longer used
+ */
+ public static int getDebug() {
+ return (debug);
+ }
+
+ /**
+ * @deprecated The <code>debug</code> static property is no longer used
+ */
+ public static void setDebug(int newDebug) {
+ debug = newDebug;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Clear any cached property descriptors information for all classes
+ * loaded by any class loaders. This is useful in cases where class
+ * loaders are thrown away to implement class reloading.
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#clearDescriptors
+ */
+ public static void clearDescriptors() {
+
+ PropertyUtilsBean.getInstance().clearDescriptors();
+
+ }
+
+
+ /**
+ * <p>Copy property values from the "origin" bean to the "destination" bean
+ * for all cases where the property names are the same (even though the
+ * actual getter and setter methods might have been customized via
+ * <code>BeanInfo</code> classes).</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#copyProperties
+ */
+ public static void copyProperties(Object dest, Object orig)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ PropertyUtilsBean.getInstance().copyProperties(dest, orig);
+ }
+
+
+ /**
+ * <p>Return the entire set of properties for which the specified bean
+ * provides a read method.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#describe
+ */
+ public static Map describe(Object bean)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return (PropertyUtilsBean.getInstance().describe(bean));
+
+ }
+
+
+ /**
+ * <p>Return the value of the specified indexed property of the specified
+ * bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getIndexedProperty(Object,String)
+ */
+ public static Object getIndexedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return (PropertyUtilsBean.getInstance().getIndexedProperty(bean, name));
+
+ }
+
+
+ /**
+ * <p>Return the value of the specified indexed property of the specified
+ * bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getIndexedProperty(Object,String, int)
+ */
+ public static Object getIndexedProperty(Object bean,
+ String name, int index)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return (PropertyUtilsBean.getInstance().getIndexedProperty(bean, name, index));
+ }
+
+
+ /**
+ * <p>Return the value of the specified mapped property of the
+ * specified bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getMappedProperty(Object,String)
+ */
+ public static Object getMappedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return (PropertyUtilsBean.getInstance().getMappedProperty(bean, name));
+
+ }
+
+
+ /**
+ * <p>Return the value of the specified mapped property of the specified
+ * bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getMappedProperty(Object,String, String)
+ */
+ public static Object getMappedProperty(Object bean,
+ String name, String key)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return PropertyUtilsBean.getInstance().getMappedProperty(bean, name, key);
+
+ }
+
+
+ /**
+ * <p>Return the mapped property descriptors for this bean class.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getMappedPropertyDescriptors(Class)
+ * @deprecated This method should not be exposed
+ */
+ public static FastHashMap getMappedPropertyDescriptors(Class beanClass) {
+
+ return PropertyUtilsBean.getInstance().getMappedPropertyDescriptors(beanClass);
+
+ }
+
+
+ /**
+ * <p>Return the mapped property descriptors for this bean.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getMappedPropertyDescriptors(Object)
+ * @deprecated This method should not be exposed
+ */
+ public static FastHashMap getMappedPropertyDescriptors(Object bean) {
+
+ return PropertyUtilsBean.getInstance().getMappedPropertyDescriptors(bean);
+
+ }
+
+
+ /**
+ * <p>Return the value of the (possibly nested) property of the specified
+ * name, for the specified bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getNestedProperty
+ */
+ public static Object getNestedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return PropertyUtilsBean.getInstance().getNestedProperty(bean, name);
+
+ }
+
+
+ /**
+ * <p>Return the value of the specified property of the specified bean,
+ * no matter which property reference format is used, with no
+ * type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getProperty
+ */
+ public static Object getProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return (PropertyUtilsBean.getInstance().getProperty(bean, name));
+
+ }
+
+
+ /**
+ * <p>Retrieve the property descriptor for the specified property of the
+ * specified bean, or return <code>null</code> if there is no such
+ * descriptor.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getPropertyDescriptor
+ */
+ public static PropertyDescriptor getPropertyDescriptor(Object bean,
+ String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return PropertyUtilsBean.getInstance().getPropertyDescriptor(bean, name);
+
+ }
+
+
+ /**
+ * <p>Retrieve the property descriptors for the specified class,
+ * introspecting and caching them the first time a particular bean class
+ * is encountered.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getPropertyDescriptors(Class)
+ */
+ public static PropertyDescriptor[]
+ getPropertyDescriptors(Class beanClass) {
+
+ return PropertyUtilsBean.getInstance().getPropertyDescriptors(beanClass);
+
+ }
+
+
+ /**
+ * <p>Retrieve the property descriptors for the specified bean,
+ * introspecting and caching them the first time a particular bean class
+ * is encountered.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getPropertyDescriptors(Object)
+ */
+ public static PropertyDescriptor[] getPropertyDescriptors(Object bean) {
+
+ return PropertyUtilsBean.getInstance().getPropertyDescriptors(bean);
+
+ }
+
+
+ /**
+ * <p>Return the Java Class repesenting the property editor class that has
+ * been registered for this property (if any).</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getPropertyEditorClass(Object,String)
+ */
+ public static Class getPropertyEditorClass(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return PropertyUtilsBean.getInstance().getPropertyEditorClass(bean, name);
+
+ }
+
+
+ /**
+ * <p>Return the Java Class representing the property type of the specified
+ * property, or <code>null</code> if there is no such property for the
+ * specified bean.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getPropertyType
+ */
+ public static Class getPropertyType(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return PropertyUtilsBean.getInstance().getPropertyType(bean, name);
+ }
+
+
+ /**
+ * <p>Return an accessible property getter method for this property,
+ * if there is one; otherwise return <code>null</code>.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getReadMethod
+ */
+ public static Method getReadMethod(PropertyDescriptor descriptor) {
+
+ return (PropertyUtilsBean.getInstance().getReadMethod(descriptor));
+
+ }
+
+
+ /**
+ * <p>Return the value of the specified simple property of the specified
+ * bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getSimpleProperty
+ */
+ public static Object getSimpleProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return PropertyUtilsBean.getInstance().getSimpleProperty(bean, name);
+
+ }
+
+
+ /**
+ * <p>Return an accessible property setter method for this property,
+ * if there is one; otherwise return <code>null</code>.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#getWriteMethod
+ */
+ public static Method getWriteMethod(PropertyDescriptor descriptor) {
+
+ return PropertyUtilsBean.getInstance().getWriteMethod(descriptor);
+
+ }
+
+
+ /**
+ * <p>Return <code>true</code> if the specified property name identifies
+ * a readable property on the specified bean; otherwise, return
+ * <code>false</code>.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#isReadable
+ * @since BeanUtils 1.6
+ */
+ public static boolean isReadable(Object bean, String name) {
+
+ return PropertyUtilsBean.getInstance().isReadable(bean, name);
+ }
+
+
+ /**
+ * <p>Return <code>true</code> if the specified property name identifies
+ * a writeable property on the specified bean; otherwise, return
+ * <code>false</code>.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#isWriteable
+ * @since BeanUtils 1.6
+ */
+ public static boolean isWriteable(Object bean, String name) {
+
+ return PropertyUtilsBean.getInstance().isWriteable(bean, name);
+ }
+
+
+ /**
+ * <p>Sets the value of the specified indexed property of the specified
+ * bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#setIndexedProperty(Object, String, Object)
+ */
+ public static void setIndexedProperty(Object bean, String name,
+ Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ PropertyUtilsBean.getInstance().setIndexedProperty(bean, name, value);
+
+ }
+
+
+ /**
+ * <p>Sets the value of the specified indexed property of the specified
+ * bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#setIndexedProperty(Object, String, Object)
+ */
+ public static void setIndexedProperty(Object bean, String name,
+ int index, Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ PropertyUtilsBean.getInstance().setIndexedProperty(bean, name, index, value);
+ }
+
+
+ /**
+ * <p>Sets the value of the specified mapped property of the
+ * specified bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#setMappedProperty(Object, String, Object)
+ */
+ public static void setMappedProperty(Object bean, String name,
+ Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ PropertyUtilsBean.getInstance().setMappedProperty(bean, name, value);
+ }
+
+
+ /**
+ * <p>Sets the value of the specified mapped property of the specified
+ * bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#setMappedProperty(Object, String, String, Object)
+ */
+ public static void setMappedProperty(Object bean, String name,
+ String key, Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ PropertyUtilsBean.getInstance().setMappedProperty(bean, name, key, value);
+ }
+
+
+ /**
+ * <p>Sets the value of the (possibly nested) property of the specified
+ * name, for the specified bean, with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#setNestedProperty
+ */
+ public static void setNestedProperty(Object bean,
+ String name, Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ PropertyUtilsBean.getInstance().setNestedProperty(bean, name, value);
+ }
+
+
+ /**
+ * <p>Set the value of the specified property of the specified bean,
+ * no matter which property reference format is used, with no
+ * type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#setProperty
+ */
+ public static void setProperty(Object bean, String name, Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ PropertyUtilsBean.getInstance().setProperty(bean, name, value);
+
+ }
+
+
+ /**
+ * <p>Set the value of the specified simple property of the specified bean,
+ * with no type conversions.</p>
+ *
+ * <p>For more details see <code>PropertyUtilsBean</code>.</p>
+ *
+ * @see PropertyUtilsBean#setSimpleProperty
+ */
+ public static void setSimpleProperty(Object bean,
+ String name, Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ PropertyUtilsBean.getInstance().setSimpleProperty(bean, name, value);
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/PropertyUtilsBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/PropertyUtilsBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/PropertyUtilsBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,1784 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+import java.beans.BeanInfo;
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.FastHashMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * Utility methods for using Java Reflection APIs to facilitate generic
+ * property getter and setter operations on Java objects. Much of this
+ * code was originally included in <code>BeanUtils</code>, but has been
+ * separated because of the volume of code involved.
+ * <p>
+ * In general, the objects that are examined and modified using these
+ * methods are expected to conform to the property getter and setter method
+ * naming conventions described in the JavaBeans Specification (Version 1.0.1).
+ * No data type conversions are performed, and there are no usage of any
+ * <code>PropertyEditor</code> classes that have been registered, although
+ * a convenient way to access the registered classes themselves is included.
+ * <p>
+ * For the purposes of this class, five formats for referencing a particular
+ * property value of a bean are defined, with the layout of an identifying
+ * String in parentheses:
+ * <ul>
+ * <li><strong>Simple (<code>name</code>)</strong> - The specified
+ * <code>name</code> identifies an individual property of a particular
+ * JavaBean. The name of the actual getter or setter method to be used
+ * is determined using standard JavaBeans instrospection, so that (unless
+ * overridden by a <code>BeanInfo</code> class, a property named "xyz"
+ * will have a getter method named <code>getXyz()</code> or (for boolean
+ * properties only) <code>isXyz()</code>, and a setter method named
+ * <code>setXyz()</code>.</li>
+ * <li><strong>Nested (<code>name1.name2.name3</code>)</strong> The first
+ * name element is used to select a property getter, as for simple
+ * references above. The object returned for this property is then
+ * consulted, using the same approach, for a property getter for a
+ * property named <code>name2</code>, and so on. The property value that
+ * is ultimately retrieved or modified is the one identified by the
+ * last name element.</li>
+ * <li><strong>Indexed (<code>name[index]</code>)</strong> - The underlying
+ * property value is assumed to be an array, or this JavaBean is assumed
+ * to have indexed property getter and setter methods. The appropriate
+ * (zero-relative) entry in the array is selected. <code>List</code>
+ * objects are now also supported for read/write. You simply need to define
+ * a getter that returns the <code>List</code></li>
+ * <li><strong>Mapped (<code>name(key)</code>)</strong> - The JavaBean
+ * is assumed to have an property getter and setter methods with an
+ * additional attribute of type <code>java.lang.String</code>.</li>
+ * <li><strong>Combined (<code>name1.name2[index].name3(key)</code>)</strong> -
+ * Combining mapped, nested, and indexed references is also
+ * supported.</li>
+ * </ul>
+ *
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author Rey François
+ * @author Gregor Raýman
+ * @author Jan Sorensen
+ * @author Scott Sanders
+ * @version $Revision: 1.14.2.1 $ $Date: 2004/07/27 21:31:00 $
+ * @see PropertyUtils
+ * @since 1.7
+ */
+
+public class PropertyUtilsBean {
+
+ // --------------------------------------------------------- Class Methods
+
+ protected static PropertyUtilsBean getInstance() {
+ return BeanUtilsBean.getInstance().getPropertyUtils();
+ }
+
+ // --------------------------------------------------------- Variables
+
+ /**
+ * The cache of PropertyDescriptor arrays for beans we have already
+ * introspected, keyed by the java.lang.Class of this object.
+ */
+ private FastHashMap descriptorsCache = null;
+ private FastHashMap mappedDescriptorsCache = null;
+
+ /** Log instance */
+ private Log log = LogFactory.getLog(PropertyUtils.class);
+
+ // ---------------------------------------------------------- Constructors
+
+ /** Base constructor */
+ public PropertyUtilsBean() {
+ descriptorsCache = new FastHashMap();
+ descriptorsCache.setFast(true);
+ mappedDescriptorsCache = new FastHashMap();
+ mappedDescriptorsCache.setFast(true);
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Clear any cached property descriptors information for all classes
+ * loaded by any class loaders. This is useful in cases where class
+ * loaders are thrown away to implement class reloading.
+ */
+ public void clearDescriptors() {
+
+ descriptorsCache.clear();
+ mappedDescriptorsCache.clear();
+ Introspector.flushCaches();
+
+ }
+
+
+ /**
+ * <p>Copy property values from the "origin" bean to the "destination" bean
+ * for all cases where the property names are the same (even though the
+ * actual getter and setter methods might have been customized via
+ * <code>BeanInfo</code> classes). No conversions are performed on the
+ * actual property values -- it is assumed that the values retrieved from
+ * the origin bean are assignment-compatible with the types expected by
+ * the destination bean.</p>
+ *
+ * <p>If the origin "bean" is actually a <code>Map</code>, it is assumed
+ * to contain String-valued <strong>simple</strong> property names as the keys, pointing
+ * at the corresponding property values that will be set in the destination
+ * bean.<strong>Note</strong> that this method is intended to perform
+ * a "shallow copy" of the properties and so complex properties
+ * (for example, nested ones) will not be copied.</p>
+ *
+ * @param dest Destination bean whose properties are modified
+ * @param orig Origin bean whose properties are retrieved
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if the <code>dest</code> or
+ * <code>orig</code> argument is null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public void copyProperties(Object dest, Object orig)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (dest == null) {
+ throw new IllegalArgumentException
+ ("No destination bean specified");
+ }
+ if (orig == null) {
+ throw new IllegalArgumentException("No origin bean specified");
+ }
+
+ if (orig instanceof DynaBean) {
+ DynaProperty origDescriptors[] =
+ ((DynaBean) orig).getDynaClass().getDynaProperties();
+ for (int i = 0; i < origDescriptors.length; i++) {
+ String name = origDescriptors[i].getName();
+ if (dest instanceof DynaBean) {
+ if (isWriteable(dest, name)) {
+ Object value = ((DynaBean) orig).get(name);
+ ((DynaBean) dest).set(name, value);
+ }
+ } else /* if (dest is a standard JavaBean) */ {
+ if (isWriteable(dest, name)) {
+ Object value = ((DynaBean) orig).get(name);
+ setSimpleProperty(dest, name, value);
+ }
+ }
+ }
+ } else if (orig instanceof Map) {
+ Iterator names = ((Map) orig).keySet().iterator();
+ while (names.hasNext()) {
+ String name = (String) names.next();
+ if (dest instanceof DynaBean) {
+ if (isWriteable(dest, name)) {
+ Object value = ((Map) orig).get(name);
+ ((DynaBean) dest).set(name, value);
+ }
+ } else /* if (dest is a standard JavaBean) */ {
+ if (isWriteable(dest, name)) {
+ Object value = ((Map) orig).get(name);
+ setSimpleProperty(dest, name, value);
+ }
+ }
+ }
+ } else /* if (orig is a standard JavaBean) */ {
+ PropertyDescriptor origDescriptors[] =
+ getPropertyDescriptors(orig);
+ for (int i = 0; i < origDescriptors.length; i++) {
+ String name = origDescriptors[i].getName();
+ if (isReadable(orig, name)) {
+ if (dest instanceof DynaBean) {
+ if (isWriteable(dest, name)) {
+ Object value = getSimpleProperty(orig, name);
+ ((DynaBean) dest).set(name, value);
+ }
+ } else /* if (dest is a standard JavaBean) */ {
+ if (isWriteable(dest, name)) {
+ Object value = getSimpleProperty(orig, name);
+ setSimpleProperty(dest, name, value);
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * <p>Return the entire set of properties for which the specified bean
+ * provides a read method. This map contains the unconverted property
+ * values for all properties for which a read method is provided
+ * (i.e. where the <code>getReadMethod()</code> returns non-null).</p>
+ *
+ * <p><strong>FIXME</strong> - Does not account for mapped properties.</p>
+ *
+ * @param bean Bean whose properties are to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> is null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public Map describe(Object bean)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ Map description = new HashMap();
+ if (bean instanceof DynaBean) {
+ DynaProperty descriptors[] =
+ ((DynaBean) bean).getDynaClass().getDynaProperties();
+ for (int i = 0; i < descriptors.length; i++) {
+ String name = descriptors[i].getName();
+ description.put(name, getProperty(bean, name));
+ }
+ } else {
+ PropertyDescriptor descriptors[] =
+ getPropertyDescriptors(bean);
+ for (int i = 0; i < descriptors.length; i++) {
+ String name = descriptors[i].getName();
+ if (descriptors[i].getReadMethod() != null)
+ description.put(name, getProperty(bean, name));
+ }
+ }
+ return (description);
+
+ }
+
+
+ /**
+ * Return the value of the specified indexed property of the specified
+ * bean, with no type conversions. The zero-relative index of the
+ * required value must be included (in square brackets) as a suffix to
+ * the property name, or <code>IllegalArgumentException</code> will be
+ * thrown. In addition to supporting the JavaBeans specification, this
+ * method has been extended to support <code>List</code> objects as well.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name <code>propertyname[index]</code> of the property value
+ * to be extracted
+ *
+ * @exception ArrayIndexOutOfBoundsException if the specified index
+ * is outside the valid range for the underlying array
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public Object getIndexedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Identify the index of the requested individual property
+ int delim = name.indexOf(PropertyUtils.INDEXED_DELIM);
+ int delim2 = name.indexOf(PropertyUtils.INDEXED_DELIM2);
+ if ((delim < 0) || (delim2 <= delim)) {
+ throw new IllegalArgumentException("Invalid indexed property '" +
+ name + "'");
+ }
+ int index = -1;
+ try {
+ String subscript = name.substring(delim + 1, delim2);
+ index = Integer.parseInt(subscript);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid indexed property '" +
+ name + "'");
+ }
+ name = name.substring(0, delim);
+
+ // Request the specified indexed property value
+ return (getIndexedProperty(bean, name, index));
+
+ }
+
+
+ /**
+ * Return the value of the specified indexed property of the specified
+ * bean, with no type conversions. In addition to supporting the JavaBeans
+ * specification, this method has been extended to support
+ * <code>List</code> objects as well.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Simple property name of the property value to be extracted
+ * @param index Index of the property value to be extracted
+ *
+ * @exception ArrayIndexOutOfBoundsException if the specified index
+ * is outside the valid range for the underlying array
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public Object getIndexedProperty(Object bean,
+ String name, int index)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Handle DynaBean instances specially
+ if (bean instanceof DynaBean) {
+ DynaProperty descriptor =
+ ((DynaBean) bean).getDynaClass().getDynaProperty(name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+ return (((DynaBean) bean).get(name, index));
+ }
+
+ // Retrieve the property descriptor for the specified property
+ PropertyDescriptor descriptor =
+ getPropertyDescriptor(bean, name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+
+ // Call the indexed getter method if there is one
+ if (descriptor instanceof IndexedPropertyDescriptor) {
+ Method readMethod = ((IndexedPropertyDescriptor) descriptor).
+ getIndexedReadMethod();
+ if (readMethod != null) {
+ Object subscript[] = new Object[1];
+ subscript[0] = new Integer(index);
+ try {
+ return (invokeMethod(readMethod,bean, subscript));
+ } catch (InvocationTargetException e) {
+ if (e.getTargetException() instanceof
+ ArrayIndexOutOfBoundsException) {
+ throw (ArrayIndexOutOfBoundsException)
+ e.getTargetException();
+ } else {
+ throw e;
+ }
+ }
+ }
+ }
+
+ // Otherwise, the underlying property must be an array
+ Method readMethod = getReadMethod(descriptor);
+ if (readMethod == null) {
+ throw new NoSuchMethodException("Property '" + name +
+ "' has no getter method");
+ }
+
+ // Call the property getter and return the value
+ Object value = invokeMethod(readMethod, bean, new Object[0]);
+ if (!value.getClass().isArray()) {
+ if (!(value instanceof java.util.List)) {
+ throw new IllegalArgumentException("Property '" + name
+ + "' is not indexed");
+ } else {
+ //get the List's value
+ return ((java.util.List) value).get(index);
+ }
+ } else {
+ //get the array's value
+ return (Array.get(value, index));
+ }
+
+ }
+
+
+ /**
+ * Return the value of the specified mapped property of the
+ * specified bean, with no type conversions. The key of the
+ * required value must be included (in brackets) as a suffix to
+ * the property name, or <code>IllegalArgumentException</code> will be
+ * thrown.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name <code>propertyname(key)</code> of the property value
+ * to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public Object getMappedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Identify the index of the requested individual property
+ int delim = name.indexOf(PropertyUtils.MAPPED_DELIM);
+ int delim2 = name.indexOf(PropertyUtils.MAPPED_DELIM2);
+ if ((delim < 0) || (delim2 <= delim)) {
+ throw new IllegalArgumentException
+ ("Invalid mapped property '" + name + "'");
+ }
+
+ // Isolate the name and the key
+ String key = name.substring(delim + 1, delim2);
+ name = name.substring(0, delim);
+
+ // Request the specified indexed property value
+ return (getMappedProperty(bean, name, key));
+
+ }
+
+
+ /**
+ * Return the value of the specified mapped property of the specified
+ * bean, with no type conversions.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Mapped property name of the property value to be extracted
+ * @param key Key of the property value to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public Object getMappedProperty(Object bean,
+ String name, String key)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+ if (key == null) {
+ throw new IllegalArgumentException("No key specified");
+ }
+
+ // Handle DynaBean instances specially
+ if (bean instanceof DynaBean) {
+ DynaProperty descriptor =
+ ((DynaBean) bean).getDynaClass().getDynaProperty(name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+ return (((DynaBean) bean).get(name, key));
+ }
+
+ Object result = null;
+
+ // Retrieve the property descriptor for the specified property
+ PropertyDescriptor descriptor = getPropertyDescriptor(bean, name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+
+ if (descriptor instanceof MappedPropertyDescriptor) {
+ // Call the keyed getter method if there is one
+ Method readMethod = ((MappedPropertyDescriptor) descriptor).
+ getMappedReadMethod();
+ if (readMethod != null) {
+ Object keyArray[] = new Object[1];
+ keyArray[0] = key;
+ result = invokeMethod(readMethod, bean, keyArray);
+ } else {
+ throw new NoSuchMethodException("Property '" + name +
+ "' has no mapped getter method");
+ }
+ } else {
+ /* means that the result has to be retrieved from a map */
+ Method readMethod = descriptor.getReadMethod();
+ if (readMethod != null) {
+ Object invokeResult = invokeMethod(readMethod, bean, new Object[0]);
+ /* test and fetch from the map */
+ if (invokeResult instanceof java.util.Map) {
+ result = ((java.util.Map)invokeResult).get(key);
+ }
+ } else {
+ throw new NoSuchMethodException("Property '" + name +
+ "' has no mapped getter method");
+ }
+ }
+ return result;
+
+ }
+
+
+ /**
+ * <p>Return the mapped property descriptors for this bean class.</p>
+ *
+ * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
+ *
+ * @param beanClass Bean class to be introspected
+ * @deprecated This method should not be exposed
+ */
+ public FastHashMap getMappedPropertyDescriptors(Class beanClass) {
+
+ if (beanClass == null) {
+ return null;
+ }
+
+ // Look up any cached descriptors for this bean class
+ return (FastHashMap) mappedDescriptorsCache.get(beanClass);
+
+ }
+
+
+ /**
+ * <p>Return the mapped property descriptors for this bean.</p>
+ *
+ * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
+ *
+ * @param bean Bean to be introspected
+ * @deprecated This method should not be exposed
+ */
+ public FastHashMap getMappedPropertyDescriptors(Object bean) {
+
+ if (bean == null) {
+ return null;
+ }
+ return (getMappedPropertyDescriptors(bean.getClass()));
+
+ }
+
+
+ /**
+ * Return the value of the (possibly nested) property of the specified
+ * name, for the specified bean, with no type conversions.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Possibly nested name of the property to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception NestedNullException if a nested reference to a
+ * property returns null
+ * @exception InvocationTargetException
+ * if the property accessor method throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public Object getNestedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ int indexOfINDEXED_DELIM = -1;
+ int indexOfMAPPED_DELIM = -1;
+ int indexOfMAPPED_DELIM2 = -1;
+ int indexOfNESTED_DELIM = -1;
+ while (true) {
+ indexOfNESTED_DELIM = name.indexOf(PropertyUtils.NESTED_DELIM);
+ indexOfMAPPED_DELIM = name.indexOf(PropertyUtils.MAPPED_DELIM);
+ indexOfMAPPED_DELIM2 = name.indexOf(PropertyUtils.MAPPED_DELIM2);
+ if (indexOfMAPPED_DELIM2 >= 0 && indexOfMAPPED_DELIM >=0 &&
+ (indexOfNESTED_DELIM < 0 || indexOfNESTED_DELIM > indexOfMAPPED_DELIM)) {
+ indexOfNESTED_DELIM =
+ name.indexOf(PropertyUtils.NESTED_DELIM, indexOfMAPPED_DELIM2);
+ } else {
+ indexOfNESTED_DELIM = name.indexOf(PropertyUtils.NESTED_DELIM);
+ }
+ if (indexOfNESTED_DELIM < 0) {
+ break;
+ }
+ String next = name.substring(0, indexOfNESTED_DELIM);
+ indexOfINDEXED_DELIM = next.indexOf(PropertyUtils.INDEXED_DELIM);
+ indexOfMAPPED_DELIM = next.indexOf(PropertyUtils.MAPPED_DELIM);
+ if (bean instanceof Map) {
+ bean = ((Map) bean).get(next);
+ } else if (indexOfMAPPED_DELIM >= 0) {
+ bean = getMappedProperty(bean, next);
+ } else if (indexOfINDEXED_DELIM >= 0) {
+ bean = getIndexedProperty(bean, next);
+ } else {
+ bean = getSimpleProperty(bean, next);
+ }
+ if (bean == null) {
+ throw new NestedNullException
+ ("Null property value for '" +
+ name.substring(0, indexOfNESTED_DELIM) + "'");
+ }
+ name = name.substring(indexOfNESTED_DELIM + 1);
+ }
+
+ indexOfINDEXED_DELIM = name.indexOf(PropertyUtils.INDEXED_DELIM);
+ indexOfMAPPED_DELIM = name.indexOf(PropertyUtils.MAPPED_DELIM);
+
+ if (bean instanceof Map) {
+ bean = ((Map) bean).get(name);
+ } else if (indexOfMAPPED_DELIM >= 0) {
+ bean = getMappedProperty(bean, name);
+ } else if (indexOfINDEXED_DELIM >= 0) {
+ bean = getIndexedProperty(bean, name);
+ } else {
+ bean = getSimpleProperty(bean, name);
+ }
+ return bean;
+
+ }
+
+
+ /**
+ * Return the value of the specified property of the specified bean,
+ * no matter which property reference format is used, with no
+ * type conversions.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Possibly indexed and/or nested name of the property
+ * to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public Object getProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return (getNestedProperty(bean, name));
+
+ }
+
+
+ /**
+ * <p>Retrieve the property descriptor for the specified property of the
+ * specified bean, or return <code>null</code> if there is no such
+ * descriptor. This method resolves indexed and nested property
+ * references in the same manner as other methods in this class, except
+ * that if the last (or only) name element is indexed, the descriptor
+ * for the last resolved property itself is returned.</p>
+ *
+ * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
+ *
+ * @param bean Bean for which a property descriptor is requested
+ * @param name Possibly indexed and/or nested name of the property for
+ * which a property descriptor is requested
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception IllegalArgumentException if a nested reference to a
+ * property returns null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public PropertyDescriptor getPropertyDescriptor(Object bean,
+ String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Resolve nested references
+ while (true) {
+ int period = findNextNestedIndex(name);
+ if (period < 0) {
+ break;
+ }
+ String next = name.substring(0, period);
+ int indexOfINDEXED_DELIM = next.indexOf(PropertyUtils.INDEXED_DELIM);
+ int indexOfMAPPED_DELIM = next.indexOf(PropertyUtils.MAPPED_DELIM);
+ if (indexOfMAPPED_DELIM >= 0 &&
+ (indexOfINDEXED_DELIM < 0 ||
+ indexOfMAPPED_DELIM < indexOfINDEXED_DELIM)) {
+ bean = getMappedProperty(bean, next);
+ } else {
+ if (indexOfINDEXED_DELIM >= 0) {
+ bean = getIndexedProperty(bean, next);
+ } else {
+ bean = getSimpleProperty(bean, next);
+ }
+ }
+ if (bean == null) {
+ throw new IllegalArgumentException
+ ("Null property value for '" +
+ name.substring(0, period) + "'");
+ }
+ name = name.substring(period + 1);
+ }
+
+ // Remove any subscript from the final name value
+ int left = name.indexOf(PropertyUtils.INDEXED_DELIM);
+ if (left >= 0) {
+ name = name.substring(0, left);
+ }
+ left = name.indexOf(PropertyUtils.MAPPED_DELIM);
+ if (left >= 0) {
+ name = name.substring(0, left);
+ }
+
+ // Look up and return this property from our cache
+ // creating and adding it to the cache if not found.
+ if ((bean == null) || (name == null)) {
+ return (null);
+ }
+
+ PropertyDescriptor descriptors[] = getPropertyDescriptors(bean);
+ if (descriptors != null) {
+
+ for (int i = 0; i < descriptors.length; i++) {
+ if (name.equals(descriptors[i].getName()))
+ return (descriptors[i]);
+ }
+ }
+
+ PropertyDescriptor result = null;
+ FastHashMap mappedDescriptors =
+ getMappedPropertyDescriptors(bean);
+ if (mappedDescriptors == null) {
+ mappedDescriptors = new FastHashMap();
+ mappedDescriptors.setFast(true);
+ mappedDescriptorsCache.put(bean.getClass(), mappedDescriptors);
+ }
+ result = (PropertyDescriptor) mappedDescriptors.get(name);
+ if (result == null) {
+ // not found, try to create it
+ try {
+ result =
+ new MappedPropertyDescriptor(name, bean.getClass());
+ } catch (IntrospectionException ie) {
+ }
+ if (result != null) {
+ mappedDescriptors.put(name, result);
+ }
+ }
+
+ return result;
+
+ }
+
+ private int findNextNestedIndex(String expression)
+ {
+ // walk back from the end to the start
+ // and find the first index that
+ int bracketCount = 0;
+ for (int i=0, size=expression.length(); i<size ; i++) {
+ char at = expression.charAt(i);
+ switch (at) {
+ case PropertyUtils.NESTED_DELIM:
+ if (bracketCount < 1) {
+ return i;
+ }
+ break;
+
+ case PropertyUtils.MAPPED_DELIM:
+ case PropertyUtils.INDEXED_DELIM:
+ // not bothered which
+ ++bracketCount;
+ break;
+
+ case PropertyUtils.MAPPED_DELIM2:
+ case PropertyUtils.INDEXED_DELIM2:
+ // not bothered which
+ --bracketCount;
+ break;
+ }
+ }
+ // can't find any
+ return -1;
+ }
+
+
+ /**
+ * <p>Retrieve the property descriptors for the specified class,
+ * introspecting and caching them the first time a particular bean class
+ * is encountered.</p>
+ *
+ * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
+ *
+ * @param beanClass Bean class for which property descriptors are requested
+ *
+ * @exception IllegalArgumentException if <code>beanClass</code> is null
+ */
+ public PropertyDescriptor[]
+ getPropertyDescriptors(Class beanClass) {
+
+ if (beanClass == null) {
+ throw new IllegalArgumentException("No bean class specified");
+ }
+
+ // Look up any cached descriptors for this bean class
+ PropertyDescriptor descriptors[] = null;
+ descriptors =
+ (PropertyDescriptor[]) descriptorsCache.get(beanClass);
+ if (descriptors != null) {
+ return (descriptors);
+ }
+
+ // Introspect the bean and cache the generated descriptors
+ BeanInfo beanInfo = null;
+ try {
+ beanInfo = Introspector.getBeanInfo(beanClass);
+ } catch (IntrospectionException e) {
+ return (new PropertyDescriptor[0]);
+ }
+ descriptors = beanInfo.getPropertyDescriptors();
+ if (descriptors == null) {
+ descriptors = new PropertyDescriptor[0];
+ }
+ descriptorsCache.put(beanClass, descriptors);
+ return (descriptors);
+
+ }
+
+
+ /**
+ * <p>Retrieve the property descriptors for the specified bean,
+ * introspecting and caching them the first time a particular bean class
+ * is encountered.</p>
+ *
+ * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
+ *
+ * @param bean Bean for which property descriptors are requested
+ *
+ * @exception IllegalArgumentException if <code>bean</code> is null
+ */
+ public PropertyDescriptor[] getPropertyDescriptors(Object bean) {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ return (getPropertyDescriptors(bean.getClass()));
+
+ }
+
+
+ /**
+ * <p>Return the Java Class repesenting the property editor class that has
+ * been registered for this property (if any). This method follows the
+ * same name resolution rules used by <code>getPropertyDescriptor()</code>,
+ * so if the last element of a name reference is indexed, the property
+ * editor for the underlying property's class is returned.</p>
+ *
+ * <p>Note that <code>null</code> will be returned if there is no property,
+ * or if there is no registered property editor class. Because this
+ * return value is ambiguous, you should determine the existence of the
+ * property itself by other means.</p>
+ *
+ * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
+ *
+ * @param bean Bean for which a property descriptor is requested
+ * @param name Possibly indexed and/or nested name of the property for
+ * which a property descriptor is requested
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception IllegalArgumentException if a nested reference to a
+ * property returns null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public Class getPropertyEditorClass(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ PropertyDescriptor descriptor =
+ getPropertyDescriptor(bean, name);
+ if (descriptor != null) {
+ return (descriptor.getPropertyEditorClass());
+ } else {
+ return (null);
+ }
+
+ }
+
+
+ /**
+ * Return the Java Class representing the property type of the specified
+ * property, or <code>null</code> if there is no such property for the
+ * specified bean. This method follows the same name resolution rules
+ * used by <code>getPropertyDescriptor()</code>, so if the last element
+ * of a name reference is indexed, the type of the property itself will
+ * be returned. If the last (or only) element has no property with the
+ * specified name, <code>null</code> is returned.
+ *
+ * @param bean Bean for which a property descriptor is requested
+ * @param name Possibly indexed and/or nested name of the property for
+ * which a property descriptor is requested
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception IllegalArgumentException if a nested reference to a
+ * property returns null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public Class getPropertyType(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Special handling for DynaBeans
+ if (bean instanceof DynaBean) {
+ DynaProperty descriptor =
+ ((DynaBean) bean).getDynaClass().getDynaProperty(name);
+ if (descriptor == null) {
+ return (null);
+ }
+ Class type = descriptor.getType();
+ if (type == null) {
+ return (null);
+ } else if (type.isArray()) {
+ return (type.getComponentType());
+ } else {
+ return (type);
+ }
+ }
+
+ PropertyDescriptor descriptor =
+ getPropertyDescriptor(bean, name);
+ if (descriptor == null) {
+ return (null);
+ } else if (descriptor instanceof IndexedPropertyDescriptor) {
+ return (((IndexedPropertyDescriptor) descriptor).
+ getIndexedPropertyType());
+ } else if (descriptor instanceof MappedPropertyDescriptor) {
+ return (((MappedPropertyDescriptor) descriptor).
+ getMappedPropertyType());
+ } else {
+ return (descriptor.getPropertyType());
+ }
+
+ }
+
+
+ /**
+ * <p>Return an accessible property getter method for this property,
+ * if there is one; otherwise return <code>null</code>.</p>
+ *
+ * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
+ *
+ * @param descriptor Property descriptor to return a getter for
+ */
+ public Method getReadMethod(PropertyDescriptor descriptor) {
+
+ return (MethodUtils.getAccessibleMethod(descriptor.getReadMethod()));
+
+ }
+
+
+ /**
+ * Return the value of the specified simple property of the specified
+ * bean, with no type conversions.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Name of the property to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception IllegalArgumentException if the property name
+ * is nested or indexed
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public Object getSimpleProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Validate the syntax of the property name
+ if (name.indexOf(PropertyUtils.NESTED_DELIM) >= 0) {
+ throw new IllegalArgumentException
+ ("Nested property names are not allowed");
+ } else if (name.indexOf(PropertyUtils.INDEXED_DELIM) >= 0) {
+ throw new IllegalArgumentException
+ ("Indexed property names are not allowed");
+ } else if (name.indexOf(PropertyUtils.MAPPED_DELIM) >= 0) {
+ throw new IllegalArgumentException
+ ("Mapped property names are not allowed");
+ }
+
+ // Handle DynaBean instances specially
+ if (bean instanceof DynaBean) {
+ DynaProperty descriptor =
+ ((DynaBean) bean).getDynaClass().getDynaProperty(name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+ return (((DynaBean) bean).get(name));
+ }
+
+ // Retrieve the property getter method for the specified property
+ PropertyDescriptor descriptor =
+ getPropertyDescriptor(bean, name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+ Method readMethod = getReadMethod(descriptor);
+ if (readMethod == null) {
+ throw new NoSuchMethodException("Property '" + name +
+ "' has no getter method");
+ }
+
+ // Call the property getter and return the value
+ Object value = invokeMethod(readMethod, bean, new Object[0]);
+ return (value);
+
+ }
+
+
+ /**
+ * <p>Return an accessible property setter method for this property,
+ * if there is one; otherwise return <code>null</code>.</p>
+ *
+ * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
+ *
+ * @param descriptor Property descriptor to return a setter for
+ */
+ public Method getWriteMethod(PropertyDescriptor descriptor) {
+
+ return (MethodUtils.getAccessibleMethod(descriptor.getWriteMethod()));
+
+ }
+
+
+ /**
+ * <p>Return <code>true</code> if the specified property name identifies
+ * a readable property on the specified bean; otherwise, return
+ * <code>false</code>.
+ *
+ * @param bean Bean to be examined (may be a {@link DynaBean}
+ * @param name Property name to be evaluated
+ *
+ * @exception IllegalArgumentException if <code>bean</code>
+ * or <code>name</code> is <code>null</code>
+ *
+ * @since BeanUtils 1.6
+ */
+ public boolean isReadable(Object bean, String name) {
+
+ // Validate method parameters
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Return the requested result
+ if (bean instanceof DynaBean) {
+ // All DynaBean properties are readable
+ return (((DynaBean) bean).getDynaClass().getDynaProperty(name) != null);
+ } else {
+ try {
+ PropertyDescriptor desc =
+ getPropertyDescriptor(bean, name);
+ if (desc != null) {
+ Method readMethod = desc.getReadMethod();
+ if ((readMethod == null) &&
+ (desc instanceof IndexedPropertyDescriptor)) {
+ readMethod = ((IndexedPropertyDescriptor) desc).getIndexedReadMethod();
+ }
+ return (readMethod != null);
+ } else {
+ return (false);
+ }
+ } catch (IllegalAccessException e) {
+ return (false);
+ } catch (InvocationTargetException e) {
+ return (false);
+ } catch (NoSuchMethodException e) {
+ return (false);
+ }
+ }
+
+ }
+
+
+ /**
+ * <p>Return <code>true</code> if the specified property name identifies
+ * a writeable property on the specified bean; otherwise, return
+ * <code>false</code>.
+ *
+ * @param bean Bean to be examined (may be a {@link DynaBean}
+ * @param name Property name to be evaluated
+ *
+ * @exception IllegalPointerException if <code>bean</code>
+ * or <code>name</code> is <code>null</code>
+ *
+ * @since BeanUtils 1.6
+ */
+ public boolean isWriteable(Object bean, String name) {
+
+ // Validate method parameters
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Return the requested result
+ if (bean instanceof DynaBean) {
+ // All DynaBean properties are writeable
+ return (((DynaBean) bean).getDynaClass().getDynaProperty(name) != null);
+ } else {
+ try {
+ PropertyDescriptor desc =
+ getPropertyDescriptor(bean, name);
+ if (desc != null) {
+ Method writeMethod = desc.getWriteMethod();
+ if ((writeMethod == null) &&
+ (desc instanceof IndexedPropertyDescriptor)) {
+ writeMethod = ((IndexedPropertyDescriptor) desc).getIndexedWriteMethod();
+ }
+ return (writeMethod != null);
+ } else {
+ return (false);
+ }
+ } catch (IllegalAccessException e) {
+ return (false);
+ } catch (InvocationTargetException e) {
+ return (false);
+ } catch (NoSuchMethodException e) {
+ return (false);
+ }
+ }
+
+ }
+
+
+ /**
+ * Set the value of the specified indexed property of the specified
+ * bean, with no type conversions. The zero-relative index of the
+ * required value must be included (in square brackets) as a suffix to
+ * the property name, or <code>IllegalArgumentException</code> will be
+ * thrown. In addition to supporting the JavaBeans specification, this
+ * method has been extended to support <code>List</code> objects as well.
+ *
+ * @param bean Bean whose property is to be modified
+ * @param name <code>propertyname[index]</code> of the property value
+ * to be modified
+ * @param value Value to which the specified property element
+ * should be set
+ *
+ * @exception ArrayIndexOutOfBoundsException if the specified index
+ * is outside the valid range for the underlying array
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public void setIndexedProperty(Object bean, String name,
+ Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Identify the index of the requested individual property
+ int delim = name.indexOf(PropertyUtils.INDEXED_DELIM);
+ int delim2 = name.indexOf(PropertyUtils.INDEXED_DELIM2);
+ if ((delim < 0) || (delim2 <= delim)) {
+ throw new IllegalArgumentException("Invalid indexed property '" +
+ name + "'");
+ }
+ int index = -1;
+ try {
+ String subscript = name.substring(delim + 1, delim2);
+ index = Integer.parseInt(subscript);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid indexed property '" +
+ name + "'");
+ }
+ name = name.substring(0, delim);
+
+ // Set the specified indexed property value
+ setIndexedProperty(bean, name, index, value);
+
+ }
+
+
+ /**
+ * Set the value of the specified indexed property of the specified
+ * bean, with no type conversions. In addition to supporting the JavaBeans
+ * specification, this method has been extended to support
+ * <code>List</code> objects as well.
+ *
+ * @param bean Bean whose property is to be set
+ * @param name Simple property name of the property value to be set
+ * @param index Index of the property value to be set
+ * @param value Value to which the indexed property element is to be set
+ *
+ * @exception ArrayIndexOutOfBoundsException if the specified index
+ * is outside the valid range for the underlying array
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public void setIndexedProperty(Object bean, String name,
+ int index, Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Handle DynaBean instances specially
+ if (bean instanceof DynaBean) {
+ DynaProperty descriptor =
+ ((DynaBean) bean).getDynaClass().getDynaProperty(name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+ ((DynaBean) bean).set(name, index, value);
+ return;
+ }
+
+ // Retrieve the property descriptor for the specified property
+ PropertyDescriptor descriptor =
+ getPropertyDescriptor(bean, name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+
+ // Call the indexed setter method if there is one
+ if (descriptor instanceof IndexedPropertyDescriptor) {
+ Method writeMethod = ((IndexedPropertyDescriptor) descriptor).
+ getIndexedWriteMethod();
+ if (writeMethod != null) {
+ Object subscript[] = new Object[2];
+ subscript[0] = new Integer(index);
+ subscript[1] = value;
+ try {
+ if (log.isTraceEnabled()) {
+ String valueClassName =
+ value == null ? "<null>"
+ : value.getClass().getName();
+ log.trace("setSimpleProperty: Invoking method "
+ + writeMethod +" with index=" + index
+ + ", value=" + value
+ + " (class " + valueClassName+ ")");
+ }
+ invokeMethod(writeMethod, bean, subscript);
+ } catch (InvocationTargetException e) {
+ if (e.getTargetException() instanceof
+ ArrayIndexOutOfBoundsException) {
+ throw (ArrayIndexOutOfBoundsException)
+ e.getTargetException();
+ } else {
+ throw e;
+ }
+ }
+ return;
+ }
+ }
+
+ // Otherwise, the underlying property must be an array or a list
+ Method readMethod = descriptor.getReadMethod();
+ if (readMethod == null) {
+ throw new NoSuchMethodException("Property '" + name +
+ "' has no getter method");
+ }
+
+ // Call the property getter to get the array or list
+ Object array = invokeMethod(readMethod, bean, new Object[0]);
+ if (!array.getClass().isArray()) {
+ if (array instanceof List) {
+ // Modify the specified value in the List
+ ((List) array).set(index, value);
+ } else {
+ throw new IllegalArgumentException("Property '" + name +
+ "' is not indexed");
+ }
+ } else {
+ // Modify the specified value in the array
+ Array.set(array, index, value);
+ }
+
+ }
+
+
+ /**
+ * Set the value of the specified mapped property of the
+ * specified bean, with no type conversions. The key of the
+ * value to set must be included (in brackets) as a suffix to
+ * the property name, or <code>IllegalArgumentException</code> will be
+ * thrown.
+ *
+ * @param bean Bean whose property is to be set
+ * @param name <code>propertyname(key)</code> of the property value
+ * to be set
+ * @param value The property value to be set
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public void setMappedProperty(Object bean, String name,
+ Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Identify the index of the requested individual property
+ int delim = name.indexOf(PropertyUtils.MAPPED_DELIM);
+ int delim2 = name.indexOf(PropertyUtils.MAPPED_DELIM2);
+ if ((delim < 0) || (delim2 <= delim)) {
+ throw new IllegalArgumentException
+ ("Invalid mapped property '" + name + "'");
+ }
+
+ // Isolate the name and the key
+ String key = name.substring(delim + 1, delim2);
+ name = name.substring(0, delim);
+
+ // Request the specified indexed property value
+ setMappedProperty(bean, name, key, value);
+
+ }
+
+
+ /**
+ * Set the value of the specified mapped property of the specified
+ * bean, with no type conversions.
+ *
+ * @param bean Bean whose property is to be set
+ * @param name Mapped property name of the property value to be set
+ * @param key Key of the property value to be set
+ * @param value The property value to be set
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public void setMappedProperty(Object bean, String name,
+ String key, Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+ if (key == null) {
+ throw new IllegalArgumentException("No key specified");
+ }
+
+ // Handle DynaBean instances specially
+ if (bean instanceof DynaBean) {
+ DynaProperty descriptor =
+ ((DynaBean) bean).getDynaClass().getDynaProperty(name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+ ((DynaBean) bean).set(name, key, value);
+ return;
+ }
+
+ // Retrieve the property descriptor for the specified property
+ PropertyDescriptor descriptor =
+ getPropertyDescriptor(bean, name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+
+ if (descriptor instanceof MappedPropertyDescriptor) {
+ // Call the keyed setter method if there is one
+ Method mappedWriteMethod =
+ ((MappedPropertyDescriptor) descriptor).
+ getMappedWriteMethod();
+ if (mappedWriteMethod != null) {
+ Object params[] = new Object[2];
+ params[0] = key;
+ params[1] = value;
+ if (log.isTraceEnabled()) {
+ String valueClassName =
+ value == null ? "<null>" : value.getClass().getName();
+ log.trace("setSimpleProperty: Invoking method "
+ + mappedWriteMethod + " with key=" + key
+ + ", value=" + value
+ + " (class " + valueClassName +")");
+ }
+ invokeMethod(mappedWriteMethod, bean, params);
+ } else {
+ throw new NoSuchMethodException
+ ("Property '" + name +
+ "' has no mapped setter method");
+ }
+ } else {
+ /* means that the result has to be retrieved from a map */
+ Method readMethod = descriptor.getReadMethod();
+ if (readMethod != null) {
+ Object invokeResult = invokeMethod(readMethod, bean, new Object[0]);
+ /* test and fetch from the map */
+ if (invokeResult instanceof java.util.Map) {
+ ((java.util.Map)invokeResult).put(key, value);
+ }
+ } else {
+ throw new NoSuchMethodException("Property '" + name +
+ "' has no mapped getter method");
+ }
+ }
+
+ }
+
+
+ /**
+ * Set the value of the (possibly nested) property of the specified
+ * name, for the specified bean, with no type conversions.
+ *
+ * @param bean Bean whose property is to be modified
+ * @param name Possibly nested name of the property to be modified
+ * @param value Value to which the property is to be set
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception IllegalArgumentException if a nested reference to a
+ * property returns null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public void setNestedProperty(Object bean,
+ String name, Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ int indexOfINDEXED_DELIM = -1;
+ int indexOfMAPPED_DELIM = -1;
+ while (true) {
+ int delim = name.indexOf(PropertyUtils.NESTED_DELIM);
+ if (delim < 0) {
+ break;
+ }
+ String next = name.substring(0, delim);
+ indexOfINDEXED_DELIM = next.indexOf(PropertyUtils.INDEXED_DELIM);
+ indexOfMAPPED_DELIM = next.indexOf(PropertyUtils.MAPPED_DELIM);
+ if (bean instanceof Map) {
+ bean = ((Map) bean).get(next);
+ } else if (indexOfMAPPED_DELIM >= 0) {
+ bean = getMappedProperty(bean, next);
+ } else if (indexOfINDEXED_DELIM >= 0) {
+ bean = getIndexedProperty(bean, next);
+ } else {
+ bean = getSimpleProperty(bean, next);
+ }
+ if (bean == null) {
+ throw new IllegalArgumentException
+ ("Null property value for '" +
+ name.substring(0, delim) + "'");
+ }
+ name = name.substring(delim + 1);
+ }
+
+ indexOfINDEXED_DELIM = name.indexOf(PropertyUtils.INDEXED_DELIM);
+ indexOfMAPPED_DELIM = name.indexOf(PropertyUtils.MAPPED_DELIM);
+
+ if (bean instanceof Map) {
+ // check to see if the class has a standard property
+ PropertyDescriptor descriptor =
+ getPropertyDescriptor(bean, name);
+ if (descriptor == null) {
+ // no - then put the value into the map
+ ((Map) bean).put(name, value);
+ } else {
+ // yes - use that instead
+ setSimpleProperty(bean, name, value);
+ }
+ } else if (indexOfMAPPED_DELIM >= 0) {
+ setMappedProperty(bean, name, value);
+ } else if (indexOfINDEXED_DELIM >= 0) {
+ setIndexedProperty(bean, name, value);
+ } else {
+ setSimpleProperty(bean, name, value);
+ }
+
+ }
+
+
+ /**
+ * Set the value of the specified property of the specified bean,
+ * no matter which property reference format is used, with no
+ * type conversions.
+ *
+ * @param bean Bean whose property is to be modified
+ * @param name Possibly indexed and/or nested name of the property
+ * to be modified
+ * @param value Value to which this property is to be set
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public void setProperty(Object bean, String name, Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ setNestedProperty(bean, name, value);
+
+ }
+
+
+ /**
+ * Set the value of the specified simple property of the specified bean,
+ * with no type conversions.
+ *
+ * @param bean Bean whose property is to be modified
+ * @param name Name of the property to be modified
+ * @param value Value to which the property should be set
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if <code>bean</code> or
+ * <code>name</code> is null
+ * @exception IllegalArgumentException if the property name is
+ * nested or indexed
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public void setSimpleProperty(Object bean,
+ String name, Object value)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified");
+ }
+
+ // Validate the syntax of the property name
+ if (name.indexOf(PropertyUtils.NESTED_DELIM) >= 0) {
+ throw new IllegalArgumentException
+ ("Nested property names are not allowed");
+ } else if (name.indexOf(PropertyUtils.INDEXED_DELIM) >= 0) {
+ throw new IllegalArgumentException
+ ("Indexed property names are not allowed");
+ } else if (name.indexOf(PropertyUtils.MAPPED_DELIM) >= 0) {
+ throw new IllegalArgumentException
+ ("Mapped property names are not allowed");
+ }
+
+ // Handle DynaBean instances specially
+ if (bean instanceof DynaBean) {
+ DynaProperty descriptor =
+ ((DynaBean) bean).getDynaClass().getDynaProperty(name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+ ((DynaBean) bean).set(name, value);
+ return;
+ }
+
+ // Retrieve the property setter method for the specified property
+ PropertyDescriptor descriptor =
+ getPropertyDescriptor(bean, name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'");
+ }
+ Method writeMethod = getWriteMethod(descriptor);
+ if (writeMethod == null) {
+ throw new NoSuchMethodException("Property '" + name +
+ "' has no setter method");
+ }
+
+ // Call the property setter method
+ Object values[] = new Object[1];
+ values[0] = value;
+ if (log.isTraceEnabled()) {
+ String valueClassName =
+ value == null ? "<null>" : value.getClass().getName();
+ log.trace("setSimpleProperty: Invoking method " + writeMethod
+ + " with value " + value + " (class " + valueClassName + ")");
+ }
+ invokeMethod(writeMethod, bean, values);
+
+ }
+
+ /** This just catches and wraps IllegalArgumentException. */
+ private Object invokeMethod(
+ Method method,
+ Object bean,
+ Object[] values)
+ throws
+ IllegalAccessException,
+ InvocationTargetException {
+ try {
+
+ return method.invoke(bean, values);
+
+ } catch (IllegalArgumentException e) {
+
+ log.error("Method invocation failed.", e);
+ throw new IllegalArgumentException(
+ "Cannot invoke " + method.getDeclaringClass().getName() + "."
+ + method.getName() + " - " + e.getMessage());
+
+ }
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ResultSetDynaClass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ResultSetDynaClass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ResultSetDynaClass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Iterator;
+
+
+/**
+ * <p>Implementation of <code>DynaClass</code> for DynaBeans that wrap the
+ * <code>java.sql.Row</code> objects of a <code>java.sql.ResultSet</code>.
+ * The normal usage pattern is something like:</p>
+ * <pre>
+ * ResultSet rs = ...;
+ * ResultSetDynaClass rsdc = new ResultSetDynaClass(rs);
+ * Iterator rows = rsdc.iterator();
+ * while (rows.hasNext()) {
+ * DynaBean row = (DynaBean) rows.next();
+ * ... process this row ...
+ * }
+ * rs.close();
+ * </pre>
+ *
+ * <p>Each column in the result set will be represented as a DynaBean
+ * property of the corresponding name (optionally forced to lower case
+ * for portability).</p>
+ *
+ * <p><strong>WARNING</strong> - Any {@link DynaBean} instance returned by
+ * this class, or from the <code>Iterator</code> returned by the
+ * <code>iterator()</code> method, is directly linked to the row that the
+ * underlying result set is currently positioned at. This has the following
+ * implications:</p>
+ * <ul>
+ * <li>Once you retrieve a different {@link DynaBean} instance, you should
+ * no longer use any previous instance.</li>
+ * <li>Changing the position of the underlying result set will change the
+ * data that the {@link DynaBean} references.</li>
+ * <li>Once the underlying result set is closed, the {@link DynaBean}
+ * instance may no longer be used.</li>
+ * </ul>
+ *
+ * <p>Any database data that you wish to utilize outside the context of the
+ * current row of an open result set must be copied. For example, you could
+ * use the following code to create standalone copies of the information in
+ * a result set:</p>
+ * <pre>
+ * ArrayList results = new ArrayList(); // To hold copied list
+ * ResultSetDynaClass rsdc = ...;
+ * DynaProperty properties[] = rsdc.getDynaProperties();
+ * BasicDynaClass bdc =
+ * new BasicDynaClass("foo", BasicDynaBean.class,
+ * rsdc.getDynaProperties());
+ * Iterator rows = rsdc.iterator();
+ * while (rows.hasNext()) {
+ * DynaBean oldRow = (DynaBean) rows.next();
+ * DynaBean newRow = bdc.newInstance();
+ * PropertyUtils.copyProperties(newRow, oldRow);
+ * results.add(newRow);
+ * }
+ * </pre>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.15 $ $Date: 2004/02/28 13:18:33 $
+ */
+
+public class ResultSetDynaClass extends JDBCDynaClass implements DynaClass {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * <p>Construct a new ResultSetDynaClass for the specified
+ * <code>ResultSet</code>. The property names corresponding
+ * to column names in the result set will be lower cased.</p>
+ *
+ * @param resultSet The result set to be wrapped
+ *
+ * @exception NullPointerException if <code>resultSet</code>
+ * is <code>null</code>
+ * @exception SQLException if the metadata for this result set
+ * cannot be introspected
+ */
+ public ResultSetDynaClass(ResultSet resultSet) throws SQLException {
+
+ this(resultSet, true);
+
+ }
+
+
+ /**
+ * <p>Construct a new ResultSetDynaClass for the specified
+ * <code>ResultSet</code>. The property names corresponding
+ * to the column names in the result set will be lower cased or not,
+ * depending on the specified <code>lowerCase</code> value.</p>
+ *
+ * <p><strong>WARNING</strong> - If you specify <code>false</code>
+ * for <code>lowerCase</code>, the returned property names will
+ * exactly match the column names returned by your JDBC driver.
+ * Because different drivers might return column names in different
+ * cases, the property names seen by your application will vary
+ * depending on which JDBC driver you are using.</p>
+ *
+ * @param resultSet The result set to be wrapped
+ * @param lowerCase Should property names be lower cased?
+ *
+ * @exception NullPointerException if <code>resultSet</code>
+ * is <code>null</code>
+ * @exception SQLException if the metadata for this result set
+ * cannot be introspected
+ */
+ public ResultSetDynaClass(ResultSet resultSet, boolean lowerCase)
+ throws SQLException {
+
+ if (resultSet == null) {
+ throw new NullPointerException();
+ }
+ this.resultSet = resultSet;
+ this.lowerCase = lowerCase;
+ introspect(resultSet);
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * <p>The <code>ResultSet</code> we are wrapping.</p>
+ */
+ protected ResultSet resultSet = null;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * <p>Return an <code>Iterator</code> of {@link DynaBean} instances for
+ * each row of the wrapped <code>ResultSet</code>, in "forward" order.
+ * Unless the underlying result set supports scrolling, this method
+ * should be called only once.</p>
+ */
+ public Iterator iterator() {
+
+ return (new ResultSetIterator(this));
+
+ }
+
+
+ // -------------------------------------------------------- Package Methods
+
+
+ /**
+ * <p>Return the result set we are wrapping.</p>
+ */
+ ResultSet getResultSet() {
+
+ return (this.resultSet);
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+ /**
+ * <p>Loads the class of the given name which by default uses the class loader used
+ * to load this library.
+ * Dervations of this class could implement alternative class loading policies such as
+ * using custom ClassLoader or using the Threads's context class loader etc.
+ * </p>
+ */
+ protected Class loadClass(String className) throws SQLException {
+
+ try {
+ return getClass().getClassLoader().loadClass(className);
+ }
+ catch (Exception e) {
+ throw new SQLException("Cannot load column class '" +
+ className + "': " + e);
+ }
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ResultSetIterator.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ResultSetIterator.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/ResultSetIterator.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+
+/**
+ * <p>Implementation of <code>java.util.Iterator</code> returned by the
+ * <code>iterator()</code> method of {@link ResultSetDynaClass}. Each
+ * object returned by this iterator will be a {@link DynaBean} that
+ * represents a single row from the result set being wrapped.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.5 $ $Date: 2004/02/28 13:18:34 $
+ */
+
+public class ResultSetIterator implements DynaBean, Iterator {
+
+
+ // ------------------------------------------------------------ Constructor
+
+
+ /**
+ * <p>Construct an <code>Iterator</code> for the result set being wrapped
+ * by the specified {@link ResultSetDynaClass}.</p>
+ *
+ * @param dynaClass The {@link ResultSetDynaClass} wrapping the
+ * result set we will iterate over
+ */
+ ResultSetIterator(ResultSetDynaClass dynaClass) {
+
+ this.dynaClass = dynaClass;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+
+ /**
+ * <p>Flag indicating whether the result set is currently positioned at a
+ * row for which we have not yet returned an element in the iteration.</p>
+ */
+ protected boolean current = false;
+
+
+ /**
+ * <p>The {@link ResultSetDynaClass} we are associated with.</p>
+ */
+ protected ResultSetDynaClass dynaClass = null;
+
+
+ /**
+ * <p>Flag indicating whether the result set has indicated that there are
+ * no further rows.</p>
+ */
+ protected boolean eof = false;
+
+
+ // ------------------------------------------------------- DynaBean Methods
+
+
+ /**
+ * Does the specified mapped property contain a value for the specified
+ * key value?
+ *
+ * @param name Name of the property to check
+ * @param key Name of the key to check
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public boolean contains(String name, String key) {
+
+ throw new UnsupportedOperationException
+ ("FIXME - mapped properties not currently supported");
+
+ }
+
+
+ /**
+ * Return the value of a simple property with the specified name.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public Object get(String name) {
+
+ if (dynaClass.getDynaProperty(name) == null) {
+ throw new IllegalArgumentException(name);
+ }
+ try {
+ return (dynaClass.getResultSet().getObject(name));
+ } catch (SQLException e) {
+ throw new RuntimeException
+ ("get(" + name + "): SQLException: " + e);
+ }
+
+ }
+
+
+ /**
+ * Return the value of an indexed property with the specified name.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ * @param index Index of the value to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not indexed
+ * @exception IndexOutOfBoundsException if the specified index
+ * is outside the range of the underlying property
+ * @exception NullPointerException if no array or List has been
+ * initialized for this property
+ */
+ public Object get(String name, int index) {
+
+ throw new UnsupportedOperationException
+ ("FIXME - indexed properties not currently supported");
+
+ }
+
+
+ /**
+ * Return the value of a mapped property with the specified name,
+ * or <code>null</code> if there is no value for the specified key.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ * @param key Key of the value to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not mapped
+ */
+ public Object get(String name, String key) {
+
+ throw new UnsupportedOperationException
+ ("FIXME - mapped properties not currently supported");
+
+ }
+
+
+ /**
+ * Return the <code>DynaClass</code> instance that describes the set of
+ * properties available for this DynaBean.
+ */
+ public DynaClass getDynaClass() {
+
+ return (this.dynaClass);
+
+ }
+
+
+ /**
+ * Remove any existing value for the specified key on the
+ * specified mapped property.
+ *
+ * @param name Name of the property for which a value is to
+ * be removed
+ * @param key Key of the value to be removed
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public void remove(String name, String key) {
+
+ throw new UnsupportedOperationException
+ ("FIXME - mapped operations not currently supported");
+
+ }
+
+
+ /**
+ * Set the value of a simple property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception NullPointerException if an attempt is made to set a
+ * primitive property to null
+ */
+ public void set(String name, Object value) {
+
+ if (dynaClass.getDynaProperty(name) == null) {
+ throw new IllegalArgumentException(name);
+ }
+ try {
+ dynaClass.getResultSet().updateObject(name, value);
+ } catch (SQLException e) {
+ throw new RuntimeException
+ ("set(" + name + "): SQLException: " + e);
+ }
+
+ }
+
+
+ /**
+ * Set the value of an indexed property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param index Index of the property to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not indexed
+ * @exception IndexOutOfBoundsException if the specified index
+ * is outside the range of the underlying property
+ */
+ public void set(String name, int index, Object value) {
+
+ throw new UnsupportedOperationException
+ ("FIXME - indexed properties not currently supported");
+
+ }
+
+
+ /**
+ * Set the value of a mapped property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param key Key of the property to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not mapped
+ */
+ public void set(String name, String key, Object value) {
+
+ throw new UnsupportedOperationException
+ ("FIXME - mapped properties not currently supported");
+
+ }
+
+
+ // ------------------------------------------------------- Iterator Methods
+
+
+ /**
+ * <p>Return <code>true</code> if the iteration has more elements.</p>
+ */
+ public boolean hasNext() {
+
+ try {
+ advance();
+ return (!eof);
+ } catch (SQLException e) {
+ throw new RuntimeException("hasNext(): SQLException: " + e);
+ }
+
+ }
+
+
+ /**
+ * <p>Return the next element in the iteration.</p>
+ */
+ public Object next() {
+
+ try {
+ advance();
+ if (eof) {
+ throw new NoSuchElementException();
+ }
+ current = false;
+ return (this);
+ } catch (SQLException e) {
+ throw new RuntimeException("next(): SQLException: " + e);
+ }
+
+ }
+
+
+ /**
+ * <p>Remove the current element from the iteration. This method is
+ * not supported.</p>
+ */
+ public void remove() {
+
+ throw new UnsupportedOperationException("remove()");
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * <p>Advance the result set to the next row, if there is not a current
+ * row (and if we are not already at eof).</p>
+ *
+ * @exception SQLException if the result set throws an exception
+ */
+ protected void advance() throws SQLException {
+
+ if (!current && !eof) {
+ if (dynaClass.getResultSet().next()) {
+ current = true;
+ eof = false;
+ } else {
+ current = false;
+ eof = true;
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/RowSetDynaClass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/RowSetDynaClass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/RowSetDynaClass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.io.Serializable;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * <p>Implementation of {@link DynaClass} that creates an in-memory collection
+ * of {@link DynaBean}s representing the results of an SQL query. Once the
+ * {@link DynaClass} instance has been created, the JDBC <code>ResultSet</code>
+ * and <code>Statement</code> on which it is based can be closed, and the
+ * underlying <code>Connection</code> can be returned to its connection pool
+ * (if you are using one).</p>
+ *
+ * <p>The normal usage pattern is something like:</p>
+ * <pre>
+ * Connection conn = ...; // Acquire connection from pool
+ * Statement stmt = conn.createStatement();
+ * ResultSet rs = stmt.executeQuery("SELECT ...");
+ * RowSetDynaClass rsdc = new RowSetDynaClass(rs);
+ * rs.close();
+ * stmt.close();
+ * ...; // Return connection to pool
+ * List rows = rsdc.getRows();
+ * ...; // Process the rows as desired
+ * </pre>
+ *
+ * <p>Each column in the result set will be represented as a {@link DynaBean}
+ * property of the corresponding name (optionally forced to lower case
+ * for portability). There will be one {@link DynaBean} in the
+ * <code>List</code> returned by <code>getRows()</code> for each
+ * row in the original <code>ResultSet</code>.</p>
+ *
+ * <p>In general, instances of {@link RowSetDynaClass} can be serialized
+ * and deserialized, which will automatically include the list of
+ * {@link DynaBean}s representing the data content. The only exception
+ * to this rule would be when the underlying property values that were
+ * copied from the <code>ResultSet</code> originally cannot themselves
+ * be serialized. Therefore, a {@link RowSetDynaClass} makes a very
+ * convenient mechanism for transporting data sets to remote Java-based
+ * application components.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.9 $ $Date: 2004/02/28 13:18:34 $
+ */
+
+public class RowSetDynaClass extends JDBCDynaClass implements DynaClass, Serializable {
+
+
+ // ----------------------------------------------------- Instance variables
+
+ /**
+ * <p>Limits the size of the returned list. The call to
+ * <code>getRows()</code> will return at most limit number of rows.
+ * If less than or equal to 0, does not limit the size of the result.
+ */
+ protected int limit = -1;
+
+ /**
+ * <p>The list of {@link DynaBean}s representing the contents of
+ * the original <code>ResultSet</code> on which this
+ * {@link RowSetDynaClass} was based.</p>
+ */
+ protected List rows = new ArrayList();
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * <p>Construct a new {@link RowSetDynaClass} for the specified
+ * <code>ResultSet</code>. The property names corresponding
+ * to column names in the result set will be lower cased.</p>
+ *
+ * @param resultSet The result set to be wrapped
+ *
+ * @exception NullPointerException if <code>resultSet</code>
+ * is <code>null</code>
+ * @exception SQLException if the metadata for this result set
+ * cannot be introspected
+ */
+ public RowSetDynaClass(ResultSet resultSet) throws SQLException {
+
+ this(resultSet, true, -1);
+
+ }
+
+ /**
+ * <p>Construct a new {@link RowSetDynaClass} for the specified
+ * <code>ResultSet</code>. The property names corresponding
+ * to column names in the result set will be lower cased.</p>
+ *
+ * If <code>limit</code> is not less than 0, max <code>limit</code>
+ * number of rows will be copied into the list.
+ *
+ * @param resultSet The result set to be wrapped
+ * @param limit The maximum for the size of the result.
+ *
+ * @exception NullPointerException if <code>resultSet</code>
+ * is <code>null</code>
+ * @exception SQLException if the metadata for this result set
+ * cannot be introspected
+ */
+ public RowSetDynaClass(ResultSet resultSet, int limit) throws SQLException {
+
+ this(resultSet, true, limit);
+
+ }
+
+
+ /**
+ * <p>Construct a new {@link RowSetDynaClass} for the specified
+ * <code>ResultSet</code>. The property names corresponding
+ * to the column names in the result set will be lower cased or not,
+ * depending on the specified <code>lowerCase</code> value.</p>
+ *
+ * If <code>limit</code> is not less than 0, max <code>limit</code>
+ * number of rows will be copied into the resultset.
+ *
+ *
+ * @param resultSet The result set to be wrapped
+ * @param lowerCase Should property names be lower cased?
+ *
+ * @exception NullPointerException if <code>resultSet</code>
+ * is <code>null</code>
+ * @exception SQLException if the metadata for this result set
+ * cannot be introspected
+ */
+ public RowSetDynaClass(ResultSet resultSet, boolean lowerCase)
+ throws SQLException {
+ this(resultSet, lowerCase, -1);
+
+ }
+
+ /**
+ * <p>Construct a new {@link RowSetDynaClass} for the specified
+ * <code>ResultSet</code>. The property names corresponding
+ * to the column names in the result set will be lower cased or not,
+ * depending on the specified <code>lowerCase</code> value.</p>
+ *
+ * <p><strong>WARNING</strong> - If you specify <code>false</code>
+ * for <code>lowerCase</code>, the returned property names will
+ * exactly match the column names returned by your JDBC driver.
+ * Because different drivers might return column names in different
+ * cases, the property names seen by your application will vary
+ * depending on which JDBC driver you are using.</p>
+ *
+ * @param resultSet The result set to be wrapped
+ * @param lowerCase Should property names be lower cased?
+ *
+ * @exception NullPointerException if <code>resultSet</code>
+ * is <code>null</code>
+ * @exception SQLException if the metadata for this result set
+ * cannot be introspected
+ */
+ public RowSetDynaClass(ResultSet resultSet, boolean lowerCase, int limit)
+ throws SQLException {
+
+ if (resultSet == null) {
+ throw new NullPointerException();
+ }
+ this.lowerCase = lowerCase;
+ this.limit = limit;
+ introspect(resultSet);
+ copy(resultSet);
+
+ }
+
+ /**
+ * <p>Return a <code>List</code> containing the {@link DynaBean}s that
+ * represent the contents of each <code>Row</code> from the
+ * <code>ResultSet</code> that was the basis of this
+ * {@link RowSetDynaClass} instance. These {@link DynaBean}s are
+ * disconnected from the database itself, so there is no problem with
+ * modifying the contents of the list, or the values of the properties
+ * of these {@link DynaBean}s. However, it is the application's
+ * responsibility to persist any such changes back to the database,
+ * if it so desires.</p>
+ */
+ public List getRows() {
+
+ return (this.rows);
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * <p>Copy the column values for each row in the specified
+ * <code>ResultSet</code> into a newly created {@link DynaBean}, and add
+ * this bean to the list of {@link DynaBean}s that will later by
+ * returned by a call to <code>getRows()</code>.</p>
+ *
+ * @param resultSet The <code>ResultSet</code> whose data is to be
+ * copied
+ *
+ * @exception SQLException if an error is encountered copying the data
+ */
+ protected void copy(ResultSet resultSet) throws SQLException {
+
+ int cnt = 0;
+ while (resultSet.next() && (limit < 0 || cnt++ < limit) ) {
+ DynaBean bean = createDynaBean();
+ for (int i = 0; i < properties.length; i++) {
+ String name = properties[i].getName();
+ bean.set(name, resultSet.getObject(name));
+ }
+ rows.add(bean);
+ }
+
+ }
+
+
+ /**
+ * <p>Create and return a new {@link DynaBean} instance to be used for
+ * representing a row in the underlying result set.</p>
+ */
+ protected DynaBean createDynaBean() {
+
+ return (new BasicDynaBean(this));
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/WrapDynaBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/WrapDynaBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/WrapDynaBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+
+
+
+/**
+ * <p>Implementation of <code>DynaBean</code> that wraps a standard JavaBean
+ * instance, so that DynaBean APIs can be used to access its properties.</p>
+ *
+ * <p>
+ * The most common use cases for this class involve wrapping an existing java bean.
+ * (This makes it different from the typical use cases for other <code>DynaBean</code>'s.)
+ * For example:
+ * </p>
+ * <code><pre>
+ * Object aJavaBean = ...;
+ * ...
+ * DynaBean db = new WrapDynaBean(aJavaBean);
+ * ...
+ * </pre></code>
+ *
+ * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does not
+ * support the <code>contains()</code> and <code>remove()</code> methods.</p>
+ *
+ * @author Craig McClanahan
+ * @version $Revision: 1.9 $ $Date: 2004/02/28 13:18:34 $
+ */
+
+public class WrapDynaBean implements DynaBean {
+
+
+ // ---------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new <code>DynaBean</code> associated with the specified
+ * JavaBean instance.
+ *
+ * @param instance JavaBean instance to be wrapped
+ */
+ public WrapDynaBean(Object instance) {
+
+ super();
+ this.instance = instance;
+ this.dynaClass = WrapDynaClass.createDynaClass(instance.getClass());
+
+ }
+
+
+ // ---------------------------------------------------- Instance Variables
+
+
+ /**
+ * The <code>DynaClass</code> "base class" that this DynaBean
+ * is associated with.
+ */
+ protected WrapDynaClass dynaClass = null;
+
+
+ /**
+ * The JavaBean instance wrapped by this WrapDynaBean.
+ */
+ protected Object instance = null;
+
+
+ // ------------------------------------------------------ DynaBean Methods
+
+
+ /**
+ * Does the specified mapped property contain a value for the specified
+ * key value?
+ *
+ * @param name Name of the property to check
+ * @param key Name of the key to check
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public boolean contains(String name, String key) {
+
+ throw new UnsupportedOperationException
+ ("WrapDynaBean does not support contains()");
+
+ }
+
+
+ /**
+ * Return the value of a simple property with the specified name.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public Object get(String name) {
+
+ Object value = null;
+ try {
+ value = PropertyUtils.getSimpleProperty(instance, name);
+ } catch (Throwable t) {
+ throw new IllegalArgumentException
+ ("Property '" + name + "' has no read method");
+ }
+ return (value);
+
+ }
+
+
+ /**
+ * Return the value of an indexed property with the specified name.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ * @param index Index of the value to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not indexed
+ * @exception IndexOutOfBoundsException if the specified index
+ * is outside the range of the underlying property
+ * @exception NullPointerException if no array or List has been
+ * initialized for this property
+ */
+ public Object get(String name, int index) {
+
+ Object value = null;
+ try {
+ value = PropertyUtils.getIndexedProperty(instance, name, index);
+ } catch (IndexOutOfBoundsException e) {
+ throw e;
+ } catch (Throwable t) {
+ throw new IllegalArgumentException
+ ("Property '" + name + "' has no indexed read method");
+ }
+ return (value);
+
+ }
+
+
+ /**
+ * Return the value of a mapped property with the specified name,
+ * or <code>null</code> if there is no value for the specified key.
+ *
+ * @param name Name of the property whose value is to be retrieved
+ * @param key Key of the value to be retrieved
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not mapped
+ */
+ public Object get(String name, String key) {
+
+ Object value = null;
+ try {
+ value = PropertyUtils.getMappedProperty(instance, name, key);
+ } catch (Throwable t) {
+ throw new IllegalArgumentException
+ ("Property '" + name + "' has no mapped read method");
+ }
+ return (value);
+
+ }
+
+
+ /**
+ * Return the <code>DynaClass</code> instance that describes the set of
+ * properties available for this DynaBean.
+ */
+ public DynaClass getDynaClass() {
+
+ return (this.dynaClass);
+
+ }
+
+
+ /**
+ * Remove any existing value for the specified key on the
+ * specified mapped property.
+ *
+ * @param name Name of the property for which a value is to
+ * be removed
+ * @param key Key of the value to be removed
+ *
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ */
+ public void remove(String name, String key) {
+
+
+ throw new UnsupportedOperationException
+ ("WrapDynaBean does not support remove()");
+
+ }
+
+
+ /**
+ * Set the value of a simple property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception NullPointerException if an attempt is made to set a
+ * primitive property to null
+ */
+ public void set(String name, Object value) {
+
+ try {
+ PropertyUtils.setSimpleProperty(instance, name, value);
+ } catch (Throwable t) {
+ throw new IllegalArgumentException
+ ("Property '" + name + "' has no write method");
+ }
+
+ }
+
+
+ /**
+ * Set the value of an indexed property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param index Index of the property to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not indexed
+ * @exception IndexOutOfBoundsException if the specified index
+ * is outside the range of the underlying property
+ */
+ public void set(String name, int index, Object value) {
+
+ try {
+ PropertyUtils.setIndexedProperty(instance, name, index, value);
+ } catch (IndexOutOfBoundsException e) {
+ throw e;
+ } catch (Throwable t) {
+ throw new IllegalArgumentException
+ ("Property '" + name + "' has no indexed write method");
+ }
+
+ }
+
+
+ /**
+ * Set the value of a mapped property with the specified name.
+ *
+ * @param name Name of the property whose value is to be set
+ * @param key Key of the property to be set
+ * @param value Value to which this property is to be set
+ *
+ * @exception ConversionException if the specified value cannot be
+ * converted to the type required for this property
+ * @exception IllegalArgumentException if there is no property
+ * of the specified name
+ * @exception IllegalArgumentException if the specified property
+ * exists, but is not mapped
+ */
+ public void set(String name, String key, Object value) {
+
+ try {
+ PropertyUtils.setMappedProperty(instance, name, key, value);
+ } catch (Throwable t) {
+ throw new IllegalArgumentException
+ ("Property '" + name + "' has no mapped write method");
+ }
+
+ }
+
+ /**
+ * Gets the bean instance wrapped by this DynaBean.
+ * For most common use cases,
+ * this object should already be known
+ * and this method safely be ignored.
+ * But some creators of frameworks using <code>DynaBean</code>'s may
+ * find this useful.
+ *
+ * @return the java bean Object wrapped by this <code>DynaBean</code>
+ */
+ public Object getInstance() {
+ return instance;
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Return the property descriptor for the specified property name.
+ *
+ * @param name Name of the property for which to retrieve the descriptor
+ *
+ * @exception IllegalArgumentException if this is not a valid property
+ * name for our DynaClass
+ */
+ protected DynaProperty getDynaProperty(String name) {
+
+ DynaProperty descriptor = getDynaClass().getDynaProperty(name);
+ if (descriptor == null) {
+ throw new IllegalArgumentException
+ ("Invalid property name '" + name + "'");
+ }
+ return (descriptor);
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/WrapDynaClass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/WrapDynaClass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/WrapDynaClass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+import java.beans.PropertyDescriptor;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+
+/**
+ * <p>Implementation of <code>DynaClass</code> for DynaBeans that wrap
+ * standard JavaBean instances.</p>
+ *
+ * <p>
+ * It is suggested that this class should not usually need to be used directly
+ * to create new <code>WrapDynaBean</code> instances.
+ * It's usually better to call the <code>WrapDynaBean</code> constructor directly.
+ * For example:</p>
+ * <code><pre>
+ * Object javaBean = ...;
+ * DynaBean wrapper = new WrapDynaBean(javaBean);
+ * </pre></code>
+ * <p>
+ *
+ * @author Craig McClanahan
+ * @version $Revision: 1.8 $ $Date: 2004/02/28 13:18:34 $
+ */
+
+public class WrapDynaClass implements DynaClass {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new WrapDynaClass for the specified JavaBean class. This
+ * constructor is private; WrapDynaClass instances will be created as
+ * needed via calls to the <code>createDynaClass(Class)</code> method.
+ *
+ * @param beanClass JavaBean class to be introspected around
+ */
+ private WrapDynaClass(Class beanClass) {
+
+ this.beanClass = beanClass;
+ introspect();
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The JavaBean <code>Class</code> which is represented by this
+ * <code>WrapDynaClass</code>.
+ */
+ protected Class beanClass = null;
+
+
+ /**
+ * The set of PropertyDescriptors for this bean class.
+ */
+ protected PropertyDescriptor descriptors[] = null;
+
+
+ /**
+ * The set of PropertyDescriptors for this bean class, keyed by the
+ * property name. Individual descriptor instances will be the same
+ * instances as those in the <code>descriptors</code> list.
+ */
+ protected HashMap descriptorsMap = new HashMap();
+
+
+ /**
+ * The set of dynamic properties that are part of this DynaClass.
+ */
+ protected DynaProperty properties[] = null;
+
+
+ /**
+ * The set of dynamic properties that are part of this DynaClass,
+ * keyed by the property name. Individual descriptor instances will
+ * be the same instances as those in the <code>properties</code> list.
+ */
+ protected HashMap propertiesMap = new HashMap();
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * The set of <code>WrapDynaClass</code> instances that have ever been
+ * created, keyed by the underlying bean Class.
+ */
+ protected static HashMap dynaClasses = new HashMap();
+
+
+ // ------------------------------------------------------ DynaClass Methods
+
+
+ /**
+ * Return the name of this DynaClass (analogous to the
+ * <code>getName()</code> method of <code>java.lang.Class</code), which
+ * allows the same <code>DynaClass</code> implementation class to support
+ * different dynamic classes, with different sets of properties.
+ */
+ public String getName() {
+
+ return (this.beanClass.getName());
+
+ }
+
+
+ /**
+ * Return a property descriptor for the specified property, if it exists;
+ * otherwise, return <code>null</code>.
+ *
+ * @param name Name of the dynamic property for which a descriptor
+ * is requested
+ *
+ * @exception IllegalArgumentException if no property name is specified
+ */
+ public DynaProperty getDynaProperty(String name) {
+
+ if (name == null) {
+ throw new IllegalArgumentException
+ ("No property name specified");
+ }
+ return ((DynaProperty) propertiesMap.get(name));
+
+ }
+
+
+ /**
+ * <p>Return an array of <code>ProperyDescriptors</code> for the properties
+ * currently defined in this DynaClass. If no properties are defined, a
+ * zero-length array will be returned.</p>
+ *
+ * <p><strong>FIXME</strong> - Should we really be implementing
+ * <code>getBeanInfo()</code> instead, which returns property descriptors
+ * and a bunch of other stuff?</p>
+ */
+ public DynaProperty[] getDynaProperties() {
+
+ return (properties);
+
+ }
+
+
+ /**
+ * <p>Instantiates a new standard JavaBean instance associated with
+ * this DynaClass and return it wrapped in a new WrapDynaBean
+ * instance. <strong>NOTE</strong> the JavaBean should have a
+ * no argument constructor.</p>
+ *
+ * <strong>NOTE</strong> - Most common use cases should not need to use
+ * this method. It is usually better to create new
+ * <code>WrapDynaBean</code> instances by calling its constructor.
+ * For example:</p>
+ * <code><pre>
+ * Object javaBean = ...;
+ * DynaBean wrapper = new WrapDynaBean(javaBean);
+ * </pre></code>
+ * <p>
+ * (This method is needed for some kinds of <code>DynaBean</code> framework.)
+ * </p>
+ *
+ * @exception IllegalAccessException if the Class or the appropriate
+ * constructor is not accessible
+ * @exception InstantiationException if this Class represents an abstract
+ * class, an array class, a primitive type, or void; or if instantiation
+ * fails for some other reason
+ */
+ public DynaBean newInstance()
+ throws IllegalAccessException, InstantiationException {
+
+ return new WrapDynaBean(beanClass.newInstance());
+
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Return the PropertyDescriptor for the specified property name, if any;
+ * otherwise return <code>null</code>.
+ *
+ * @param name Name of the property to be retrieved
+ */
+ public PropertyDescriptor getPropertyDescriptor(String name) {
+
+ return ((PropertyDescriptor) descriptorsMap.get(name));
+
+ }
+
+
+ // --------------------------------------------------------- Static Methods
+
+
+ /**
+ * Clear our cache of WrapDynaClass instances.
+ */
+ public static void clear() {
+
+ synchronized (dynaClasses) {
+ dynaClasses.clear();
+ }
+
+ }
+
+
+ /**
+ * Create (if necessary) and return a new <code>WrapDynaClass</code>
+ * instance for the specified bean class.
+ *
+ * @param beanClass Bean class for which a WrapDynaClass is requested
+ */
+ public static WrapDynaClass createDynaClass(Class beanClass) {
+
+ synchronized (dynaClasses) {
+ WrapDynaClass dynaClass =
+ (WrapDynaClass) dynaClasses.get(beanClass);
+ if (dynaClass == null) {
+ dynaClass = new WrapDynaClass(beanClass);
+ dynaClasses.put(beanClass, dynaClass);
+ }
+ return (dynaClass);
+ }
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Introspect our bean class to identify the supported properties.
+ */
+ protected void introspect() {
+
+ // Look up the property descriptors for this bean class
+ PropertyDescriptor regulars[] =
+ PropertyUtils.getPropertyDescriptors(beanClass);
+ if (regulars == null) {
+ regulars = new PropertyDescriptor[0];
+ }
+ HashMap mappeds =
+ PropertyUtils.getMappedPropertyDescriptors(beanClass);
+ if (mappeds == null) {
+ mappeds = new HashMap();
+ }
+
+ // Construct corresponding DynaProperty information
+ properties = new DynaProperty[regulars.length + mappeds.size()];
+ for (int i = 0; i < regulars.length; i++) {
+ descriptorsMap.put(regulars[i].getName(),
+ regulars[i]);
+ properties[i] =
+ new DynaProperty(regulars[i].getName(),
+ regulars[i].getPropertyType());
+ propertiesMap.put(properties[i].getName(),
+ properties[i]);
+ }
+ int j = regulars.length;
+ Iterator names = mappeds.keySet().iterator();
+ while (names.hasNext()) {
+ String name = (String) names.next();
+ PropertyDescriptor descriptor =
+ (PropertyDescriptor) mappeds.get(name);
+ properties[j] =
+ new DynaProperty(descriptor.getName(),
+ Map.class);
+ propertiesMap.put(properties[j].getName(),
+ properties[j]);
+ j++;
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/AbstractArrayConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/AbstractArrayConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/AbstractArrayConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.io.IOException;
+import java.io.StreamTokenizer;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+
+/**
+ * <p>Convenience base class for converters that translate the String
+ * representation of an array into a corresponding array of primitives
+ * object. This class encapsulates the functionality required to parse
+ * the String into a list of String elements that can later be
+ * individually converted to the appropriate primitive type.</p>
+ *
+ * <p>The input syntax accepted by the <code>parseElements()</code> method
+ * is designed to be compatible with the syntax used to initialize arrays
+ * in a Java source program, except that only String literal values are
+ * supported. For maximum flexibility, the surrounding '{' and '}'
+ * characters are optional, and individual elements may be separated by
+ * any combination of whitespace and comma characters.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.6 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public abstract class AbstractArrayConverter implements Converter {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ protected Object defaultValue = null;
+
+
+ /**
+ * <p>Model object for string arrays.</p>
+ */
+ protected static String strings[] = new String[0];
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ protected boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type. This method must be implemented by a concrete
+ * subclass.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public abstract Object convert(Class type, Object value);
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * <p>Parse an incoming String of the form similar to an array initializer
+ * in the Java language into a <code>List</code> individual Strings
+ * for each element, according to the following rules.</p>
+ * <ul>
+ * <li>The string must have matching '{' and '}' delimiters around
+ * a comma-delimited list of values.</li>
+ * <li>Whitespace before and after each element is stripped.
+ * <li>If an element is itself delimited by matching single or double
+ * quotes, the usual rules for interpreting a quoted String apply.</li>
+ * </ul>
+ *
+ * @param svalue String value to be parsed
+ *
+ * @exception ConversionException if the syntax of <code>svalue</code>
+ * is not syntactically valid
+ * @exception NullPointerException if <code>svalue</code>
+ * is <code>null</code>
+ */
+ protected List parseElements(String svalue) {
+
+ // Validate the passed argument
+ if (svalue == null) {
+ throw new NullPointerException();
+ }
+
+ // Trim any matching '{' and '}' delimiters
+ svalue = svalue.trim();
+ if (svalue.startsWith("{") && svalue.endsWith("}")) {
+ svalue = svalue.substring(1, svalue.length() - 1);
+ }
+
+ try {
+
+ // Set up a StreamTokenizer on the characters in this String
+ StreamTokenizer st =
+ new StreamTokenizer(new StringReader(svalue));
+ st.whitespaceChars(',',','); // Commas are delimiters
+ st.ordinaryChars('0', '9'); // Needed to turn off numeric flag
+ st.ordinaryChars('.', '.');
+ st.ordinaryChars('-', '-');
+ st.wordChars('0', '9'); // Needed to make part of tokens
+ st.wordChars('.', '.');
+ st.wordChars('-', '-');
+
+ // Split comma-delimited tokens into a List
+ ArrayList list = new ArrayList();
+ while (true) {
+ int ttype = st.nextToken();
+ if ((ttype == StreamTokenizer.TT_WORD) ||
+ (ttype > 0)) {
+ list.add(st.sval);
+ } else if (ttype == StreamTokenizer.TT_EOF) {
+ break;
+ } else {
+ throw new ConversionException
+ ("Encountered token of type " + ttype);
+ }
+ }
+
+ // Return the completed list
+ return (list);
+
+ } catch (IOException e) {
+
+ throw new ConversionException(e);
+
+ }
+
+
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BigDecimalConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BigDecimalConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BigDecimalConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.math.BigDecimal;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.math.BigDecimal</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class BigDecimalConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public BigDecimalConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public BigDecimalConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof BigDecimal) {
+ return (value);
+ }
+
+ try {
+ return (new BigDecimal(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BigIntegerConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BigIntegerConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BigIntegerConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.math.BigInteger;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.math.BigInteger</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class BigIntegerConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public BigIntegerConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public BigIntegerConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof BigInteger) {
+ return (value);
+ }
+
+ try {
+ return (new BigInteger(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BooleanArrayConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BooleanArrayConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BooleanArrayConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.util.List;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a primitive array of boolean. On a conversion failure, returns
+ * a specified default value or throws a {@link ConversionException} depending
+ * on how this instance is constructed.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public final class BooleanArrayConverter extends AbstractArrayConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public BooleanArrayConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public BooleanArrayConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * <p>Model object for type comparisons.</p>
+ */
+ private static boolean model[] = new boolean[0];
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ // Deal with a null value
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ // Deal with the no-conversion-needed case
+ if (model.getClass() == value.getClass()) {
+ return (value);
+ }
+
+ // Deal with input value as a String array
+ if (strings.getClass() == value.getClass()) {
+ try {
+ String values[] = (String[]) value;
+ boolean results[] = new boolean[values.length];
+ for (int i = 0; i < values.length; i++) {
+ String stringValue = values[i];
+ if (stringValue.equalsIgnoreCase("yes") ||
+ stringValue.equalsIgnoreCase("y") ||
+ stringValue.equalsIgnoreCase("true") ||
+ stringValue.equalsIgnoreCase("on") ||
+ stringValue.equalsIgnoreCase("1")) {
+ results[i] = true;
+ } else if (stringValue.equalsIgnoreCase("no") ||
+ stringValue.equalsIgnoreCase("n") ||
+ stringValue.equalsIgnoreCase("false") ||
+ stringValue.equalsIgnoreCase("off") ||
+ stringValue.equalsIgnoreCase("0")) {
+ results[i] = false;
+ } else {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString());
+ }
+ }
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+ }
+
+ // Parse the input value as a String into elements
+ // and convert to the appropriate type
+ try {
+ List list = parseElements(value.toString());
+ boolean results[] = new boolean[list.size()];
+ for (int i = 0; i < results.length; i++) {
+ String stringValue = (String) list.get(i);
+ if (stringValue.equalsIgnoreCase("yes") ||
+ stringValue.equalsIgnoreCase("y") ||
+ stringValue.equalsIgnoreCase("true") ||
+ stringValue.equalsIgnoreCase("on") ||
+ stringValue.equalsIgnoreCase("1")) {
+ results[i] = true;
+ } else if (stringValue.equalsIgnoreCase("no") ||
+ stringValue.equalsIgnoreCase("n") ||
+ stringValue.equalsIgnoreCase("false") ||
+ stringValue.equalsIgnoreCase("off") ||
+ stringValue.equalsIgnoreCase("0")) {
+ results[i] = false;
+ } else {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString());
+ }
+ }
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BooleanConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BooleanConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/BooleanConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.lang.Boolean</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.9 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class BooleanConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public BooleanConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public BooleanConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Boolean) {
+ return (value);
+ }
+
+ try {
+ String stringValue = value.toString();
+ if (stringValue.equalsIgnoreCase("yes") ||
+ stringValue.equalsIgnoreCase("y") ||
+ stringValue.equalsIgnoreCase("true") ||
+ stringValue.equalsIgnoreCase("on") ||
+ stringValue.equalsIgnoreCase("1")) {
+ return (Boolean.TRUE);
+ } else if (stringValue.equalsIgnoreCase("no") ||
+ stringValue.equalsIgnoreCase("n") ||
+ stringValue.equalsIgnoreCase("false") ||
+ stringValue.equalsIgnoreCase("off") ||
+ stringValue.equalsIgnoreCase("0")) {
+ return (Boolean.FALSE);
+ } else if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(stringValue);
+ }
+ } catch (ClassCastException e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ByteArrayConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ByteArrayConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ByteArrayConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.util.List;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a primitive array of byte. On a conversion failure, returns
+ * a specified default value or throws a {@link ConversionException} depending
+ * on how this instance is constructed.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public final class ByteArrayConverter extends AbstractArrayConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public ByteArrayConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public ByteArrayConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * <p>Model object for type comparisons.</p>
+ */
+ private static byte model[] = new byte[0];
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ // Deal with a null value
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ // Deal with the no-conversion-needed case
+ if (model.getClass() == value.getClass()) {
+ return (value);
+ }
+
+ // Deal with input value as a String array
+ if (strings.getClass() == value.getClass()) {
+ try {
+ String values[] = (String[]) value;
+ byte results[] = new byte[values.length];
+ for (int i = 0; i < values.length; i++) {
+ results[i] = Byte.parseByte(values[i]);
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+ }
+
+ // Parse the input value as a String into elements
+ // and convert to the appropriate type
+ try {
+ List list = parseElements(value.toString());
+ byte results[] = new byte[list.size()];
+ for (int i = 0; i < results.length; i++) {
+ results[i] = Byte.parseByte((String) list.get(i));
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ByteConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ByteConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ByteConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.lang.Byte</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.9 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class ByteConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public ByteConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public ByteConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ // System.err.println("VALUE=" + value + ", TYPE=" + value.getClass().getName());
+
+ if (value instanceof Byte) {
+ return (value);
+ } else if (value instanceof Number) {
+ return new Byte(((Number)value).byteValue());
+ }
+
+ try {
+ return (new Byte(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/CharacterArrayConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/CharacterArrayConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/CharacterArrayConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.util.List;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a primitive array of char. On a conversion failure, returns
+ * a specified default value or throws a {@link ConversionException} depending
+ * on how this instance is constructed.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public final class CharacterArrayConverter extends AbstractArrayConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public CharacterArrayConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public CharacterArrayConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * <p>Model object for type comparisons.</p>
+ */
+ private static char model[] = new char[0];
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ // Deal with a null value
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ // Deal with the no-conversion-needed case
+ if (model.getClass() == value.getClass()) {
+ return (value);
+ }
+
+ // Deal with input value as a String array
+ if (strings.getClass() == value.getClass()) {
+ try {
+ String values[] = (String[]) value;
+ char results[] = new char[values.length];
+ for (int i = 0; i < values.length; i++) {
+ results[i] = values[i].charAt(0);
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+ }
+
+ // Parse the input value as a String into elements
+ // and convert to the appropriate type
+ try {
+ List list = parseElements(value.toString());
+ char results[] = new char[list.size()];
+ for (int i = 0; i < results.length; i++) {
+ results[i] = ((String) list.get(i)).charAt(0);
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/CharacterConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/CharacterConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/CharacterConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.lang.Character</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class CharacterConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public CharacterConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public CharacterConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Character) {
+ return (value);
+ }
+
+ try {
+ return (new Character(value.toString().charAt(0)));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ClassConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ClassConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ClassConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.lang.Class</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs. The class will be loaded from the thread context class
+ * loader (if it exists); otherwise the class loader that loaded this class
+ * will be used.</p>
+ *
+ * @author Tomas Viberg
+ * @version $Revision: 1.6 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public final class ClassConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public ClassConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public ClassConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Class) {
+ return (value);
+ }
+
+ try {
+ ClassLoader classLoader =
+ Thread.currentThread().getContextClassLoader();
+ if (classLoader == null) {
+ classLoader = ClassConverter.class.getClassLoader();
+ }
+ return (classLoader.loadClass(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/DoubleArrayConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/DoubleArrayConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/DoubleArrayConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.util.List;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a primitive array of double. On a conversion failure, returns
+ * a specified default value or throws a {@link ConversionException} depending
+ * on how this instance is constructed.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public final class DoubleArrayConverter extends AbstractArrayConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public DoubleArrayConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public DoubleArrayConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * <p>Model object for type comparisons.</p>
+ */
+ private static double model[] = new double[0];
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ // Deal with a null value
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ // Deal with the no-conversion-needed case
+ if (model.getClass() == value.getClass()) {
+ return (value);
+ }
+
+ // Deal with input value as a String array
+ if (strings.getClass() == value.getClass()) {
+ try {
+ String values[] = (String[]) value;
+ double results[] = new double[values.length];
+ for (int i = 0; i < values.length; i++) {
+ results[i] = Double.parseDouble(values[i]);
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+ }
+
+ // Parse the input value as a String into elements
+ // and convert to the appropriate type
+ try {
+ List list = parseElements(value.toString());
+ double results[] = new double[list.size()];
+ for (int i = 0; i < results.length; i++) {
+ results[i] = Double.parseDouble((String) list.get(i));
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/DoubleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/DoubleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/DoubleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.lang.Double</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.8 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class DoubleConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public DoubleConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public DoubleConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Double) {
+ return (value);
+ } else if(value instanceof Number) {
+ return new Double(((Number)value).doubleValue());
+ }
+
+
+ try {
+ return (new Double(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FileConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FileConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FileConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import java.io.File;
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.io.FileL</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author James Strachan
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.6
+ */
+public final class FileConverter implements Converter {
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public FileConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public FileConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof File) {
+ return (value);
+ }
+
+ return new File(value.toString());
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FloatArrayConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FloatArrayConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FloatArrayConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.util.List;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a primitive array of float. On a conversion failure, returns
+ * a specified default value or throws a {@link ConversionException} depending
+ * on how this instance is constructed.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public final class FloatArrayConverter extends AbstractArrayConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public FloatArrayConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public FloatArrayConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * <p>Model object for type comparisons.</p>
+ */
+ private static float model[] = new float[0];
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ // Deal with a null value
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ // Deal with the no-conversion-needed case
+ if (model.getClass() == value.getClass()) {
+ return (value);
+ }
+
+ // Deal with input value as a String array
+ if (strings.getClass() == value.getClass()) {
+ try {
+ String values[] = (String[]) value;
+ float results[] = new float[values.length];
+ for (int i = 0; i < values.length; i++) {
+ results[i] = Float.parseFloat(values[i]);
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+ }
+
+ // Parse the input value as a String into elements
+ // and convert to the appropriate type
+ try {
+ List list = parseElements(value.toString());
+ float results[] = new float[list.size()];
+ for (int i = 0; i < results.length; i++) {
+ results[i] = Float.parseFloat((String) list.get(i));
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FloatConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FloatConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/FloatConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.lang.Float</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.8 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class FloatConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public FloatConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public FloatConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Float) {
+ return (value);
+ } else if(value instanceof Number) {
+ return new Float(((Number)value).floatValue());
+ }
+
+ try {
+ return (new Float(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/IntegerArrayConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/IntegerArrayConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/IntegerArrayConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.util.List;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a primitive array of int. On a conversion failure, returns
+ * a specified default value or throws a {@link ConversionException} depending
+ * on how this instance is constructed.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public final class IntegerArrayConverter extends AbstractArrayConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public IntegerArrayConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public IntegerArrayConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * <p>Model object for type comparisons.</p>
+ */
+ private static int model[] = new int[0];
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ // Deal with a null value
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ // Deal with the no-conversion-needed case
+ if (model.getClass() == value.getClass()) {
+ return (value);
+ }
+
+ // Deal with input value as a String array
+ if (strings.getClass() == value.getClass()) {
+ try {
+ String values[] = (String[]) value;
+ int results[] = new int[values.length];
+ for (int i = 0; i < values.length; i++) {
+ results[i] = Integer.parseInt(values[i]);
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+ }
+
+ // Parse the input value as a String into elements
+ // and convert to the appropriate type
+ try {
+ List list = parseElements(value.toString());
+ int results[] = new int[list.size()];
+ for (int i = 0; i < results.length; i++) {
+ results[i] = Integer.parseInt((String) list.get(i));
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/IntegerConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/IntegerConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/IntegerConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.lang.Integer</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.8 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class IntegerConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public IntegerConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public IntegerConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Integer) {
+ return (value);
+ } else if(value instanceof Number) {
+ return new Integer(((Number)value).intValue());
+ }
+
+ try {
+ return (new Integer(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/LongArrayConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/LongArrayConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/LongArrayConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.util.List;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a primitive array of long. On a conversion failure, returns
+ * a specified default value or throws a {@link ConversionException} depending
+ * on how this instance is constructed.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public final class LongArrayConverter extends AbstractArrayConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public LongArrayConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public LongArrayConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * <p>Model object for type comparisons.</p>
+ */
+ private static long model[] = new long[0];
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ // Deal with a null value
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ // Deal with the no-conversion-needed case
+ if (model.getClass() == value.getClass()) {
+ return (value);
+ }
+
+ // Deal with input value as a String array
+ if (strings.getClass() == value.getClass()) {
+ try {
+ String values[] = (String[]) value;
+ long results[] = new long[values.length];
+ for (int i = 0; i < values.length; i++) {
+ results[i] = Long.parseLong(values[i]);
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+ }
+
+ // Parse the input value as a String into elements
+ // and convert to the appropriate type
+ try {
+ List list = parseElements(value.toString());
+ long results[] = new long[list.size()];
+ for (int i = 0; i < results.length; i++) {
+ results[i] = Long.parseLong((String) list.get(i));
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/LongConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/LongConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/LongConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.lang.Long</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.8 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class LongConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public LongConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public LongConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Long) {
+ return (value);
+ } else if(value instanceof Number) {
+ return new Long(((Number)value).longValue());
+ }
+
+ try {
+ return (new Long(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ShortArrayConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ShortArrayConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ShortArrayConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.util.List;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a primitive array of short. On a conversion failure, returns
+ * a specified default value or throws a {@link ConversionException} depending
+ * on how this instance is constructed.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public final class ShortArrayConverter extends AbstractArrayConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public ShortArrayConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public ShortArrayConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * <p>Model object for type comparisons.</p>
+ */
+ private static short model[] = new short[0];
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ // Deal with a null value
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ // Deal with the no-conversion-needed case
+ if (model.getClass() == value.getClass()) {
+ return (value);
+ }
+
+ // Deal with input value as a String array
+ if (strings.getClass() == value.getClass()) {
+ try {
+ String values[] = (String[]) value;
+ short results[] = new short[values.length];
+ for (int i = 0; i < values.length; i++) {
+ results[i] = Short.parseShort(values[i]);
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+ }
+
+ // Parse the input value as a String into elements
+ // and convert to the appropriate type
+ try {
+ List list = parseElements(value.toString());
+ short results[] = new short[list.size()];
+ for (int i = 0; i < results.length; i++) {
+ results[i] = Short.parseShort((String) list.get(i));
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ShortConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ShortConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/ShortConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.lang.Short</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.8 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class ShortConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public ShortConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public ShortConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Short) {
+ return (value);
+ } else if (value instanceof Number) {
+ return new Short(((Number)value).shortValue());
+ }
+
+ try {
+ return (new Short(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlDateConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlDateConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlDateConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.sql.Date;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.sql.Date</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class SqlDateConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public SqlDateConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public SqlDateConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Date) {
+ return (value);
+ }
+
+ try {
+ return (Date.valueOf(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlTimeConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlTimeConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlTimeConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.sql.Time;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.sql.Time</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class SqlTimeConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public SqlTimeConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public SqlTimeConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Time) {
+ return (value);
+ }
+
+ try {
+ return (Time.valueOf(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlTimestampConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlTimestampConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/SqlTimestampConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.sql.Timestamp;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.sql.Timestamp</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class SqlTimestampConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public SqlTimestampConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public SqlTimestampConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof Timestamp) {
+ return (value);
+ }
+
+ try {
+ return (Timestamp.valueOf(value.toString()));
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/StringArrayConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/StringArrayConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/StringArrayConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import java.util.List;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into an array of String. On a conversion failure, returns
+ * a specified default value or throws a {@link ConversionException} depending
+ * on how this instance is constructed.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.4
+ */
+
+public final class StringArrayConverter extends AbstractArrayConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public StringArrayConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public StringArrayConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * <p>Model object for type comparisons.</p>
+ */
+ private static String model[] = new String[0];
+
+ /**
+ * <p> Model object for int arrays.</p>
+ */
+ private static int ints[] = new int[0];
+
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ // Deal with a null value
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ // Deal with the no-conversion-needed case
+ if (model.getClass() == value.getClass()) {
+ return (value);
+ }
+
+ // Deal with the input value as an int array
+ if (ints.getClass() == value.getClass())
+ {
+ int[] values = (int[]) value;
+ String[] results = new String[values.length];
+ for (int i = 0; i < values.length; i++)
+ {
+ results[i] = Integer.toString(values[i]);
+ }
+
+ return (results);
+ }
+
+ // Parse the input value as a String into elements
+ // and convert to the appropriate type
+ try {
+ List list = parseElements(value.toString());
+ String results[] = new String[list.size()];
+ for (int i = 0; i < results.length; i++) {
+ results[i] = (String) list.get(i);
+ }
+ return (results);
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(value.toString(), e);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/StringConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/StringConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/StringConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.lang.String</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.5 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class StringConverter implements Converter {
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ return ((String) null);
+ } else {
+ return (value.toString());
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/URLConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/URLConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/URLConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.converters;
+
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+import java.net.URL;
+import java.net.MalformedURLException;
+
+
+
+/**
+ * <p>Standard {@link Converter} implementation that converts an incoming
+ * String into a <code>java.net.URL</code> object, optionally using a
+ * default value or throwing a {@link ConversionException} if a conversion
+ * error occurs.</p>
+ *
+ * @author Henri Yandell
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:34 $
+ * @since 1.3
+ */
+
+public final class URLConverter implements Converter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a {@link Converter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ */
+ public URLConverter() {
+
+ this.defaultValue = null;
+ this.useDefault = false;
+
+ }
+
+
+ /**
+ * Create a {@link Converter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public URLConverter(Object defaultValue) {
+
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The default value specified to our Constructor, if any.
+ */
+ private Object defaultValue = null;
+
+
+ /**
+ * Should we return the default value on conversion errors?
+ */
+ private boolean useDefault = true;
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Convert the specified input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException("No value specified");
+ }
+ }
+
+ if (value instanceof URL) {
+ return (value);
+ }
+
+ try {
+ return new URL(value.toString());
+ } catch(MalformedURLException murle) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(murle);
+ }
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/package.html
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/package.html 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/converters/package.html 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,12 @@
+<html>
+<head>
+<title>Package Documentation for org.apache.commons.beanutils.converters</title>
+</head>
+<body bgcolor="white">
+<p>Standard implementations of the
+<code>Converter</code>
+interface that are pre-registered with
+<code>ConvertUtils</code>
+at startup time.</p>
+</body>
+</html>
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/BaseLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/BaseLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/BaseLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale;
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.text.ParseException;
+import java.util.Locale;
+
+
+/**
+ * <p>The base class for all standart type locale-sensitive converters.
+ * It has {@link LocaleConverter} and {@link org.apache.commons.beanutils.Converter} implementations,
+ * that convert an incoming locale-sensitive Object into an object of correspond type,
+ * optionally using a default value or throwing a {@link ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public abstract class BaseLocaleConverter implements LocaleConverter {
+
+ // ----------------------------------------------------- Instance Variables
+
+ /** All logging goes through this logger */
+ private static Log log = LogFactory.getLog(BaseLocaleConverter.class);
+
+ /** The default value specified to our Constructor, if any. */
+ private Object defaultValue = null;
+
+ /** Should we return the default value on conversion errors? */
+ protected boolean useDefault = false;
+
+ /** The locale specified to our Constructor, by default - system locale. */
+ protected Locale locale = Locale.getDefault();
+
+ /** The default pattern specified to our Constructor, if any. */
+ protected String pattern = null;
+
+ /** The flag indicating whether the given pattern string is localized or not. */
+ protected boolean locPattern = false;
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link LocaleConverter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ * An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ protected BaseLocaleConverter(Locale locale, String pattern) {
+
+ this(null, locale, pattern, false, false);
+ }
+
+ /**
+ * Create a {@link LocaleConverter} that will throw a {@link ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ protected BaseLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ this(null, locale, pattern, false, locPattern);
+ }
+
+ /**
+ * Create a {@link LocaleConverter} that will return the specified default value
+ * if a conversion error occurs.
+ * An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ protected BaseLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link LocaleConverter} that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ protected BaseLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ this(defaultValue, locale, pattern, true, locPattern);
+ }
+
+ /**
+ * Create a {@link LocaleConverter} that will return the specified default value
+ * or throw a {@link ConversionException} if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param useDefault Indicate whether the default value is used or not
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ private BaseLocaleConverter(Object defaultValue, Locale locale,
+ String pattern, boolean useDefault, boolean locPattern) {
+
+ if (useDefault) {
+ this.defaultValue = defaultValue;
+ this.useDefault = true;
+ }
+
+ if (locale != null) {
+ this.locale = locale;
+ }
+
+ this.pattern = pattern;
+ this.locPattern = locPattern;
+ }
+
+ // --------------------------------------------------------- Methods
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+
+ abstract protected Object parse(Object value, String pattern) throws ParseException;
+
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object.
+ * The default pattern is used for the convertion.
+ *
+ * @param value The input object to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Object value) {
+ return convert(value, null);
+ }
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Object value, String pattern) {
+ return convert(null, value, pattern);
+ }
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type. The default pattern is used for the convertion.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input object to be converted
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value) {
+ return convert(type, value, null);
+ }
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value, String pattern) {
+ if (value == null) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ // symmetric beanutils function allows null
+ // so do not: throw new ConversionException("No value specified");
+ log.debug("Null value specified for conversion, returing null");
+ return null;
+ }
+ }
+
+ try {
+ if (pattern != null) {
+ return parse(value, pattern);
+ } else {
+ return parse(value, this.pattern);
+ }
+ } catch (Exception e) {
+ if (useDefault) {
+ return (defaultValue);
+ } else {
+ throw new ConversionException(e);
+ }
+ }
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/BaseLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleBeanUtils.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleBeanUtils.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleBeanUtils.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,533 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale;
+
+
+import org.apache.commons.beanutils.*;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Locale;
+
+
+/**
+ * <p>Utility methods for populating JavaBeans properties
+ * via reflection in a locale-dependent manner.</p>
+ *
+ * <p>The implementations for these methods are provided by <code>LocaleBeanUtilsBean</code>.
+ * For more details see {@link LocaleBeanUtilsBean}.</p>
+ *
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author Rey François
+ * @author Gregor Raýman
+ * @author Yauheny Mikulski
+ */
+
+public class LocaleBeanUtils extends BeanUtils {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+ /** All logging goes through this logger */
+ private static Log log = LogFactory.getLog(LocaleBeanUtils.class);
+
+ /**
+ * <p>Gets the locale used when no locale is passed.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getDefaultLocale()
+ */
+ public static Locale getDefaultLocale() {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getDefaultLocale();
+ }
+
+
+ /**
+ * <p>Sets the locale used when no locale is passed.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#setDefaultLocale(Locale)
+ */
+ public static void setDefaultLocale(Locale locale) {
+
+ LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().setDefaultLocale(locale);
+ }
+
+ /**
+ * <p>Gets whether the pattern is localized or not.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getApplyLocalized()
+ */
+ public static boolean getApplyLocalized() {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getApplyLocalized();
+ }
+
+ /**
+ * <p>Sets whether the pattern is localized or not.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#setApplyLocalized(boolean)
+ */
+ public static void setApplyLocalized(boolean newApplyLocalized) {
+
+ LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().setApplyLocalized(newApplyLocalized);
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * <p>Return the value of the specified locale-sensitive indexed property
+ * of the specified bean, as a String.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getIndexedProperty(Object, String, String)
+ */
+ public static String getIndexedProperty(Object bean, String name, String pattern)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getIndexedProperty(bean, name, pattern);
+ }
+
+ /**
+ * Return the value of the specified locale-sensitive indexed property
+ * of the specified bean, as a String using the default convertion pattern of
+ * the corresponding {@link LocaleConverter}.
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getIndexedProperty(Object, String)
+ */
+ public static String getIndexedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getIndexedProperty(bean, name);
+ }
+
+ /**
+ * <p>Return the value of the specified locale-sensetive indexed property
+ * of the specified bean, as a String using the specified convertion pattern.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getIndexedProperty(Object, String, int, String)
+ */
+ public static String getIndexedProperty(Object bean,
+ String name, int index, String pattern)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getIndexedProperty(bean, name, index, pattern);
+ }
+
+ /**
+ * <p>Return the value of the specified locale-sensetive indexed property
+ * of the specified bean, as a String using the default convertion pattern of
+ * the corresponding {@link LocaleConverter}.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getIndexedProperty(Object, String, int)
+ */
+ public static String getIndexedProperty(Object bean,
+ String name, int index)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getIndexedProperty(bean, name, index);
+ }
+
+ /**
+ * <p>Return the value of the specified simple locale-sensitive property
+ * of the specified bean, converted to a String using the specified
+ * convertion pattern.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getSimpleProperty(Object, String, String)
+ */
+ public static String getSimpleProperty(Object bean, String name, String pattern)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getSimpleProperty(bean, name, pattern);
+ }
+
+ /**
+ * <p>Return the value of the specified simple locale-sensitive property
+ * of the specified bean, converted to a String using the default
+ * convertion pattern of the corresponding {@link LocaleConverter}.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getSimpleProperty(Object, String)
+ */
+ public static String getSimpleProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getSimpleProperty(bean, name);
+ }
+
+ /**
+ * <p>Return the value of the specified mapped locale-sensitive property
+ * of the specified bean, as a String using the specified convertion pattern.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getMappedProperty(Object, String, String, String)
+ */
+ public static String getMappedProperty(Object bean,
+ String name, String key, String pattern)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getMappedProperty(bean, name, key, pattern);
+ }
+
+ /**
+ * <p>Return the value of the specified mapped locale-sensitive property
+ * of the specified bean, as a String
+ * The key is specified as a method parameter and must *not* be included
+ * in the property name expression.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getMappedProperty(Object, String, String)
+ */
+ public static String getMappedProperty(Object bean,
+ String name, String key)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getMappedProperty(bean, name, key);
+ }
+
+
+ /**
+ * <p>Return the value of the specified locale-sensitive mapped property
+ * of the specified bean, as a String using the specified pattern.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getMappedPropertyLocale(Object, String, String)
+ */
+ public static String getMappedPropertyLocale(Object bean, String name, String pattern)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getMappedPropertyLocale(bean, name, pattern);
+ }
+
+
+ /**
+ * <p>Return the value of the specified locale-sensitive mapped property
+ * of the specified bean, as a String using the default
+ * convertion pattern of the corresponding {@link LocaleConverter}.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getMappedProperty(Object, String)
+ */
+ public static String getMappedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getMappedProperty(bean, name);
+ }
+
+ /**
+ * <p>Return the value of the (possibly nested) locale-sensitive property
+ * of the specified name, for the specified bean,
+ * as a String using the specified pattern.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getNestedProperty(Object, String, String)
+ */
+ public static String getNestedProperty(Object bean, String name, String pattern)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getNestedProperty(bean, name, pattern);
+ }
+
+ /**
+ * <p>Return the value of the (possibly nested) locale-sensitive property
+ * of the specified name.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getNestedProperty(Object, String)
+ */
+ public static String getNestedProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getNestedProperty(bean, name);
+ }
+
+ /**
+ * <p>Return the value of the specified locale-sensitive property
+ * of the specified bean.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getProperty(Object, String, String)
+ */
+ public static String getProperty(Object bean, String name, String pattern)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getProperty(bean, name, pattern);
+ }
+
+ /**
+ * <p>Return the value of the specified locale-sensitive property
+ * of the specified bean.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#getProperty(Object, String)
+ */
+ public static String getProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getProperty(bean, name);
+ }
+
+ /**
+ * <p>Set the specified locale-sensitive property value, performing type
+ * conversions as required to conform to the type of the destination property
+ * using the default convertion pattern of the corresponding {@link LocaleConverter}.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#setProperty(Object, String, Object)
+ */
+ public static void setProperty(Object bean, String name, Object value)
+ throws IllegalAccessException, InvocationTargetException {
+
+ LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().setProperty(bean, name, value);
+ }
+
+ /**
+ * <p>Set the specified locale-sensitive property value, performing type
+ * conversions as required to conform to the type of the destination
+ * property using the specified convertion pattern.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#setProperty(Object, String, Object, String)
+ */
+ public static void setProperty(Object bean, String name, Object value, String pattern)
+ throws IllegalAccessException, InvocationTargetException {
+
+ LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().setProperty(bean, name, value, pattern);
+ }
+
+ /**
+ * <p>Calculate the property type.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#definePropertyType(Object, String, String)
+ */
+ protected static Class definePropertyType(Object target, String name, String propName)
+ throws IllegalAccessException, InvocationTargetException {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().definePropertyType(target, name, propName);
+ }
+
+ /**
+ * <p>Convert the specified value to the required type using the
+ * specified convertion pattern.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#convert(Class, int, Object, String)
+ */
+ protected static Object convert(Class type, int index, Object value, String pattern) {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().convert(type, index, value, pattern);
+ }
+
+ /**
+ * <p>Convert the specified value to the required type.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#convert(Class, int, Object)
+ */
+ protected static Object convert(Class type, int index, Object value) {
+
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().convert(type, index, value);
+ }
+
+ /**
+ * <p>Invoke the setter method.</p>
+ *
+ * <p>For more details see <code>LocaleBeanUtilsBean</code></p>
+ *
+ * @see LocaleBeanUtilsBean#invokeSetter(Object, String, String, int, Object)
+ */
+ protected static void invokeSetter(Object target, String propName, String key, int index, Object newValue)
+ throws IllegalAccessException, InvocationTargetException {
+
+ LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().invokeSetter(target, propName, key, index, newValue);
+ }
+
+ /**
+ * Resolve any nested expression to get the actual target bean.
+ *
+ * @deprecated moved into <code>LocaleBeanUtilsBean</code>
+ * @param bean The bean
+ * @param name The property name
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ */
+ protected static Descriptor calculate(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException {
+
+ String propName = null; // Simple name of target property
+ int index = -1; // Indexed subscript value (if any)
+ String key = null; // Mapped key value (if any)
+
+ Object target = bean;
+ int delim = name.lastIndexOf(PropertyUtils.NESTED_DELIM);
+ if (delim >= 0) {
+ try {
+ target =
+ PropertyUtils.getProperty(bean, name.substring(0, delim));
+ }
+ catch (NoSuchMethodException e) {
+ return null; // Skip this property setter
+ }
+ name = name.substring(delim + 1);
+ if (log.isTraceEnabled()) {
+ log.trace(" Target bean = " + target);
+ log.trace(" Target name = " + name);
+ }
+ }
+
+ // Calculate the property name, index, and key values
+ propName = name;
+ int i = propName.indexOf(PropertyUtils.INDEXED_DELIM);
+ if (i >= 0) {
+ int k = propName.indexOf(PropertyUtils.INDEXED_DELIM2);
+ try {
+ index =
+ Integer.parseInt(propName.substring(i + 1, k));
+ }
+ catch (NumberFormatException e) {
+ ;
+ }
+ propName = propName.substring(0, i);
+ }
+ int j = propName.indexOf(PropertyUtils.MAPPED_DELIM);
+ if (j >= 0) {
+ int k = propName.indexOf(PropertyUtils.MAPPED_DELIM2);
+ try {
+ key = propName.substring(j + 1, k);
+ }
+ catch (IndexOutOfBoundsException e) {
+ ;
+ }
+ propName = propName.substring(0, j);
+ }
+ return new Descriptor(target, name, propName, key, index);
+ }
+
+ /** @deprecated moved into <code>LocaleBeanUtils</code> */
+ protected static class Descriptor {
+
+ private int index = -1; // Indexed subscript value (if any)
+ private String name;
+ private String propName; // Simple name of target property
+ private String key; // Mapped key value (if any)
+ private Object target;
+
+ public Descriptor(Object target, String name, String propName, String key, int index) {
+
+ setTarget(target);
+ setName(name);
+ setPropName(propName);
+ setKey(key);
+ setIndex(index);
+ }
+
+ public Object getTarget() {
+ return target;
+ }
+
+ public void setTarget(Object target) {
+ this.target = target;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPropName() {
+ return propName;
+ }
+
+ public void setPropName(String propName) {
+ this.propName = propName;
+ }
+ }
+}
+
+
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleBeanUtils.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleBeanUtilsBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleBeanUtilsBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleBeanUtilsBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,957 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale;
+
+
+import org.apache.commons.beanutils.*;
+import org.apache.commons.beanutils.ContextClassLoaderLocal;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Locale;
+
+
+/**
+ * <p>Utility methods for populating JavaBeans properties
+ * via reflection in a locale-dependent manner.</p>
+ *
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author Rey François
+ * @author Gregor Raýman
+ * @author Yauheny Mikulski
+ * @since 1.7
+ */
+
+public class LocaleBeanUtilsBean extends BeanUtilsBean {
+
+ /**
+ * Contains <code>LocaleBeanUtilsBean</code> instances indexed by context classloader.
+ */
+ private static final ContextClassLoaderLocal
+ localeBeansByClassLoader = new ContextClassLoaderLocal() {
+ // Creates the default instance used when the context classloader is unavailable
+ protected Object initialValue() {
+ return new LocaleBeanUtilsBean();
+ }
+ };
+
+ /** Gets singleton instance */
+ public synchronized static LocaleBeanUtilsBean getLocaleBeanUtilsInstance() {
+ return (LocaleBeanUtilsBean)localeBeansByClassLoader.get();
+ }
+
+ /**
+ * Sets the instance which provides the functionality for {@link LocaleBeanUtils}.
+ * This is a pseudo-singleton - an single instance is provided per (thread) context classloader.
+ * This mechanism provides isolation for web apps deployed in the same container.
+ */
+ public synchronized static void setInstance(LocaleBeanUtilsBean newInstance) {
+ localeBeansByClassLoader.set(newInstance);
+ }
+
+ /** All logging goes through this logger */
+ private static Log log = LogFactory.getLog(LocaleBeanUtilsBean.class);
+
+ // ----------------------------------------------------- Instance Variables
+
+ /** Convertor used by this class */
+ private LocaleConvertUtilsBean localeConvertUtils;
+
+ // --------------------------------------------------------- Constructors
+
+ /** Construct instance with standard conversion bean */
+ public LocaleBeanUtilsBean() {
+ this.localeConvertUtils = new LocaleConvertUtilsBean();
+ }
+
+ /**
+ * Construct instance that uses given locale conversion
+ *
+ * @param localeConvertUtils use this <code>localeConvertUtils</code> to perform
+ * conversions
+ * @param convertUtilsBean use this for standard conversions
+ * @param propertyUtilsBean use this for property conversions
+ */
+ public LocaleBeanUtilsBean(
+ LocaleConvertUtilsBean localeConvertUtils,
+ ConvertUtilsBean convertUtilsBean,
+ PropertyUtilsBean propertyUtilsBean) {
+ super(convertUtilsBean, propertyUtilsBean);
+ this.localeConvertUtils = localeConvertUtils;
+ }
+
+ /**
+ * Construct instance that uses given locale conversion
+ *
+ * @param localeConvertUtils use this <code>localeConvertUtils</code> to perform
+ * conversions
+ */
+ public LocaleBeanUtilsBean(LocaleConvertUtilsBean localeConvertUtils) {
+ this.localeConvertUtils = localeConvertUtils;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+ /** Gets the bean instance used for conversions */
+ public LocaleConvertUtilsBean getLocaleConvertUtils() {
+ return localeConvertUtils;
+ }
+
+ /**
+ * Gets the default Locale
+ */
+ public Locale getDefaultLocale() {
+
+ return getLocaleConvertUtils().getDefaultLocale();
+ }
+
+
+ /**
+ * Sets the default Locale
+ */
+ public void setDefaultLocale(Locale locale) {
+
+ getLocaleConvertUtils().setDefaultLocale(locale);
+ }
+
+ /**
+ * Is the pattern to be applied localized
+ * (Indicate whether the pattern is localized or not)
+ */
+ public boolean getApplyLocalized() {
+
+ return getLocaleConvertUtils().getApplyLocalized();
+ }
+
+ /**
+ * Sets whether the pattern is applied localized
+ * (Indicate whether the pattern is localized or not)
+ */
+ public void setApplyLocalized(boolean newApplyLocalized) {
+
+ getLocaleConvertUtils().setApplyLocalized(newApplyLocalized);
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Return the value of the specified locale-sensitive indexed property
+ * of the specified bean, as a String. The zero-relative index of the
+ * required value must be included (in square brackets) as a suffix to
+ * the property name, or <code>IllegalArgumentException</code> will be
+ * thrown.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name <code>propertyname[index]</code> of the property value
+ * to be extracted
+ * @param pattern The convertion pattern
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getIndexedProperty(
+ Object bean,
+ String name,
+ String pattern)
+ throws
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getIndexedProperty(bean, name);
+ return getLocaleConvertUtils().convert(value, pattern);
+ }
+
+ /**
+ * Return the value of the specified locale-sensitive indexed property
+ * of the specified bean, as a String using the default convertion pattern of
+ * the corresponding {@link LocaleConverter}. The zero-relative index
+ * of the required value must be included (in square brackets) as a suffix
+ * to the property name, or <code>IllegalArgumentException</code> will be thrown.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name <code>propertyname[index]</code> of the property value
+ * to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getIndexedProperty(
+ Object bean,
+ String name)
+ throws
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchMethodException {
+
+ return getIndexedProperty(bean, name, null);
+ }
+
+ /**
+ * Return the value of the specified locale-sensetive indexed property
+ * of the specified bean, as a String using the specified convertion pattern.
+ * The index is specified as a method parameter and
+ * must *not* be included in the property name expression
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Simple property name of the property value to be extracted
+ * @param index Index of the property value to be extracted
+ * @param pattern The convertion pattern
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getIndexedProperty(Object bean,
+ String name, int index, String pattern)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getIndexedProperty(bean, name, index);
+ return getLocaleConvertUtils().convert(value, pattern);
+ }
+
+ /**
+ * Return the value of the specified locale-sensetive indexed property
+ * of the specified bean, as a String using the default convertion pattern of
+ * the corresponding {@link LocaleConverter}.
+ * The index is specified as a method parameter and
+ * must *not* be included in the property name expression
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Simple property name of the property value to be extracted
+ * @param index Index of the property value to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getIndexedProperty(Object bean,
+ String name, int index)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+ return getIndexedProperty(bean, name, index, null);
+ }
+
+ /**
+ * Return the value of the specified simple locale-sensitive property
+ * of the specified bean, converted to a String using the specified
+ * convertion pattern.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Name of the property to be extracted
+ * @param pattern The convertion pattern
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getSimpleProperty(Object bean, String name, String pattern)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getSimpleProperty(bean, name);
+ return getLocaleConvertUtils().convert(value, pattern);
+ }
+
+ /**
+ * Return the value of the specified simple locale-sensitive property
+ * of the specified bean, converted to a String using the default
+ * convertion pattern of the corresponding {@link LocaleConverter}.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Name of the property to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getSimpleProperty(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return getSimpleProperty(bean, name, null);
+ }
+
+ /**
+ * Return the value of the specified mapped locale-sensitive property
+ * of the specified bean, as a String using the specified convertion pattern.
+ * The key is specified as a method parameter and must *not* be included in
+ * the property name expression.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Simple property name of the property value to be extracted
+ * @param key Lookup key of the property value to be extracted
+ * @param pattern The convertion pattern
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getMappedProperty(
+ Object bean,
+ String name,
+ String key,
+ String pattern)
+ throws
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getMappedProperty(bean, name, key);
+ return getLocaleConvertUtils().convert(value, pattern);
+ }
+
+ /**
+ * Return the value of the specified mapped locale-sensitive property
+ * of the specified bean, as a String
+ * The key is specified as a method parameter and must *not* be included
+ * in the property name expression
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Simple property name of the property value to be extracted
+ * @param key Lookup key of the property value to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getMappedProperty(Object bean,
+ String name, String key)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ return getMappedProperty(bean, name, key, null);
+ }
+
+
+ /**
+ * Return the value of the specified locale-sensitive mapped property
+ * of the specified bean, as a String using the specified pattern.
+ * The String-valued key of the required value
+ * must be included (in parentheses) as a suffix to
+ * the property name, or <code>IllegalArgumentException</code> will be
+ * thrown.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name <code>propertyname(index)</code> of the property value
+ * to be extracted
+ * @param pattern The convertion pattern
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getMappedPropertyLocale(
+ Object bean,
+ String name,
+ String pattern)
+ throws
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getMappedProperty(bean, name);
+ return getLocaleConvertUtils().convert(value, pattern);
+ }
+
+
+ /**
+ * Return the value of the specified locale-sensitive mapped property
+ * of the specified bean, as a String using the default
+ * convertion pattern of the corresponding {@link LocaleConverter}.
+ * The String-valued key of the required value
+ * must be included (in parentheses) as a suffix to
+ * the property name, or <code>IllegalArgumentException</code> will be
+ * thrown.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name <code>propertyname(index)</code> of the property value
+ * to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getMappedProperty(Object bean, String name)
+ throws
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchMethodException {
+
+ return getMappedPropertyLocale(bean, name, null);
+ }
+
+ /**
+ * Return the value of the (possibly nested) locale-sensitive property
+ * of the specified name, for the specified bean,
+ * as a String using the specified pattern.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Possibly nested name of the property to be extracted
+ * @param pattern The convertion pattern
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if a nested reference to a
+ * property returns null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getNestedProperty(
+ Object bean,
+ String name,
+ String pattern)
+ throws
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchMethodException {
+
+ Object value = getPropertyUtils().getNestedProperty(bean, name);
+ return getLocaleConvertUtils().convert(value, pattern);
+ }
+
+ /**
+ * Return the value of the (possibly nested) locale-sensitive property
+ * of the specified name, for the specified bean, as a String using the default
+ * convertion pattern of the corresponding {@link LocaleConverter}.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Possibly nested name of the property to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception IllegalArgumentException if a nested reference to a
+ * property returns null
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getNestedProperty(Object bean, String name)
+ throws
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchMethodException {
+
+ return getNestedProperty(bean, name, null);
+ }
+
+ /**
+ * Return the value of the specified locale-sensitive property
+ * of the specified bean, no matter which property reference
+ * format is used, as a String using the specified convertion pattern.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Possibly indexed and/or nested name of the property
+ * to be extracted
+ * @param pattern The convertion pattern
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getProperty(Object bean, String name, String pattern)
+ throws
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchMethodException {
+
+ return getNestedProperty(bean, name, pattern);
+ }
+
+ /**
+ * Return the value of the specified locale-sensitive property
+ * of the specified bean, no matter which property reference
+ * format is used, as a String using the default
+ * convertion pattern of the corresponding {@link LocaleConverter}.
+ *
+ * @param bean Bean whose property is to be extracted
+ * @param name Possibly indexed and/or nested name of the property
+ * to be extracted
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found
+ */
+ public String getProperty(Object bean, String name)
+ throws
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchMethodException {
+
+ return getNestedProperty(bean, name);
+ }
+
+ /**
+ * Set the specified locale-sensitive property value, performing type
+ * conversions as required to conform to the type of the destination property
+ * using the default convertion pattern of the corresponding {@link LocaleConverter}.
+ *
+ * @param bean Bean on which setting is to be performed
+ * @param name Property name (can be nested/indexed/mapped/combo)
+ * @param value Value to be set
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ */
+ public void setProperty(Object bean, String name, Object value)
+ throws
+ IllegalAccessException,
+ InvocationTargetException {
+
+ setProperty(bean, name, value, null);
+ }
+
+ /**
+ * Set the specified locale-sensitive property value, performing type
+ * conversions as required to conform to the type of the destination
+ * property using the specified convertion pattern.
+ *
+ * @param bean Bean on which setting is to be performed
+ * @param name Property name (can be nested/indexed/mapped/combo)
+ * @param value Value to be set
+ * @param pattern The convertion pattern
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ */
+ public void setProperty(
+ Object bean,
+ String name,
+ Object value,
+ String pattern)
+ throws
+ IllegalAccessException,
+ InvocationTargetException {
+
+ // Trace logging (if enabled)
+ if (log.isTraceEnabled()) {
+ StringBuffer sb = new StringBuffer(" setProperty(");
+ sb.append(bean);
+ sb.append(", ");
+ sb.append(name);
+ sb.append(", ");
+ if (value == null) {
+ sb.append("<NULL>");
+ }
+ else if (value instanceof String) {
+ sb.append((String) value);
+ }
+ else if (value instanceof String[]) {
+ String values[] = (String[]) value;
+ sb.append('[');
+ for (int i = 0; i < values.length; i++) {
+ if (i > 0) {
+ sb.append(',');
+ }
+ sb.append(values[i]);
+ }
+ sb.append(']');
+ }
+ else {
+ sb.append(value.toString());
+ }
+ sb.append(')');
+ log.trace(sb.toString());
+ }
+
+ Descriptor propInfo = calculate(bean, name);
+
+ if (propInfo != null) {
+ Class type = definePropertyType(propInfo.getTarget(), name, propInfo.getPropName());
+
+ if (type != null) {
+
+ Object newValue = convert(type, propInfo.getIndex(), value, pattern);
+ invokeSetter(propInfo.getTarget(), propInfo.getPropName(),
+ propInfo.getKey(), propInfo.getIndex(), newValue);
+ }
+ }
+ }
+
+ /**
+ * Calculate the property type.
+ *
+ * @param target The bean
+ * @param name The property name
+ * @param propName The Simple name of target property
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ */
+ protected Class definePropertyType(Object target, String name, String propName)
+ throws IllegalAccessException, InvocationTargetException {
+
+ Class type = null; // Java type of target property
+
+ if (target instanceof DynaBean) {
+ DynaClass dynaClass = ((DynaBean) target).getDynaClass();
+ DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
+ if (dynaProperty == null) {
+ return null; // Skip this property setter
+ }
+ type = dynaProperty.getType();
+ }
+ else {
+ PropertyDescriptor descriptor = null;
+ try {
+ descriptor =
+ getPropertyUtils().getPropertyDescriptor(target, name);
+ if (descriptor == null) {
+ return null; // Skip this property setter
+ }
+ }
+ catch (NoSuchMethodException e) {
+ return null; // Skip this property setter
+ }
+ if (descriptor instanceof MappedPropertyDescriptor) {
+ type = ((MappedPropertyDescriptor) descriptor).
+ getMappedPropertyType();
+ }
+ else if (descriptor instanceof IndexedPropertyDescriptor) {
+ type = ((IndexedPropertyDescriptor) descriptor).
+ getIndexedPropertyType();
+ }
+ else {
+ type = descriptor.getPropertyType();
+ }
+ }
+ return type;
+ }
+
+ /**
+ * Convert the specified value to the required type using the
+ * specified convertion pattern.
+ *
+ * @param type The Java type of target property
+ * @param index The indexed subscript value (if any)
+ * @param value The value to be converted
+ * @param pattern The convertion pattern
+ */
+ protected Object convert(Class type, int index, Object value, String pattern) {
+
+ if (log.isTraceEnabled()) {
+ log.trace("Converting value '" + value + "' to type:" + type);
+ }
+
+ Object newValue = null;
+
+ if (type.isArray() && (index < 0)) { // Scalar value into array
+ if (value instanceof String) {
+ String values[] = new String[1];
+ values[0] = (String) value;
+ newValue = getLocaleConvertUtils().convert((String[]) values, type, pattern);
+ }
+ else if (value instanceof String[]) {
+ newValue = getLocaleConvertUtils().convert((String[]) value, type, pattern);
+ }
+ else {
+ newValue = value;
+ }
+ }
+ else if (type.isArray()) { // Indexed value into array
+ if (value instanceof String) {
+ newValue = getLocaleConvertUtils().convert((String) value,
+ type.getComponentType(), pattern);
+ }
+ else if (value instanceof String[]) {
+ newValue = getLocaleConvertUtils().convert(((String[]) value)[0],
+ type.getComponentType(), pattern);
+ }
+ else {
+ newValue = value;
+ }
+ }
+ else { // Value into scalar
+ if (value instanceof String) {
+ newValue = getLocaleConvertUtils().convert((String) value, type, pattern);
+ }
+ else if (value instanceof String[]) {
+ newValue = getLocaleConvertUtils().convert(((String[]) value)[0],
+ type, pattern);
+ }
+ else {
+ newValue = value;
+ }
+ }
+ return newValue;
+ }
+
+ /**
+ * Convert the specified value to the required type.
+ *
+ * @param type The Java type of target property
+ * @param index The indexed subscript value (if any)
+ * @param value The value to be converted
+ */
+ protected Object convert(Class type, int index, Object value) {
+
+ Object newValue = null;
+
+ if (type.isArray() && (index < 0)) { // Scalar value into array
+ if (value instanceof String) {
+ String values[] = new String[1];
+ values[0] = (String) value;
+ newValue = ConvertUtils.convert((String[]) values, type);
+ }
+ else if (value instanceof String[]) {
+ newValue = ConvertUtils.convert((String[]) value, type);
+ }
+ else {
+ newValue = value;
+ }
+ }
+ else if (type.isArray()) { // Indexed value into array
+ if (value instanceof String) {
+ newValue = ConvertUtils.convert((String) value,
+ type.getComponentType());
+ }
+ else if (value instanceof String[]) {
+ newValue = ConvertUtils.convert(((String[]) value)[0],
+ type.getComponentType());
+ }
+ else {
+ newValue = value;
+ }
+ }
+ else { // Value into scalar
+ if (value instanceof String) {
+ newValue = ConvertUtils.convert((String) value, type);
+ }
+ else if (value instanceof String[]) {
+ newValue = ConvertUtils.convert(((String[]) value)[0],
+ type);
+ }
+ else {
+ newValue = value;
+ }
+ }
+ return newValue;
+ }
+
+ /**
+ * Invoke the setter method.
+ *
+ * @param target The bean
+ * @param propName The Simple name of target property
+ * @param key The Mapped key value (if any)
+ * @param index The indexed subscript value (if any)
+ * @param newValue The value to be set
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ */
+ protected void invokeSetter(Object target, String propName, String key, int index, Object newValue)
+ throws IllegalAccessException, InvocationTargetException {
+
+ try {
+ if (index >= 0) {
+ getPropertyUtils().setIndexedProperty(target, propName,
+ index, newValue);
+ }
+ else if (key != null) {
+ getPropertyUtils().setMappedProperty(target, propName,
+ key, newValue);
+ }
+ else {
+ getPropertyUtils().setProperty(target, propName, newValue);
+ }
+ }
+ catch (NoSuchMethodException e) {
+ throw new InvocationTargetException
+ (e, "Cannot set " + propName);
+ }
+ }
+
+ /**
+ * Resolve any nested expression to get the actual target bean.
+ *
+ * @param bean The bean
+ * @param name The property name
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ */
+ protected Descriptor calculate(Object bean, String name)
+ throws IllegalAccessException, InvocationTargetException {
+
+ String propName = null; // Simple name of target property
+ int index = -1; // Indexed subscript value (if any)
+ String key = null; // Mapped key value (if any)
+
+ Object target = bean;
+ int delim = name.lastIndexOf(PropertyUtils.NESTED_DELIM);
+ if (delim >= 0) {
+ try {
+ target =
+ getPropertyUtils().getProperty(bean, name.substring(0, delim));
+ }
+ catch (NoSuchMethodException e) {
+ return null; // Skip this property setter
+ }
+ name = name.substring(delim + 1);
+ if (log.isTraceEnabled()) {
+ log.trace(" Target bean = " + target);
+ log.trace(" Target name = " + name);
+ }
+ }
+
+ // Calculate the property name, index, and key values
+ propName = name;
+ int i = propName.indexOf(PropertyUtils.INDEXED_DELIM);
+ if (i >= 0) {
+ int k = propName.indexOf(PropertyUtils.INDEXED_DELIM2);
+ try {
+ index =
+ Integer.parseInt(propName.substring(i + 1, k));
+ }
+ catch (NumberFormatException e) {
+ ;
+ }
+ propName = propName.substring(0, i);
+ }
+ int j = propName.indexOf(PropertyUtils.MAPPED_DELIM);
+ if (j >= 0) {
+ int k = propName.indexOf(PropertyUtils.MAPPED_DELIM2);
+ try {
+ key = propName.substring(j + 1, k);
+ }
+ catch (IndexOutOfBoundsException e) {
+ ;
+ }
+ propName = propName.substring(0, j);
+ }
+ return new Descriptor(target, name, propName, key, index);
+ }
+
+ protected class Descriptor {
+
+ private int index = -1; // Indexed subscript value (if any)
+ private String name;
+ private String propName; // Simple name of target property
+ private String key; // Mapped key value (if any)
+ private Object target;
+
+ public Descriptor(Object target, String name, String propName, String key, int index) {
+
+ setTarget(target);
+ setName(name);
+ setPropName(propName);
+ setKey(key);
+ setIndex(index);
+ }
+
+ public Object getTarget() {
+ return target;
+ }
+
+ public void setTarget(Object target) {
+ this.target = target;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPropName() {
+ return propName;
+ }
+
+ public void setPropName(String propName) {
+ this.propName = propName;
+ }
+ }
+}
+
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtils.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtils.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtils.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale;
+
+import org.apache.commons.collections.FastHashMap;
+
+import java.util.Locale;
+
+/**
+ * <p>Utility methods for converting locale-sensitive String scalar values to objects of the
+ * specified Class, String arrays to arrays of the specified Class and
+ * object to locale-sensitive String scalar value.</p>
+ *
+ * <p>The implementations for these method are provided by {@link LocaleConvertUtilsBean}.
+ * These static utility method use the default instance. More sophisticated can be provided
+ * by using a <code>LocaleConvertUtilsBean</code> instance.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+public class LocaleConvertUtils {
+
+ // ----------------------------------------------------- Instance Variables
+
+ /**
+ * <p>Gets the <code>Locale</code> which will be used when
+ * no <code>Locale</code> is passed to a method.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#getDefaultLocale()
+ */
+ public static Locale getDefaultLocale() {
+
+ return LocaleConvertUtilsBean.getInstance().getDefaultLocale();
+ }
+
+ /**
+ * <p>Sets the <code>Locale</code> which will be used when
+ * no <code>Locale</code> is passed to a method.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#setDefaultLocale(Locale)
+ */
+ public static void setDefaultLocale(Locale locale) {
+
+ LocaleConvertUtilsBean.getInstance().setDefaultLocale(locale);
+ }
+
+ /**
+ * <p>Gets applyLocalized.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#getApplyLocalized()
+ */
+ public static boolean getApplyLocalized() {
+ return LocaleConvertUtilsBean.getInstance().getApplyLocalized();
+ }
+
+ /**
+ * <p>Sets applyLocalized.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#setApplyLocalized(boolean)
+ */
+ public static void setApplyLocalized(boolean newApplyLocalized) {
+ LocaleConvertUtilsBean.getInstance().setApplyLocalized(newApplyLocalized);
+ }
+
+ // --------------------------------------------------------- Methods
+
+ /**
+ * <p>Convert the specified locale-sensitive value into a String.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#convert(Object)
+ */
+ public static String convert(Object value) {
+ return LocaleConvertUtilsBean.getInstance().convert(value);
+ }
+
+ /**
+ * <p>Convert the specified locale-sensitive value into a String
+ * using the convertion pattern.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#convert(Object, String)
+ */
+ public static String convert(Object value, String pattern) {
+ return LocaleConvertUtilsBean.getInstance().convert(value, pattern);
+ }
+
+ /**
+ * <p>Convert the specified locale-sensitive value into a String
+ * using the paticular convertion pattern.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#convert(Object, Locale, String)
+ */
+ public static String convert(Object value, Locale locale, String pattern) {
+
+ return LocaleConvertUtilsBean.getInstance().convert(value, locale, pattern);
+ }
+
+ /**
+ * <p>Convert the specified value to an object of the specified class (if
+ * possible). Otherwise, return a String representation of the value.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#convert(String, Class)
+ */
+ public static Object convert(String value, Class clazz) {
+
+ return LocaleConvertUtilsBean.getInstance().convert(value, clazz);
+ }
+
+ /**
+ * <p>Convert the specified value to an object of the specified class (if
+ * possible) using the convertion pattern. Otherwise, return a String
+ * representation of the value.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#convert(String, Class, String)
+ */
+ public static Object convert(String value, Class clazz, String pattern) {
+
+ return LocaleConvertUtilsBean.getInstance().convert(value, clazz, pattern);
+ }
+
+ /**
+ * <p>Convert the specified value to an object of the specified class (if
+ * possible) using the convertion pattern. Otherwise, return a String
+ * representation of the value.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#convert(String, Class, Locale, String)
+ */
+ public static Object convert(String value, Class clazz, Locale locale, String pattern) {
+
+ return LocaleConvertUtilsBean.getInstance().convert(value, clazz, locale, pattern);
+ }
+
+ /**
+ * <p>Convert an array of specified values to an array of objects of the
+ * specified class (if possible) using the convertion pattern.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#convert(String[], Class, String)
+ */
+ public static Object convert(String values[], Class clazz, String pattern) {
+
+ return LocaleConvertUtilsBean.getInstance().convert(values, clazz, pattern);
+ }
+
+ /**
+ * <p>Convert an array of specified values to an array of objects of the
+ * specified class (if possible).</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#convert(String[], Class)
+ */
+ public static Object convert(String values[], Class clazz) {
+
+ return LocaleConvertUtilsBean.getInstance().convert(values, clazz);
+ }
+
+ /**
+ * <p>Convert an array of specified values to an array of objects of the
+ * specified class (if possible) using the convertion pattern.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#convert(String[], Class, Locale, String)
+ */
+ public static Object convert(String values[], Class clazz, Locale locale, String pattern) {
+
+ return LocaleConvertUtilsBean.getInstance().convert(values, clazz, locale, pattern);
+ }
+
+ /**
+ * <p>Register a custom {@link LocaleConverter} for the specified destination
+ * <code>Class</code>, replacing any previously registered converter.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#register(LocaleConverter, Class, Locale)
+ */
+ public static void register(LocaleConverter converter, Class clazz, Locale locale) {
+
+ LocaleConvertUtilsBean.getInstance().register(converter, clazz, locale);
+ }
+
+ /**
+ * <p>Remove any registered {@link LocaleConverter}.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#deregister()
+ */
+ public static void deregister() {
+
+ LocaleConvertUtilsBean.getInstance().deregister();
+ }
+
+
+ /**
+ * <p>Remove any registered {@link LocaleConverter} for the specified locale.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#deregister(Locale)
+ */
+ public static void deregister(Locale locale) {
+
+ LocaleConvertUtilsBean.getInstance().deregister(locale);
+ }
+
+
+ /**
+ * <p>Remove any registered {@link LocaleConverter} for the specified locale and Class.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#deregister(Class, Locale)
+ */
+ public static void deregister(Class clazz, Locale locale) {
+
+ LocaleConvertUtilsBean.getInstance().deregister(clazz, locale);
+ }
+
+ /**
+ * <p>Look up and return any registered {@link LocaleConverter} for the specified
+ * destination class and locale; if there is no registered Converter, return
+ * <code>null</code>.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#lookup(Class, Locale)
+ */
+ public static LocaleConverter lookup(Class clazz, Locale locale) {
+
+ return LocaleConvertUtilsBean.getInstance().lookup(clazz, locale);
+ }
+
+ /**
+ * <p>Look up and return any registered FastHashMap instance for the specified locale.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#lookup(Locale)
+ */
+ protected static FastHashMap lookup(Locale locale) {
+ return LocaleConvertUtilsBean.getInstance().lookup(locale);
+ }
+
+ /**
+ * <p>Create all {@link LocaleConverter} types for specified locale.</p>
+ *
+ * <p>For more details see <code>LocaleConvertUtilsBean</code></p>
+ *
+ * @see LocaleConvertUtilsBean#create(Locale)
+ */
+ protected static FastHashMap create(Locale locale) {
+
+ return LocaleConvertUtilsBean.getInstance().create(locale);
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtils.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtilsBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtilsBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtilsBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,456 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale;
+
+import org.apache.commons.beanutils.locale.converters.*;
+import org.apache.commons.beanutils.Converter;
+import org.apache.commons.collections.FastHashMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.lang.reflect.Array;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Locale;
+
+/**
+ * <p>Utility methods for converting locale-sensitive String scalar values to objects of the
+ * specified Class, String arrays to arrays of the specified Class and
+ * object to locale-sensitive String scalar value.</p>
+ *
+ * <p>This class provides the implementations used by the static utility methods in
+ * {@link LocaleConvertUtils}.</p>
+ *
+ * <p>The actual {@link LocaleConverter} instance to be used
+ * can be registered for each possible destination Class. Unless you override them, standard
+ * {@link LocaleConverter} instances are provided for all of the following
+ * destination Classes:</p>
+ * <ul>
+ * <li>java.lang.BigDecimal</li>
+ * <li>java.lang.BigInteger</li>
+ * <li>byte and java.lang.Byte</li>
+ * <li>double and java.lang.Double</li>
+ * <li>float and java.lang.Float</li>
+ * <li>int and java.lang.Integer</li>
+ * <li>long and java.lang.Long</li>
+ * <li>short and java.lang.Short</li>
+ * <li>java.lang.String</li>
+ * <li>java.sql.Date</li>
+ * <li>java.sql.Time</li>
+ * <li>java.sql.Timestamp</li>
+ * </ul>
+ *
+ * <p>For backwards compatibility, the standard locale converters
+ * for primitive types (and the corresponding wrapper classes).
+ *
+ * If you prefer to have another {@link LocaleConverter}
+ * thrown instead, replace the standard {@link LocaleConverter} instances
+ * with ones created with the one of the appropriate constructors.
+ *
+ * It's important that {@link LocaleConverter} should be registered for
+ * the specified locale and Class (or primitive type).
+ *
+ * @author Yauheny Mikulski
+ * @since 1.7
+ */
+public class LocaleConvertUtilsBean {
+
+ /**
+ * Gets singleton instance.
+ * This is the same as the instance used by the default {@link LocaleBeanUtilsBean} singleton.
+ */
+ public static LocaleConvertUtilsBean getInstance() {
+ return LocaleBeanUtilsBean.getLocaleBeanUtilsInstance().getLocaleConvertUtils();
+ }
+
+ // ----------------------------------------------------- Instance Variables
+
+ /** The locale - default for convertion. */
+ private Locale defaultLocale = Locale.getDefault();
+
+ /** Indicate whether the pattern is localized or not */
+ private boolean applyLocalized = false;
+
+ /** The <code>Log</code> instance for this class. */
+ private Log log = LogFactory.getLog(LocaleConvertUtils.class);
+
+ /** Every entry of the mapConverters is:
+ * key = locale
+ * value = FastHashMap of converters for the certain locale.
+ */
+ private FastHashMap mapConverters = new FastHashMap();
+
+ // --------------------------------------------------------- Constructors
+
+ /**
+ * Makes the state by default (deregisters all converters for all locales)
+ * and then registers default locale converters.
+ */
+ public LocaleConvertUtilsBean() {
+ deregister();
+ }
+
+ // --------------------------------------------------------- Properties
+
+ /**
+ * getter for defaultLocale
+ */
+ public Locale getDefaultLocale() {
+
+ return defaultLocale;
+ }
+
+ /**
+ * setter for defaultLocale
+ */
+ public void setDefaultLocale(Locale locale) {
+
+ if (locale == null) {
+ defaultLocale = Locale.getDefault();
+ }
+ else {
+ defaultLocale = locale;
+ }
+ }
+
+ /**
+ * getter for applyLocalized
+ */
+ public boolean getApplyLocalized() {
+ return applyLocalized;
+ }
+
+ /**
+ * setter for applyLocalized
+ */
+ public void setApplyLocalized(boolean newApplyLocalized) {
+ applyLocalized = newApplyLocalized;
+ }
+
+ // --------------------------------------------------------- Methods
+
+ /**
+ * Convert the specified locale-sensitive value into a String.
+ *
+ * @param value The Value to be converted
+ *
+ * @exception org.apache.commons.beanutils.ConversionException if thrown by an underlying Converter
+ */
+ public String convert(Object value) {
+ return convert(value, defaultLocale, null);
+ }
+
+ /**
+ * Convert the specified locale-sensitive value into a String
+ * using the convertion pattern.
+ *
+ * @param value The Value to be converted
+ * @param pattern The convertion pattern
+ *
+ * @exception ConversionException if thrown by an underlying Converter
+ */
+ public String convert(Object value, String pattern) {
+ return convert(value, defaultLocale, pattern);
+ }
+
+ /**
+ * Convert the specified locale-sensitive value into a String
+ * using the paticular convertion pattern.
+ *
+ * @param value The Value to be converted
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ *
+ * @exception ConversionException if thrown by an underlying Converter
+ */
+ public String convert(Object value, Locale locale, String pattern) {
+
+ LocaleConverter converter = lookup(String.class, locale);
+
+ return (String) converter.convert(String.class, value, pattern);
+ }
+
+ /**
+ * Convert the specified value to an object of the specified class (if
+ * possible). Otherwise, return a String representation of the value.
+ *
+ * @param value The String scalar value to be converted
+ * @param clazz The Data type to which this value should be converted.
+ *
+ * @exception ConversionException if thrown by an underlying Converter
+ */
+ public Object convert(String value, Class clazz) {
+
+ return convert(value, clazz, defaultLocale, null);
+ }
+
+ /**
+ * Convert the specified value to an object of the specified class (if
+ * possible) using the convertion pattern. Otherwise, return a String
+ * representation of the value.
+ *
+ * @param value The String scalar value to be converted
+ * @param clazz The Data type to which this value should be converted.
+ * @param pattern The convertion pattern
+ *
+ * @exception ConversionException if thrown by an underlying Converter
+ */
+ public Object convert(String value, Class clazz, String pattern) {
+
+ return convert(value, clazz, defaultLocale, pattern);
+ }
+
+ /**
+ * Convert the specified value to an object of the specified class (if
+ * possible) using the convertion pattern. Otherwise, return a String
+ * representation of the value.
+ *
+ * @param value The String scalar value to be converted
+ * @param clazz The Data type to which this value should be converted.
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ *
+ * @exception ConversionException if thrown by an underlying Converter
+ */
+ public Object convert(String value, Class clazz, Locale locale, String pattern) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Convert string " + value + " to class " +
+ clazz.getName() + " using " + locale.toString() +
+ " locale and " + pattern + " pattern");
+ }
+
+ LocaleConverter converter = lookup(clazz, locale);
+
+ if (converter == null) {
+ converter = (LocaleConverter) lookup(String.class, locale);
+ }
+ if (log.isTraceEnabled()) {
+ log.trace(" Using converter " + converter);
+ }
+
+ return (converter.convert(clazz, value, pattern));
+ }
+
+ /**
+ * Convert an array of specified values to an array of objects of the
+ * specified class (if possible) using the convertion pattern.
+ *
+ * @param values Value to be converted (may be null)
+ * @param clazz Java array or element class to be converted to
+ * @param pattern The convertion pattern
+ *
+ * @exception ConversionException if thrown by an underlying Converter
+ */
+ public Object convert(String values[], Class clazz, String pattern) {
+
+ return convert(values, clazz, getDefaultLocale(), pattern);
+ }
+
+ /**
+ * Convert an array of specified values to an array of objects of the
+ * specified class (if possible) .
+ *
+ * @param values Value to be converted (may be null)
+ * @param clazz Java array or element class to be converted to
+ *
+ * @exception ConversionException if thrown by an underlying Converter
+ */
+ public Object convert(String values[], Class clazz) {
+
+ return convert(values, clazz, getDefaultLocale(), null);
+ }
+
+ /**
+ * Convert an array of specified values to an array of objects of the
+ * specified class (if possible) using the convertion pattern.
+ *
+ * @param values Value to be converted (may be null)
+ * @param clazz Java array or element class to be converted to
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ *
+ * @exception ConversionException if thrown by an underlying Converter
+ */
+ public Object convert(String values[], Class clazz, Locale locale, String pattern) {
+
+ Class type = clazz;
+ if (clazz.isArray()) {
+ type = clazz.getComponentType();
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Convert String[" + values.length + "] to class " +
+ type.getName() + "[] using " + locale.toString() +
+ " locale and " + pattern + " pattern");
+ }
+
+ Object array = Array.newInstance(type, values.length);
+ for (int i = 0; i < values.length; i++) {
+ Array.set(array, i, convert(values[i], type, locale, pattern));
+ }
+
+ return (array);
+ }
+
+ /**
+ * Register a custom {@link LocaleConverter} for the specified destination
+ * <code>Class</code>, replacing any previously registered converter.
+ *
+ * @param converter The LocaleConverter to be registered
+ * @param clazz The Destination class for conversions performed by this
+ * Converter
+ * @param locale The locale
+ */
+ public void register(LocaleConverter converter, Class clazz, Locale locale) {
+
+ lookup(locale).put(clazz, converter);
+ }
+
+ /**
+ * Remove any registered {@link LocaleConverter}.
+ */
+ public void deregister() {
+
+ FastHashMap defaultConverter = lookup(defaultLocale);
+
+ mapConverters.setFast(false);
+
+ mapConverters.clear();
+ mapConverters.put(defaultLocale, defaultConverter);
+
+ mapConverters.setFast(true);
+ }
+
+
+ /**
+ * Remove any registered {@link LocaleConverter} for the specified locale
+ *
+ * @param locale The locale
+ */
+ public void deregister(Locale locale) {
+
+ mapConverters.remove(locale);
+ }
+
+
+ /**
+ * Remove any registered {@link LocaleConverter} for the specified locale and Class.
+ *
+ * @param clazz Class for which to remove a registered Converter
+ * @param locale The locale
+ */
+ public void deregister(Class clazz, Locale locale) {
+
+ lookup(locale).remove(clazz);
+ }
+
+ /**
+ * Look up and return any registered {@link LocaleConverter} for the specified
+ * destination class and locale; if there is no registered Converter, return
+ * <code>null</code>.
+ *
+ * @param clazz Class for which to return a registered Converter
+ * @param locale The Locale
+ */
+ public LocaleConverter lookup(Class clazz, Locale locale) {
+
+ LocaleConverter converter = (LocaleConverter) lookup(locale).get(clazz);
+
+ if (log.isTraceEnabled()) {
+ log.trace("LocaleConverter:" + converter);
+ }
+
+ return converter;
+ }
+
+ /**
+ * Look up and return any registered FastHashMap instance for the specified locale;
+ * if there is no registered one, return <code>null</code>.
+ *
+ * @param locale The Locale
+ * @return The FastHashMap instance contains the all {@link LocaleConverter} types for
+ * the specified locale.
+ */
+ protected FastHashMap lookup(Locale locale) {
+ FastHashMap localeConverters;
+
+ if (locale == null) {
+ localeConverters = (FastHashMap) mapConverters.get(defaultLocale);
+ }
+ else {
+ localeConverters = (FastHashMap) mapConverters.get(locale);
+
+ if (localeConverters == null) {
+ localeConverters = create(locale);
+ mapConverters.put(locale, localeConverters);
+ }
+ }
+
+ return localeConverters;
+ }
+
+ /**
+ * Create all {@link LocaleConverter} types for specified locale.
+ *
+ * @param locale The Locale
+ * @return The FastHashMap instance contains the all {@link LocaleConverter} types
+ * for the specified locale.
+ */
+ protected FastHashMap create(Locale locale) {
+
+ FastHashMap converter = new FastHashMap();
+ converter.setFast(false);
+
+ converter.put(BigDecimal.class, new BigDecimalLocaleConverter(locale, applyLocalized));
+ converter.put(BigInteger.class, new BigIntegerLocaleConverter(locale, applyLocalized));
+
+ converter.put(Byte.class, new ByteLocaleConverter(locale, applyLocalized));
+ converter.put(Byte.TYPE, new ByteLocaleConverter(locale, applyLocalized));
+
+ converter.put(Double.class, new DoubleLocaleConverter(locale, applyLocalized));
+ converter.put(Double.TYPE, new DoubleLocaleConverter(locale, applyLocalized));
+
+ converter.put(Float.class, new FloatLocaleConverter(locale, applyLocalized));
+ converter.put(Float.TYPE, new FloatLocaleConverter(locale, applyLocalized));
+
+ converter.put(Integer.class, new IntegerLocaleConverter(locale, applyLocalized));
+ converter.put(Integer.TYPE, new IntegerLocaleConverter(locale, applyLocalized));
+
+ converter.put(Long.class, new LongLocaleConverter(locale, applyLocalized));
+ converter.put(Long.TYPE, new LongLocaleConverter(locale, applyLocalized));
+
+ converter.put(Short.class, new ShortLocaleConverter(locale, applyLocalized));
+ converter.put(Short.TYPE, new ShortLocaleConverter(locale, applyLocalized));
+
+ converter.put(String.class, new StringLocaleConverter(locale, applyLocalized));
+
+ // conversion format patterns of java.sql.* types should correspond to default
+ // behaviour of toString and valueOf methods of these classes
+ converter.put(java.sql.Date.class, new SqlDateLocaleConverter(locale, "yyyy-MM-dd"));
+ converter.put(java.sql.Time.class, new SqlTimeLocaleConverter(locale, "HH:mm:ss"));
+ converter.put( java.sql.Timestamp.class,
+ new SqlTimestampLocaleConverter(locale, "yyyy-MM-dd HH:mm:ss.S")
+ );
+
+ converter.setFast(true);
+
+ return converter;
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale;
+
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * <p>General purpose locale-sensitive data type converter that can be registered and used
+ * within the BeanUtils package to manage the conversion of objects from
+ * one type to another.
+ *
+ * @author Yauheny Mikulski
+ */
+
+public interface LocaleConverter extends Converter {
+
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type.
+ *
+ * @param type Data type to which this value should be converted
+ * @param value The input value to be converted
+ * @param pattern The user-defined pattern is used for the input object formatting.
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ public Object convert(Class type, Object value, String pattern);
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/LocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import java.util.Locale;
+
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.math.BigDecimal</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class BigDecimalLocaleConverter extends DecimalLocaleConverter {
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public BigDecimalLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigDecimalLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public BigDecimalLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigDecimalLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public BigDecimalLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigDecimalLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public BigDecimalLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigDecimalLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public BigDecimalLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigDecimalLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public BigDecimalLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigDecimalLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern);
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import java.util.Locale;
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.math.BigInteger</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class BigIntegerLocaleConverter extends DecimalLocaleConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public BigIntegerLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigIntegerLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public BigIntegerLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigIntegerLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public BigIntegerLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigIntegerLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public BigIntegerLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigIntegerLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public BigIntegerLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigIntegerLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public BigIntegerLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public BigIntegerLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern);
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/ByteLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/ByteLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/ByteLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import org.apache.commons.beanutils.ConversionException;
+
+import java.util.Locale;
+import java.text.ParseException;
+
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.lang.Byte</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class ByteLocaleConverter extends DecimalLocaleConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public ByteLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ByteLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public ByteLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ByteLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public ByteLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ByteLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public ByteLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ByteLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public ByteLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ByteLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public ByteLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ByteLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern);
+ }
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type. This method will return values of type Byte.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception org.apache.commons.beanutils.ConversionException if conversion cannot be performed
+ * successfully
+ */
+ protected Object parse(Object value, String pattern) throws ParseException {
+ final Number parsed = (Number) super.parse(value, pattern);
+ if (parsed.longValue() != parsed.byteValue()) {
+ throw new ConversionException("Supplied number is not of type Byte: " + parsed.longValue());
+ }
+ // now returns property Byte
+ return new Byte(parsed.byteValue());
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/ByteLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DateLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DateLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DateLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import org.apache.commons.beanutils.locale.BaseLocaleConverter;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
+
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.util.Date</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ * @author Michael Szlapa
+ */
+
+public class DateLocaleConverter extends BaseLocaleConverter {
+
+ // ----------------------------------------------------- Instance Variables
+
+ /** All logging goes through this logger */
+ private static Log log = LogFactory.getLog(DateLocaleConverter.class);
+
+ /** Should the date conversion be lenient? */
+ boolean isLenient = false;
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public DateLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DateLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public DateLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DateLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public DateLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DateLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public DateLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DateLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public DateLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DateLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public DateLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DateLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern, locPattern);
+ }
+
+ // --------------------------------------------------------- Methods
+
+ /**
+ * Returns whether date formatting is lenient.
+ *
+ * @return true if the <code>DateFormat</code> used for formatting is lenient
+ * @see java.text.DateFormat#isLenient
+ */
+ public boolean isLenient() {
+ return isLenient;
+ }
+
+ /**
+ * Specify whether or not date-time parsing should be lenient.
+ *
+ * @param lenient true if the <code>DateFormat</code> used for formatting should be lenient
+ * @see java.text.DateFormat#setLenient
+ */
+ public void setLenient(boolean lenient) {
+ isLenient = lenient;
+ }
+
+ // --------------------------------------------------------- Methods
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception org.apache.commons.beanutils.ConversionException if conversion cannot be performed
+ * successfully
+ */
+ protected Object parse(Object value, String pattern) throws ParseException {
+ SimpleDateFormat formatter = getFormatter(pattern, locale);
+ if (locPattern) {
+ formatter.applyLocalizedPattern(pattern);
+ }
+ else {
+ formatter.applyPattern(pattern);
+ }
+ return formatter.parse((String) value);
+ }
+
+ /**
+ * Gets an appropriate <code>SimpleDateFormat</code> for given locale,
+ * default Date format pattern is not provided.
+ */
+ private SimpleDateFormat getFormatter(String pattern, Locale locale) {
+ // This method is a fix for null pattern, which would cause
+ // Null pointer exception when applied
+ // Note: that many constructors default the pattern to null,
+ // so it only makes sense to handle nulls gracefully
+ if(pattern == null) {
+ pattern = locPattern ?
+ new SimpleDateFormat().toLocalizedPattern() : new SimpleDateFormat().toPattern();
+ log.warn("Null pattern was provided, defaulting to: " + pattern);
+ }
+ SimpleDateFormat format = new SimpleDateFormat(pattern, locale);
+ format.setLenient(isLenient);
+ return format;
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DateLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DecimalLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DecimalLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DecimalLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import org.apache.commons.beanutils.locale.BaseLocaleConverter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.text.DecimalFormat;
+import java.text.ParseException;
+import java.util.Locale;
+
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.lang.Decimal</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ * @author Yoav Shapira
+ * @since 1.7
+ */
+
+public class DecimalLocaleConverter extends BaseLocaleConverter {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+ /** All logging goes through this logger */
+ private static Log log = LogFactory.getLog(DecimalLocaleConverter.class);
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public DecimalLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DecimalLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public DecimalLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DecimalLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public DecimalLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DecimalLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ this(null, locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public DecimalLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DecimalLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public DecimalLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DecimalLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public DecimalLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DecimalLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern, locPattern);
+
+ }
+
+ // --------------------------------------------------------- Methods
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ protected Object parse(Object value, String pattern) throws ParseException {
+ // DecimalFormat is not thread safe so best to construct one each time
+ DecimalFormat formatter = (DecimalFormat) DecimalFormat.getInstance(locale);
+ // if some constructors default pattern to null, it makes only sense to handle null pattern gracefully
+ if (pattern != null) {
+ if (locPattern) {
+ formatter.applyLocalizedPattern(pattern);
+ } else {
+ formatter.applyPattern(pattern);
+ }
+ } else {
+ log.warn("No pattern provided, using default.");
+ }
+
+ return formatter.parse((String) value);
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DecimalLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DoubleLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DoubleLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DoubleLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+
+import java.text.ParseException;
+import java.util.Locale;
+
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.lang.Double</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class DoubleLocaleConverter extends DecimalLocaleConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public DoubleLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DoubleLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public DoubleLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DoubleLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public DoubleLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DoubleLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public DoubleLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DoubleLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public DoubleLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DoubleLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public DoubleLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public DoubleLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern);
+ }
+
+ protected Object parse(Object value, String pattern) throws ParseException {
+ Number result = (Number) super.parse(value, pattern);
+ if (result instanceof Long) {
+ return new Double(result.doubleValue());
+ } else {
+ return (result);
+ }
+ }
+
+
+}
+
+
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/DoubleLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/FloatLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/FloatLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/FloatLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import org.apache.commons.beanutils.ConversionException;
+
+import java.util.Locale;
+import java.text.ParseException;
+
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.math.BigDecimal</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class FloatLocaleConverter extends DecimalLocaleConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public FloatLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public FloatLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public FloatLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public FloatLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public FloatLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public FloatLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public FloatLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public FloatLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public FloatLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public FloatLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public FloatLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public FloatLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern);
+ }
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type. This method will return Float value or throw exception if value
+ * can not be stored in the Float.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ protected Object parse(Object value, String pattern) throws ParseException {
+ final Number parsed = (Number) super.parse(value, pattern);
+ if( Math.abs(parsed.doubleValue() - parsed.floatValue()) > parsed.floatValue() * 0.00001 ) {
+ throw new ConversionException("Suplied number is not of type Float: "+parsed.longValue());
+ }
+ return new Float(parsed.floatValue()); // unlike superclass it returns Float type
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/FloatLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/IntegerLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/IntegerLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/IntegerLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import org.apache.commons.beanutils.ConversionException;
+
+import java.util.Locale;
+import java.text.ParseException;
+
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.lang.Integer</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class IntegerLocaleConverter extends DecimalLocaleConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+
+ public IntegerLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public IntegerLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public IntegerLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public IntegerLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public IntegerLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public IntegerLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public IntegerLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public IntegerLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public IntegerLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public IntegerLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public IntegerLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public IntegerLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern, locPattern);
+ }
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type. This method will return Integer type.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ protected Object parse(Object value, String pattern) throws ParseException {
+ final Number parsed = (Number) super.parse(value, pattern);
+ if (parsed.longValue() != parsed.intValue()) {
+ throw new ConversionException("Suplied number is not of type Integer: " + parsed.longValue());
+ }
+ return new Integer(parsed.intValue()); // unlike superclass it will return proper Integer
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/IntegerLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/LongLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/LongLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/LongLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import java.util.Locale;
+
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.lang.Long</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class LongLocaleConverter extends DecimalLocaleConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public LongLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public LongLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public LongLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public LongLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public LongLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public LongLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public LongLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public LongLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public LongLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public LongLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public LongLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public LongLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern, locPattern);
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/LongLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/ShortLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/ShortLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/ShortLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import java.util.Locale;
+
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.lang.Short</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class ShortLocaleConverter extends DecimalLocaleConverter {
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public ShortLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ShortLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public ShortLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ShortLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public ShortLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ShortLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public ShortLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ShortLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public ShortLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ShortLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public ShortLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public ShortLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern);
+ }
+}
+
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/ShortLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlDateLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlDateLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlDateLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import java.sql.Date;
+import java.text.ParseException;
+import java.util.Locale;
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.sql.Date</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class SqlDateLocaleConverter extends DateLocaleConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public SqlDateLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlDateLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public SqlDateLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlDateLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public SqlDateLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlDateLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public SqlDateLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlDateLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public SqlDateLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlDateLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public SqlDateLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlDateLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern, locPattern);
+ }
+
+
+ // --------------------------------------------------------- Methods
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ protected Object parse(Object value, String pattern) throws ParseException {
+
+ return new Date(((java.util.Date) super.parse((String) value, pattern)).getTime());
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlDateLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlTimeLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlTimeLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlTimeLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import java.sql.Time;
+import java.text.ParseException;
+import java.util.Locale;
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.sql.Time</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class SqlTimeLocaleConverter extends DateLocaleConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public SqlTimeLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimeLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public SqlTimeLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimeLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public SqlTimeLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimeLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public SqlTimeLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimeLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public SqlTimeLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimeLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public SqlTimeLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimeLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern, locPattern);
+ }
+
+ // --------------------------------------------------------- Methods
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ protected Object parse(Object value, String pattern) throws ParseException {
+
+ return new Time(((java.util.Date) super.parse((String) value, pattern)).getTime());
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlTimeLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlTimestampLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlTimestampLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlTimestampLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import java.sql.Timestamp;
+import java.text.ParseException;
+import java.util.Locale;
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive String into a <code>java.sql.Timestamp</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class SqlTimestampLocaleConverter extends DateLocaleConverter {
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public SqlTimestampLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimestampLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public SqlTimestampLocaleConverter(Locale locale) {
+
+ this(locale, (String) null);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimestampLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public SqlTimestampLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimestampLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public SqlTimestampLocaleConverter(Object defaultValue) {
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimestampLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public SqlTimestampLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimestampLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public SqlTimestampLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public SqlTimestampLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern, locPattern);
+ }
+
+ // --------------------------------------------------------- Methods
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ protected Object parse(Object value, String pattern) throws ParseException {
+
+ return new Timestamp(((java.util.Date) super.parse(value, pattern)).getTime());
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/SqlTimestampLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/StringLocaleConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/StringLocaleConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/StringLocaleConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import org.apache.commons.beanutils.locale.BaseLocaleConverter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+
+/**
+ * <p>Standard {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * implementation that converts an incoming
+ * locale-sensitive object into a <code>java.lang.String</code> object,
+ * optionally using a default value or throwing a
+ * {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.</p>
+ *
+ * @author Yauheny Mikulski
+ */
+
+public class StringLocaleConverter extends BaseLocaleConverter {
+
+ // ----------------------------------------------------- Instance Variables
+
+ /** All logging goes through this logger */
+ private static Log log = LogFactory.getLog(StringLocaleConverter.class); //msz fix
+
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ */
+ public StringLocaleConverter() {
+
+ this(false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public StringLocaleConverter(boolean locPattern) {
+
+ this(Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ */
+ public StringLocaleConverter(Locale locale) {
+
+ this(locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public StringLocaleConverter(Locale locale, boolean locPattern) {
+
+ this(locale, (String) null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public StringLocaleConverter(Locale locale, String pattern) {
+
+ this(locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will throw a {@link org.apache.commons.beanutils.ConversionException}
+ * if a conversion error occurs.
+ *
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public StringLocaleConverter(Locale locale, String pattern, boolean locPattern) {
+
+ super(locale, pattern, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine and an unlocalized pattern is used
+ * for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ */
+ public StringLocaleConverter(Object defaultValue) {
+
+ this(defaultValue, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. The locale is the default locale for
+ * this instance of the Java Virtual Machine.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public StringLocaleConverter(Object defaultValue, boolean locPattern) {
+
+ this(defaultValue, Locale.getDefault(), locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ */
+ public StringLocaleConverter(Object defaultValue, Locale locale) {
+
+ this(defaultValue, locale, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public StringLocaleConverter(Object defaultValue, Locale locale, boolean locPattern) {
+
+ this(defaultValue, locale, null, locPattern);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs. An unlocalized pattern is used for the convertion.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ */
+ public StringLocaleConverter(Object defaultValue, Locale locale, String pattern) {
+
+ this(defaultValue, locale, pattern, false);
+ }
+
+ /**
+ * Create a {@link org.apache.commons.beanutils.locale.LocaleConverter}
+ * that will return the specified default value
+ * if a conversion error occurs.
+ *
+ * @param defaultValue The default value to be returned
+ * @param locale The locale
+ * @param pattern The convertion pattern
+ * @param locPattern Indicate whether the pattern is localized or not
+ */
+ public StringLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
+
+ super(defaultValue, locale, pattern, locPattern);
+ }
+
+ // --------------------------------------------------------- Methods
+
+ /**
+ * Convert the specified locale-sensitive input object into an output object of the
+ * specified type.
+ *
+ * @param value The input object to be converted
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ protected Object parse(Object value, String pattern) throws ParseException {
+
+ String result = null;
+
+ if ((value instanceof Integer) ||
+ (value instanceof Long) ||
+ (value instanceof BigInteger) ||
+ (value instanceof Byte) ||
+ (value instanceof Short)) {
+
+ result = getDecimalFormat(locale, pattern).format(((Number) value).longValue());
+ }
+ else if ((value instanceof Double) ||
+ (value instanceof BigDecimal) ||
+ (value instanceof Float)) {
+
+ result = getDecimalFormat(locale, pattern).format(((Number) value).doubleValue());
+ }
+ else if (value instanceof Date) { // java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp
+
+ SimpleDateFormat dateFormat =
+ new SimpleDateFormat(pattern, locale);
+
+ result = dateFormat.format(value);
+ }
+ else {
+ result = value.toString();
+ }
+
+ return result;
+ }
+
+ /**
+ * Make an instance of DecimalFormat.
+ *
+ * @param locale The locale
+ * @param pattern The pattern is used for the convertion
+ *
+ * @exception ConversionException if conversion cannot be performed
+ * successfully
+ */
+ private DecimalFormat getDecimalFormat(Locale locale, String pattern) {
+
+ DecimalFormat numberFormat = (DecimalFormat) NumberFormat.getInstance(locale);
+
+ // if some constructors default pattern to null, it makes only sense to handle null pattern gracefully
+ if (pattern != null) {
+ if (locPattern) {
+ numberFormat.applyLocalizedPattern(pattern);
+ } else {
+ numberFormat.applyPattern(pattern);
+ }
+ } else {
+ log.warn("No pattern provided, using default.");
+ }
+
+ return numberFormat;
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/StringLocaleConverter.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/package.html
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/package.html 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/converters/package.html 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,12 @@
+<html>
+<head>
+<title>Package Documentation for org.apache.commons.beanutils.locale.converters</title>
+</head>
+<body bgcolor="white">
+<p>Standard implementations of the locale-aware
+<code>LocaleConverter</code>
+interface that are pre-registered with locale-aware
+<code>LocaleConvertUtils</code>
+at startup time.</p>
+</body>
+</html>
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/package.html
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/package.html 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/locale/package.html 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title>Package Documentation for org.apache.commons.beanutils.locale Package</title>
+</head>
+<body bgcolor="white">
+<p>Locale-aware extensions of the standard beanutils classes.
+This package allows locale-dependent population of JavaBeans.</p>
+
+</body>
+</html>
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/package.html
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/package.html 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/beanutils/package.html 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,990 @@
+<html>
+<head>
+<title>Package Documentation for org.apache.commons.beanutils Package</title>
+</head>
+<body bgcolor="white">
+<p>The <em>Bean Introspection Utilities</em> component of the Jakarta Commons
+subproject offers low-level utility classes that assist in getting and setting
+property values on Java classes that follow the naming design patterns outlined
+in the JavaBeans Specification, as well as mechanisms for dynamically defining
+and accessing bean properties.</p>
+
+<h1>Table of Contents</h1>
+
+<ol>
+<li><a href="#overview">Overview</a>
+ <ul>
+ <li><a href="#overview.background">Background</a></li>
+ <li><a href="#overview.dependencies">External Dependencies</a></li>
+ </ul></li>
+<li><a href="#standard">Standard JavaBeans</a>
+ <ul>
+ <li><a href="#standard.background">Background</a></li>
+ <li><a href="#standard.basic">Basic Property Access</a></li>
+ <li><a href="#standard.nested">Nested Property Access</a></li>
+ </ul></li>
+<li><a href="#dynamic">Dynamic Beans (DynaBeans)</a>
+ <ul>
+ <li><a href="#dynamic.background">Background</a></li>
+ <li><a href="#dynamic.basic">BasicDynaBean and BasicDynaClass</a></li>
+ <li><a href="#dynamic.resultSet">ResultSetDynaClass (Wraps ResultSet in DynaBeans)</a></li>
+ <li><a href="#dynamic.rowSet">RowSetDynaClass (Disconnected ResultSet as DynaBeans)</a></li>
+ <li><a href="#dynamic.wrap">WrapDynaBean and WrapDynaClass</a></li>
+ <li><a href="#dynamic.lazy"><i>Lazy</i> DynaBeans</a></li>
+ </ul></li>
+<li><a href="#conversion">Data Type Conversions</a>
+ <ul>
+ <li><a href="#conversion.background">Background</a></li>
+ <li><a href="#conversion.beanutils">BeanUtils and ConvertUtils
+ Conversions</a></li>
+ <li><a href="#conversion.defining">Defining Your Own Converters</a></li>
+ <li><a href="#conversion.i18n">Locale Aware Conversions</a></li>
+ </ul></li>
+<li><a href="#instances">Utility Objects And Static Utility Classes</a>
+ <ul>
+ <li><a href="#instances.background">Background</a></li>
+ </ul></li>
+<li><a href="#collections">Collections</a>
+ <ul>
+ <li><a href="#bean-comparator">Comparing Beans</a></li>
+ <li><a href="#bean-property-closure">Operating On Collections Of Beans</a></li>
+ <li><a href="#bean-property-predicate">Querying Or Filtering Collections Of Beans</a></li>
+ <li><a href="#bean-property-transformer">Transforming Collections Of Beans</a></li>
+ </ul></li>
+<li><a href="#FAQ">Frequently Asked Questions</a>
+ <ul>
+ <li><a href="#FAQ.property">Why Can't BeanUtils Find My Method?</a></li>
+ <li><a href="#FAQ.bc.order">How Do I Set The BeanComparator Order To Be Ascending/Descending?</a></li>
+ </ul></li>
+<li><a href='#Packaging'>Packaging</a></li>
+</ol>
+
+<a name="overview"></a>
+<h1>Overview</h1>
+
+<a name="overview.background"></a>
+<h3>Background</h3>
+
+<p>The <em>JavaBeans</em> name comes from a
+<a href="http://java.sun.com/products/javabeans/">Java API specification</a>
+for a component architecture for the Java language. Writing Java classes that
+conform to the JavaBeans design patterns makes it easier for Java developers
+to understand the functionality provided by your class, as well as allowing
+JavaBeans-aware tools to use Java's <em>introspection</em> capabilities to
+learn about the properties and operations provided by your class, and present
+them in a visually appealing manner in development tools.</p>
+
+<p>The <a href="http://java.sun.com/products/javabeans/docs/spec.html">JavaBeans
+Specification</a> describes the complete set of characteristics that makes
+an arbitrary Java class a JavaBean or not -- and you should consider reading
+this document to be an important part of developing your Java programming
+skills. However, the required characteristics of JavaBeans that are
+important for most development scenarios are listed here:</p>
+<ul>
+<li>The class must be <strong>public</strong>, and provide a
+ <strong>public</strong> constructor that accepts no arguments. This allows
+ tools and applications to dynamically create new instances of your bean,
+ without necessarily knowing what Java class name will be used ahead of
+ time, like this:
+<pre>
+ String className = ...;
+ Class beanClass = Class.forName(className);
+ Object beanInstance = beanClass.newInstance();
+</pre></li>
+<li>As a necessary consequence of having a no-arguments constructor,
+ configuration of your bean's behavior must be accomplished separately
+ from its instantiation. This is typically done by defining a set of
+ <em>properties</em> of your bean, which can be used to modify its behavior
+ or the data that the bean represents. The normal convention for
+ property names is that they start with a lower case letter, and be
+ comprised only of characters that are legal in a Java identifier.</li>
+<li>Typically, each bean property will have a public <em>getter</em> and
+ <em>setter</em> method that are used to retrieve or define the property's
+ value, respectively. The JavaBeans Specification defines a design
+ pattern for these names, using <code>get</code> or <code>set</code> as the
+ prefix for the property name with it's first character capitalized. Thus,
+ you a JavaBean representing an employee might have
+ (among others) properties named <code>firstName</code>,
+ <code>lastName</code>, and <code>hireDate</code>, with method signatures
+ like this:
+<pre>
+ public class Employee {
+ public Employee(); // Zero-arguments constructor
+ public String getFirstName();
+ public void setFirstName(String firstName);
+ public String getLastName();
+ public void setLastName(String lastName);
+ public Date getHireDate();
+ public void setHireDate(Date hireDate);
+ public boolean isManager();
+ public void setManager(boolean manager);
+ public String getFullName();
+ }
+</pre></li>
+<li>As you can see from the above example, there is a special variant allowed
+ for boolean properties -- you can name the <em>getter</em> method with a
+ <code>is</code> prefix instead of a <code>get</code> prefix if that makes
+ for a more understandable method name.</li>
+<li>If you have both a <em>getter</em> and a <em>setter</em> method for a
+ property, the data type returned by the <em>getter</em> must match the
+ data type accepted by the <em>setter</em>. In addition, it is contrary
+ to the JavaBeans specification to have more than one <em>setter</em>
+ with the same name, but different property types.</li>
+<li>It is not required that you provide a <em>getter</em> and a
+ <em>setter</em> for every property. In the example above, the
+ <code>fullName</code> property is read-only, because there is no
+ <em>setter</em> method. It is also possible, but less common, to provide
+ write-only properties.</li>
+<li>It is also possible to create a JavaBean where the <em>getter</em> and
+ <em>setter</em> methods do not match the naming pattern described above.
+ The standard JavaBeans support classes in the Java language, as well as
+ all classes in the BeanUtils package, allow you to describe the actual
+ property method names in a <code>BeanInfo</code> class associated with
+ your bean class. See the JavaBeans Specification for full details.</li>
+<li>The JavaBeans Specification also describes many additional design patterns
+ for event listeners, wiring JavaBeans together into component hierarchies,
+ and other useful features that are beyond the scope of the BeanUtils
+ package.</li>
+</ul>
+
+<p>Using standard Java coding techniques, it is very easy to deal with
+JavaBeans if you know ahead of time which bean classes you will be using, and
+which properties you are interested in:</p>
+<pre>
+ Employee employee = ...;
+ System.out.println("Hello " + employee.getFirstName() + "!");
+</pre>
+
+<a name="overview.dependencies"></a>
+<h3>External Dependencies</h3>
+
+<p>The <em>commons-beanutils</em> package requires that the following
+additional packages be available in the application's class path at runtime:
+</p>
+<ul>
+<li><a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-collections">
+Collections Package (Jakarta Commons)</a>, version 1.0 or later</li>
+<li><a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-logging">
+Logging Package (Jakarta Commons)</a>, version 1.0 or later</li>
+</ul>
+
+
+<a name="standard"></a>
+<h1>Standard JavaBeans</h1>
+
+<a name="standard.background"></a>
+<h3>Background</h3>
+
+<p>As described above, the standard facilities of the Java programming language
+make it easy and natural to access the property values of your beans using
+calls to the appropriate getter methods.
+But what happens in more sophisticated environments where you do not
+necessarily know ahead of time which bean class you are going to be using,
+or which property you want to retrieve or modify? The Java language provides
+classes like <code>java.beans.Introspector</code>, which can examine a Java
+class at runtime and identify for you the names of the property getter and
+setter methods, plus the <em>Reflection</em> capabilities to dynamically call
+such a method. However, these APIs can be difficult to use, and expose the
+application developer to many unnecessary details of the underlying structure
+of Java classes. The APIs in the BeanUtils package are intended to simplify
+getting and setting bean properties dynamically, where the objects you are
+accessing -- and the names of the properties you care about -- are determined
+at runtime in your application, rather than as you are writing and compiling
+your application's classes.</p>
+
+<p>This is the set of needs that are satisfied by the static methods of the
+<a href="PropertyUtils.html">PropertyUtils</a>
+class, which are described further in this section. First, however, some
+further definitions will prove to be useful:</p>
+
+<p>The general set of possible property types supported by a JavaBean can be
+broken into three categories -- some of which are supported by the standard
+JavaBeans specification, and some of which are uniquely supported by the
+<em>BeanUtils</em> package:</p>
+<ul>
+<li><strong>Simple</strong> - Simple, or scalar, properties have a single
+ value that may be retrieved or modified. The underlying property type
+ might be a Java language primitive (such as <code>int</code>, a simple
+ object (such as a <code>java.lang.String</code>), or a more complex
+ object whose class is defined either by the Java language, by the
+ application, or by a class library included with the application.</li>
+<li><strong>Indexed</strong> - An indexed property stores an ordered collection
+ of objects (all of the same type) that can be individually accessed by an
+ integer-valued, non-negative index (or subscript). Alternatively, the
+ entire set of values may be set or retrieved using an array.
+ As an extension to the JavaBeans specification, the
+ <em>BeanUtils</em> package considers any property whose underlying data
+ type is <code>java.util.List</code> (or an implementation of List) to be
+ indexed as well.</li>
+<li><strong>Mapped</strong> - As an extension to standard JavaBeans APIs,
+ the <em>BeanUtils</em> package considers any property whose underlying
+ value is a <code>java.util.Map</code> to be "mapped". You can set and
+ retrieve individual values via a String-valued key.</li>
+</ul>
+
+<p>A variety of API methods are provided in the <a href="PropertyUtils.html">
+PropertyUtils</a> class to get and set property values of all of these types.
+In the code fragments below, assume that there are two bean classes defined
+with the following method signatures:</p>
+<pre>
+ public class Employee {
+ public Address getAddress(String type);
+ public void setAddress(String type, Address address);
+ public Employee getSubordinate(int index);
+ public void setSubordinate(int index, Employee subordinate);
+ public String getFirstName();
+ public void setFirstName(String firstName);
+ public String getLastName();
+ public void setLastName(String lastName);
+ }
+</pre>
+
+<a name="standard.basic"></a>
+<h3>Basic Property Access</h3>
+
+<p>Getting and setting <strong>simple</strong> property values is, well,
+simple :-). Check out the following API signatures in the Javadocs:</p>
+
+<ul>
+<li><a href="PropertyUtils.html#getSimpleProperty(java.lang.Object,java.lang.String)">
+ PropertyUtils.getSimpleProperty(Object bean, String name)</a></li>
+<li><a href="PropertyUtils.html#setSimpleProperty(java.lang.Object,java.lang.String,java.lang.Object)">
+ PropertyUtils.setSimpleProperty(Object bean, String name, Object value)</a></li>
+</ul>
+
+<p>Using these methods, you might dynamically manipulate the employee's name
+in an application:</p>
+<pre>
+ Employee employee = ...;
+ String firstName = (String)
+ PropertyUtils.getSimpleProperty(employee, "firstName");
+ String lastName = (String)
+ PropertyUtils.getSimpleProperty(employee, "lastName");
+ ... manipulate the values ...
+ PropertyUtils.setSimpleProperty(employee, "firstName", firstName);
+ PropertyUtils.setSimpleProperty(employee, "lastName", lastName);
+</pre>
+
+<p>For <strong>indexed</strong> properties, you have two choices - you can
+either build a subscript into the "property name" string, using square
+brackets, or you can specify the subscript in a separate argument to the
+method call:</p>
+
+<ul>
+<li><a href="PropertyUtils.html#getIndexedProperty(java.lang.Object,java.lang.String)">
+ PropertyUtils.getIndexedProperty(Object bean, String name)</a></li>
+<li><a href="PropertyUtils.html#getIndexedProperty(java.lang.Object,java.lang.String,int)">
+ PropertyUtils.getIndexedProperty(Object bean, String name, int index)</a></li>
+<li><a href="PropertyUtils.html#setIndexedProperty(java.lang.Object,java.lang.String,java.lang.Object)">
+ PropertyUtils.setIndexedProperty(Object bean, String name, Object value)</a></li>
+<li><a href="PropertyUtils.html#setIndexedProperty(java.lang.Object,java.lang.String,int,java.lang.Object)">
+ PropertyUtils.setIndexedProperty(Object bean, String name, int index, Object value)</a></li>
+</ul>
+
+<p>Only integer constants are allowed when you add a subscript to the property
+name. If you need to calculate the index of the entry you wish to retrieve,
+you can use String concatenation to assemble the property name expression.
+For example, you might do either of the following:</p>
+<pre>
+ Employee employee = ...;
+ int index = ...;
+ String name = "subordinate[" + index + "]";
+ Employee subordinate = (Employee)
+ PropertyUtils.getIndexedProperty(employee, name);
+
+ Employee employee = ...;
+ int index = ...;
+ Employee subordinate = (Employee)
+ PropertyUtils.getIndexedProperty(employee, "subordinate", index);
+</pre>
+
+<p>In a similar manner, there are two possible method signatures for getting
+and setting <strong>mapped</strong> properties. The difference is that the
+extra argument is surrounded by parentheses ("(" and ")") instead of square
+brackets, and it is considered to be a String-value key used to get or set
+the appropriate value from an underlying map.</p>
+
+<ul>
+<li><a href="PropertyUtils.html#getMappedProperty(java.lang.Object,java.lang.String)">
+ PropertyUtils.getMappedProperty(Object bean, String name)</a></li>
+<li><a href="PropertyUtils.html#getMappedProperty(java.lang.Object,java.lang.String,java.lang.String)">
+ PropertyUtils.getMappedProperty(Object bean, String name, String key)</a></li>
+<li><a href="PropertyUtils.html#setMappedProperty(java.lang.Object,java.lang.String,java.lang.Object)">
+ PropertyUtils.setMappedProperty(Object bean, String name, Object value)</a></li>
+<li><a href="PropertyUtils.html#setMappedProperty(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)">
+ PropertyUtils.setMappedProperty(Object bean, String name, String key, Object value)</a></li>
+</ul>
+
+<p>You can, for example, set the employee's home address in either of these
+two manners:</p>
+
+<pre>
+ Employee employee = ...;
+ Address address = ...;
+ PropertyUtils.setMappedProperty(employee, "address(home)", address);
+
+ Employee employee = ...;
+ Address address = ...;
+ PropertyUtils.setMappedProperty(employee, "address", "home", address);
+</pre>
+
+<a name="standard.nested"></a>
+<h3>Nested Property Access</h3>
+
+<p>In all of the examples above, we have assumed that you wished to retrieve
+the value of a property of the bean being passed as the first argument to a
+PropertyUtils method. However, what if the property value you retrieve is
+really a Java object, and you wish to retrieve a property of <em>that</em>
+object instead?</p>
+
+<p>For example, assume we really wanted the <code>city</code> property of the
+employee's home address. Using standard Java programming techniques for direct
+access to the bean properties, we might write:</p>
+
+<pre>
+ String city = employee.getAddress("home").getCity();
+</pre>
+
+<p>The equivalent mechanism using the PropertyUtils class is called
+<strong>nested</strong> property access. To use this approach, you concatenate
+together the property names of the access path, using "." separators -- very
+similar to the way you can perform nested property access in JavaScript.</p>
+
+<ul>
+<li><a href="PropertyUtils.html#getNestedProperty(java.lang.Object,java.lang.String)">
+ PropertyUtils.getNestedProperty(Object bean, String name)</a></li>
+<li><a href="PropertyUtils.html#setNestedProperty(java.lang.Object,java.lang.String,java.lang.Object)">
+ PropertyUtils.setNestedProperty(Object bean, String name, Object value)</a></li>
+</ul>
+
+<p>The PropertyUtils equivalent to the above Java expression would be:</p>
+
+<pre>
+ String city = (String)
+ PropertyUtils.getNestedProperty(employee, "address(home).city");
+</pre>
+
+<p>Finally, for convenience, PropertyUtils provides method signatures that
+accept any arbitrary combination of simple, indexed, and mapped property
+access, using any arbitrary level of nesting:</p>
+
+<ul>
+<li><a href="PropertyUtils.html#getProperty(java.lang.Object,java.lang.String)">
+ PropertyUtils.getProperty(Object bean, String name)</a></li>
+<li><a href="PropertyUtils.html#setProperty(java.lang.Object,java.lang.String,java.lang.Object)">
+ PropertyUtils.setProperty(Object bean, String name, Object value)</a></li>
+</ul>
+
+<p>which you might use like this:</p>
+
+<pre>
+ Employee employee = ...;
+ String city = (String) PropertyUtils.getProperty(employee,
+ "subordinate[3].address(home).city");
+</pre>
+
+<a name="dynamic"></a>
+<h1>Dynamic Beans (DynaBeans)</h1>
+
+<a name="dynamic.background"></a>
+<h3>Background</h3>
+
+<p>The <a href="PropertyUtils.html">PropertyUtils</a> class described in the
+preceding section is designed to provide dynamic property access on existing
+JavaBean classes, without modifying them in any way. A different use case for
+dynamic property access is when you wish to represent a dynamically calculated
+set of property values as a JavaBean, but <em>without</em> having to actually
+write a Java class to represent these properties. Besides the effort savings
+in not having to create and maintain a separate Java class, this ability also
+means you can deal with situations where the set of properties you care about
+is determined dynamically (think of representing the result set of an SQL
+select as a set of JavaBeans ...).</p>
+
+<p>To support this use case, the <em>BeanUtils</em> package provides the
+<a href="DynaBean.html">DynaBean</a> interface, which must be implemented by a
+bean class actually implementing the interface's methods, and the associated
+<a href="DynaClass.html">DynaClass</a> interface that defines the set of
+properties supported by a particular group of DynaBeans, in much the same way
+that <code>java.lang.Class</code> defines the set of properties supported by
+all instances of a particular JavaBean class.</p>
+
+<p>For example, the <code>Employee</code> class used in the examples above
+might be implemented as a DynaBean, rather than as a standard JavaBean. You
+can access its properties like this:</p>
+
+<pre>
+ DynaBean employee = ...; // Details depend on which
+ // DynaBean implementation you use
+ String firstName = (String) employee.get("firstName");
+ Address homeAddress = (Address) employee.get("address", "home");
+ Object subordinate = employee.get("subordinate", 2);
+</pre>
+
+<p>One very important convenience feature should be noted: <em>the
+PropertyUtils property getter and setter methods understand how to access
+properties in DynaBeans</em>. Therefore, if the bean you pass as the first
+argument to, say, <code>PropertyUtils.getSimpleProperty()</code> is really a
+DynaBean implementation, the call will get converted to the appropriate
+DynaBean getter method transparently. Thus, you can base your application's
+dynamic property access totally on the PropertyUtils APIs, if you wish, and
+use them to access either standard JavaBeans or DynaBeans without having to
+care ahead of time how a particular bean is implemented.</p>
+
+<p>Because DynaBean and DynaClass are interfaces, they may be implemented
+multiple times, in different ways, to address different usage scenarios. The
+following subsections describe the implementations that are provided as a part
+of the standard <em>BeanUtils</em> package, although you are encouraged to
+provide your own custom implementations for cases where the standard
+implementations are not sufficient.</p>
+
+<a name="dynamic.basic"></a>
+<h3><code>BasicDynaBean</code> and <code>BasicDynaClass</code></h3>
+
+<p>The <a href="BasicDynaBean.html">BasicDynaBean</a> and
+<a href="BasicDynaClass.html">BasicDynaClass</a> implementation provides a
+basic set of
+dynamic property capabilities where you want to dynamically define the
+set of properties (described by instances of <a href="DynaProperty.html">
+DynaProperty</a>). You start by defining the DynaClass that establishes
+the set of properties you care about:</p>
+
+<pre>
+ DynaProperty[] props = new DynaProperty[]{
+ new DynaProperty("address", java.util.Map.class),
+ new DynaProperty("subordinate", mypackage.Employee[].class),
+ new DynaProperty("firstName", String.class),
+ new DynaProperty("lastName", String.class)
+ };
+ BasicDynaClass dynaClass = new BasicDynaClass("employee", null, props);
+</pre>
+
+<p>Note that the 'dynaBeanClass' argument (in the constructor of
+<code>BasicDynaClass</code>) can have the value of <code>null</code>. In this
+case, the value of <code>dynaClass.getDynaBeanClass</code> will just be the
+<code>Class</code> for BasicDynaBean.</p>
+
+<p>Next, you use the <code>newInstance()</code> method of this DynaClass to
+create new DynaBean instances that conform to this DynaClass, and populate
+its initial property values (much as you would instantiate a new standard
+JavaBean and then call its property setters):</p>
+
+<pre>
+ DynaBean employee = dynaClass.newInstance();
+ employee.set("address", new HashMap());
+ employee.set("subordinate", new mypackage.Employee[0]);
+ employee.set("firstName", "Fred");
+ employee.set("lastName", "Flintstone");
+</pre>
+
+<p>Note that the DynaBean class was declared to be
+<code>DynaBean</code> instead of <code>BasicDynaBean</code>. In
+general, if you are using DynaBeans, you will not want to care about the
+actual implementation class that is being used -- you only care about
+declaring that it is a <code>DynaBean</code> so that you can use the
+DynaBean APIs.</p>
+
+<p>As stated above, you can pass a DynaBean instance as the first argument
+to a <code>PropertyUtils</code> method that gets and sets properties, and it
+will be interpreted as you expect -- the dynamic properties of the DynaBean
+will be retrieved or modified, instead of underlying properties on the
+actual BasicDynaBean implementation class.</p>
+
+<a name="dynamic.resultSet"></a>
+<h3><code>ResultSetDynaClass</code> (Wraps ResultSet in DynaBeans)</h3>
+
+<p>A very common use case for DynaBean APIs is to wrap other collections of
+"stuff" that do not normally present themselves as JavaBeans. One of the most
+common collections that would be nice to wrap is the
+<code>java.sql.ResultSet</code> that is returned when you ask a JDBC driver
+to perform a SQL SELECT statement. Commons BeanUtils offers a standard
+mechanism for making each row of the result set visible as a DynaBean,
+which you can utilize as shown in this example:</p>
+<pre>
+ Connection conn = ...;
+ Statement stmt = conn.createStatement();
+ ResultSet rs = stmt.executeQuery
+ ("select account_id, name from customers");
+ Iterator rows = (new ResultSetDynaClass(rs)).iterator();
+ while (rows.hasNext()) {
+ DynaBean row = (DynaBean) rows.next();
+ System.out.println("Account number is " +
+ row.get("account_id") +
+ " and name is " + row.get("name"));
+ }
+ rs.close();
+ stmt.close();
+</pre>
+
+
+<a name="dynamic.rowSet"></a>
+<h3><code>RowSetDynaClass</code> (Disconnected ResultSet as DynaBeans)</h3>
+<p>Although <a href="#dynamic.resultSet"><code>ResultSetDynaClass</code></a> is
+a very useful technique for representing the results of an SQL query as a
+series of DynaBeans, an important problem is that the underlying
+<code>ResultSet</code> must remain open throughout the period of time that the
+rows are being processed by your application. This hinders the ability to use
+<code>ResultSetDynaClass</code> as a means of communicating information from
+the model layer to the view layer in a model-view-controller architecture
+such as that provided by the <a href="http://jakarta.apache.org/struts/">Struts
+Framework</a>, because there is no easy mechanism to assure that the result set
+is finally closed (and the underlying <code>Connection</code> returned to its
+connection pool, if you are using one).</p>
+
+<p>The <code>RowSetDynaClass</code> class represents a different approach to
+this problem. When you construct such an instance, the underlying data is
+<em>copied</em> into a set of in-memory DynaBeans that represent the result.
+The advantage of this technique, of course, is that you can immediately close
+the ResultSet (and the corresponding Statement), normally before you even
+process the actual data that was returned. The disadvantage, of course, is
+that you must pay the performance and memory costs of copying the result data,
+and the result data must fit entirely into available heap memory. For many
+environments (particularly in web applications), this tradeoff is usually
+quite beneficial.</p>
+
+<p>As an additional benefit, the <code>RowSetDynaClass</code> class is defined
+to implement <code>java.io.Serializable</code>, so that it (and the
+DynaBeans that correspond to each row of the result) can be conveniently
+serialized and deserialized (as long as the underlying column values are
+also Serializable). Thus, <code>RowSetDynaClass</code> represents a very
+convenient way to transmit the results of an SQL query to a remote Java-based
+client application (such as an applet).</p>
+
+<p>The normal usage pattern for a <code>RowSetDynaClass</code> will look
+something like this:</p>
+<pre>
+ Connection conn = ...; // Acquire connection from pool
+ Statement stmt = conn.createStatement();
+ ResultSet rs = stmt.executeQuery("SELECT ...");
+ RowSetDynaClass rsdc = new RowSetDynaClass(rs);
+ rs.close();
+ stmt.close();
+ ...; // Return connection to pool
+ List rows = rsdc.getRows();
+ ...; // Process the rows as desired
+</pre>
+
+
+<a name="dynamic.wrap"></a>
+<h3><code>WrapDynaBean</code> and <code>WrapDynaClass</code></h3>
+
+<p>OK, you've tried the DynaBeans APIs and they are cool -- very simple
+<code>get()</code> and <code>set()</code> methods provide easy access to all
+of the dynamically defined simple, indexed, and mapped properties of your
+DynaBeans. You'd like to use the DynaBean APIs to access <strong>all</strong>
+of your beans, but you've got a bunch of existing standard JavaBeans classes
+to deal with as well. This is where the
+<a href="WrapDynaBean.html">WrapDynaBean</a> (and its associated
+<a href="WrapDynaClass.html">WrapDynaClass</a>) come into play. As the name
+implies, a WrapDynaBean is used to "wrap" the DynaBean APIs around an
+existing standard JavaBean class. To use it, simply create the wrapper
+like this:</p>
+
+<pre>
+ MyBean bean = ...;
+ DynaBean wrapper = new WrapDynaBean(bean);
+ String firstName = wrapper.get("firstName");
+</pre>
+
+<p>Note that, although appropriate <code>WrapDynaClass</code> instances are
+created internally, you never need to deal with them.</p>
+
+<a name="dynamic.lazy"></a>
+<h3><i>Lazy</i> DynaBeans (<a href="LazyDynaBean.html">LazyDynaBean</a>,
+<a href="LazyDynaMap.html">LazyDynaMap</a> and <a href="LazyDynaClass.html">LazyDynaClass</a>)</h3>
+
+<p>You bought into the DynaBeans because it saves coding all those POJO JavaBeans but
+ you're here because <i>lazy</i> caught your eye and wondered whats that about?
+ What makes these flavors of DynaBean <i>lazy</i> are the following features:</p>
+ <ul>
+ <li><strong><i>Lazy</i> property addition</strong> - lazy beans use a
+ <code><a href="DynaClass.html">DynaClass</a></code> which implements
+ the <code><a href="MutableDynaClass.html">MutableDynaClass</a></code>
+ interface. This provides the ability to add and remove a DynaClass's
+ properties. <i>Lazy</i> beans use this feature to automatically add
+ a property which doesn't exist to the DynaClass when
+ the <code>set(name, value)</code> method is called.</li>
+ <li><strong><i>Lazy</i> List/Array growth</strong> - If an <i>indexed</i> property is not large
+ enough to accomodate the <code>index</code> being set then the <code>List</code> or
+ <code>Array</code> is automatically <i>grown</i> so that it is.</li>
+ <li><strong><i>Lazy</i> List/Array instantiation</strong> - if an <i>indexed</i>
+ property doesn't exist then calling the <a href="DynaBean.html">DynaBean</a>'s
+ <i>indexed</i> property getter/setter methods (i.e. <code>get(name, index)</code> or
+ <code>set(name, index, value)</code>) results in either a new <code>List</code>
+ or <code>Array</code> being instantiated. If the indexed property has not been
+ defined in the DynaClass then it is automatically added and a default <code>List</code>
+ implementation instantiated.</li>
+ <li><strong><i>Lazy</i> Map instantiation</strong> - if a <i>mapped</i>
+ property doesn't exist then calling the <a href="DynaBean.html">DynaBean</a>'s
+ <i>mapped</i> property getter/setter methods (i.e. <code>get(name, key)</code> or
+ <code>set(name, key, value)</code>) results in a new <code>Map</code>
+ being instantiated. If the mapped property has not been defined in the DynaClass
+ then it is automatically added and a default <code>Map</code> implementation
+ instantiated.</li>
+ <li><strong><i>Lazy</i> Bean instantiation</strong> - if a property is defined in
+ the <code>DynaClass</code> as a <code>DynaBean</code> or regular bean and
+ doesn't exist in the <code>DynaBean</code> then <code>LazyDynaBean</code> wiill
+ try to instantiate the bean using a default empty constructor.</li>
+ </ul>
+
+<p><strong><a href="LazyDynaBean.html">LazyDynaBean</a></strong> is the standard <i>lazy</i> bean
+ implementation. By default it is associated with a <a href="LazyDynaClass.html">LazyDynaClass</a>
+ which implements the <a href="MutableDynaClass.html">MutableDynaClass</a> interface - however
+ it can be used with any <code>MutableDynaClass</code> implementation. The question is <i>how do
+ I use it?</i> - well it can be as simple as creating a new bean and then calling the getters/setters...</p>
+
+<pre>
+ DynaBean dynaBean = new LazyDynaBean();
+
+ dynaBean.set("foo", "bar"); // simple
+
+ dynaBean.set("customer", "title", "Mr"); // mapped
+ dynaBean.set("customer", "surname", "Smith"); // mapped
+
+ dynaBean.set("address", 0, addressLine1); // indexed
+ dynaBean.set("address", 1, addressLine2); // indexed
+ dynaBean.set("address", 2, addressLine3); // indexed
+</pre>
+
+<p><strong><a href="LazyDynaMap.html">LazyDynaMap</a></strong> is a <i>light wieght</i> <code>DynaBean</code>
+ facade to a <code>Map</code> with all the usual <i>lazy</i> features. Its <i>light weight</i> because it doesn't
+ have an associated <code>DynaClass</code> containing all the properties. In fact it actually implements
+ the <code>DynaClass</code> interface itself (and <code>MutableDynaClass</code>) and derives all the <i>DynaClass</i>
+ information from the actual contents of the <code>Map</code>. A <code>LazyDynaMap</code> can be created around an
+ existing <code>Map</code> or can instantiate its own <code>Map</code>. After any <code>DynaBean</code>
+ processing has finished the <code>Map</code> can be retrieved and the DynaBean <i>facade</i> discarded.</p>
+
+<p>If you need a new <code>Map</code> then to use....</p>
+
+<pre>
+ DynaBean dynaBean = new LazyDynaMap(); // create DynaBean
+
+ dynaBean.set("foo", "bar"); // simple
+ dynaBean.set("customer", "title", "Mr"); // mapped
+ dynaBean.set("address", 0, addressLine1); // indexed
+
+ Map myMap = dynaBean.getMap() // retrieve the Map
+</pre>
+<p><i>or</i> to use with an existing <code>Map</code> ....</p>
+
+<pre>
+ Map myMap = .... // exisitng Map
+ DynaBean dynaBean = new LazyDynaMap(myMap); // wrap Map in DynaBean
+ dynaBean.set("foo", "bar"); // set properties
+</pre>
+
+<p><strong><a href="LazyDynaClass.html">LazyDynaClass</a></strong> extends <a href="BasicDynaClass.html">BasicDynaClass</a>
+ and implements the <a href="MutableDynaClass.html">MutableDynaClass</a> interface. It can be used with other
+ <code>DynaBean</code> implementations, but it is the default <code>DynaClass</code> used by <code>LazyDynaBean</code>.
+ When using the <code>LazyDynaBean</code> there may be no need to have anything to do with the <code>DynaClass</code>
+ However sometimes there is a requirement to set up the <code>DynaClass</code> first - perhaps to
+ define the type of array for an indexed property, or if using the DynaBean in <i>restricted</i> mode (see note below)
+ is required. Doing so is straight forward...</p>
+
+<p><i>Either</i> create a <code>LazyDynaClass</code> first...
+
+<pre>
+ MutableDynaClass dynaClass = new LazyDynaClass(); // create DynaClass
+
+ dynaClass.add("amount", java.lang.Integer.class); // add property
+ dynaClass.add("orders", OrderBean[].class); // add indexed property
+ dynaClass.add("orders", java.util.TreeMapp.class); // add mapped property
+
+ DynaBean dynaBean = new LazyDynaBean(dynaClass); // Create DynaBean with associated DynaClass
+</pre>
+
+<p><i>or</i> create a <code>LazyDynaBean</code> and get the <code>DynaClass</code>...
+
+<pre>
+ DynaBean dynaBean = new LazyDynaBean(); // Create LazyDynaBean
+ MutableDynaClass dynaClass =
+ (MutableDynaClass)dynaBean.getDynaClass(); // get DynaClass
+
+ dynaClass.add("amount", java.lang.Integer.class); // add property
+ dynaClass.add("myBeans", myPackage.MyBean[].class); // add 'array' indexed property
+ dynaClass.add("myMap", java.util.TreeMapp.class); // add mapped property
+</pre>
+
+<p><strong>NOTE:</strong> One feature of <a href="MutableDynaClass.html">MutableDynaClass</a> is that it
+ has a <i>Restricted</i> property. When the DynaClass is <i>restricted</i> no properties can be added
+ or removed from the <code>DynaClass</code>. Neither the <code>LazyDynaBean</code> or <code>LazyDynaMap</code>
+ will add properties automatically if the <code>DynaClass</code> is <i>restricted</i>.</p>
+
+
+
+<a name="conversion"></a>
+<h1>Data Type Conversions</h1>
+
+<a name="conversion.background"></a>
+<h3>Background</h3>
+
+<p>So far, we've only considered the cases where the data types of the
+dynamically accessed properties are known, and where we can use Java casts
+to perform type conversions. What happens if you want to automatically
+perform type conversions when casting is not possible? The
+<em>BeanUtils</em> package provides a variety of APIs and design patterns
+for performing this task as well.</p>
+
+<a name="conversion.beanutils"></a>
+<h3><code>BeanUtils</code> and <code>ConvertUtils</code> Conversions</h3>
+
+<p>A very common use case (and the situation that caused the initial creation
+of the <em>BeanUtils</em> package) was the desire to convert the set of request
+parameters that were included in a
+<code>javax.servlet.HttpServletRequest</code> received by a web application
+into a set of corresponding property setter calls on an arbitrary JavaBean.
+(This is one of the fundamental services provided by the
+<a href="http://jakarta.apache.org/struts">Struts Framework</a>, which uses
+<em>BeanUtils</em> internally to implement this functionality.)</p>
+
+<p>In an HTTP request, the set of included parameters is made available as a
+series of String (or String array, if there is more than one value for the
+same parameter name) instances, which need to be converted to the underlying
+data type. The <a href="BeanUtils.html">BeanUtils</a> class provides
+property setter methods that accept String values, and automatically convert
+them to appropriate property types for Java primitives (such as
+<code>int</code> or <code>boolean</code>), and property getter methods that
+perform the reverse conversion. Finally, a <code>populate()</code> method
+is provided that accepts a <code>java.util.Map</code> containing a set of
+property values (keyed by property name), and calls all of the appropriate
+setters whenever the underlying bean has a property with the same name as
+one of the request parameters. So, you can perform the all-in-one property
+setting operation like this:</p>
+
+<pre>
+ HttpServletRequest request = ...;
+ MyBean bean = ...;
+ HashMap map = new HashMap();
+ Enumeration names = request.getParameterNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ map.put(name, request.getParameterValues(name));
+ }
+ BeanUtils.populate(bean, map);
+</pre>
+
+<p>The <code>BeanUtils</code> class relies on conversion methods defined in
+the <a href="ConvertUtils.html">ConvertUtils</a> class to perform the actual
+conversions, and these methods are availablve for direct use as well.
+<strong>WARNING</strong> - It is likely that the hard coded use of
+<code>ConvertUtils</code> methods will be deprecated in the future, and
+replaced with a mechanism that allows you to plug in your own implementations
+of the <a href="Converter.html">Converter</a> interface instead. Therefore,
+new code should not be written with reliance on ConvertUtils.</p>
+
+<a name="conversion.defining"></a>
+<h3>Defining Your Own Converters</h3>
+
+<p>The <code>ConvertUtils</code> class supports the ability to define and
+register your own String --> Object conversions for any given Java class.
+Once registered, such converters will be used transparently by all of the
+<code>BeanUtils</code> methods (including <code>populate()</code>). To
+create and register your own converter, follow these steps:</p>
+<ul>
+<li>Write a class that implements the <a href="Converter.html">Converter</a>
+ interface. The <code>convert()</code> method should accept the
+ <code>java.lang.Class</code> object of your application class (i.e.
+ the class that you want to convert to, and a String representing the
+ incoming value to be converted.</li>
+<li>At application startup time, register an instance of your converter class
+ by calling the <code>ConvertUtils.register()</code> method.</li>
+</ul>
+
+<a name="conversion.i18n"></a>
+<h3>Locale Aware Conversions</h3>
+<p>The standard classes in <code>org.apache.commons.beanutils</code> are not
+locale aware. This gives them a cleaner interface and makes then easier to use
+in situations where the locale is not important.</p>
+<p>Extended, locale-aware analogues can be found in
+<code><a href='locale/package-summary.html'>org.apache.commons.beanutils.locale
+</a></code>. These are built along the same
+lines as the basic classes but support localization.</p>
+
+
+<a name="instances"></a>
+<h1>Utility Objects And Static Utility Classes</h1>
+<a name="instances.background"></a>
+<h3>Background</h3>
+<p>
+So far, the examples have covered the static utility classes (<code>BeanUtils</code>,
+<code>ConvertUtils</code> and <code>PropertyUtils</code>). These are easy to use but are
+somewhat inflexible. These all share the same registered converters and the same caches.
+</p>
+<p>
+This functionality can also be accessed through utility objects (in fact, the static utility
+class use worker instances of these classes). For each static utility class, there is a corresponding
+class with the same functionality that can be instantiated:
+</p>
+<p>
+<table cols='2' width='60%'>
+<tr><th>Static Utility Class</th><th>Utility Object</th></tr>
+<tr><td>BeanUtils</td><td>BeanUtilsBean</td></tr>
+<tr><td>ConvertUtils</td><td>ConvertUtilsBean</td></tr>
+<tr><td>PropertyUtils</td><td>PropertyUtilsBean</td></tr>
+</table>
+</p>
+<p>
+Creating an instances allow gives guarenteed control of the caching and registration
+to the code that creates it.
+</p>
+
+<a name="collections"></a>
+<h1>Collections</h1>
+<strong>Note:</strong> these classes depend on
+<a href='http://jakarta.apache.org/commons/collections'>Commons Collection</a> 3.0 or higher
+and are optional. To use them, please ensure that this library is available
+and that either the all-in-one jar is used or the modular
+<code>commons-beanutils-bean-collections.jar</code> is available
+(in addition to <code>commons-beanutils-core.jar</code>, of course :-).
+<a name="bean-comparator"></a>
+<h3>Comparing Beans</h3>
+<p>
+<code>org.apache.commons.beanutils.BeanComparator</code> is a <code>Comparator</code> implementation
+that compares beans based on a shared property value.
+</p>
+<a name="bean-property-closure"></a>
+<h3>Operating On Collections Of Beans</h3>
+<p>
+The <code>Closure</code> interface in <code>commons-collections</code> encapsulates a block of code that
+executes on an arbitrary input Object. <code>Commons-collections</code> contains code that allows
+<code>Closures</code> to be applied to the contents of a Collection. For more details, see the
+<a href='http://jakarta.apache.org/commons/collections.html'>commons-collections</a>
+documentation.
+</p>
+<p>
+<code>BeanPropertyValueChangeClosure</code> is a <code>Closure</code> that sets a specified property
+to a particular value. A typical usage is to combine this with <code>commons-collections</code>
+so that all the beans in a collection can have a particular property set to a particular value.
+</p>
+<p>
+For example, set the activeEmployee property to TRUE for an entire collection:
+ <code><pre>
+ // create the closure
+ BeanPropertyValueChangeClosure closure =
+ new BeanPropertyValueChangeClosure( "activeEmployee", Boolean.TRUE );
+
+ // update the Collection
+ CollectionUtils.forAllDo( peopleCollection, closure );
+ </pre></code>
+</p>
+
+<a name="bean-property-predicate"></a>
+<h3>Querying Or Filtering Collections Of Beans</h3>
+<p>
+The <code>Predicate</code> interface in <code>commons-collections</code> encapsulates an evaluation
+of an input Object that returns either true or false. <code>Commons-collections</code> contains code
+that allows
+<code>Predicates</code> to be applied to be used to filter collections. For more details, see the
+<a href='http://jakarta.apache.org/commons/collections.html'>commons-collections</a>
+documentation.
+</p>
+<p>
+<code>BeanPropertyValueEqualsPredicate</code> is a <code>Predicate</code> that evaluates a
+set property value against a given value. A typical usage is
+(in combination with <code>commons-collections</code>)
+to filter collections on the basis of a property value.
+</p>
+<p>
+For example, to filter a collection to find all beans where active employee is false use:
+<code><pre>
+ BeanPropertyValueEqualsPredicate predicate =
+ new BeanPropertyValueEqualsPredicate( "activeEmployee", Boolean.FALSE );
+
+ // filter the Collection
+ CollectionUtils.filter( peopleCollection, predicate );
+</pre></code>
+</p>
+
+<a href="bean-property-transformer"></a>
+<h3>Transforming Collections Of Beans</h3>
+<p>
+The <code>Transformer</code> interface in <code>commons-collections</code> encapsulates the transformation
+of an input Object into an output object. <code>Commons-collections</code> contains code
+that allows
+<code>Transformers</code> to be applied produce a collection of outputs from a collection of inputs.
+For more details, see the
+<a href='http://jakarta.apache.org/commons/collections.html'>commons-collections</a>
+documentation.
+</p>
+<p>
+<code>BeanToPropertyTransformer</code> is a <code>Transformer</code> implementation
+that transforms a bean into it's property value.
+</p>
+<p>
+For example, to find all cities that are contained in the address of each person property of each bean in
+a collection:
+ <code><pre>
+ // create the transformer
+ BeanToPropertyValueTransformer transformer = new BeanToPropertyValueTransformer( "person.address.city" );
+
+ // transform the Collection
+ Collection peoplesCities = CollectionUtils.collect( peopleCollection, transformer );
+ </pre></code>
+</p>
+
+<a name="FAQ"></a>
+<h1>Frequently Asked Questions</h1>
+
+<a name="FAQ.property"></a>
+<h3>Why Can't BeanUtils Find My Method?</h3>
+<p>The <em>BeanUtils</em> package relies on <em>introspection</em> rather than
+<em>reflection</em>. This means that it will find only
+<a href='http://java.sun.com/products/javabeans'><em>JavaBean</em>
+compliant</a> properties.</p>
+<p>There are some subtleties of this specification that can catch out the unwary:
+<ul>
+<li>A property can have only one set and one get method. Overloading is not allowed.</li>
+<li>The <code>java.beans.Introspector</code> searches widely for a custom <em>BeanInfo</em>
+class. If your class has the same name as another with a custom <em>BeanUtils</em>
+(typically a java API class) then the <code>Introspector</code> may use that instead of
+creating via reflection based on your class. If this happens, the only solution is to
+create your own <em>BeanInfo</em>.</li>
+</ul>
+</p>
+<a name="FAQ.bc.order"></a>
+<h3>How Do I Set The BeanComparator Order To Be Ascending/Descending?</h3>
+<p>
+BeanComparator relies on an internal Comparator to perform the actual
+comparisions. By default,
+<code>org.apache.commons.collections.comparators.ComparableComparator</code>
+is used which imposes a natural order. If you want to change the order,
+then a custom Comparator should be created and passed into the
+appropriate constructor.
+</p>
+<p>
+For example:
+</p>
+<code><pre>
+ import org.apache.commons.collections.comparators.ComparableComparator;
+ import org.apache.commons.collections.comparators.ReverseComparator;
+ import org.apache.commons.beanutils.BeanComparator;
+ ...
+ BeanComparator reversedNaturalOrderBeanComparator
+ = new BeanComparator("propertyName", new ReverseComparator(new ComparableComparator()));
+ Collections.sort(myList, reversedNaturalOrderBeanComparator);
+ ...
+</pre></code>
+
+<a name="Packaging"></a>
+<h1>Packaging</h1>
+<p>
+BeanUtils now comes packaged (into jars) in two different ways:
+</p>
+<ol>
+ <li>an all-in-one jar (<code>commons-beanutils.jar</code>)</li>
+ <li>and as modular component jars:
+ <ul>
+ <li><code>commons-beanutils-core.jar</code> (core classes)</li>
+ <li><code>commons-beanutils-bean-collections.jar</code>
+ (additional dependency on commons-collections 3.0)</li>
+</ol>
+<p>
+Those who want it all should grab the all-in-one <code>commons-beanutils.jar</code>
+(and remember to add any optional dependencies needed)
+whereas those who need minimal dependencies should use <code>commons-beanutils-core.jar</code>
+plus any optional jars they plan to use.
+</p>
+<p>
+The binary distribution contains all these jars.
+</p>
+</body>
+</html>
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/ArrayStack.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/ArrayStack.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/ArrayStack.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections;
+
+import java.util.ArrayList;
+import java.util.EmptyStackException;
+
+/**
+ * An implementation of the {@link java.util.Stack} API that is based on an
+ * <code>ArrayList</code> instead of a <code>Vector</code>, so it is not
+ * synchronized to protect against multi-threaded access. The implementation
+ * is therefore operates faster in environments where you do not need to
+ * worry about multiple thread contention.
+ * <p>
+ * The removal order of an <code>ArrayStack</code> is based on insertion
+ * order: The most recently added element is removed first. The iteration
+ * order is <i>not</i> the same as the removal order. The iterator returns
+ * elements from the bottom up, whereas the {@link #remove()} method removes
+ * them from the top down.
+ * <p>
+ * Unlike <code>Stack</code>, <code>ArrayStack</code> accepts null entries.
+ * <p>
+ * <strong>Note:</strong> this class should be bytecode-identical to the
+ * version in commons collections. This is required to allow backwards
+ * compability with both previous versions of BeanUtils and also allow
+ * coexistance with both collections 2.1 and 3.0.
+ *
+ * @see java.util.Stack
+ * @since Commons Collections 1.0
+ * @version $Revision: 1.1 $ $Date: 2004/05/10 19:50:13 $
+ *
+ * @author Craig R. McClanahan
+ * @author Paul Jack
+ * @author Stephen Colebourne
+ */
+public class ArrayStack extends ArrayList implements Buffer {
+
+ /** Ensure serialization compatibility */
+ private static final long serialVersionUID = 2130079159931574599L;
+
+ /**
+ * Constructs a new empty <code>ArrayStack</code>. The initial size
+ * is controlled by <code>ArrayList</code> and is currently 10.
+ */
+ public ArrayStack() {
+ super();
+ }
+
+ /**
+ * Constructs a new empty <code>ArrayStack</code> with an initial size.
+ *
+ * @param initialSize the initial size to use
+ * @throws IllegalArgumentException if the specified initial size
+ * is negative
+ */
+ public ArrayStack(int initialSize) {
+ super(initialSize);
+ }
+
+ /**
+ * Return <code>true</code> if this stack is currently empty.
+ * <p>
+ * This method exists for compatibility with <code>java.util.Stack</code>.
+ * New users of this class should use <code>isEmpty</code> instead.
+ *
+ * @return true if the stack is currently empty
+ */
+ public boolean empty() {
+ return isEmpty();
+ }
+
+ /**
+ * Returns the top item off of this stack without removing it.
+ *
+ * @return the top item on the stack
+ * @throws EmptyStackException if the stack is empty
+ */
+ public Object peek() throws EmptyStackException {
+ int n = size();
+ if (n <= 0) {
+ throw new EmptyStackException();
+ } else {
+ return get(n - 1);
+ }
+ }
+
+ /**
+ * Returns the n'th item down (zero-relative) from the top of this
+ * stack without removing it.
+ *
+ * @param n the number of items down to go
+ * @return the n'th item on the stack, zero relative
+ * @throws EmptyStackException if there are not enough items on the
+ * stack to satisfy this request
+ */
+ public Object peek(int n) throws EmptyStackException {
+ int m = (size() - n) - 1;
+ if (m < 0) {
+ throw new EmptyStackException();
+ } else {
+ return get(m);
+ }
+ }
+
+ /**
+ * Pops the top item off of this stack and return it.
+ *
+ * @return the top item on the stack
+ * @throws EmptyStackException if the stack is empty
+ */
+ public Object pop() throws EmptyStackException {
+ int n = size();
+ if (n <= 0) {
+ throw new EmptyStackException();
+ } else {
+ return remove(n - 1);
+ }
+ }
+
+ /**
+ * Pushes a new item onto the top of this stack. The pushed item is also
+ * returned. This is equivalent to calling <code>add</code>.
+ *
+ * @param item the item to be added
+ * @return the item just pushed
+ */
+ public Object push(Object item) {
+ add(item);
+ return item;
+ }
+
+ /**
+ * Returns the one-based position of the distance from the top that the
+ * specified object exists on this stack, where the top-most element is
+ * considered to be at distance <code>1</code>. If the object is not
+ * present on the stack, return <code>-1</code> instead. The
+ * <code>equals()</code> method is used to compare to the items
+ * in this stack.
+ *
+ * @param object the object to be searched for
+ * @return the 1-based depth into the stack of the object, or -1 if not found
+ */
+ public int search(Object object) {
+ int i = size() - 1; // Current index
+ int n = 1; // Current distance
+ while (i >= 0) {
+ Object current = get(i);
+ if ((object == null && current == null) ||
+ (object != null && object.equals(current))) {
+ return n;
+ }
+ i--;
+ n++;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the element on the top of the stack.
+ *
+ * @return the element on the top of the stack
+ * @throws BufferUnderflowException if the stack is empty
+ */
+ public Object get() {
+ int size = size();
+ if (size == 0) {
+ throw new BufferUnderflowException();
+ }
+ return get(size - 1);
+ }
+
+ /**
+ * Removes the element on the top of the stack.
+ *
+ * @return the removed element
+ * @throws BufferUnderflowException if the stack is empty
+ */
+ public Object remove() {
+ int size = size();
+ if (size == 0) {
+ throw new BufferUnderflowException();
+ }
+ return remove(size - 1);
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/Buffer.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/Buffer.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/Buffer.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections;
+
+import java.util.Collection;
+
+/**
+ * Defines a collection that allows objects to be removed in some well-defined order.
+ * <p>
+ * The removal order can be based on insertion order (eg, a FIFO queue or a
+ * LIFO stack), on access order (eg, an LRU cache), on some arbitrary comparator
+ * (eg, a priority queue) or on any other well-defined ordering.
+ * <p>
+ * Note that the removal order is not necessarily the same as the iteration
+ * order. A <code>Buffer</code> implementation may have equivalent removal
+ * and iteration orders, but this is not required.
+ * <p>
+ * This interface does not specify any behavior for
+ * {@link Object#equals(Object)} and {@link Object#hashCode} methods. It
+ * is therefore possible for a <code>Buffer</code> implementation to also
+ * also implement {@link java.util.List}, {@link java.util.Set} or
+ * {@link Bag}.
+ * <p>
+ * <strong>Note:</strong> this class should be bytecode-identical to the
+ * version in commons collections. This is required to allow backwards
+ * compability with both previous versions of BeanUtils and also allow
+ * coexistance with both collections 2.1 and 3.0.
+ *
+ * @since Commons Collections 2.1
+ * @version $Revision: 1.1 $ $Date: 2004/05/10 19:50:28 $
+ *
+ * @author Avalon
+ * @author Berin Loritsch
+ * @author Paul Jack
+ * @author Stephen Colebourne
+ */
+public interface Buffer extends Collection {
+
+ /**
+ * Gets and removes the next object from the buffer.
+ *
+ * @return the next object in the buffer, which is also removed
+ * @throws BufferUnderflowException if the buffer is already empty
+ */
+ Object remove();
+
+ /**
+ * Gets the next object from the buffer without removing it.
+ *
+ * @return the next object in the buffer, which is not removed
+ * @throws BufferUnderflowException if the buffer is empty
+ */
+ Object get();
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/BufferUnderflowException.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/BufferUnderflowException.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/BufferUnderflowException.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections;
+
+import java.util.NoSuchElementException;
+
+/**
+ * The BufferUnderflowException is used when the buffer is already empty.
+ * <p>
+ * NOTE: From version 3.0, this exception extends NoSuchElementException.
+ *
+ * @since Commons Collections 2.1
+ * @version $Revision: 1.1 $ $Date: 2004/05/10 19:50:52 $
+ *
+ * @author Avalon
+ * @author Berin Loritsch
+ * @author Jeff Turner
+ * @author Paul Jack
+ * @author Stephen Colebourne
+ */
+public class BufferUnderflowException extends NoSuchElementException {
+
+ /** The root cause throwable */
+ private final Throwable throwable;
+
+ /**
+ * Constructs a new <code>BufferUnderflowException</code>.
+ */
+ public BufferUnderflowException() {
+ super();
+ throwable = null;
+ }
+
+ /**
+ * Construct a new <code>BufferUnderflowException</code>.
+ *
+ * @param message the detail message for this exception
+ */
+ public BufferUnderflowException(String message) {
+ this(message, null);
+ }
+
+ /**
+ * Construct a new <code>BufferUnderflowException</code>.
+ *
+ * @param message the detail message for this exception
+ * @param exception the root cause of the exception
+ */
+ public BufferUnderflowException(String message, Throwable exception) {
+ super(message);
+ throwable = exception;
+ }
+
+ /**
+ * Gets the root cause of the exception.
+ *
+ * @return the root cause
+ */
+ public final Throwable getCause() {
+ return throwable;
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/FastHashMap.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/FastHashMap.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/FastHashMap.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,714 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections;
+
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>A customized implementation of <code>java.util.HashMap</code> designed
+ * to operate in a multithreaded environment where the large majority of
+ * method calls are read-only, instead of structural changes. When operating
+ * in "fast" mode, read calls are non-synchronized and write calls perform the
+ * following steps:</p>
+ * <ul>
+ * <li>Clone the existing collection
+ * <li>Perform the modification on the clone
+ * <li>Replace the existing collection with the (modified) clone
+ * </ul>
+ * <p>When first created, objects of this class default to "slow" mode, where
+ * all accesses of any type are synchronized but no cloning takes place. This
+ * is appropriate for initially populating the collection, followed by a switch
+ * to "fast" mode (by calling <code>setFast(true)</code>) after initialization
+ * is complete.</p>
+ *
+ * <p><strong>NOTE</strong>: If you are creating and accessing a
+ * <code>HashMap</code> only within a single thread, you should use
+ * <code>java.util.HashMap</code> directly (with no synchronization), for
+ * maximum performance.</p>
+ *
+ * <p><strong>NOTE</strong>: <i>This class is not cross-platform.
+ * Using it may cause unexpected failures on some architectures.</i>
+ * It suffers from the same problems as the double-checked locking idiom.
+ * In particular, the instruction that clones the internal collection and the
+ * instruction that sets the internal reference to the clone can be executed
+ * or perceived out-of-order. This means that any read operation might fail
+ * unexpectedly, as it may be reading the state of the internal collection
+ * before the internal collection is fully formed.
+ * For more information on the double-checked locking idiom, see the
+ * <a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">
+ * Double-Checked Locking Idiom Is Broken Declaration</a>.</p>
+ *
+ * @since Commons Collections 1.0
+ * @version $Revision: 1.1 $ $Date: 2004/05/10 19:51:13 $
+ *
+ * @author Craig R. McClanahan
+ * @author Stephen Colebourne
+ */
+public class FastHashMap extends HashMap {
+
+ /**
+ * The underlying map we are managing.
+ */
+ protected HashMap map = null;
+
+ /**
+ * Are we currently operating in "fast" mode?
+ */
+ protected boolean fast = false;
+
+ // Constructors
+ // ----------------------------------------------------------------------
+
+ /**
+ * Construct an empty map.
+ */
+ public FastHashMap() {
+ super();
+ this.map = new HashMap();
+ }
+
+ /**
+ * Construct an empty map with the specified capacity.
+ *
+ * @param capacity the initial capacity of the empty map
+ */
+ public FastHashMap(int capacity) {
+ super();
+ this.map = new HashMap(capacity);
+ }
+
+ /**
+ * Construct an empty map with the specified capacity and load factor.
+ *
+ * @param capacity the initial capacity of the empty map
+ * @param factor the load factor of the new map
+ */
+ public FastHashMap(int capacity, float factor) {
+ super();
+ this.map = new HashMap(capacity, factor);
+ }
+
+ /**
+ * Construct a new map with the same mappings as the specified map.
+ *
+ * @param map the map whose mappings are to be copied
+ */
+ public FastHashMap(Map map) {
+ super();
+ this.map = new HashMap(map);
+ }
+
+
+ // Property access
+ // ----------------------------------------------------------------------
+
+ /**
+ * Returns true if this map is operating in fast mode.
+ *
+ * @return true if this map is operating in fast mode
+ */
+ public boolean getFast() {
+ return (this.fast);
+ }
+
+ /**
+ * Sets whether this map is operating in fast mode.
+ *
+ * @param fast true if this map should operate in fast mode
+ */
+ public void setFast(boolean fast) {
+ this.fast = fast;
+ }
+
+
+ // Map access
+ // ----------------------------------------------------------------------
+ // These methods can forward straight to the wrapped Map in 'fast' mode.
+ // (because they are query methods)
+
+ /**
+ * Return the value to which this map maps the specified key. Returns
+ * <code>null</code> if the map contains no mapping for this key, or if
+ * there is a mapping with a value of <code>null</code>. Use the
+ * <code>containsKey()</code> method to disambiguate these cases.
+ *
+ * @param key the key whose value is to be returned
+ * @return the value mapped to that key, or null
+ */
+ public Object get(Object key) {
+ if (fast) {
+ return (map.get(key));
+ } else {
+ synchronized (map) {
+ return (map.get(key));
+ }
+ }
+ }
+
+ /**
+ * Return the number of key-value mappings in this map.
+ *
+ * @return the current size of the map
+ */
+ public int size() {
+ if (fast) {
+ return (map.size());
+ } else {
+ synchronized (map) {
+ return (map.size());
+ }
+ }
+ }
+
+ /**
+ * Return <code>true</code> if this map contains no mappings.
+ *
+ * @return is the map currently empty
+ */
+ public boolean isEmpty() {
+ if (fast) {
+ return (map.isEmpty());
+ } else {
+ synchronized (map) {
+ return (map.isEmpty());
+ }
+ }
+ }
+
+ /**
+ * Return <code>true</code> if this map contains a mapping for the
+ * specified key.
+ *
+ * @param key the key to be searched for
+ * @return true if the map contains the key
+ */
+ public boolean containsKey(Object key) {
+ if (fast) {
+ return (map.containsKey(key));
+ } else {
+ synchronized (map) {
+ return (map.containsKey(key));
+ }
+ }
+ }
+
+ /**
+ * Return <code>true</code> if this map contains one or more keys mapping
+ * to the specified value.
+ *
+ * @param value the value to be searched for
+ * @return true if the map contains the value
+ */
+ public boolean containsValue(Object value) {
+ if (fast) {
+ return (map.containsValue(value));
+ } else {
+ synchronized (map) {
+ return (map.containsValue(value));
+ }
+ }
+ }
+
+ // Map modification
+ // ----------------------------------------------------------------------
+ // These methods perform special behaviour in 'fast' mode.
+ // The map is cloned, updated and then assigned back.
+ // See the comments at the top as to why this won't always work.
+
+ /**
+ * Associate the specified value with the specified key in this map.
+ * If the map previously contained a mapping for this key, the old
+ * value is replaced and returned.
+ *
+ * @param key the key with which the value is to be associated
+ * @param value the value to be associated with this key
+ * @return the value previously mapped to the key, or null
+ */
+ public Object put(Object key, Object value) {
+ if (fast) {
+ synchronized (this) {
+ HashMap temp = (HashMap) map.clone();
+ Object result = temp.put(key, value);
+ map = temp;
+ return (result);
+ }
+ } else {
+ synchronized (map) {
+ return (map.put(key, value));
+ }
+ }
+ }
+
+ /**
+ * Copy all of the mappings from the specified map to this one, replacing
+ * any mappings with the same keys.
+ *
+ * @param in the map whose mappings are to be copied
+ */
+ public void putAll(Map in) {
+ if (fast) {
+ synchronized (this) {
+ HashMap temp = (HashMap) map.clone();
+ temp.putAll(in);
+ map = temp;
+ }
+ } else {
+ synchronized (map) {
+ map.putAll(in);
+ }
+ }
+ }
+
+ /**
+ * Remove any mapping for this key, and return any previously
+ * mapped value.
+ *
+ * @param key the key whose mapping is to be removed
+ * @return the value removed, or null
+ */
+ public Object remove(Object key) {
+ if (fast) {
+ synchronized (this) {
+ HashMap temp = (HashMap) map.clone();
+ Object result = temp.remove(key);
+ map = temp;
+ return (result);
+ }
+ } else {
+ synchronized (map) {
+ return (map.remove(key));
+ }
+ }
+ }
+
+ /**
+ * Remove all mappings from this map.
+ */
+ public void clear() {
+ if (fast) {
+ synchronized (this) {
+ map = new HashMap();
+ }
+ } else {
+ synchronized (map) {
+ map.clear();
+ }
+ }
+ }
+
+ // Basic object methods
+ // ----------------------------------------------------------------------
+
+ /**
+ * Compare the specified object with this list for equality. This
+ * implementation uses exactly the code that is used to define the
+ * list equals function in the documentation for the
+ * <code>Map.equals</code> method.
+ *
+ * @param o the object to be compared to this list
+ * @return true if the two maps are equal
+ */
+ public boolean equals(Object o) {
+ // Simple tests that require no synchronization
+ if (o == this) {
+ return (true);
+ } else if (!(o instanceof Map)) {
+ return (false);
+ }
+ Map mo = (Map) o;
+
+ // Compare the two maps for equality
+ if (fast) {
+ if (mo.size() != map.size()) {
+ return (false);
+ }
+ Iterator i = map.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry e = (Map.Entry) i.next();
+ Object key = e.getKey();
+ Object value = e.getValue();
+ if (value == null) {
+ if (!(mo.get(key) == null && mo.containsKey(key))) {
+ return (false);
+ }
+ } else {
+ if (!value.equals(mo.get(key))) {
+ return (false);
+ }
+ }
+ }
+ return (true);
+
+ } else {
+ synchronized (map) {
+ if (mo.size() != map.size()) {
+ return (false);
+ }
+ Iterator i = map.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry e = (Map.Entry) i.next();
+ Object key = e.getKey();
+ Object value = e.getValue();
+ if (value == null) {
+ if (!(mo.get(key) == null && mo.containsKey(key))) {
+ return (false);
+ }
+ } else {
+ if (!value.equals(mo.get(key))) {
+ return (false);
+ }
+ }
+ }
+ return (true);
+ }
+ }
+ }
+
+ /**
+ * Return the hash code value for this map. This implementation uses
+ * exactly the code that is used to define the list hash function in the
+ * documentation for the <code>Map.hashCode</code> method.
+ *
+ * @return suitable integer hash code
+ */
+ public int hashCode() {
+ if (fast) {
+ int h = 0;
+ Iterator i = map.entrySet().iterator();
+ while (i.hasNext()) {
+ h += i.next().hashCode();
+ }
+ return (h);
+ } else {
+ synchronized (map) {
+ int h = 0;
+ Iterator i = map.entrySet().iterator();
+ while (i.hasNext()) {
+ h += i.next().hashCode();
+ }
+ return (h);
+ }
+ }
+ }
+
+ /**
+ * Return a shallow copy of this <code>FastHashMap</code> instance.
+ * The keys and values themselves are not copied.
+ *
+ * @return a clone of this map
+ */
+ public Object clone() {
+ FastHashMap results = null;
+ if (fast) {
+ results = new FastHashMap(map);
+ } else {
+ synchronized (map) {
+ results = new FastHashMap(map);
+ }
+ }
+ results.setFast(getFast());
+ return (results);
+ }
+
+ // Map views
+ // ----------------------------------------------------------------------
+
+ /**
+ * Return a collection view of the mappings contained in this map. Each
+ * element in the returned collection is a <code>Map.Entry</code>.
+ */
+ public Set entrySet() {
+ return new EntrySet();
+ }
+
+ /**
+ * Return a set view of the keys contained in this map.
+ */
+ public Set keySet() {
+ return new KeySet();
+ }
+
+ /**
+ * Return a collection view of the values contained in this map.
+ */
+ public Collection values() {
+ return new Values();
+ }
+
+ // Map view inner classes
+ // ----------------------------------------------------------------------
+
+ /**
+ * Abstract collection implementation shared by keySet(), values() and entrySet().
+ */
+ private abstract class CollectionView implements Collection {
+
+ public CollectionView() {
+ }
+
+ protected abstract Collection get(Map map);
+ protected abstract Object iteratorNext(Map.Entry entry);
+
+
+ public void clear() {
+ if (fast) {
+ synchronized (FastHashMap.this) {
+ map = new HashMap();
+ }
+ } else {
+ synchronized (map) {
+ get(map).clear();
+ }
+ }
+ }
+
+ public boolean remove(Object o) {
+ if (fast) {
+ synchronized (FastHashMap.this) {
+ HashMap temp = (HashMap) map.clone();
+ boolean r = get(temp).remove(o);
+ map = temp;
+ return r;
+ }
+ } else {
+ synchronized (map) {
+ return get(map).remove(o);
+ }
+ }
+ }
+
+ public boolean removeAll(Collection o) {
+ if (fast) {
+ synchronized (FastHashMap.this) {
+ HashMap temp = (HashMap) map.clone();
+ boolean r = get(temp).removeAll(o);
+ map = temp;
+ return r;
+ }
+ } else {
+ synchronized (map) {
+ return get(map).removeAll(o);
+ }
+ }
+ }
+
+ public boolean retainAll(Collection o) {
+ if (fast) {
+ synchronized (FastHashMap.this) {
+ HashMap temp = (HashMap) map.clone();
+ boolean r = get(temp).retainAll(o);
+ map = temp;
+ return r;
+ }
+ } else {
+ synchronized (map) {
+ return get(map).retainAll(o);
+ }
+ }
+ }
+
+ public int size() {
+ if (fast) {
+ return get(map).size();
+ } else {
+ synchronized (map) {
+ return get(map).size();
+ }
+ }
+ }
+
+
+ public boolean isEmpty() {
+ if (fast) {
+ return get(map).isEmpty();
+ } else {
+ synchronized (map) {
+ return get(map).isEmpty();
+ }
+ }
+ }
+
+ public boolean contains(Object o) {
+ if (fast) {
+ return get(map).contains(o);
+ } else {
+ synchronized (map) {
+ return get(map).contains(o);
+ }
+ }
+ }
+
+ public boolean containsAll(Collection o) {
+ if (fast) {
+ return get(map).containsAll(o);
+ } else {
+ synchronized (map) {
+ return get(map).containsAll(o);
+ }
+ }
+ }
+
+ public Object[] toArray(Object[] o) {
+ if (fast) {
+ return get(map).toArray(o);
+ } else {
+ synchronized (map) {
+ return get(map).toArray(o);
+ }
+ }
+ }
+
+ public Object[] toArray() {
+ if (fast) {
+ return get(map).toArray();
+ } else {
+ synchronized (map) {
+ return get(map).toArray();
+ }
+ }
+ }
+
+
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if (fast) {
+ return get(map).equals(o);
+ } else {
+ synchronized (map) {
+ return get(map).equals(o);
+ }
+ }
+ }
+
+ public int hashCode() {
+ if (fast) {
+ return get(map).hashCode();
+ } else {
+ synchronized (map) {
+ return get(map).hashCode();
+ }
+ }
+ }
+
+ public boolean add(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean addAll(Collection c) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Iterator iterator() {
+ return new CollectionViewIterator();
+ }
+
+ private class CollectionViewIterator implements Iterator {
+
+ private Map expected;
+ private Map.Entry lastReturned = null;
+ private Iterator iterator;
+
+ public CollectionViewIterator() {
+ this.expected = map;
+ this.iterator = expected.entrySet().iterator();
+ }
+
+ public boolean hasNext() {
+ if (expected != map) {
+ throw new ConcurrentModificationException();
+ }
+ return iterator.hasNext();
+ }
+
+ public Object next() {
+ if (expected != map) {
+ throw new ConcurrentModificationException();
+ }
+ lastReturned = (Map.Entry)iterator.next();
+ return iteratorNext(lastReturned);
+ }
+
+ public void remove() {
+ if (lastReturned == null) {
+ throw new IllegalStateException();
+ }
+ if (fast) {
+ synchronized (FastHashMap.this) {
+ if (expected != map) {
+ throw new ConcurrentModificationException();
+ }
+ FastHashMap.this.remove(lastReturned.getKey());
+ lastReturned = null;
+ expected = map;
+ }
+ } else {
+ iterator.remove();
+ lastReturned = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * Set implementation over the keys of the FastHashMap
+ */
+ private class KeySet extends CollectionView implements Set {
+
+ protected Collection get(Map map) {
+ return map.keySet();
+ }
+
+ protected Object iteratorNext(Map.Entry entry) {
+ return entry.getKey();
+ }
+
+ }
+
+ /**
+ * Collection implementation over the values of the FastHashMap
+ */
+ private class Values extends CollectionView {
+
+ protected Collection get(Map map) {
+ return map.values();
+ }
+
+ protected Object iteratorNext(Map.Entry entry) {
+ return entry.getValue();
+ }
+ }
+
+ /**
+ * Set implementation over the entries of the FastHashMap
+ */
+ private class EntrySet extends CollectionView implements Set {
+
+ protected Collection get(Map map) {
+ return map.entrySet();
+ }
+
+ protected Object iteratorNext(Map.Entry entry) {
+ return entry;
+ }
+
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/package.html
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/package.html 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/org/apache/commons/collections/package.html 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>Package Documentation for org.apache.commons.collections Package</title>
+</head>
+<body bgcolor="white">
+<p>
+This package contains a small number of collections classes that are needed for beanutils
+to function. The dependencies will be deprecated in the 1.7.0 release and the need for these
+classes will be removed in the future. These classes are identical to those in both 2.x and 3.x
+series of commons-collections releases.
+</p>
+</body>
+</html>
Added: trunk/commons-beanutils/branches/upstream/current/src/java/overview.html
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/java/overview.html 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/java/overview.html 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<title>Overview Documentation for COMMONS-BEANUTILS</title>
+</head>
+<body bgcolor="white">
+<p>The <em>Bean Introspection Utilities</em> component of the Jakarta Commons
+subproject offers low-level utility classes that assist in getting and setting
+property values on Java classes that follow the naming design patterns outlined
+in the JavaBeans Specification, as well as mechanisms for dynamically defining
+and accessing bean properties.</p>
+
+<p>See the
+<a href="org/apache/commons/beanutils/package-summary.html#package_description">
+Package Description</a> for the <code>org.apache.commons.beanutils</code>
+package for more information.</p>
+</body>
+</html>
Added: trunk/commons-beanutils/branches/upstream/current/src/media/logo.xcf
===================================================================
(Binary files differ)
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/media/logo.xcf
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/A.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/A.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/A.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+import java.io.OutputStream;
+
+/**
+ * <p>Class used in MethodUtils test</p>
+ *
+ */
+public class A {
+
+ boolean called = false;
+
+ public void foo(OutputStream os)
+ {
+ called = true;
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AbstractChild.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AbstractChild.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AbstractChild.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+public class AbstractChild implements Child {
+
+ private String name;
+
+ protected void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AbstractParent.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AbstractParent.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AbstractParent.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+public abstract class AbstractParent {
+
+ private Child child;
+
+ public Child getChild()
+ {
+ return child;
+ }
+
+ /**
+ * Method which matches signature but which has wrong parameters
+ */
+ public String testAddChild(String badParameter) {
+ return null;
+ }
+
+ /**
+ * Method which matches signature but which has wrong parameters
+ */
+ public String testAddChild2(String ignore, String badParameter) {
+ return null;
+ }
+
+ public String testAddChild(Child child) {
+ this.child = child;
+ return child.getName();
+ }
+
+
+ public String testAddChild2(String ignore, Child child) {
+ this.child = child;
+ return child.getName();
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AlphaBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AlphaBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/AlphaBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+public class AlphaBean extends AbstractParent implements Child {
+
+ private String name;
+
+ public AlphaBean() {}
+
+ public AlphaBean(String name) {
+ setName(name);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Used for testing that correct exception is thrown.
+ */
+ public void bogus(String badParameter){}
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BasicDynaBeanTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BasicDynaBeanTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BasicDynaBeanTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,1030 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * <p>Test Case for the <code>BasicDynaBean</code> implementation class.
+ * These tests were based on the ones in <code>PropertyUtilsTestCase</code>
+ * because the two classes provide similar levels of functionality.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.10 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class BasicDynaBeanTestCase extends TestCase {
+
+
+ // ---------------------------------------------------- Instance Variables
+
+
+ /**
+ * The basic test bean for each test.
+ */
+ protected DynaBean bean = null;
+
+
+ /**
+ * The set of property names we expect to have returned when calling
+ * <code>getDynaProperties()</code>. You should update this list
+ * when new properties are added to TestBean.
+ */
+ protected final static String[] properties = {
+ "booleanProperty",
+ "booleanSecond",
+ "doubleProperty",
+ "floatProperty",
+ "intArray",
+ "intIndexed",
+ "intProperty",
+ "listIndexed",
+ "longProperty",
+ "mappedProperty",
+ "mappedIntProperty",
+ "nullProperty",
+ "shortProperty",
+ "stringArray",
+ "stringIndexed",
+ "stringProperty",
+ };
+
+
+ // ---------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public BasicDynaBeanTestCase(String name) {
+
+ super(name);
+
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+
+ // Instantiate a new DynaBean instance
+ DynaClass dynaClass = createDynaClass();
+ bean = dynaClass.newInstance();
+
+ // Initialize the DynaBean's property values (like TestBean)
+ bean.set("booleanProperty", new Boolean(true));
+ bean.set("booleanSecond", new Boolean(true));
+ bean.set("doubleProperty", new Double(321.0));
+ bean.set("floatProperty", new Float((float) 123.0));
+ int intArray[] = { 0, 10, 20, 30, 40 };
+ bean.set("intArray", intArray);
+ int intIndexed[] = { 0, 10, 20, 30, 40 };
+ bean.set("intIndexed", intIndexed);
+ bean.set("intProperty", new Integer(123));
+ List listIndexed = new ArrayList();
+ listIndexed.add("String 0");
+ listIndexed.add("String 1");
+ listIndexed.add("String 2");
+ listIndexed.add("String 3");
+ listIndexed.add("String 4");
+ bean.set("listIndexed", listIndexed);
+ bean.set("longProperty", new Long((long) 321));
+ HashMap mappedProperty = new HashMap();
+ mappedProperty.put("First Key", "First Value");
+ mappedProperty.put("Second Key", "Second Value");
+ bean.set("mappedProperty", mappedProperty);
+ HashMap mappedIntProperty = new HashMap();
+ mappedIntProperty.put("One", new Integer(1));
+ mappedIntProperty.put("Two", new Integer(2));
+ bean.set("mappedIntProperty", mappedIntProperty);
+ // Property "nullProperty" is not initialized, so it should return null
+ bean.set("shortProperty", new Short((short) 987));
+ String stringArray[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+ bean.set("stringArray", stringArray);
+ String stringIndexed[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+ bean.set("stringIndexed", stringIndexed);
+ bean.set("stringProperty", "This is a string");
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+
+ return (new TestSuite(BasicDynaBeanTestCase.class));
+
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+
+ bean = null;
+
+ }
+
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ /**
+ * Corner cases on getDynaProperty invalid arguments.
+ */
+ public void testGetDescriptorArguments() {
+
+ try {
+ DynaProperty descriptor =
+ bean.getDynaClass().getDynaProperty("unknown");
+ assertNull("Unknown property descriptor should be null",
+ descriptor);
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of returning null");
+ }
+
+ try {
+ bean.getDynaClass().getDynaProperty(null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException");
+ }
+
+ }
+
+
+ /**
+ * Positive getDynaProperty on property <code>booleanProperty</code>.
+ */
+ public void testGetDescriptorBoolean() {
+
+ testGetDescriptorBase("booleanProperty", Boolean.TYPE);
+
+ }
+
+
+ /**
+ * Positive getDynaProperty on property <code>doubleProperty</code>.
+ */
+ public void testGetDescriptorDouble() {
+
+ testGetDescriptorBase("doubleProperty", Double.TYPE);
+
+ }
+
+
+ /**
+ * Positive getDynaProperty on property <code>floatProperty</code>.
+ */
+ public void testGetDescriptorFloat() {
+
+ testGetDescriptorBase("floatProperty", Float.TYPE);
+
+ }
+
+
+ /**
+ * Positive getDynaProperty on property <code>intProperty</code>.
+ */
+ public void testGetDescriptorInt() {
+
+ testGetDescriptorBase("intProperty", Integer.TYPE);
+
+ }
+
+
+ /**
+ * Positive getDynaProperty on property <code>longProperty</code>.
+ */
+ public void testGetDescriptorLong() {
+
+ testGetDescriptorBase("longProperty", Long.TYPE);
+
+ }
+
+
+ /**
+ * Positive getDynaProperty on property <code>booleanSecond</code>
+ * that uses an "is" method as the getter.
+ */
+ public void testGetDescriptorSecond() {
+
+ testGetDescriptorBase("booleanSecond", Boolean.TYPE);
+
+ }
+
+
+ /**
+ * Positive getDynaProperty on property <code>shortProperty</code>.
+ */
+ public void testGetDescriptorShort() {
+
+ testGetDescriptorBase("shortProperty", Short.TYPE);
+
+ }
+
+
+ /**
+ * Positive getDynaProperty on property <code>stringProperty</code>.
+ */
+ public void testGetDescriptorString() {
+
+ testGetDescriptorBase("stringProperty", String.class);
+
+ }
+
+
+ /**
+ * Positive test for getDynaPropertys(). Each property name
+ * listed in <code>properties</code> should be returned exactly once.
+ */
+ public void testGetDescriptors() {
+
+ DynaProperty pd[] = bean.getDynaClass().getDynaProperties();
+ assertNotNull("Got descriptors", pd);
+ int count[] = new int[properties.length];
+ for (int i = 0; i < pd.length; i++) {
+ String name = pd[i].getName();
+ for (int j = 0; j < properties.length; j++) {
+ if (name.equals(properties[j]))
+ count[j]++;
+ }
+ }
+ for (int j = 0; j < properties.length; j++) {
+ if (count[j] < 0)
+ fail("Missing property " + properties[j]);
+ else if (count[j] > 1)
+ fail("Duplicate property " + properties[j]);
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getIndexedProperty invalid arguments.
+ */
+ public void testGetIndexedArguments() {
+
+ try {
+ bean.get("intArray", -1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IndexOutOfBoundsException");
+ }
+
+
+ }
+
+
+ /**
+ * Positive and negative tests on getIndexedProperty valid arguments.
+ */
+ public void testGetIndexedValues() {
+
+ Object value = null;
+
+ for (int i = 0; i < 5; i++) {
+
+ try {
+ value = bean.get("intArray", i);
+ assertNotNull("intArray returned value " + i, value);
+ assertTrue("intArray returned Integer " + i,
+ value instanceof Integer);
+ assertEquals("intArray returned correct " + i, i * 10,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("intArray " + i + " threw " + t);
+ }
+
+ try {
+ value = bean.get("intIndexed", i);
+ assertNotNull("intIndexed returned value " + i, value);
+ assertTrue("intIndexed returned Integer " + i,
+ value instanceof Integer);
+ assertEquals("intIndexed returned correct " + i, i * 10,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("intIndexed " + i + " threw " + t);
+ }
+
+ try {
+ value = bean.get("listIndexed", i);
+ assertNotNull("listIndexed returned value " + i, value);
+ assertTrue("list returned String " + i,
+ value instanceof String);
+ assertEquals("listIndexed returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("listIndexed " + i + " threw " + t);
+ }
+
+ try {
+ value = bean.get("stringArray", i);
+ assertNotNull("stringArray returned value " + i, value);
+ assertTrue("stringArray returned String " + i,
+ value instanceof String);
+ assertEquals("stringArray returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("stringArray " + i + " threw " + t);
+ }
+
+ try {
+ value = bean.get("stringIndexed", i);
+ assertNotNull("stringIndexed returned value " + i, value);
+ assertTrue("stringIndexed returned String " + i,
+ value instanceof String);
+ assertEquals("stringIndexed returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("stringIndexed " + i + " threw " + t);
+ }
+
+ }
+
+
+ }
+
+
+ /**
+ * Corner cases on getMappedProperty invalid arguments.
+ */
+ public void testGetMappedArguments() {
+
+
+ try {
+ Object value = bean.get("mappedProperty", "unknown");
+ assertNull("Should not return a value", value);
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of returning null");
+ }
+
+
+ }
+
+
+ /**
+ * Positive and negative tests on getMappedProperty valid arguments.
+ */
+ public void testGetMappedValues() {
+
+ Object value = null;
+
+ try {
+ value = bean.get("mappedProperty", "First Key");
+ assertEquals("Can find first value", "First Value", value);
+ } catch (Throwable t) {
+ fail("Finding first value threw " + t);
+ }
+
+ try {
+ value = bean.get("mappedProperty", "Second Key");
+ assertEquals("Can find second value", "Second Value", value);
+ } catch (Throwable t) {
+ fail("Finding second value threw " + t);
+ }
+
+ try {
+ value = bean.get("mappedProperty", "Third Key");
+ assertNull("Can not find third value", value);
+ } catch (Throwable t) {
+ fail("Finding third value threw " + t);
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getSimpleProperty invalid arguments.
+ */
+ public void testGetSimpleArguments() {
+
+ try {
+ bean.get(null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a boolean property.
+ */
+ public void testGetSimpleBoolean() {
+
+ try {
+ Object value = bean.get("booleanProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Boolean));
+ assertTrue("Got correct value",
+ ((Boolean) value).booleanValue() == true);
+ } catch (Throwable e) {
+ fail("Exception: " + e);
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a double property.
+ */
+ public void testGetSimpleDouble() {
+
+ try {
+ Object value = bean.get("doubleProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Double));
+ assertEquals("Got correct value",
+ ((Double) value).doubleValue(),
+ (double) 321.0,
+ (double) 0.005);
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a float property.
+ */
+ public void testGetSimpleFloat() {
+
+ try {
+ Object value = bean.get("floatProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Float));
+ assertEquals("Got correct value",
+ ((Float) value).floatValue(),
+ (float) 123.0,
+ (float) 0.005);
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a int property.
+ */
+ public void testGetSimpleInt() {
+
+ try {
+ Object value = bean.get("intProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Integer));
+ assertEquals("Got correct value",
+ ((Integer) value).intValue(),
+ (int) 123);
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a long property.
+ */
+ public void testGetSimpleLong() {
+
+ try {
+ Object value = bean.get("longProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Long));
+ assertEquals("Got correct value",
+ ((Long) value).longValue(),
+ (long) 321);
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a short property.
+ */
+ public void testGetSimpleShort() {
+
+ try {
+ Object value = bean.get("shortProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Short));
+ assertEquals("Got correct value",
+ ((Short) value).shortValue(),
+ (short) 987);
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a String property.
+ */
+ public void testGetSimpleString() {
+
+ try {
+ Object value = bean.get("stringProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof String));
+ assertEquals("Got correct value",
+ (String) value,
+ "This is a string");
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ }
+
+
+ /**
+ * Test <code>contains()</code> method for mapped properties.
+ */
+ public void testMappedContains() {
+
+ try {
+ assertTrue("Can see first key",
+ bean.contains("mappedProperty", "First Key"));
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+
+ try {
+ assertTrue("Can not see unknown key",
+ !bean.contains("mappedProperty", "Unknown Key"));
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ }
+
+
+ /**
+ * Test <code>remove()</code> method for mapped properties.
+ */
+ public void testMappedRemove() {
+
+ try {
+ assertTrue("Can see first key",
+ bean.contains("mappedProperty", "First Key"));
+ bean.remove("mappedProperty", "First Key");
+ assertTrue("Can not see first key",
+ !bean.contains("mappedProperty", "First Key"));
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ try {
+ assertTrue("Can not see unknown key",
+ !bean.contains("mappedProperty", "Unknown Key"));
+ bean.remove("mappedProperty", "Unknown Key");
+ assertTrue("Can not see unknown key",
+ !bean.contains("mappedProperty", "Unknown Key"));
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ }
+
+
+ /**
+ * Test serialization and deserialization.
+ */
+ public void testSerialization() {
+
+ // Serialize the test bean
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(bean);
+ oos.flush();
+ oos.close();
+ } catch (Exception e) {
+ fail("Exception during serialization: " + e);
+ }
+
+ // Deserialize the test bean
+ try {
+ bean = null;
+ ByteArrayInputStream bais =
+ new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ bean = (DynaBean) ois.readObject();
+ bais.close();
+ } catch (Exception e) {
+ fail("Exception during deserialization: " + e);
+ }
+
+ // Confirm property values
+ testGetDescriptorArguments();
+ testGetDescriptorBoolean();
+ testGetDescriptorDouble();
+ testGetDescriptorFloat();
+ testGetDescriptorInt();
+ testGetDescriptorLong();
+ testGetDescriptorSecond();
+ testGetDescriptorShort();
+ testGetDescriptorString();
+ testGetDescriptors();
+ testGetIndexedArguments();
+ testGetIndexedValues();
+ testGetMappedArguments();
+ testGetMappedValues();
+ testGetSimpleArguments();
+ testGetSimpleBoolean();
+ testGetSimpleDouble();
+ testGetSimpleFloat();
+ testGetSimpleInt();
+ testGetSimpleLong();
+ testGetSimpleShort();
+ testGetSimpleString();
+ testMappedContains();
+ testMappedRemove();
+
+ // Ensure that we can create a new instance of the same DynaClass
+ try {
+ bean = bean.getDynaClass().newInstance();
+ } catch (Exception e) {
+ fail("Exception creating new instance: " + e);
+ }
+ testGetDescriptorArguments();
+ testGetDescriptorBoolean();
+ testGetDescriptorDouble();
+ testGetDescriptorFloat();
+ testGetDescriptorInt();
+ testGetDescriptorLong();
+ testGetDescriptorSecond();
+ testGetDescriptorShort();
+ testGetDescriptorString();
+ testGetDescriptors();
+
+ }
+
+
+ /**
+ * Corner cases on setIndexedProperty invalid arguments.
+ */
+ public void testSetIndexedArguments() {
+
+ try {
+ bean.set("intArray", -1, new Integer(0));
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IndexOutOfBoundsException");
+ }
+
+ }
+
+
+ /**
+ * Positive and negative tests on setIndexedProperty valid arguments.
+ */
+ public void testSetIndexedValues() {
+
+ Object value = null;
+
+ try {
+ bean.set("intArray", 0, new Integer(1));
+ value = (Integer) bean.get("intArray", 0);
+ assertNotNull("Returned new value 0", value);
+ assertTrue("Returned Integer new value 0",
+ value instanceof Integer);
+ assertEquals("Returned correct new value 0", 1,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ bean.set("intIndexed", 1, new Integer(11));
+ value = (Integer) bean.get("intIndexed", 1);
+ assertNotNull("Returned new value 1", value);
+ assertTrue("Returned Integer new value 1",
+ value instanceof Integer);
+ assertEquals("Returned correct new value 1", 11,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ bean.set("listIndexed", 2, "New Value 2");
+ value = (String) bean.get("listIndexed", 2);
+ assertNotNull("Returned new value 2", value);
+ assertTrue("Returned String new value 2",
+ value instanceof String);
+ assertEquals("Returned correct new value 2", "New Value 2",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ bean.set("stringArray", 3, "New Value 3");
+ value = (String) bean.get("stringArray", 3);
+ assertNotNull("Returned new value 3", value);
+ assertTrue("Returned String new value 3",
+ value instanceof String);
+ assertEquals("Returned correct new value 3", "New Value 3",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ bean.set("stringIndexed", 4, "New Value 4");
+ value = (String) bean.get("stringIndexed", 4);
+ assertNotNull("Returned new value 4", value);
+ assertTrue("Returned String new value 4",
+ value instanceof String);
+ assertEquals("Returned correct new value 4", "New Value 4",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+
+ }
+
+
+ /**
+ * Positive and negative tests on setMappedProperty valid arguments.
+ */
+ public void testSetMappedValues() {
+
+ try {
+ bean.set("mappedProperty", "First Key", "New First Value");
+ assertEquals("Can replace old value",
+ "New First Value",
+ (String) bean.get("mappedProperty", "First Key"));
+ } catch (Throwable t) {
+ fail("Finding fourth value threw " + t);
+ }
+
+ try {
+ bean.set("mappedProperty", "Fourth Key", "Fourth Value");
+ assertEquals("Can set new value",
+ "Fourth Value",
+ (String) bean.get("mappedProperty", "Fourth Key"));
+ } catch (Throwable t) {
+ fail("Finding fourth value threw " + t);
+ }
+
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a boolean property.
+ */
+ public void testSetSimpleBoolean() {
+
+ try {
+ boolean oldValue =
+ ((Boolean) bean.get("booleanProperty")).booleanValue();
+ boolean newValue = !oldValue;
+ bean.set("booleanProperty", new Boolean(newValue));
+ assertTrue("Matched new value",
+ newValue ==
+ ((Boolean) bean.get("booleanProperty")).booleanValue());
+ } catch (Throwable e) {
+ fail("Exception: " + e);
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a double property.
+ */
+ public void testSetSimpleDouble() {
+
+ try {
+ double oldValue =
+ ((Double) bean.get("doubleProperty")).doubleValue();
+ double newValue = oldValue + 1.0;
+ bean.set("doubleProperty", new Double(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ ((Double) bean.get("doubleProperty")).doubleValue(),
+ (double) 0.005);
+ } catch (Throwable e) {
+ fail("Exception: " + e);
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a float property.
+ */
+ public void testSetSimpleFloat() {
+
+ try {
+ float oldValue =
+ ((Float) bean.get("floatProperty")).floatValue();
+ float newValue = oldValue + (float) 1.0;
+ bean.set("floatProperty", new Float(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ ((Float) bean.get("floatProperty")).floatValue(),
+ (float) 0.005);
+ } catch (Throwable e) {
+ fail("Exception: " + e);
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a int property.
+ */
+ public void testSetSimpleInt() {
+
+ try {
+ int oldValue =
+ ((Integer) bean.get("intProperty")).intValue();
+ int newValue = oldValue + 1;
+ bean.set("intProperty", new Integer(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ ((Integer) bean.get("intProperty")).intValue());
+ } catch (Throwable e) {
+ fail("Exception: " + e);
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a long property.
+ */
+ public void testSetSimpleLong() {
+
+ try {
+ long oldValue =
+ ((Long) bean.get("longProperty")).longValue();
+ long newValue = oldValue + 1;
+ bean.set("longProperty", new Long(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ ((Long) bean.get("longProperty")).longValue());
+ } catch (Throwable e) {
+ fail("Exception: " + e);
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a short property.
+ */
+ public void testSetSimpleShort() {
+
+ try {
+ short oldValue =
+ ((Short) bean.get("shortProperty")).shortValue();
+ short newValue = (short) (oldValue + 1);
+ bean.set("shortProperty", new Short(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ ((Short) bean.get("shortProperty")).shortValue());
+ } catch (Throwable e) {
+ fail("Exception: " + e);
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a String property.
+ */
+ public void testSetSimpleString() {
+
+ try {
+ String oldValue = (String) bean.get("stringProperty");
+ String newValue = oldValue + " Extra Value";
+ bean.set("stringProperty", newValue);
+ assertEquals("Matched new value",
+ newValue,
+ (String) bean.get("stringProperty"));
+ } catch (Throwable e) {
+ fail("Exception: " + e);
+ }
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Create and return a <code>DynaClass</code> instance for our test
+ * <code>DynaBean</code>.
+ */
+ protected DynaClass createDynaClass() {
+
+ int intArray[] = new int[0];
+ String stringArray[] = new String[0];
+
+ DynaClass dynaClass = new BasicDynaClass
+ ("TestDynaClass", null,
+ new DynaProperty[]{
+ new DynaProperty("booleanProperty", Boolean.TYPE),
+ new DynaProperty("booleanSecond", Boolean.TYPE),
+ new DynaProperty("doubleProperty", Double.TYPE),
+ new DynaProperty("floatProperty", Float.TYPE),
+ new DynaProperty("intArray", intArray.getClass()),
+ new DynaProperty("intIndexed", intArray.getClass()),
+ new DynaProperty("intProperty", Integer.TYPE),
+ new DynaProperty("listIndexed", List.class),
+ new DynaProperty("longProperty", Long.TYPE),
+ new DynaProperty("mappedProperty", Map.class),
+ new DynaProperty("mappedIntProperty", Map.class),
+ new DynaProperty("nullProperty", String.class),
+ new DynaProperty("shortProperty", Short.TYPE),
+ new DynaProperty("stringArray", stringArray.getClass()),
+ new DynaProperty("stringIndexed", stringArray.getClass()),
+ new DynaProperty("stringProperty", String.class),
+ });
+ return (dynaClass);
+
+ }
+
+
+ /**
+ * Base for testGetDescriptorXxxxx() series of tests.
+ *
+ * @param name Name of the property to be retrieved
+ * @param type Expected class type of this property
+ */
+ protected void testGetDescriptorBase(String name, Class type) {
+
+ try {
+ DynaProperty descriptor =
+ bean.getDynaClass().getDynaProperty(name);
+ assertNotNull("Got descriptor", descriptor);
+ assertEquals("Got correct type", type, descriptor.getType());
+ } catch (Throwable t) {
+ fail("Threw an exception: " + t);
+ }
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanUtilsBenchCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanUtilsBenchCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanUtilsBenchCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,373 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * JUnit Test Case containing microbenchmarks for BeanUtils.
+ */
+
+public class BeanUtilsBenchCase extends TestCase {
+
+
+ // ------------------------------------------------------------ Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public BeanUtilsBenchCase(String name) {
+
+ super(name);
+
+ }
+
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ // Basic loop counter
+ private long counter = 100000;
+
+ // DynaClass for inDyna and outDyna
+ private DynaClass dynaClass = null;
+
+ // Input objects that have identical sets of properties and values.
+ private BenchBean inBean = null;
+ private DynaBean inDyna = null;
+ private Map inMap = null; // Map of Objects requiring no conversion
+ private Map inStrs = null; // Map of Strings requiring conversion
+
+ // Output objects that have identical sets of properties.
+ private BenchBean outBean = null;
+ private DynaBean outDyna = null;
+
+ // BeanUtilsBean instance to be used
+ private BeanUtilsBean bu = null;
+
+
+ // ---------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+
+ // Set up loop counter (if property specified)
+ String prop = System.getProperty("counter");
+ if (prop != null) {
+ counter = Long.parseLong(prop);
+ }
+
+ // Set up DynaClass for our DynaBean instances
+ dynaClass = new BasicDynaClass
+ ("BenchDynaClass", null,
+ new DynaProperty[]{
+ new DynaProperty("booleanProperty", Boolean.TYPE),
+ new DynaProperty("byteProperty", Byte.TYPE),
+ new DynaProperty("doubleProperty", Double.TYPE),
+ new DynaProperty("floatProperty", Float.TYPE),
+ new DynaProperty("intProperty", Integer.TYPE),
+ new DynaProperty("longProperty", Long.TYPE),
+ new DynaProperty("shortProperty", Short.TYPE),
+ new DynaProperty("stringProperty", String.class),
+ });
+
+ // Create input instances
+ inBean = new BenchBean();
+ inMap = new HashMap();
+ inMap.put("booleanProperty", new Boolean(inBean.getBooleanProperty()));
+ inMap.put("byteProperty", new Byte(inBean.getByteProperty()));
+ inMap.put("doubleProperty", new Double(inBean.getDoubleProperty()));
+ inMap.put("floatProperty", new Float(inBean.getFloatProperty()));
+ inMap.put("intProperty", new Integer(inBean.getIntProperty()));
+ inMap.put("longProperty", new Long(inBean.getLongProperty()));
+ inMap.put("shortProperty", new Short(inBean.getShortProperty()));
+ inMap.put("stringProperty", inBean.getStringProperty());
+ inDyna = dynaClass.newInstance();
+ Iterator inKeys = inMap.keySet().iterator();
+ while (inKeys.hasNext()) {
+ String inKey = (String) inKeys.next();
+ inDyna.set(inKey, inMap.get(inKey));
+ }
+ inStrs = new HashMap();
+ inKeys = inMap.keySet().iterator();
+ while (inKeys.hasNext()) {
+ String inKey = (String) inKeys.next();
+ inStrs.put(inKey, inMap.get(inKey).toString());
+ }
+
+ // Create output instances
+ outBean = new BenchBean();
+ outDyna = dynaClass.newInstance();
+ Iterator outKeys = inMap.keySet().iterator();
+ while (outKeys.hasNext()) {
+ String outKey = (String) outKeys.next();
+ outDyna.set(outKey, inMap.get(outKey));
+ }
+
+ // Set up BeanUtilsBean instance we will use
+ bu = BeanUtilsBean.getInstance();
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+
+ return (new TestSuite(BeanUtilsBenchCase.class));
+
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+
+ dynaClass = null;
+ inBean = null;
+ inDyna = null;
+ inMap = null;
+ outBean = null;
+ outDyna = null;
+ bu = null;
+
+ }
+
+
+
+ // ------------------------------------------------- Individual Test Methods
+
+
+ // Time copyProperties() from a bean
+ public void testCopyPropertiesBean() throws Exception {
+
+ long start;
+ long stop;
+
+ // Bean->Bean
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outBean, inBean);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outBean, inBean);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.copyProperties(bean,bean), count=" + counter +
+ ", time=" + (stop - start));
+
+ // Bean->Dyna
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outDyna, inBean);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outDyna, inBean);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.copyProperties(dyna,bean), count=" + counter +
+ ", time=" + (stop - start));
+
+ }
+
+
+ // Time copyProperties() from a DynaBean
+ public void testCopyPropertiesDyna() throws Exception {
+
+ long start;
+ long stop;
+
+ // Dyna->Bean
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outBean, inDyna);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outBean, inDyna);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.copyProperties(bean,dyna), count=" + counter +
+ ", time=" + (stop - start));
+
+ // Dyna->Dyna
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outDyna, inDyna);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outDyna, inDyna);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.copyProperties(dyna,dyna), count=" + counter +
+ ", time=" + (stop - start));
+
+ }
+
+
+ // Time copyProperties() from a Map of Objects
+ public void testCopyPropertiesMap() throws Exception {
+
+ long start;
+ long stop;
+
+ // Map->Bean
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outBean, inMap);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outBean, inMap);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.copyProperties(bean, map), count=" + counter +
+ ", time=" + (stop - start));
+
+ // Map->Dyna
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outDyna, inMap);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outDyna, inMap);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.copyProperties(dyna, map), count=" + counter +
+ ", time=" + (stop - start));
+
+ }
+
+
+ // Time copyProperties() from a Map of Strings
+ public void testCopyPropertiesStrs() throws Exception {
+
+ long start;
+ long stop;
+
+ // Strs->Bean
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outBean, inStrs);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outBean, inStrs);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.copyProperties(bean,strs), count=" + counter +
+ ", time=" + (stop - start));
+
+ // Strs->Dyna
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outDyna, inStrs);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.copyProperties(outDyna, inStrs);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.copyProperties(dyna,strs), count=" + counter +
+ ", time=" + (stop - start));
+
+ }
+
+
+ // Time populate() from a Map of Objects
+ public void testPopulateMap() throws Exception {
+
+ long start;
+ long stop;
+
+ // Map->Bean
+ for (long i = 0; i < counter; i++) {
+ bu.populate(outBean, inMap);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.populate(outBean, inMap);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.populate(bean, map), count=" + counter +
+ ", time=" + (stop - start));
+
+ // Map->Dyna
+ for (long i = 0; i < counter; i++) {
+ bu.populate(outDyna, inMap);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.populate(outDyna, inMap);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.populate(dyna, map), count=" + counter +
+ ", time=" + (stop - start));
+
+ }
+
+
+ // Time populate() from a Map of Strings
+ // NOTE - This simulates what Struts does when processing form beans
+ public void testPopulateStrs() throws Exception {
+
+ long start;
+ long stop;
+
+ // Strs->Bean
+ for (long i = 0; i < counter; i++) {
+ bu.populate(outBean, inStrs);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.populate(outBean, inStrs);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.populate(bean,strs), count=" + counter +
+ ", time=" + (stop - start));
+
+ // Strs->Dyna
+ for (long i = 0; i < counter; i++) {
+ bu.populate(outDyna, inStrs);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ bu.populate(outDyna, inStrs);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("BU.populate(dyna,strs), count=" + counter +
+ ", time=" + (stop - start));
+
+ }
+
+
+ // --------------------------------------------------------- Support Methods
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,1341 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+
+/**
+ * <p>
+ * Test Case for the BeanUtils class. The majority of these tests use
+ * instances of the TestBean class, so be sure to update the tests if you
+ * change the characteristics of that class.
+ * </p>
+ *
+ * <p>
+ * Template for this stolen from Craigs PropertyUtilsTestCase
+ * </p>
+ *
+ * <p>
+ * Note that the tests are dependant upon the static aspects
+ * (such as array sizes...) of the TestBean.java class, so ensure
+ * than all changes to TestBean are reflected here.
+ * </p>
+ *
+ * <p>
+ * So far, this test case has tests for the following methods of the
+ * <code>BeanUtils</code> class:
+ * </p>
+ * <ul>
+ * <li>getArrayProperty(Object bean, String name)</li>
+ * </ul>
+ *
+ * @author <a href="mailto:geirm at optonline.net">Geir Magnusson Jr.</a>
+ * @version $Revision: 1.29 $
+ */
+
+public class BeanUtilsTestCase extends TestCase {
+
+ // ---------------------------------------------------- Instance Variables
+
+ /**
+ * The test bean for each test.
+ */
+ protected TestBean bean = null;
+
+
+ /**
+ * The set of properties that should be described.
+ */
+ protected String describes[] =
+ { "booleanProperty",
+ "booleanSecond",
+ "byteProperty",
+ "doubleProperty",
+ "dupProperty",
+ "floatProperty",
+ "intArray",
+ // "intIndexed",
+ "longProperty",
+ "listIndexed",
+ "longProperty",
+ // "mappedProperty",
+ // "mappedIntProperty",
+ "nested",
+ "nullProperty",
+ "readOnlyProperty",
+ "shortProperty",
+ "stringArray",
+ // "stringIndexed",
+ "stringProperty"
+ };
+
+
+ // ---------------------------------------------------------- Constructors
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public BeanUtilsTestCase(String name) {
+ super(name);
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+ bean = new TestBean();
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(BeanUtilsTestCase.class));
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ bean = null;
+ }
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ /**
+ * Test the copyProperties() method from a DynaBean.
+ */
+ public void testCopyPropertiesDynaBean() {
+
+ // Set up an origin bean with customized properties
+ DynaClass dynaClass = DynaBeanUtilsTestCase.createDynaClass();
+ DynaBean orig = null;
+ try {
+ orig = dynaClass.newInstance();
+ } catch (Exception e) {
+ fail("newInstance(): " + e);
+ }
+ orig.set("booleanProperty", Boolean.FALSE);
+ orig.set("byteProperty", new Byte((byte) 111));
+ orig.set("doubleProperty", new Double(333.33));
+ orig.set("dupProperty",
+ new String[] { "New 0", "New 1", "New 2" });
+ orig.set("intArray", new int[] { 100, 200, 300 });
+ orig.set("intProperty", new Integer(333));
+ orig.set("longProperty", new Long(3333));
+ orig.set("shortProperty", new Short((short) 33));
+ orig.set("stringArray", new String[] { "New 0", "New 1" });
+ orig.set("stringProperty", "Custom string");
+
+ // Copy the origin bean to our destination test bean
+ try {
+ BeanUtils.copyProperties(bean, orig);
+ } catch (Exception e) {
+ fail("Threw exception: " + e);
+ }
+
+ // Validate the results for scalar properties
+ assertEquals("Copied boolean property",
+ false,
+ bean.getBooleanProperty());
+ assertEquals("Copied byte property",
+ (byte) 111,
+ bean.getByteProperty());
+ assertEquals("Copied double property",
+ 333.33,
+ bean.getDoubleProperty(),
+ 0.005);
+ assertEquals("Copied int property",
+ 333,
+ bean.getIntProperty());
+ assertEquals("Copied long property",
+ (long) 3333,
+ bean.getLongProperty());
+ assertEquals("Copied short property",
+ (short) 33,
+ bean.getShortProperty());
+ assertEquals("Copied string property",
+ "Custom string",
+ bean.getStringProperty());
+
+ // Validate the results for array properties
+ String dupProperty[] = bean.getDupProperty();
+ assertNotNull("dupProperty present", dupProperty);
+ assertEquals("dupProperty length", 3, dupProperty.length);
+ assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
+ assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
+ assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
+ int intArray[] = bean.getIntArray();
+ assertNotNull("intArray present", intArray);
+ assertEquals("intArray length", 3, intArray.length);
+ assertEquals("intArray[0]", 100, intArray[0]);
+ assertEquals("intArray[1]", 200, intArray[1]);
+ assertEquals("intArray[2]", 300, intArray[2]);
+ String stringArray[] = bean.getStringArray();
+ assertNotNull("stringArray present", stringArray);
+ assertEquals("stringArray length", 2, stringArray.length);
+ assertEquals("stringArray[0]", "New 0", stringArray[0]);
+ assertEquals("stringArray[1]", "New 1", stringArray[1]);
+
+ }
+
+
+ /**
+ * Test copyProperties() when the origin is a a <code>Map</code>.
+ */
+ public void testCopyPropertiesMap() {
+
+ Map map = new HashMap();
+ map.put("booleanProperty", "false");
+ map.put("byteProperty", "111");
+ map.put("doubleProperty", "333.0");
+ map.put("dupProperty", new String[] { "New 0", "New 1", "New 2" });
+ map.put("floatProperty", "222.0");
+ map.put("intArray", new String[] { "0", "100", "200" });
+ map.put("intProperty", "111");
+ map.put("longProperty", "444");
+ map.put("shortProperty", "555");
+ map.put("stringProperty", "New String Property");
+
+ try {
+ BeanUtils.copyProperties(bean, map);
+ } catch (Throwable t) {
+ fail("Threw " + t.toString());
+ }
+
+ // Scalar properties
+ assertEquals("booleanProperty", false,
+ bean.getBooleanProperty());
+ assertEquals("byteProperty", (byte) 111,
+ bean.getByteProperty());
+ assertEquals("doubleProperty", 333.0,
+ bean.getDoubleProperty(), 0.005);
+ assertEquals("floatProperty", (float) 222.0,
+ bean.getFloatProperty(), (float) 0.005);
+ assertEquals("longProperty", 111,
+ bean.getIntProperty());
+ assertEquals("longProperty", (long) 444,
+ bean.getLongProperty());
+ assertEquals("shortProperty", (short) 555,
+ bean.getShortProperty());
+ assertEquals("stringProperty", "New String Property",
+ bean.getStringProperty());
+
+ // Indexed Properties
+ String dupProperty[] = bean.getDupProperty();
+ assertNotNull("dupProperty present", dupProperty);
+ assertEquals("dupProperty length", 3, dupProperty.length);
+ assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
+ assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
+ assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
+ int intArray[] = bean.getIntArray();
+ assertNotNull("intArray present", intArray);
+ assertEquals("intArray length", 3, intArray.length);
+ assertEquals("intArray[0]", 0, intArray[0]);
+ assertEquals("intArray[1]", 100, intArray[1]);
+ assertEquals("intArray[2]", 200, intArray[2]);
+
+ }
+
+
+ /**
+ * Test the copyProperties() method from a standard JavaBean.
+ */
+ public void testCopyPropertiesStandard() {
+
+ // Set up an origin bean with customized properties
+ TestBean orig = new TestBean();
+ orig.setBooleanProperty(false);
+ orig.setByteProperty((byte) 111);
+ orig.setDoubleProperty(333.33);
+ orig.setDupProperty(new String[] { "New 0", "New 1", "New 2" });
+ orig.setIntArray(new int[] { 100, 200, 300 });
+ orig.setIntProperty(333);
+ orig.setLongProperty(3333);
+ orig.setShortProperty((short) 33);
+ orig.setStringArray(new String[] { "New 0", "New 1" });
+ orig.setStringProperty("Custom string");
+
+ // Copy the origin bean to our destination test bean
+ try {
+ BeanUtils.copyProperties(bean, orig);
+ } catch (Exception e) {
+ fail("Threw exception: " + e);
+ }
+
+ // Validate the results for scalar properties
+ assertEquals("Copied boolean property",
+ false,
+ bean.getBooleanProperty());
+ assertEquals("Copied byte property",
+ (byte) 111,
+ bean.getByteProperty());
+ assertEquals("Copied double property",
+ 333.33,
+ bean.getDoubleProperty(),
+ 0.005);
+ assertEquals("Copied int property",
+ 333,
+ bean.getIntProperty());
+ assertEquals("Copied long property",
+ (long) 3333,
+ bean.getLongProperty());
+ assertEquals("Copied short property",
+ (short) 33,
+ bean.getShortProperty());
+ assertEquals("Copied string property",
+ "Custom string",
+ bean.getStringProperty());
+
+ // Validate the results for array properties
+ String dupProperty[] = bean.getDupProperty();
+ assertNotNull("dupProperty present", dupProperty);
+ assertEquals("dupProperty length", 3, dupProperty.length);
+ assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
+ assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
+ assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
+ int intArray[] = bean.getIntArray();
+ assertNotNull("intArray present", intArray);
+ assertEquals("intArray length", 3, intArray.length);
+ assertEquals("intArray[0]", 100, intArray[0]);
+ assertEquals("intArray[1]", 200, intArray[1]);
+ assertEquals("intArray[2]", 300, intArray[2]);
+ String stringArray[] = bean.getStringArray();
+ assertNotNull("stringArray present", stringArray);
+ assertEquals("stringArray length", 2, stringArray.length);
+ assertEquals("stringArray[0]", "New 0", stringArray[0]);
+ assertEquals("stringArray[1]", "New 1", stringArray[1]);
+
+ }
+
+
+ /**
+ * Test the describe() method.
+ */
+ public void testDescribe() {
+
+ Map map = null;
+ try {
+ map = BeanUtils.describe(bean);
+ } catch (Exception e) {
+ fail("Threw exception " + e);
+ }
+
+ // Verify existence of all the properties that should be present
+ for (int i = 0; i < describes.length; i++) {
+ assertTrue("Property '" + describes[i] + "' is present",
+ map.containsKey(describes[i]));
+ }
+ assertTrue("Property 'writeOnlyProperty' is not present",
+ !map.containsKey("writeOnlyProperty"));
+
+ // Verify the values of scalar properties
+ assertEquals("Value of 'booleanProperty'",
+ "true",
+ (String) map.get("booleanProperty"));
+ assertEquals("Value of 'byteProperty'",
+ "121",
+ (String) map.get("byteProperty"));
+ assertEquals("Value of 'doubleProperty'",
+ "321.0",
+ (String) map.get("doubleProperty"));
+ assertEquals("Value of 'floatProperty'",
+ "123.0",
+ (String) map.get("floatProperty"));
+ assertEquals("Value of 'intProperty'",
+ "123",
+ (String) map.get("intProperty"));
+ assertEquals("Value of 'longProperty'",
+ "321",
+ (String) map.get("longProperty"));
+ assertEquals("Value of 'shortProperty'",
+ "987",
+ (String) map.get("shortProperty"));
+ assertEquals("Value of 'stringProperty'",
+ "This is a string",
+ (String) map.get("stringProperty"));
+
+ }
+
+
+ /**
+ * tests the string and int arrays of TestBean
+ */
+ public void testGetArrayProperty() {
+ try {
+ String arr[] = BeanUtils.getArrayProperty(bean, "stringArray");
+ String comp[] = bean.getStringArray();
+
+ assertTrue("String array length = " + comp.length,
+ (comp.length == arr.length));
+
+ arr = BeanUtils.getArrayProperty(bean, "intArray");
+ int iarr[] = bean.getIntArray();
+
+ assertTrue("String array length = " + iarr.length,
+ (iarr.length == arr.length));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * tests getting an indexed property
+ */
+ public void testGetIndexedProperty1() {
+ try {
+ String val = BeanUtils.getIndexedProperty(bean, "intIndexed[3]");
+ String comp = String.valueOf(bean.getIntIndexed(3));
+ assertTrue("intIndexed[3] == " + comp, val.equals(comp));
+
+ val = BeanUtils.getIndexedProperty(bean, "stringIndexed[3]");
+ comp = bean.getStringIndexed(3);
+ assertTrue("stringIndexed[3] == " + comp, val.equals(comp));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+ }
+
+
+ /**
+ * tests getting an indexed property
+ */
+ public void testGetIndexedProperty2() {
+ try {
+ String val = BeanUtils.getIndexedProperty(bean, "intIndexed", 3);
+ String comp = String.valueOf(bean.getIntIndexed(3));
+
+ assertTrue("intIndexed,3 == " + comp, val.equals(comp));
+
+ val = BeanUtils.getIndexedProperty(bean, "stringIndexed", 3);
+ comp = bean.getStringIndexed(3);
+
+ assertTrue("stringIndexed,3 == " + comp, val.equals(comp));
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+ }
+
+
+ /**
+ * tests getting a nested property
+ */
+ public void testGetNestedProperty() {
+ try {
+ String val = BeanUtils.getNestedProperty(bean, "nested.stringProperty");
+ String comp = bean.getNested().getStringProperty();
+ assertTrue("nested.StringProperty == " + comp,
+ val.equals(comp));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+ }
+
+
+ /**
+ * tests getting a 'whatever' property
+ */
+ public void testGetGeneralProperty() {
+ try {
+ String val = BeanUtils.getProperty(bean, "nested.intIndexed[2]");
+ String comp = String.valueOf(bean.getIntIndexed(2));
+
+ assertTrue("nested.intIndexed[2] == " + comp,
+ val.equals(comp));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+ }
+
+
+ /**
+ * tests getting a 'whatever' property
+ */
+ public void testGetSimpleProperty() {
+ try {
+ String val = BeanUtils.getSimpleProperty(bean, "shortProperty");
+ String comp = String.valueOf(bean.getShortProperty());
+
+ assertTrue("shortProperty == " + comp,
+ val.equals(comp));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+ }
+
+
+ /**
+ * Test populate() method on individual array elements.
+ */
+ public void testPopulateArrayElements() {
+
+ try {
+
+ HashMap map = new HashMap();
+ map.put("intIndexed[0]", "100");
+ map.put("intIndexed[2]", "120");
+ map.put("intIndexed[4]", "140");
+
+ BeanUtils.populate(bean, map);
+
+ assertEquals("intIndexed[0] is 100",
+ 100, bean.getIntIndexed(0));
+ assertEquals("intIndexed[1] is 10",
+ 10, bean.getIntIndexed(1));
+ assertEquals("intIndexed[2] is 120",
+ 120, bean.getIntIndexed(2));
+ assertEquals("intIndexed[3] is 30",
+ 30, bean.getIntIndexed(3));
+ assertEquals("intIndexed[4] is 140",
+ 140, bean.getIntIndexed(4));
+
+ map.clear();
+ map.put("stringIndexed[1]", "New String 1");
+ map.put("stringIndexed[3]", "New String 3");
+
+ BeanUtils.populate(bean, map);
+
+ assertEquals("stringIndexed[0] is \"String 0\"",
+ "String 0", bean.getStringIndexed(0));
+ assertEquals("stringIndexed[1] is \"New String 1\"",
+ "New String 1", bean.getStringIndexed(1));
+ assertEquals("stringIndexed[2] is \"String 2\"",
+ "String 2", bean.getStringIndexed(2));
+ assertEquals("stringIndexed[3] is \"New String 3\"",
+ "New String 3", bean.getStringIndexed(3));
+ assertEquals("stringIndexed[4] is \"String 4\"",
+ "String 4", bean.getStringIndexed(4));
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ }
+
+ }
+
+
+ /**
+ * Test populate() method on array properties as a whole.
+ */
+ public void testPopulateArrayProperties() {
+
+ try {
+
+ HashMap map = new HashMap();
+ int intArray[] = new int[] { 123, 456, 789 };
+ map.put("intArray", intArray);
+ String stringArray[] = new String[]
+ { "New String 0", "New String 1" };
+ map.put("stringArray", stringArray);
+
+ BeanUtils.populate(bean, map);
+
+ intArray = bean.getIntArray();
+ assertNotNull("intArray is present", intArray);
+ assertEquals("intArray length",
+ 3, intArray.length);
+ assertEquals("intArray[0]", 123, intArray[0]);
+ assertEquals("intArray[1]", 456, intArray[1]);
+ assertEquals("intArray[2]", 789, intArray[2]);
+ stringArray = bean.getStringArray();
+ assertNotNull("stringArray is present", stringArray);
+ assertEquals("stringArray length", 2, stringArray.length);
+ assertEquals("stringArray[0]", "New String 0", stringArray[0]);
+ assertEquals("stringArray[1]", "New String 1", stringArray[1]);
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ }
+
+ }
+
+
+ /**
+ * Test populate() on mapped properties.
+ */
+ public void testPopulateMapped() {
+
+ try {
+
+ HashMap map = new HashMap();
+ map.put("mappedProperty(First Key)", "New First Value");
+ map.put("mappedProperty(Third Key)", "New Third Value");
+
+ BeanUtils.populate(bean, map);
+
+ assertEquals("mappedProperty(First Key)",
+ "New First Value",
+ bean.getMappedProperty("First Key"));
+ assertEquals("mappedProperty(Second Key)",
+ "Second Value",
+ bean.getMappedProperty("Second Key"));
+ assertEquals("mappedProperty(Third Key)",
+ "New Third Value",
+ bean.getMappedProperty("Third Key"));
+ assertNull("mappedProperty(Fourth Key",
+ bean.getMappedProperty("Fourth Key"));
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ }
+
+ }
+
+
+ /**
+ * Test populate() method on nested properties.
+ */
+ public void testPopulateNested() {
+
+ try {
+
+ HashMap map = new HashMap();
+ map.put("nested.booleanProperty", "false");
+ // booleanSecond is left at true
+ map.put("nested.doubleProperty", "432.0");
+ // floatProperty is left at 123.0
+ map.put("nested.intProperty", "543");
+ // longProperty is left at 321
+ map.put("nested.shortProperty", "654");
+ // stringProperty is left at "This is a string"
+ map.put("nested.writeOnlyProperty", "New writeOnlyProperty value");
+
+ BeanUtils.populate(bean, map);
+
+ assertTrue("booleanProperty is false",
+ !bean.getNested().getBooleanProperty());
+ assertTrue("booleanSecond is true",
+ bean.getNested().isBooleanSecond());
+ assertEquals("doubleProperty is 432.0",
+ (double) 432.0,
+ bean.getNested().getDoubleProperty(),
+ (double) 0.005);
+ assertEquals("floatProperty is 123.0",
+ (float) 123.0,
+ bean.getNested().getFloatProperty(),
+ (float) 0.005);
+ assertEquals("intProperty is 543",
+ 543, bean.getNested().getIntProperty());
+ assertEquals("longProperty is 321",
+ (long) 321, bean.getNested().getLongProperty());
+ assertEquals("shortProperty is 654",
+ (short) 654, bean.getNested().getShortProperty());
+ assertEquals("stringProperty is \"This is a string\"",
+ "This is a string",
+ bean.getNested().getStringProperty());
+ assertEquals("writeOnlyProperty is \"New writeOnlyProperty value\"",
+ "New writeOnlyProperty value",
+ bean.getNested().getWriteOnlyPropertyValue());
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ }
+
+ }
+
+
+ /**
+ * Test populate() method on scalar properties.
+ */
+ public void testPopulateScalar() {
+
+ try {
+
+ bean.setNullProperty("Non-null value");
+
+ HashMap map = new HashMap();
+ map.put("booleanProperty", "false");
+ // booleanSecond is left at true
+ map.put("byteProperty", "111");
+ map.put("doubleProperty", "432.0");
+ // floatProperty is left at 123.0
+ map.put("intProperty", "543");
+ map.put("longProperty", "");
+ map.put("nullProperty", null);
+ map.put("shortProperty", "654");
+ // stringProperty is left at "This is a string"
+ map.put("writeOnlyProperty", "New writeOnlyProperty value");
+ map.put("readOnlyProperty", "New readOnlyProperty value");
+
+ BeanUtils.populate(bean, map);
+
+ assertTrue("booleanProperty is false", !bean.getBooleanProperty());
+ assertTrue("booleanSecond is true", bean.isBooleanSecond());
+ assertEquals("byteProperty is 111",
+ (byte) 111, bean.getByteProperty());
+ assertEquals("doubleProperty is 432.0",
+ (double) 432.0, bean.getDoubleProperty(),
+ (double) 0.005);
+ assertEquals("floatProperty is 123.0",
+ (float) 123.0, bean.getFloatProperty(),
+ (float) 0.005);
+ assertEquals("intProperty is 543",
+ 543, bean.getIntProperty());
+ assertEquals("longProperty is 0",
+ (long) 0, bean.getLongProperty());
+ assertNull("nullProperty is null",
+ bean.getNullProperty());
+ assertEquals("shortProperty is 654",
+ (short) 654, bean.getShortProperty());
+ assertEquals("stringProperty is \"This is a string\"",
+ "This is a string", bean.getStringProperty());
+ assertEquals("writeOnlyProperty is \"New writeOnlyProperty value\"",
+ "New writeOnlyProperty value",
+ bean.getWriteOnlyPropertyValue());
+ assertEquals("readOnlyProperty is \"Read Only String Property\"",
+ "Read Only String Property",
+ bean.getReadOnlyProperty());
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ }
+
+ }
+
+
+ /**
+ * Test calling setProperty() with null property values.
+ */
+ public void testSetPropertyNullValues() throws Exception {
+
+ Object oldValue = null;
+ Object newValue = null;
+
+ // Scalar value into array
+ oldValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
+ BeanUtils.setProperty(bean, "stringArray", (String) null);
+ newValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
+ assertNotNull("stringArray is not null", newValue);
+ assertTrue("stringArray of correct type",
+ newValue instanceof String[]);
+ assertEquals("stringArray length",
+ 1, ((String[]) newValue).length);
+ assertTrue("stringArray[0] is null",
+ ((String[]) newValue)[0] == null);
+ PropertyUtils.setProperty(bean, "stringArray", oldValue);
+
+ // Indexed value into array
+ oldValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
+ BeanUtils.setProperty(bean, "stringArray[2]", (String) null);
+ newValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
+ assertNotNull("stringArray is not null", newValue);
+ assertTrue("stringArray of correct type",
+ newValue instanceof String[]);
+ assertEquals("stringArray length",
+ 5, ((String[]) newValue).length);
+ assertTrue("stringArray[2] is null",
+ ((String[]) newValue)[2] == null);
+ PropertyUtils.setProperty(bean, "stringArray", oldValue);
+
+ // Value into scalar
+ BeanUtils.setProperty(bean, "stringProperty", null);
+ assertTrue("stringProperty is now null",
+ BeanUtils.getProperty(bean, "stringProperty") == null);
+
+ }
+
+
+ /**
+ * Test converting to and from primitive wrapper types.
+ */
+ public void testSetPropertyOnPrimitiveWrappers() throws Exception {
+
+ BeanUtils.setProperty(bean,"intProperty", new Integer(1));
+ assertEquals(1,bean.getIntProperty());
+ BeanUtils.setProperty(bean,"stringProperty", new Integer(1));
+ assertEquals(1, Integer.parseInt(bean.getStringProperty()));
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on byte.
+ */
+ public void testSetPropertyByte() throws Exception {
+
+ BeanUtils.setProperty(bean, "byteProperty", new Byte((byte) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+/*
+ BeanUtils.setProperty(bean, "byteProperty", new Double((double) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+ BeanUtils.setProperty(bean, "byteProperty", new Float((float) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+*/
+ BeanUtils.setProperty(bean, "byteProperty", new Integer((int) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+ BeanUtils.setProperty(bean, "byteProperty", new Long((long) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+ BeanUtils.setProperty(bean, "byteProperty", new Short((short) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on double.
+ */
+ public void testSetPropertyDouble() throws Exception {
+
+ BeanUtils.setProperty(bean, "doubleProperty", new Byte((byte) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+ BeanUtils.setProperty(bean, "doubleProperty", new Double((double) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+ BeanUtils.setProperty(bean, "doubleProperty", new Float((float) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+ BeanUtils.setProperty(bean, "doubleProperty", new Integer((int) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+ BeanUtils.setProperty(bean, "doubleProperty", new Long((long) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+ BeanUtils.setProperty(bean, "doubleProperty", new Short((short) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on float.
+ */
+ public void testSetPropertyFloat() throws Exception {
+
+ BeanUtils.setProperty(bean, "floatProperty", new Byte((byte) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+ BeanUtils.setProperty(bean, "floatProperty", new Double((double) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+ BeanUtils.setProperty(bean, "floatProperty", new Float((float) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+ BeanUtils.setProperty(bean, "floatProperty", new Integer((int) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+ BeanUtils.setProperty(bean, "floatProperty", new Long((long) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+ BeanUtils.setProperty(bean, "floatProperty", new Short((short) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on int.
+ */
+ public void testSetPropertyInteger() throws Exception {
+
+ BeanUtils.setProperty(bean, "longProperty", new Byte((byte) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+/*
+ BeanUtils.setProperty(bean, "longProperty", new Double((double) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+ BeanUtils.setProperty(bean, "longProperty", new Float((float) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+*/
+ BeanUtils.setProperty(bean, "longProperty", new Integer((int) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+ BeanUtils.setProperty(bean, "longProperty", new Long((long) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+ BeanUtils.setProperty(bean, "longProperty", new Short((short) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on long.
+ */
+ public void testSetPropertyLong() throws Exception {
+
+ BeanUtils.setProperty(bean, "longProperty", new Byte((byte) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+/*
+ BeanUtils.setProperty(bean, "longProperty", new Double((double) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+ BeanUtils.setProperty(bean, "longProperty", new Float((float) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+*/
+ BeanUtils.setProperty(bean, "longProperty", new Integer((int) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+ BeanUtils.setProperty(bean, "longProperty", new Long((long) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+ BeanUtils.setProperty(bean, "longProperty", new Short((short) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+
+ }
+
+
+ /**
+ * Test setting a null property value.
+ */
+ public void testSetPropertyNull() throws Exception {
+
+ bean.setNullProperty("non-null value");
+ BeanUtils.setProperty(bean, "nullProperty", null);
+ assertNull("nullProperty is null", bean.getNullProperty());
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on short.
+ */
+ public void testSetPropertyShort() throws Exception {
+
+ BeanUtils.setProperty(bean, "shortProperty", new Byte((byte) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+/*
+ BeanUtils.setProperty(bean, "shortProperty", new Double((double) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+ BeanUtils.setProperty(bean, "shortProperty", new Float((float) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+*/
+ BeanUtils.setProperty(bean, "shortProperty", new Integer((int) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+ BeanUtils.setProperty(bean, "shortProperty", new Long((long) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+ BeanUtils.setProperty(bean, "shortProperty", new Short((short) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on byte.
+ */
+ public void testCopyPropertyByte() throws Exception {
+
+ BeanUtils.copyProperty(bean, "byteProperty", new Byte((byte) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+ BeanUtils.copyProperty(bean, "byteProperty", new Double((double) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+ BeanUtils.copyProperty(bean, "byteProperty", new Float((float) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+ BeanUtils.copyProperty(bean, "byteProperty", new Integer((int) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+ BeanUtils.copyProperty(bean, "byteProperty", new Long((long) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+ BeanUtils.copyProperty(bean, "byteProperty", new Short((short) 123));
+ assertEquals((byte) 123, bean.getByteProperty());
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on double.
+ */
+ public void testCopyPropertyDouble() throws Exception {
+
+ BeanUtils.copyProperty(bean, "doubleProperty", new Byte((byte) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+ BeanUtils.copyProperty(bean, "doubleProperty", new Double((double) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+ BeanUtils.copyProperty(bean, "doubleProperty", new Float((float) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+ BeanUtils.copyProperty(bean, "doubleProperty", new Integer((int) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+ BeanUtils.copyProperty(bean, "doubleProperty", new Long((long) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+ BeanUtils.copyProperty(bean, "doubleProperty", new Short((short) 123));
+ assertEquals((double) 123, bean.getDoubleProperty(), 0.005);
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on float.
+ */
+ public void testCopyPropertyFloat() throws Exception {
+
+ BeanUtils.copyProperty(bean, "floatProperty", new Byte((byte) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+ BeanUtils.copyProperty(bean, "floatProperty", new Double((double) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+ BeanUtils.copyProperty(bean, "floatProperty", new Float((float) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+ BeanUtils.copyProperty(bean, "floatProperty", new Integer((int) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+ BeanUtils.copyProperty(bean, "floatProperty", new Long((long) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+ BeanUtils.copyProperty(bean, "floatProperty", new Short((short) 123));
+ assertEquals((float) 123, bean.getFloatProperty(), 0.005);
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on int.
+ */
+ public void testCopyPropertyInteger() throws Exception {
+
+ BeanUtils.copyProperty(bean, "longProperty", new Byte((byte) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+ BeanUtils.copyProperty(bean, "longProperty", new Double((double) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+ BeanUtils.copyProperty(bean, "longProperty", new Float((float) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+ BeanUtils.copyProperty(bean, "longProperty", new Integer((int) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+ BeanUtils.copyProperty(bean, "longProperty", new Long((long) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+ BeanUtils.copyProperty(bean, "longProperty", new Short((short) 123));
+ assertEquals((int) 123, bean.getIntProperty());
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on long.
+ */
+ public void testCopyPropertyLong() throws Exception {
+
+ BeanUtils.copyProperty(bean, "longProperty", new Byte((byte) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+ BeanUtils.copyProperty(bean, "longProperty", new Double((double) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+ BeanUtils.copyProperty(bean, "longProperty", new Float((float) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+ BeanUtils.copyProperty(bean, "longProperty", new Integer((int) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+ BeanUtils.copyProperty(bean, "longProperty", new Long((long) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+ BeanUtils.copyProperty(bean, "longProperty", new Short((short) 123));
+ assertEquals((long) 123, bean.getLongProperty());
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on short.
+ */
+ public void testCopyPropertyShort() throws Exception {
+
+ BeanUtils.copyProperty(bean, "shortProperty", new Byte((byte) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+ BeanUtils.copyProperty(bean, "shortProperty", new Double((double) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+ BeanUtils.copyProperty(bean, "shortProperty", new Float((float) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+ BeanUtils.copyProperty(bean, "shortProperty", new Integer((int) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+ BeanUtils.copyProperty(bean, "shortProperty", new Long((long) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+ BeanUtils.copyProperty(bean, "shortProperty", new Short((short) 123));
+ assertEquals((short) 123, bean.getShortProperty());
+
+ }
+
+
+ /**
+ * Test copying a property using a nested indexed array expression,
+ * with and without conversions.
+ */
+ public void testCopyPropertyNestedIndexedArray() throws Exception {
+
+ int origArray[] = { 0, 10, 20, 30, 40 };
+ int intArray[] = { 0, 0, 0 };
+ bean.getNested().setIntArray(intArray);
+ int intChanged[] = { 0, 0, 0 };
+
+ // No conversion required
+ BeanUtils.copyProperty(bean, "nested.intArray[1]", new Integer(1));
+ checkIntArray(bean.getIntArray(), origArray);
+ intChanged[1] = 1;
+ checkIntArray(bean.getNested().getIntArray(), intChanged);
+
+ // Widening conversion required
+ BeanUtils.copyProperty(bean, "nested.intArray[1]", new Byte((byte) 2));
+ checkIntArray(bean.getIntArray(), origArray);
+ intChanged[1] = 2;
+ checkIntArray(bean.getNested().getIntArray(), intChanged);
+
+ // Narrowing conversion required
+ BeanUtils.copyProperty(bean, "nested.intArray[1]", new Long((long) 3));
+ checkIntArray(bean.getIntArray(), origArray);
+ intChanged[1] = 3;
+ checkIntArray(bean.getNested().getIntArray(), intChanged);
+
+ // String conversion required
+ BeanUtils.copyProperty(bean, "nested.intArray[1]", "4");
+ checkIntArray(bean.getIntArray(), origArray);
+ intChanged[1] = 4;
+ checkIntArray(bean.getNested().getIntArray(), intChanged);
+
+ }
+
+
+ /**
+ * Test copying a property using a nested mapped map property.
+ */
+ public void testCopyPropertyNestedMappedMap() throws Exception {
+
+ Map origMap = new HashMap();
+ origMap.put("First Key", "First Value");
+ origMap.put("Second Key", "Second Value");
+ Map changedMap = new HashMap();
+ changedMap.put("First Key", "First Value");
+ changedMap.put("Second Key", "Second Value");
+
+ // No conversion required
+ BeanUtils.copyProperty(bean, "nested.mapProperty(Second Key)",
+ "New Second Value");
+ checkMap(bean.getMapProperty(), origMap);
+ changedMap.put("Second Key", "New Second Value");
+ checkMap(bean.getNested().getMapProperty(), changedMap);
+
+ }
+
+
+ /**
+ * Test copying a property using a nested simple expression, with and
+ * without conversions.
+ */
+ public void testCopyPropertyNestedSimple() throws Exception {
+
+ bean.setIntProperty(0);
+ bean.getNested().setIntProperty(0);
+
+ // No conversion required
+ BeanUtils.copyProperty(bean, "nested.intProperty", new Integer(1));
+ assertNotNull(bean.getNested());
+ assertEquals(0, bean.getIntProperty());
+ assertEquals(1, bean.getNested().getIntProperty());
+
+ // Widening conversion required
+ BeanUtils.copyProperty(bean, "nested.intProperty", new Byte((byte) 2));
+ assertNotNull(bean.getNested());
+ assertEquals(0, bean.getIntProperty());
+ assertEquals(2, bean.getNested().getIntProperty());
+
+ // Narrowing conversion required
+ BeanUtils.copyProperty(bean, "nested.intProperty", new Long((long) 3));
+ assertNotNull(bean.getNested());
+ assertEquals(0, bean.getIntProperty());
+ assertEquals(3, bean.getNested().getIntProperty());
+
+ // String conversion required
+ BeanUtils.copyProperty(bean, "nested.intProperty", "4");
+ assertNotNull(bean.getNested());
+ assertEquals(0, bean.getIntProperty());
+ assertEquals(4, bean.getNested().getIntProperty());
+
+ }
+
+
+ /**
+ * Test copying a null property value.
+ */
+ public void testCopyPropertyNull() throws Exception {
+
+ bean.setNullProperty("non-null value");
+ BeanUtils.copyProperty(bean, "nullProperty", null);
+ assertNull("nullProperty is null", bean.getNullProperty());
+
+ }
+
+
+ /**
+ * Test copying a new value to a write-only property, with and without
+ * conversions.
+ */
+ public void testCopyPropertyWriteOnly() throws Exception {
+
+ bean.setWriteOnlyProperty("Original value");
+
+ // No conversion required
+ BeanUtils.copyProperty(bean, "writeOnlyProperty", "New value");
+ assertEquals("New value", bean.getWriteOnlyPropertyValue());
+
+ // Integer->String conversion required
+ BeanUtils.copyProperty(bean, "writeOnlyProperty", new Integer(123));
+ assertEquals("123", bean.getWriteOnlyPropertyValue());
+
+ }
+
+
+ /**
+ * Test setting a new value to a write-only property, with and without
+ * conversions.
+ */
+ public void testSetPropertyWriteOnly() throws Exception {
+
+ bean.setWriteOnlyProperty("Original value");
+
+ // No conversion required
+ BeanUtils.setProperty(bean, "writeOnlyProperty", "New value");
+ assertEquals("New value", bean.getWriteOnlyPropertyValue());
+
+ // Integer->String conversion required
+ BeanUtils.setProperty(bean, "writeOnlyProperty", new Integer(123));
+ assertEquals("123", bean.getWriteOnlyPropertyValue());
+
+ }
+
+ /** Tests that separate instances can register separate instances */
+ public void testSeparateInstances() throws Exception {
+ BeanUtilsBean utilsOne = new BeanUtilsBean(
+ new ConvertUtilsBean(),
+ new PropertyUtilsBean());
+ BeanUtilsBean utilsTwo = new BeanUtilsBean(
+ new ConvertUtilsBean(),
+ new PropertyUtilsBean());
+
+
+ TestBean bean = new TestBean();
+
+ // Make sure what we're testing works
+ bean.setBooleanProperty(false);
+ utilsOne.setProperty(bean, "booleanProperty", "true");
+ assertEquals("Set property failed (1)", bean.getBooleanProperty(), true);
+
+ bean.setBooleanProperty(false);
+ utilsTwo.setProperty(bean, "booleanProperty", "true");
+ assertEquals("Set property failed (2)", bean.getBooleanProperty(), true);
+
+ // now change the registered conversion
+
+ utilsOne.getConvertUtils().register(new ThrowExceptionConverter(), Boolean.TYPE);
+ try {
+
+ bean.setBooleanProperty(false);
+ utilsOne.setProperty(bean, "booleanProperty", "true");
+ fail("Registered conversion not used.");
+
+ } catch (PassTestException e) { /* Do nothing */ }
+
+ // make sure that this conversion has no been registered in the other instance
+ try {
+
+ bean.setBooleanProperty(false);
+ utilsTwo.setProperty(bean, "booleanProperty", "true");
+ assertEquals("Set property failed (3)", bean.getBooleanProperty(), true);
+
+ } catch (PassTestException e) {
+ fail("Registed converter is used by other instances");
+ }
+ }
+
+ public void testArrayPropertyConversion() throws Exception {
+ BeanUtilsBean beanUtils = new BeanUtilsBean(
+ new ConvertUtilsBean(),
+ new PropertyUtilsBean());
+ beanUtils.getConvertUtils().register(
+ new Converter () {
+ public Object convert(Class type, Object value) {
+ return "Spam, spam, spam, spam!";
+ }
+ },
+ String.class);
+
+ TestBean bean = new TestBean();
+ String [] results = beanUtils.getArrayProperty(bean, "intArray");
+
+ int[] values = bean.getIntArray();
+ assertEquals(
+ "Converted array size not equal to property array size.",
+ results.length,
+ values.length);
+ for (int i=0, size=values.length ; i<size; i++) {
+ assertEquals(
+ "Value " + i + " incorrectly converted ",
+ "Spam, spam, spam, spam!",
+ results[i]);
+ }
+ }
+
+ // Ensure that the actual int[] matches the expected int[]
+ protected void checkIntArray(int actual[], int expected[]) {
+ assertNotNull("actual array not null", actual);
+ assertEquals("actual array length", expected.length, actual.length);
+ for (int i = 0; i < actual.length; i++) {
+ assertEquals("actual array value[" + i + "]",
+ expected[i], actual[i]);
+ }
+ }
+
+
+ // Ensure that the actual Map matches the expected Map
+ protected void checkMap(Map actual, Map expected) {
+ assertNotNull("actual map not null", actual);
+ assertEquals("actual map size", expected.size(), actual.size());
+ Iterator keys = expected.keySet().iterator();
+ while (keys.hasNext()) {
+ Object key = keys.next();
+ assertEquals("actual map value(" + key + ")",
+ expected.get(key), actual.get(key));
+ }
+ }
+
+ public void testMappedProperty() throws Exception {
+ MappedPropertyTestBean bean = new MappedPropertyTestBean();
+
+ BeanUtils.setProperty(bean, "mapproperty(this.that.the-other)", "some.dotty.value");
+
+ assertEquals(
+ "Mapped property set correctly",
+ "some.dotty.value",
+ bean.getMapproperty("this.that.the-other"));
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanWithInnerBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanWithInnerBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanWithInnerBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import java.util.Properties;
+
+/**
+ * Bean with inner bean.
+ *
+ * @author John E. Conlon
+ * @author Robert Burrell Donkin
+ */
+public class BeanWithInnerBean {
+ private InnerBean innerBean = new InnerBean();
+
+ public BeanWithInnerBean() {}
+ public InnerBean getInnerBean(){
+ return innerBean;
+ }
+
+ public class InnerBean {
+ private Properties fish = new Properties();
+
+ public String getFish(String key){
+ return fish.getProperty(key);
+ }
+ public void setFish(String key, String value){
+ fish.setProperty(key, value);
+ }
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanificationTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanificationTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BeanificationTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,541 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import java.util.*;
+
+import java.lang.ref.WeakReference;
+import java.lang.ref.ReferenceQueue;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.collections.ReferenceMap;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * <p>
+ * Test Case for changes made during Beanutils Beanification
+ * </p>
+ *
+ * @author Robert Burrell Donkin
+ * @author Juozas Baliuka
+ * @version $Revision: 1.5 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class BeanificationTestCase extends TestCase {
+
+ // ---------------------------------------------------- Constants
+
+ /** Maximum number of iterations before our test fails */
+ public static final int MAX_GC_ITERATIONS = 50;
+
+ // ---------------------------------------------------- Instance Variables
+
+
+ // ---------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public BeanificationTestCase(String name) {
+ super(name);
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+
+ ConvertUtils.deregister();
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(BeanificationTestCase.class));
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ ; // No action required
+ }
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+ /** Test of the methodology we'll use for some of the later tests */
+ public void testMemoryTestMethodology() throws Exception {
+ // test methodology
+ // many thanks to Juozas Baliuka for suggesting this method
+ ClassLoader loader = new ClassLoader() {};
+ WeakReference reference = new WeakReference(loader);
+ Class myClass = loader.loadClass("org.apache.commons.beanutils.BetaBean");
+
+ assertNotNull("Weak reference released early", reference.get());
+
+ // dereference class loader and class:
+ loader = null;
+ myClass = null;
+
+ int iterations = 0;
+ int bytz = 2;
+ while(true) {
+ System.gc();
+ if(iterations++ > MAX_GC_ITERATIONS){
+ fail("Max iterations reached before resource released.");
+ }
+ if( reference.get() == null ) {
+ break;
+
+ } else {
+ // create garbage:
+ byte[] b = new byte[bytz];
+ bytz = bytz * 2;
+ }
+ }
+ }
+
+ /** Tests whether classloaders and beans are released from memory by the map used by beanutils */
+ public void testMemoryLeak2() throws Exception {
+ // tests when the map used by beanutils has the right behaviour
+
+ if (isPre14JVM()) {
+ System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");
+ return;
+ }
+
+ // many thanks to Juozas Baliuka for suggesting this methodology
+ TestClassLoader loader = new TestClassLoader();
+ ReferenceQueue queue = new ReferenceQueue();
+ WeakReference loaderReference = new WeakReference(loader, queue);
+ Integer test = new Integer(1);
+
+ WeakReference testReference = new WeakReference(test, queue);
+ //Map map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD, true);
+ Map map = new WeakHashMap();
+ map.put(loader, test);
+
+ assertEquals("In map", test, map.get(loader));
+ assertNotNull("Weak reference released early (1)", loaderReference.get());
+ assertNotNull("Weak reference released early (2)", testReference.get());
+
+ // dereference strong references
+ loader = null;
+ test = null;
+
+ int iterations = 0;
+ int bytz = 2;
+ while(true) {
+ System.gc();
+ if(iterations++ > MAX_GC_ITERATIONS){
+ fail("Max iterations reached before resource released.");
+ }
+ map.isEmpty();
+
+ if(
+ loaderReference.get() == null &&
+ testReference.get() == null) {
+ break;
+
+ } else {
+ // create garbage:
+ byte[] b = new byte[bytz];
+ bytz = bytz * 2;
+ }
+ }
+ }
+
+ /** Tests whether classloaders and beans are released from memory */
+ public void testMemoryLeak() throws Exception {
+ if (isPre14JVM()) {
+ System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");
+ return;
+ }
+
+ // many thanks to Juozas Baliuka for suggesting this methodology
+ TestClassLoader loader = new TestClassLoader();
+ WeakReference loaderReference = new WeakReference(loader);
+ BeanUtilsBean.getInstance();
+
+ class GetBeanUtilsBeanThread extends Thread {
+
+ BeanUtilsBean beanUtils;
+ ConvertUtilsBean convertUtils;
+ PropertyUtilsBean propertyUtils;
+
+ GetBeanUtilsBeanThread() {}
+
+ public void run() {
+ beanUtils = BeanUtilsBean.getInstance();
+ convertUtils = ConvertUtilsBean.getInstance();
+ propertyUtils = PropertyUtilsBean.getInstance();
+ // XXX Log keeps a reference around!
+ LogFactory.releaseAll();
+ }
+
+ public String toString() {
+ return "GetBeanUtilsBeanThread";
+ }
+ }
+
+
+ GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread();
+ WeakReference threadWeakReference = new WeakReference(thread);
+ thread.setContextClassLoader(loader);
+
+ thread.start();
+ thread.join();
+
+ WeakReference beanUtilsReference = new WeakReference(thread.beanUtils);
+ WeakReference propertyUtilsReference = new WeakReference(thread.propertyUtils);
+ WeakReference convertUtilsReference = new WeakReference(thread.convertUtils);
+
+ assertNotNull("Weak reference released early (1)", loaderReference.get());
+ assertNotNull("Weak reference released early (2)", beanUtilsReference.get());
+ assertNotNull("Weak reference released early (3)", propertyUtilsReference.get());
+ assertNotNull("Weak reference released early (4)", convertUtilsReference.get());
+
+ // dereference strong references
+ loader = null;
+ thread.setContextClassLoader(null);
+ thread = null;
+
+ int iterations = 0;
+ int bytz = 2;
+ while(true) {
+ BeanUtilsBean.getInstance();
+ System.gc();
+ if(iterations++ > MAX_GC_ITERATIONS){
+ fail("Max iterations reached before resource released.");
+ }
+
+ if(
+ loaderReference.get() == null &&
+ beanUtilsReference.get() == null &&
+ propertyUtilsReference.get() == null &&
+ convertUtilsReference.get() == null) {
+ break;
+
+ } else {
+ // create garbage:
+ byte[] b = new byte[bytz];
+ bytz = bytz * 2;
+ }
+ }
+ }
+
+ /**
+ * Tests whether difference instances are loaded by different
+ * context classloaders.
+ */
+ public void testGetByContextClassLoader() throws Exception {
+
+ class GetBeanUtilsBeanThread extends Thread {
+
+ private Signal signal;
+
+ GetBeanUtilsBeanThread(Signal signal) {
+ this.signal = signal;
+ }
+
+ public void run() {
+ signal.setSignal(2);
+ signal.setBean(BeanUtilsBean.getInstance());
+ signal.setConvertUtils(ConvertUtilsBean.getInstance());
+ signal.setPropertyUtils(PropertyUtilsBean.getInstance());
+ }
+
+ public String toString() {
+ return "GetBeanUtilsBeanThread";
+ }
+ }
+
+ Signal signal = new Signal();
+ signal.setSignal(1);
+
+ GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread(signal);
+ thread.setContextClassLoader(new TestClassLoader());
+
+ thread.start();
+ thread.join();
+
+ assertEquals("Signal not set by test thread", 2, signal.getSignal());
+ assertTrue(
+ "Different BeanUtilsBean instances per context classloader",
+ BeanUtilsBean.getInstance() != signal.getBean());
+ assertTrue(
+ "Different ConvertUtilsBean instances per context classloader",
+ ConvertUtilsBean.getInstance() != signal.getConvertUtils());
+ assertTrue(
+ "Different PropertyUtilsBean instances per context classloader",
+ PropertyUtilsBean.getInstance() != signal.getPropertyUtils());
+ }
+
+
+ /**
+ * Tests whether difference instances are loaded by different
+ * context classloaders.
+ */
+ public void testContextClassLoaderLocal() throws Exception {
+
+ class CCLLTesterThread extends Thread {
+
+ private Signal signal;
+ private ContextClassLoaderLocal ccll;
+
+ CCLLTesterThread(Signal signal, ContextClassLoaderLocal ccll) {
+ this.signal = signal;
+ this.ccll = ccll;
+ }
+
+ public void run() {
+ ccll.set(new Integer(1789));
+ signal.setSignal(2);
+ signal.setMarkerObject(ccll.get());
+ }
+
+ public String toString() {
+ return "CCLLTesterThread";
+ }
+ }
+
+ ContextClassLoaderLocal ccll = new ContextClassLoaderLocal();
+ ccll.set(new Integer(1776));
+ assertEquals("Start thread sets value", new Integer(1776), ccll.get());
+
+ Signal signal = new Signal();
+ signal.setSignal(1);
+
+ CCLLTesterThread thread = new CCLLTesterThread(signal, ccll);
+ thread.setContextClassLoader(new TestClassLoader());
+
+ thread.start();
+ thread.join();
+
+ assertEquals("Signal not set by test thread", 2, signal.getSignal());
+ assertEquals("Second thread preserves value", new Integer(1776), ccll.get());
+ assertEquals("Second thread gets value it set", new Integer(1789), signal.getMarkerObject());
+ }
+
+ /** Tests whether calls are independent for different classloaders */
+ public void testContextClassloaderIndependence() throws Exception {
+
+ class TestIndependenceThread extends Thread {
+ private Signal signal;
+ private PrimitiveBean bean;
+
+ TestIndependenceThread(Signal signal, PrimitiveBean bean) {
+ this.signal = signal;
+ this.bean = bean;
+ }
+
+ public void run() {
+ try {
+ signal.setSignal(3);
+ ConvertUtils.register(new Converter() {
+ public Object convert(Class type, Object value) {
+ return new Integer(9);
+ }
+ }, Integer.TYPE);
+ BeanUtils.setProperty(bean, "int", new Integer(1));
+ } catch (Exception e) {
+ e.printStackTrace();
+ signal.setException(e);
+ }
+ }
+
+ public String toString() {
+ return "TestIndependenceThread";
+ }
+ }
+
+ PrimitiveBean bean = new PrimitiveBean();
+ BeanUtils.setProperty(bean, "int", new Integer(1));
+ assertEquals("Wrong property value (1)", 1, bean.getInt());
+
+ ConvertUtils.register(new Converter() {
+ public Object convert(Class type, Object value) {
+ return new Integer(5);
+ }
+ }, Integer.TYPE);
+ BeanUtils.setProperty(bean, "int", new Integer(1));
+ assertEquals("Wrong property value(2)", 5, bean.getInt());
+
+ Signal signal = new Signal();
+ signal.setSignal(1);
+ TestIndependenceThread thread = new TestIndependenceThread(signal, bean);
+ thread.setContextClassLoader(new TestClassLoader());
+
+ thread.start();
+ thread.join();
+
+ assertNull("Exception thrown by test thread:" + signal.getException(), signal.getException());
+ assertEquals("Signal not set by test thread", 3, signal.getSignal());
+ assertEquals("Wrong property value(3)", 9, bean.getInt());
+
+ }
+
+ /** Tests whether different threads can set beanutils instances correctly */
+ public void testBeanUtilsBeanSetInstance() throws Exception {
+
+ class SetInstanceTesterThread extends Thread {
+
+ private Signal signal;
+ private BeanUtilsBean bean;
+
+ SetInstanceTesterThread(Signal signal, BeanUtilsBean bean) {
+ this.signal = signal;
+ this.bean = bean;
+ }
+
+ public void run() {
+ BeanUtilsBean.setInstance(bean);
+ signal.setSignal(21);
+ signal.setBean(BeanUtilsBean.getInstance());
+ }
+
+ public String toString() {
+ return "SetInstanceTesterThread";
+ }
+ }
+
+ Signal signal = new Signal();
+ signal.setSignal(1);
+
+ BeanUtilsBean beanOne = new BeanUtilsBean();
+ BeanUtilsBean beanTwo = new BeanUtilsBean();
+
+ SetInstanceTesterThread thread = new SetInstanceTesterThread(signal, beanTwo);
+ thread.setContextClassLoader(new TestClassLoader());
+
+ BeanUtilsBean.setInstance(beanOne);
+ assertEquals("Start thread gets right instance", beanOne, BeanUtilsBean.getInstance());
+
+ thread.start();
+ thread.join();
+
+ assertEquals("Signal not set by test thread", 21, signal.getSignal());
+ assertEquals("Second thread preserves value", beanOne, BeanUtilsBean.getInstance());
+ assertEquals("Second thread gets value it set", beanTwo, signal.getBean());
+ }
+
+ /** Tests whether the unset method works*/
+ public void testContextClassLoaderUnset() throws Exception {
+ BeanUtilsBean beanOne = new BeanUtilsBean();
+ ContextClassLoaderLocal ccll = new ContextClassLoaderLocal();
+ ccll.set(beanOne);
+ assertEquals("Start thread gets right instance", beanOne, ccll.get());
+ ccll.unset();
+ assertTrue("Unset works", !beanOne.equals(ccll.get()));
+ }
+
+ private boolean isPre14JVM() {
+ // some pre 1.4 JVM have buggy WeakHashMap implementations
+ // this is used to test for those JVM
+ String version = System.getProperty("java.specification.version");
+ StringTokenizer tokenizer = new StringTokenizer(version,".");
+ if (tokenizer.nextToken().equals("1")) {
+ String minorVersion = tokenizer.nextToken();
+ if (minorVersion.equals("0")) return true;
+ if (minorVersion.equals("1")) return true;
+ if (minorVersion.equals("2")) return true;
+ if (minorVersion.equals("3")) return true;
+ }
+ return false;
+ }
+
+ // ---- Auxillary classes
+
+ class TestClassLoader extends ClassLoader {
+ public String toString() {
+ return "TestClassLoader";
+ }
+ }
+
+ class Signal {
+ private Exception e;
+ private int signal = 0;
+ private BeanUtilsBean bean;
+ private PropertyUtilsBean propertyUtils;
+ private ConvertUtilsBean convertUtils;
+ private Object marker;
+
+ public Exception getException() {
+ return e;
+ }
+
+ public void setException(Exception e) {
+ this.e = e;
+ }
+
+ public int getSignal() {
+ return signal;
+ }
+
+ public void setSignal(int signal) {
+ this.signal = signal;
+ }
+
+ public Object getMarkerObject() {
+ return marker;
+ }
+
+ public void setMarkerObject(Object marker) {
+ this.marker = marker;
+ }
+
+ public BeanUtilsBean getBean() {
+ return bean;
+ }
+
+ public void setBean(BeanUtilsBean bean) {
+ this.bean = bean;
+ }
+
+ public PropertyUtilsBean getPropertyUtils() {
+ return propertyUtils;
+ }
+
+ public void setPropertyUtils(PropertyUtilsBean propertyUtils) {
+ this.propertyUtils = propertyUtils;
+ }
+
+ public ConvertUtilsBean getConvertUtils() {
+ return convertUtils;
+ }
+
+ public void setConvertUtils(ConvertUtilsBean convertUtils) {
+ this.convertUtils = convertUtils;
+ }
+ }
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BenchBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BenchBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BenchBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+/**
+ * Plain old java bean (POJO) for microbenchmarks.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class BenchBean {
+
+
+ // -------------------------------------------------------------- Properties
+
+
+ /**
+ * A boolean property.
+ */
+ private boolean booleanProperty = true;
+
+ public boolean getBooleanProperty() {
+ return (booleanProperty);
+ }
+
+ public void setBooleanProperty(boolean booleanProperty) {
+ this.booleanProperty = booleanProperty;
+ }
+
+
+ /**
+ * A byte property.
+ */
+ private byte byteProperty = (byte) 121;
+
+ public byte getByteProperty() {
+ return (this.byteProperty);
+ }
+
+ public void setByteProperty(byte byteProperty) {
+ this.byteProperty = byteProperty;
+ }
+
+
+ /**
+ * A double property.
+ */
+ private double doubleProperty = 321.0;
+
+ public double getDoubleProperty() {
+ return (this.doubleProperty);
+ }
+
+ public void setDoubleProperty(double doubleProperty) {
+ this.doubleProperty = doubleProperty;
+ }
+
+
+ /**
+ * A float property.
+ */
+ private float floatProperty = (float) 123.0;
+
+ public float getFloatProperty() {
+ return (this.floatProperty);
+ }
+
+ public void setFloatProperty(float floatProperty) {
+ this.floatProperty = floatProperty;
+ }
+
+
+ /**
+ * An integer property.
+ */
+ private int intProperty = 123;
+
+ public int getIntProperty() {
+ return (this.intProperty);
+ }
+
+ public void setIntProperty(int intProperty) {
+ this.intProperty = intProperty;
+ }
+
+
+ /**
+ * A long property.
+ */
+ private long longProperty = 321;
+
+ public long getLongProperty() {
+ return (this.longProperty);
+ }
+
+ public void setLongProperty(long longProperty) {
+ this.longProperty = longProperty;
+ }
+
+
+ /**
+ * A short property.
+ */
+ private short shortProperty = (short) 987;
+
+ public short getShortProperty() {
+ return (this.shortProperty);
+ }
+
+ public void setShortProperty(short shortProperty) {
+ this.shortProperty = shortProperty;
+ }
+
+
+ /**
+ * A String property.
+ */
+ private String stringProperty = "This is a string";
+
+ public String getStringProperty() {
+ return (this.stringProperty);
+ }
+
+ public void setStringProperty(String stringProperty) {
+ this.stringProperty = stringProperty;
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BetaBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BetaBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/BetaBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+public class BetaBean extends AbstractChild {
+
+ private String secret = "utah";
+
+ public String getSecret() {
+ return secret;
+ }
+
+ public void setNoGetterProperty(String secret) {
+ this.secret = secret;
+ }
+
+ public void setNoGetterMappedProperty(String secret, String key) {
+ this.secret = "MAP:" + secret;
+ }
+
+ public BetaBean(String name) {
+ setName(name);
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/Child.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/Child.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/Child.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+public interface Child {
+
+ public String getName();
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ConstructorUtilsTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ConstructorUtilsTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ConstructorUtilsTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+
+/**
+ * <p> Test case for <code>ConstructorUtils</code> </p>
+ *
+ */
+public class ConstructorUtilsTestCase extends TestCase {
+
+ // ---------------------------------------------------------- Constructors
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public ConstructorUtilsTestCase(String name) {
+ super(name);
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(ConstructorUtilsTestCase.class));
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+ public void testInvokeConstructor() throws Exception {
+ {
+ Object obj = ConstructorUtils.invokeConstructor(TestBean.class,"TEST");
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals("TEST",((TestBean)obj).getStringProperty());
+ }
+ {
+ Object obj = ConstructorUtils.invokeConstructor(TestBean.class,new Float(17.3f));
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals(17.3f,((TestBean)obj).getFloatProperty(),0.0f);
+ }
+ }
+
+ public void testInvokeConstructorWithArgArray() throws Exception {
+ Object[] args = { new Float(17.3f), "TEST" };
+ Object obj = ConstructorUtils.invokeConstructor(TestBean.class,args);
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals(17.3f,((TestBean)obj).getFloatProperty(),0.0f);
+ assertEquals("TEST",((TestBean)obj).getStringProperty());
+ }
+
+ public void testInvokeConstructorWithTypeArray() throws Exception {
+ {
+ Object[] args = { Boolean.TRUE, "TEST" };
+ Class[] types = { Boolean.TYPE, String.class };
+ Object obj = ConstructorUtils.invokeConstructor(TestBean.class,args,types);
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals(true,((TestBean)obj).getBooleanProperty());
+ assertEquals("TEST",((TestBean)obj).getStringProperty());
+ }
+ {
+ Object[] args = { Boolean.TRUE, "TEST" };
+ Class[] types = { Boolean.class, String.class };
+ Object obj = ConstructorUtils.invokeConstructor(TestBean.class,args,types);
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals(true,((TestBean)obj).isBooleanSecond());
+ assertEquals("TEST",((TestBean)obj).getStringProperty());
+ }
+ }
+
+ public void testInvokeExactConstructor() throws Exception {
+ {
+ Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,"TEST");
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals("TEST",((TestBean)obj).getStringProperty());
+ }
+ {
+ try {
+ Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,new Float(17.3f));
+ fail("Expected NoSuchMethodException");
+ } catch(NoSuchMethodException e) {
+ // expected
+ }
+ }
+ {
+ Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,Boolean.TRUE);
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals(true,((TestBean)obj).isBooleanSecond());
+ }
+ }
+
+ public void testInvokeExactConstructorWithArgArray() throws Exception {
+ {
+ Object[] args = { new Float(17.3f), "TEST" };
+ try {
+ Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args);
+ fail("Expected NoSuchMethodException");
+ } catch(NoSuchMethodException e) {
+ // expected
+ }
+ }
+ {
+ Object[] args = { Boolean.TRUE, "TEST" };
+ Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args);
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals(true,((TestBean)obj).isBooleanSecond());
+ assertEquals("TEST",((TestBean)obj).getStringProperty());
+ }
+ }
+
+ public void testInvokeExactConstructorWithTypeArray() throws Exception {
+ {
+ Object[] args = { Boolean.TRUE, "TEST" };
+ Class[] types = { Boolean.TYPE, String.class };
+ Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args,types);
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals(true,((TestBean)obj).getBooleanProperty());
+ assertEquals("TEST",((TestBean)obj).getStringProperty());
+ }
+ {
+ Object[] args = { Boolean.TRUE, "TEST" };
+ Class[] types = { Boolean.class, String.class };
+ Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args,types);
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals(true,((TestBean)obj).isBooleanSecond());
+ assertEquals("TEST",((TestBean)obj).getStringProperty());
+ }
+ {
+ Object[] args = { new Float(17.3f), "TEST" };
+ Class[] types = { Float.TYPE, String.class };
+ Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args,types);
+ assertNotNull(obj);
+ assertTrue(obj instanceof TestBean);
+ assertEquals(17.3f,((TestBean)obj).getFloatProperty(),0.0f);
+ assertEquals("TEST",((TestBean)obj).getStringProperty());
+ }
+ {
+ Object[] args = { new Float(17.3f), "TEST" };
+ Class[] types = { Float.class, String.class };
+ try {
+ Object obj = ConstructorUtils.invokeExactConstructor(TestBean.class,args,types);
+ fail("Expected NoSuchMethodException");
+ } catch(NoSuchMethodException e) {
+ // expected
+ }
+ }
+ }
+
+ public void testGetAccessibleConstructor() throws Exception {
+ {
+ Constructor ctor = ConstructorUtils.getAccessibleConstructor(TestBean.class,String.class);
+ assertNotNull(ctor);
+ assertTrue(Modifier.isPublic(ctor.getModifiers()));
+ }
+ {
+ Constructor ctor = ConstructorUtils.getAccessibleConstructor(TestBean.class,Integer.class);
+ assertNotNull(ctor);
+ assertTrue(Modifier.isPublic(ctor.getModifiers()));
+ }
+ {
+ Constructor ctor = ConstructorUtils.getAccessibleConstructor(TestBean.class,Integer.TYPE);
+ assertNull(ctor);
+ }
+ }
+
+ public void testGetAccessibleConstructorWithTypeArray() throws Exception {
+ {
+ Class[] types = { Boolean.TYPE, String.class };
+ Constructor ctor = ConstructorUtils.getAccessibleConstructor(TestBean.class,types);
+ assertNotNull(ctor);
+ assertTrue(Modifier.isPublic(ctor.getModifiers()));
+ }
+ {
+ Class[] types = { Boolean.TYPE, Boolean.TYPE, String.class };
+ Constructor ctor = ConstructorUtils.getAccessibleConstructor(TestBean.class,types);
+ assertNull(ctor);
+ }
+ }
+
+ public void testGetAccessibleConstructorWithConstructorArg() throws Exception {
+ {
+ Class[] types = { Integer.class };
+ Constructor c1 = TestBean.class.getConstructor(types);
+ Constructor ctor = ConstructorUtils.getAccessibleConstructor(c1);
+ assertNotNull(ctor);
+ assertTrue(Modifier.isPublic(ctor.getModifiers()));
+ }
+ {
+ Class[] types = { Integer.class };
+ Constructor c1 = TestBean.class.getDeclaredConstructor(types);
+ Constructor ctor = ConstructorUtils.getAccessibleConstructor(c1);
+ assertNotNull(ctor);
+ assertTrue(Modifier.isPublic(ctor.getModifiers()));
+ }
+ {
+ Class[] types = { Integer.TYPE };
+ Constructor c1 = TestBean.class.getDeclaredConstructor(types);
+ Constructor ctor = ConstructorUtils.getAccessibleConstructor(c1);
+ assertNull(ctor);
+ }
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ConvertUtilsTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ConvertUtilsTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ConvertUtilsTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,654 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.HashMap;
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.commons.beanutils.converters.BooleanConverter;
+
+
+/**
+ * <p>
+ * Test Case for the ConvertUtils class.
+ * </p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.10 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class ConvertUtilsTestCase extends TestCase {
+
+ // ---------------------------------------------------- Instance Variables
+
+
+ // ---------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public ConvertUtilsTestCase(String name) {
+ super(name);
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+
+ ConvertUtils.deregister();
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(ConvertUtilsTestCase.class));
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ ; // No action required
+ }
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ /**
+ * Negative String to primitive integer array tests.
+ */
+ public void testNegativeIntegerArray() {
+
+ Object value = null;
+ int intArray[] = new int[0];
+
+ value = ConvertUtils.convert((String) null, intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = ConvertUtils.convert("a", intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = ConvertUtils.convert("{ a }", intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = ConvertUtils.convert("1a3", intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = ConvertUtils.convert("{ 1a3 }", intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = ConvertUtils.convert("0,1a3", intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = ConvertUtils.convert("{ 0, 1a3 }", intArray.getClass());
+ checkIntegerArray(value, intArray);
+
+
+ }
+
+
+ /**
+ * Negative scalar conversion tests. These rely on the standard
+ * default value conversions in ConvertUtils.
+ */
+ public void testNegativeScalar() {
+
+ Object value = null;
+
+ value = ConvertUtils.convert("foo", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = ConvertUtils.convert("foo", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = ConvertUtils.convert("foo", Byte.TYPE);
+ assertTrue(value instanceof Byte);
+ assertEquals(((Byte) value).byteValue(), (byte) 0);
+
+ value = ConvertUtils.convert("foo", Byte.class);
+ assertTrue(value instanceof Byte);
+ assertEquals(((Byte) value).byteValue(), (byte) 0);
+
+ try {
+ value = ConvertUtils.convert
+ ("org.apache.commons.beanutils.Undefined", Class.class);
+ fail("Should have thrown conversion exception");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ value = ConvertUtils.convert("foo", Double.TYPE);
+ assertTrue(value instanceof Double);
+ assertEquals(((Double) value).doubleValue(), (double) 0.0,
+ (double) 0.005);
+
+ value = ConvertUtils.convert("foo", Double.class);
+ assertTrue(value instanceof Double);
+ assertEquals(((Double) value).doubleValue(), (double) 0.0,
+ (double) 0.005);
+
+ value = ConvertUtils.convert("foo", Float.TYPE);
+ assertTrue(value instanceof Float);
+ assertEquals(((Float) value).floatValue(), (float) 0.0,
+ (float) 0.005);
+
+ value = ConvertUtils.convert("foo", Float.class);
+ assertTrue(value instanceof Float);
+ assertEquals(((Float) value).floatValue(), (float) 0.0,
+ (float) 0.005);
+
+ value = ConvertUtils.convert("foo", Integer.TYPE);
+ assertTrue(value instanceof Integer);
+ assertEquals(((Integer) value).intValue(), (int) 0);
+
+ value = ConvertUtils.convert("foo", Integer.class);
+ assertTrue(value instanceof Integer);
+ assertEquals(((Integer) value).intValue(), (int) 0);
+
+ value = ConvertUtils.convert("foo", Byte.TYPE);
+ assertTrue(value instanceof Byte);
+ assertEquals(((Byte) value).byteValue(), (byte) 0);
+
+ value = ConvertUtils.convert("foo", Long.class);
+ assertTrue(value instanceof Long);
+ assertEquals(((Long) value).longValue(), (long) 0);
+
+ value = ConvertUtils.convert("foo", Short.TYPE);
+ assertTrue(value instanceof Short);
+ assertEquals(((Short) value).shortValue(), (short) 0);
+
+ value = ConvertUtils.convert("foo", Short.class);
+ assertTrue(value instanceof Short);
+ assertEquals(((Short) value).shortValue(), (short) 0);
+
+ }
+
+
+ /**
+ * Negative String to String array tests.
+ */
+ public void testNegativeStringArray() {
+
+ Object value = null;
+ String stringArray[] = new String[0];
+
+ value = ConvertUtils.convert((String) null, stringArray.getClass());
+ checkStringArray(value, stringArray);
+
+ }
+
+
+ /**
+ * Test conversion of object to string for arrays.
+ */
+ public void testObjectToStringArray() {
+
+ int intArray0[] = new int[0];
+ int intArray1[] = { 123 };
+ int intArray2[] = { 123, 456 };
+ String stringArray0[] = new String[0];
+ String stringArray1[] = { "abc" };
+ String stringArray2[] = { "abc", "def" };
+
+ assertEquals("intArray0", null,
+ ConvertUtils.convert(intArray0));
+ assertEquals("intArray1", "123",
+ ConvertUtils.convert(intArray1));
+ assertEquals("intArray2", "123",
+ ConvertUtils.convert(intArray2));
+
+ assertEquals("stringArray0", null,
+ ConvertUtils.convert(stringArray0));
+ assertEquals("stringArray1", "abc",
+ ConvertUtils.convert(stringArray1));
+ assertEquals("stringArray2", "abc",
+ ConvertUtils.convert(stringArray2));
+
+ }
+
+
+ /**
+ * Test conversion of object to string for scalars.
+ */
+ public void testObjectToStringScalar() {
+
+ assertEquals("Boolean->String", "false",
+ ConvertUtils.convert(Boolean.FALSE));
+ assertEquals("Boolean->String", "true",
+ ConvertUtils.convert(Boolean.TRUE));
+ assertEquals("Byte->String", "123",
+ ConvertUtils.convert(new Byte((byte) 123)));
+ assertEquals("Character->String", "a",
+ ConvertUtils.convert(new Character('a')));
+ assertEquals("Double->String", "123.0",
+ ConvertUtils.convert(new Double((double) 123.0)));
+ assertEquals("Float->String", "123.0",
+ ConvertUtils.convert(new Float((float) 123.0)));
+ assertEquals("Integer->String", "123",
+ ConvertUtils.convert(new Integer((int) 123)));
+ assertEquals("Long->String", "123",
+ ConvertUtils.convert(new Long((long) 123)));
+ assertEquals("Short->String", "123",
+ ConvertUtils.convert(new Short((short) 123)));
+ assertEquals("String->String", "abc",
+ ConvertUtils.convert("abc"));
+ assertEquals("String->String null", null,
+ ConvertUtils.convert(null));
+
+ }
+
+
+ /**
+ * Positive array conversion tests.
+ */
+ public void testPositiveArray() {
+
+ String values1[] = { "10", "20", "30" };
+ Object value = ConvertUtils.convert(values1, Integer.TYPE);
+ int shape[] = new int[0];
+ assertEquals(shape.getClass(), value.getClass());
+ int results1[] = (int[]) value;
+ assertEquals(results1[0], 10);
+ assertEquals(results1[1], 20);
+ assertEquals(results1[2], 30);
+
+ String values2[] = { "100", "200", "300" };
+ value = ConvertUtils.convert(values2, shape.getClass());
+ assertEquals(shape.getClass(), value.getClass());
+ int results2[] = (int[]) value;
+ assertEquals(results2[0], 100);
+ assertEquals(results2[1], 200);
+ assertEquals(results2[2], 300);
+
+ }
+
+
+ /**
+ * Positive String to primitive integer array tests.
+ */
+ public void testPositiveIntegerArray() {
+
+ Object value = null;
+ int intArray[] = new int[0];
+ int intArray1[] = new int[] { 0 };
+ int intArray2[] = new int[] { 0, 10 };
+
+ value = ConvertUtils.convert("{ }", intArray.getClass());
+ checkIntegerArray(value, intArray);
+
+ value = ConvertUtils.convert("0", intArray.getClass());
+ checkIntegerArray(value, intArray1);
+ value = ConvertUtils.convert(" 0 ", intArray.getClass());
+ checkIntegerArray(value, intArray1);
+ value = ConvertUtils.convert("{ 0 }", intArray.getClass());
+ checkIntegerArray(value, intArray1);
+
+ value = ConvertUtils.convert("0,10", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ value = ConvertUtils.convert("0 10", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ value = ConvertUtils.convert("{0,10}", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ value = ConvertUtils.convert("{0 10}", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ value = ConvertUtils.convert("{ 0, 10 }", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ value = ConvertUtils.convert("{ 0 10 }", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+
+ }
+
+
+ /**
+ * Positive scalar conversion tests.
+ */
+ public void testPositiveScalar() {
+
+ Object value = null;
+
+ value = ConvertUtils.convert("true", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = ConvertUtils.convert("true", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = ConvertUtils.convert("yes", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = ConvertUtils.convert("yes", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = ConvertUtils.convert("y", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = ConvertUtils.convert("y", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = ConvertUtils.convert("on", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = ConvertUtils.convert("on", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = ConvertUtils.convert("false", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = ConvertUtils.convert("false", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = ConvertUtils.convert("no", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = ConvertUtils.convert("no", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = ConvertUtils.convert("n", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = ConvertUtils.convert("n", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = ConvertUtils.convert("off", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = ConvertUtils.convert("off", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = ConvertUtils.convert("123", Byte.TYPE);
+ assertTrue(value instanceof Byte);
+ assertEquals(((Byte) value).byteValue(), (byte) 123);
+
+ value = ConvertUtils.convert("123", Byte.class);
+ assertTrue(value instanceof Byte);
+ assertEquals(((Byte) value).byteValue(), (byte) 123);
+
+ value = ConvertUtils.convert("a", Character.TYPE);
+ assertTrue(value instanceof Character);
+ assertEquals(((Character) value).charValue(), 'a');
+
+ value = ConvertUtils.convert("a", Character.class);
+ assertTrue(value instanceof Character);
+ assertEquals(((Character) value).charValue(), 'a');
+
+ value = ConvertUtils.convert("java.lang.String", Class.class);
+ assertTrue(value instanceof Class);
+ assertEquals(String.class, (Class) value);
+
+ value = ConvertUtils.convert("123.456", Double.TYPE);
+ assertTrue(value instanceof Double);
+ assertEquals(((Double) value).doubleValue(), (double) 123.456,
+ (double) 0.005);
+
+ value = ConvertUtils.convert("123.456", Double.class);
+ assertTrue(value instanceof Double);
+ assertEquals(((Double) value).doubleValue(), (double) 123.456,
+ (double) 0.005);
+
+ value = ConvertUtils.convert("123.456", Float.TYPE);
+ assertTrue(value instanceof Float);
+ assertEquals(((Float) value).floatValue(), (float) 123.456,
+ (float) 0.005);
+
+ value = ConvertUtils.convert("123.456", Float.class);
+ assertTrue(value instanceof Float);
+ assertEquals(((Float) value).floatValue(), (float) 123.456,
+ (float) 0.005);
+
+ value = ConvertUtils.convert("123", Integer.TYPE);
+ assertTrue(value instanceof Integer);
+ assertEquals(((Integer) value).intValue(), (int) 123);
+
+ value = ConvertUtils.convert("123", Integer.class);
+ assertTrue(value instanceof Integer);
+ assertEquals(((Integer) value).intValue(), (int) 123);
+
+ value = ConvertUtils.convert("123", Long.TYPE);
+ assertTrue(value instanceof Long);
+ assertEquals(((Long) value).longValue(), (long) 123);
+
+ value = ConvertUtils.convert("123", Long.class);
+ assertTrue(value instanceof Long);
+ assertEquals(((Long) value).longValue(), (long) 123);
+
+ value = ConvertUtils.convert("123", Short.TYPE);
+ assertTrue(value instanceof Short);
+ assertEquals(((Short) value).shortValue(), (short) 123);
+
+ value = ConvertUtils.convert("123", Short.class);
+ assertTrue(value instanceof Short);
+ assertEquals(((Short) value).shortValue(), (short) 123);
+
+ String input = null;
+
+ input = "2002-03-17";
+ value = ConvertUtils.convert(input, Date.class);
+ assertTrue(value instanceof Date);
+ assertEquals(input, value.toString());
+
+ input = "20:30:40";
+ value = ConvertUtils.convert(input, Time.class);
+ assertTrue(value instanceof Time);
+ assertEquals(input, value.toString());
+
+ input = "2002-03-17 20:30:40.0";
+ value = ConvertUtils.convert(input, Timestamp.class);
+ assertTrue(value instanceof Timestamp);
+ assertEquals(input, value.toString());
+
+ }
+
+
+ /**
+ * Positive String to String array tests.
+ */
+ public void testPositiveStringArray() {
+
+ Object value = null;
+ String stringArray[] = new String[0];
+ String stringArray1[] = new String[]
+ { "abc" };
+ String stringArray2[] = new String[]
+ { "abc", "de,f" };
+
+ value = ConvertUtils.convert("", stringArray.getClass());
+ checkStringArray(value, stringArray);
+ value = ConvertUtils.convert(" ", stringArray.getClass());
+ checkStringArray(value, stringArray);
+ value = ConvertUtils.convert("{}", stringArray.getClass());
+ checkStringArray(value, stringArray);
+ value = ConvertUtils.convert("{ }", stringArray.getClass());
+ checkStringArray(value, stringArray);
+
+ value = ConvertUtils.convert("abc", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+ value = ConvertUtils.convert("{abc}", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+ value = ConvertUtils.convert("\"abc\"", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+ value = ConvertUtils.convert("{\"abc\"}", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+ value = ConvertUtils.convert("'abc'", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+ value = ConvertUtils.convert("{'abc'}", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+
+ value = ConvertUtils.convert("abc 'de,f'",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+ value = ConvertUtils.convert("{abc, 'de,f'}",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+ value = ConvertUtils.convert("\"abc\",\"de,f\"",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+ value = ConvertUtils.convert("{\"abc\" 'de,f'}",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+ value = ConvertUtils.convert("'abc' 'de,f'",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+ value = ConvertUtils.convert("{'abc', \"de,f\"}",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+
+
+ }
+
+ public void testSeparateConvertInstances() throws Exception {
+ ConvertUtilsBean utilsOne = new ConvertUtilsBean();
+ ConvertUtilsBean utilsTwo = new ConvertUtilsBean();
+
+ // make sure that the test work ok before anything's changed
+ Object
+ value = utilsOne.convert("true", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(
+ "Standard conversion failed (1)",
+ ((Boolean) value).booleanValue(),
+ true);
+
+ value = utilsTwo.convert("true", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(
+ "Standard conversion failed (2)",
+ ((Boolean) value).booleanValue(),
+ true);
+
+ // now register a test
+
+ utilsOne.register(new ThrowExceptionConverter(), Boolean.TYPE);
+ try {
+
+ utilsOne.convert("true", Boolean.TYPE);
+ fail("Register converter failed.");
+
+ } catch (PassTestException e) { /* This shows that the registration has worked */ }
+
+ try {
+ // nothing should have changed
+ value = utilsTwo.convert("true", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(
+ "Standard conversion failed (3)",
+ ((Boolean) value).booleanValue(),
+ true);
+
+ } catch (PassTestException e) {
+ // This is a failure since utilsTwo should still have
+ // standard converters registered
+ fail("Registering a converter for an instance should not effect another instance.");
+ }
+
+ // nothing we'll test deregister
+ utilsOne.deregister();
+ value = utilsOne.convert("true", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals("Instance deregister failed.", ((Boolean) value).booleanValue(), true);
+
+ value = utilsTwo.convert("true", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(
+ "Standard conversion failed (4)",
+ ((Boolean) value).booleanValue(),
+ true);
+ }
+
+ public void testDeregisteringSingleConverter() throws Exception {
+ ConvertUtils convertUtils = new ConvertUtils();
+
+ // make sure that the test work ok before anything's changed
+ Object
+ value = convertUtils.convert("true", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(
+ "Standard conversion failed (1)",
+ ((Boolean) value).booleanValue(),
+ true);
+
+ // we'll test deregister
+ convertUtils.deregister(Boolean.TYPE);
+ assertNull("Converter should be null",convertUtils.lookup(Boolean.TYPE));
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ private void checkIntegerArray(Object value, int intArray[]) {
+
+ assertNotNull("Returned value is not null", value);
+ assertEquals("Returned value is int[]",
+ intArray.getClass(), value.getClass());
+ int results[] = (int[]) value;
+ assertEquals("Returned array length", intArray.length, results.length);
+ for (int i = 0; i < intArray.length; i++) {
+ assertEquals("Returned array value " + i,
+ intArray[i], results[i]);
+ }
+
+ }
+
+
+ private void checkStringArray(Object value, String stringArray[]) {
+
+ assertNotNull("Returned value is not null", value);
+ assertEquals("Returned value is String[]",
+ stringArray.getClass(), value.getClass());
+ String results[] = (String[]) value;
+ assertEquals("Returned array length",
+ stringArray.length, results.length);
+ for (int i = 0; i < stringArray.length; i++) {
+ assertEquals("Returned array value " + i,
+ stringArray[i], results[i]);
+ }
+
+ }
+
+
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaBeanUtilsTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaBeanUtilsTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaBeanUtilsTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,1266 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * Test case for BeanUtils when the underlying bean is actually a DynaBean.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.22 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class DynaBeanUtilsTestCase extends TestCase {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The basic test bean for each test.
+ */
+ protected DynaBean bean = null;
+
+
+ /**
+ * The nested bean pointed at by the "nested" property.
+ */
+ protected TestBean nested = null;
+
+
+ /**
+ * The set of properties that should be described.
+ */
+ protected String describes[] =
+ { "booleanProperty",
+ "booleanSecond",
+ "byteProperty",
+ "doubleProperty",
+ "dupProperty",
+ "floatProperty",
+ "intArray",
+ "intIndexed",
+ "intProperty",
+ "listIndexed",
+ "longProperty",
+ "mapProperty",
+ "mappedProperty",
+ "mappedIntProperty",
+ "nested",
+ "nullProperty",
+ // "readOnlyProperty",
+ "shortProperty",
+ "stringArray",
+ "stringIndexed",
+ "stringProperty"
+ };
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public DynaBeanUtilsTestCase(String name) {
+
+ super(name);
+
+ }
+
+
+ // --------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+
+ // Instantiate a new DynaBean instance
+ DynaClass dynaClass = createDynaClass();
+ bean = dynaClass.newInstance();
+
+ // Initialize the DynaBean's property values (like TestBean)
+ bean.set("booleanProperty", new Boolean(true));
+ bean.set("booleanSecond", new Boolean(true));
+ bean.set("byteProperty", new Byte((byte) 121));
+ bean.set("doubleProperty", new Double(321.0));
+ bean.set("floatProperty", new Float((float) 123.0));
+ String dupProperty[] = { "Dup 0", "Dup 1", "Dup 2", "Dup 3", "Dup 4"};
+ bean.set("dupProperty", dupProperty);
+ int intArray[] = { 0, 10, 20, 30, 40 };
+ bean.set("intArray", intArray);
+ int intIndexed[] = { 0, 10, 20, 30, 40 };
+ bean.set("intIndexed", intIndexed);
+ bean.set("intProperty", new Integer(123));
+ List listIndexed = new ArrayList();
+ listIndexed.add("String 0");
+ listIndexed.add("String 1");
+ listIndexed.add("String 2");
+ listIndexed.add("String 3");
+ listIndexed.add("String 4");
+ bean.set("listIndexed", listIndexed);
+ bean.set("longProperty", new Long((long) 321));
+ HashMap mapProperty = new HashMap();
+ mapProperty.put("First Key", "First Value");
+ mapProperty.put("Second Key", "Second Value");
+ bean.set("mapProperty", mapProperty);
+ HashMap mappedProperty = new HashMap();
+ mappedProperty.put("First Key", "First Value");
+ mappedProperty.put("Second Key", "Second Value");
+ bean.set("mappedProperty", mappedProperty);
+ HashMap mappedIntProperty = new HashMap();
+ mappedIntProperty.put("One", new Integer(1));
+ mappedIntProperty.put("Two", new Integer(2));
+ bean.set("mappedIntProperty", mappedIntProperty);
+ nested = new TestBean();
+ bean.set("nested", nested);
+ // Property "nullProperty" is not initialized, so it should return null
+ bean.set("shortProperty", new Short((short) 987));
+ String stringArray[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+ bean.set("stringArray", stringArray);
+ String stringIndexed[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+ bean.set("stringIndexed", stringIndexed);
+ bean.set("stringProperty", "This is a string");
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+
+ return (new TestSuite(DynaBeanUtilsTestCase.class));
+
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+
+ bean = null;
+ nested = null;
+
+ }
+
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+ /**
+ * Test the cloneBean() method from a DynaBean.
+ */
+ public void testCloneDynaBean() {
+
+ // Set up an origin bean with customized properties
+ DynaClass dynaClass = DynaBeanUtilsTestCase.createDynaClass();
+ DynaBean orig = null;
+ try {
+ orig = dynaClass.newInstance();
+ } catch (Exception e) {
+ fail("newInstance(): " + e);
+ }
+ orig.set("booleanProperty", Boolean.FALSE);
+ orig.set("byteProperty", new Byte((byte)111));
+ orig.set("doubleProperty", new Double(333.33));
+ orig.set("dupProperty", new String[] { "New 0", "New 1", "New 2" });
+ orig.set("intArray", new int[] { 100, 200, 300 });
+ orig.set("intProperty", new Integer(333));
+ orig.set("longProperty", new Long(3333));
+ orig.set("shortProperty", new Short((short) 33));
+ orig.set("stringArray", new String[] { "New 0", "New 1" });
+ orig.set("stringProperty", "Custom string");
+
+ // Copy the origin bean to our destination test bean
+ DynaBean clonedBean = null;
+ try {
+ clonedBean = (DynaBean) BeanUtils.cloneBean(orig);
+ } catch (Exception e) {
+ fail("Threw exception: " + e);
+ }
+
+ // Validate the results for scalar properties
+ assertEquals("Cloned boolean property",
+ false,
+ ((Boolean) clonedBean.get("booleanProperty")).booleanValue());
+ assertEquals("Cloned byte property",
+ (byte) 111,
+ ((Byte) clonedBean.get("byteProperty")).byteValue());
+ assertEquals("Cloned double property",
+ 333.33,
+ ((Double) clonedBean.get("doubleProperty")).doubleValue(),
+ 0.005);
+ assertEquals("Cloned int property",
+ 333,
+ ((Integer) clonedBean.get("intProperty")).intValue());
+ assertEquals("Cloned long property",
+ (long) 3333,
+ ((Long) clonedBean.get("longProperty")).longValue());
+ assertEquals("Cloned short property",
+ (short) 33,
+ ((Short) clonedBean.get("shortProperty")).shortValue());
+ assertEquals("Cloned string property",
+ "Custom string",
+ (String) clonedBean.get("stringProperty"));
+
+ // Validate the results for array properties
+ String dupProperty[] = (String[]) clonedBean.get("dupProperty");
+ assertNotNull("dupProperty present", dupProperty);
+ assertEquals("dupProperty length", 3, dupProperty.length);
+ assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
+ assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
+ assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
+ int intArray[] = (int[]) clonedBean.get("intArray");
+ assertNotNull("intArray present", intArray);
+ assertEquals("intArray length", 3, intArray.length);
+ assertEquals("intArray[0]", 100, intArray[0]);
+ assertEquals("intArray[1]", 200, intArray[1]);
+ assertEquals("intArray[2]", 300, intArray[2]);
+ String stringArray[] = (String[]) clonedBean.get("stringArray");
+ assertNotNull("stringArray present", stringArray);
+ assertEquals("stringArray length", 2, stringArray.length);
+ assertEquals("stringArray[0]", "New 0", stringArray[0]);
+ assertEquals("stringArray[1]", "New 1", stringArray[1]);
+
+ }
+
+ /**
+ * Test the copyProperties() method from a DynaBean.
+ */
+ public void testCopyPropertiesDynaBean() {
+
+ // Set up an origin bean with customized properties
+ DynaClass dynaClass = DynaBeanUtilsTestCase.createDynaClass();
+ DynaBean orig = null;
+ try {
+ orig = dynaClass.newInstance();
+ } catch (Exception e) {
+ fail("newInstance(): " + e);
+ }
+ orig.set("booleanProperty", Boolean.FALSE);
+ orig.set("byteProperty", new Byte((byte)111));
+ orig.set("doubleProperty", new Double(333.33));
+ orig.set("dupProperty", new String[] { "New 0", "New 1", "New 2" });
+ orig.set("intArray", new int[] { 100, 200, 300 });
+ orig.set("intProperty", new Integer(333));
+ orig.set("longProperty", new Long(3333));
+ orig.set("shortProperty", new Short((short) 33));
+ orig.set("stringArray", new String[] { "New 0", "New 1" });
+ orig.set("stringProperty", "Custom string");
+
+ // Copy the origin bean to our destination test bean
+ try {
+ BeanUtils.copyProperties(bean, orig);
+ } catch (Exception e) {
+ fail("Threw exception: " + e);
+ }
+
+ // Validate the results for scalar properties
+ assertEquals("Copied boolean property",
+ false,
+ ((Boolean) bean.get("booleanProperty")).booleanValue());
+ assertEquals("Copied byte property",
+ (byte) 111,
+ ((Byte) bean.get("byteProperty")).byteValue());
+ assertEquals("Copied double property",
+ 333.33,
+ ((Double) bean.get("doubleProperty")).doubleValue(),
+ 0.005);
+ assertEquals("Copied int property",
+ 333,
+ ((Integer) bean.get("intProperty")).intValue());
+ assertEquals("Copied long property",
+ (long) 3333,
+ ((Long) bean.get("longProperty")).longValue());
+ assertEquals("Copied short property",
+ (short) 33,
+ ((Short) bean.get("shortProperty")).shortValue());
+ assertEquals("Copied string property",
+ "Custom string",
+ (String) bean.get("stringProperty"));
+
+ // Validate the results for array properties
+ String dupProperty[] = (String[]) bean.get("dupProperty");
+ assertNotNull("dupProperty present", dupProperty);
+ assertEquals("dupProperty length", 3, dupProperty.length);
+ assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
+ assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
+ assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
+ int intArray[] = (int[]) bean.get("intArray");
+ assertNotNull("intArray present", intArray);
+ assertEquals("intArray length", 3, intArray.length);
+ assertEquals("intArray[0]", 100, intArray[0]);
+ assertEquals("intArray[1]", 200, intArray[1]);
+ assertEquals("intArray[2]", 300, intArray[2]);
+ String stringArray[] = (String[]) bean.get("stringArray");
+ assertNotNull("stringArray present", stringArray);
+ assertEquals("stringArray length", 2, stringArray.length);
+ assertEquals("stringArray[0]", "New 0", stringArray[0]);
+ assertEquals("stringArray[1]", "New 1", stringArray[1]);
+
+ }
+
+
+ /**
+ * Test copyProperties() when the origin is a a <code>Map</code>.
+ */
+ public void testCopyPropertiesMap() {
+
+ Map map = new HashMap();
+ map.put("booleanProperty", "false");
+ map.put("byteProperty", "111");
+ map.put("doubleProperty", "333.0");
+ map.put("dupProperty", new String[] { "New 0", "New 1", "New 2" });
+ map.put("floatProperty", "222.0");
+ map.put("intArray", new String[] { "0", "100", "200" });
+ map.put("intProperty", "111");
+ map.put("longProperty", "444");
+ map.put("shortProperty", "555");
+ map.put("stringProperty", "New String Property");
+
+ try {
+ BeanUtils.copyProperties(bean, map);
+ } catch (Throwable t) {
+ fail("Threw " + t.toString());
+ }
+
+ // Scalar properties
+ assertEquals("booleanProperty", false,
+ ((Boolean) bean.get("booleanProperty")).booleanValue());
+ assertEquals("byteProperty", (byte) 111,
+ ((Byte) bean.get("byteProperty")).byteValue());
+ assertEquals("doubleProperty", 333.0,
+ ((Double) bean.get("doubleProperty")).doubleValue(),
+ 0.005);
+ assertEquals("floatProperty", (float) 222.0,
+ ((Float) bean.get("floatProperty")).floatValue(),
+ (float) 0.005);
+ assertEquals("intProperty", 111,
+ ((Integer) bean.get("intProperty")).intValue());
+ assertEquals("longProperty", (long) 444,
+ ((Long) bean.get("longProperty")).longValue());
+ assertEquals("shortProperty", (short) 555,
+ ((Short) bean.get("shortProperty")).shortValue());
+ assertEquals("stringProperty", "New String Property",
+ (String) bean.get("stringProperty"));
+
+ // Indexed Properties
+ String dupProperty[] = (String[]) bean.get("dupProperty");
+ assertNotNull("dupProperty present", dupProperty);
+ assertEquals("dupProperty length", 3, dupProperty.length);
+ assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
+ assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
+ assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
+ int intArray[] = (int[]) bean.get("intArray");
+ assertNotNull("intArray present", intArray);
+ assertEquals("intArray length", 3, intArray.length);
+ assertEquals("intArray[0]", 0, intArray[0]);
+ assertEquals("intArray[1]", 100, intArray[1]);
+ assertEquals("intArray[2]", 200, intArray[2]);
+
+ }
+
+
+ /**
+ * Test the copyProperties() method from a standard JavaBean.
+ */
+ public void testCopyPropertiesStandard() {
+
+ // Set up an origin bean with customized properties
+ TestBean orig = new TestBean();
+ orig.setBooleanProperty(false);
+ orig.setByteProperty((byte) 111);
+ orig.setDoubleProperty(333.33);
+ orig.setDupProperty(new String[] { "New 0", "New 1", "New 2" });
+ orig.setIntArray(new int[] { 100, 200, 300 });
+ orig.setIntProperty(333);
+ orig.setLongProperty(3333);
+ orig.setShortProperty((short) 33);
+ orig.setStringArray(new String[] { "New 0", "New 1" });
+ orig.setStringProperty("Custom string");
+
+ // Copy the origin bean to our destination test bean
+ try {
+ BeanUtils.copyProperties(bean, orig);
+ } catch (Exception e) {
+ fail("Threw exception: " + e);
+ }
+
+ // Validate the results for scalar properties
+ assertEquals("Copied boolean property",
+ false,
+ ((Boolean) bean.get("booleanProperty")).booleanValue());
+ assertEquals("Copied byte property",
+ (byte) 111,
+ ((Byte) bean.get("byteProperty")).byteValue());
+ assertEquals("Copied double property",
+ 333.33,
+ ((Double) bean.get("doubleProperty")).doubleValue(),
+ 0.005);
+ assertEquals("Copied int property",
+ 333,
+ ((Integer) bean.get("intProperty")).intValue());
+ assertEquals("Copied long property",
+ (long) 3333,
+ ((Long) bean.get("longProperty")).longValue());
+ assertEquals("Copied short property",
+ (short) 33,
+ ((Short) bean.get("shortProperty")).shortValue());
+ assertEquals("Copied string property",
+ "Custom string",
+ (String) bean.get("stringProperty"));
+
+ // Validate the results for array properties
+ String dupProperty[] = (String[]) bean.get("dupProperty");
+ assertNotNull("dupProperty present", dupProperty);
+ assertEquals("dupProperty length", 3, dupProperty.length);
+ assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
+ assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
+ assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
+ int intArray[] = (int[]) bean.get("intArray");
+ assertNotNull("intArray present", intArray);
+ assertEquals("intArray length", 3, intArray.length);
+ assertEquals("intArray[0]", 100, intArray[0]);
+ assertEquals("intArray[1]", 200, intArray[1]);
+ assertEquals("intArray[2]", 300, intArray[2]);
+ String stringArray[] = (String[]) bean.get("stringArray");
+ assertNotNull("stringArray present", stringArray);
+ assertEquals("stringArray length", 2, stringArray.length);
+ assertEquals("stringArray[0]", "New 0", stringArray[0]);
+ assertEquals("stringArray[1]", "New 1", stringArray[1]);
+
+ }
+
+
+ /**
+ * Test the describe() method.
+ */
+ public void testDescribe() {
+
+ Map map = null;
+ try {
+ map = PropertyUtils.describe(bean);
+ } catch (Exception e) {
+ fail("Threw exception " + e);
+ }
+
+ // Verify existence of all the properties that should be present
+ for (int i = 0; i < describes.length; i++) {
+ assertTrue("Property '" + describes[i] + "' is present",
+ map.containsKey(describes[i]));
+ }
+ assertTrue("Property 'writeOnlyProperty' is not present",
+ !map.containsKey("writeOnlyProperty"));
+
+ // Verify the values of scalar properties
+ assertEquals("Value of 'booleanProperty'",
+ Boolean.TRUE,
+ (Boolean) map.get("booleanProperty"));
+ assertEquals("Value of 'byteProperty'",
+ new Byte((byte) 121),
+ (Byte) map.get("byteProperty"));
+ assertEquals("Value of 'doubleProperty'",
+ new Double(321.0),
+ (Double) map.get("doubleProperty"));
+ assertEquals("Value of 'floatProperty'",
+ new Float((float) 123.0),
+ (Float) map.get("floatProperty"));
+ assertEquals("Value of 'intProperty'",
+ new Integer(123),
+ (Integer) map.get("intProperty"));
+ assertEquals("Value of 'longProperty'",
+ new Long(321),
+ (Long) map.get("longProperty"));
+ assertEquals("Value of 'shortProperty'",
+ new Short((short) 987),
+ (Short) map.get("shortProperty"));
+ assertEquals("Value of 'stringProperty'",
+ "This is a string",
+ (String) map.get("stringProperty"));
+
+ }
+
+
+ /**
+ * Test populate() method on array properties as a whole.
+ */
+ public void testPopulateArrayProperties() {
+
+ try {
+
+ HashMap map = new HashMap();
+ // int intArray[] = new int[] { 123, 456, 789 };
+ String intArrayIn[] = new String[] { "123", "456", "789" };
+ map.put("intArray", intArrayIn);
+ String stringArray[] = new String[]
+ { "New String 0", "New String 1" };
+ map.put("stringArray", stringArray);
+
+ BeanUtils.populate(bean, map);
+
+ int intArray[] = (int[]) bean.get("intArray");
+ assertNotNull("intArray is present", intArray);
+ assertEquals("intArray length",
+ 3, intArray.length);
+ assertEquals("intArray[0]", 123, intArray[0]);
+ assertEquals("intArray[1]", 456, intArray[1]);
+ assertEquals("intArray[2]", 789, intArray[2]);
+ stringArray = (String[]) bean.get("stringArray");
+ assertNotNull("stringArray is present", stringArray);
+ assertEquals("stringArray length", 2, stringArray.length);
+ assertEquals("stringArray[0]", "New String 0", stringArray[0]);
+ assertEquals("stringArray[1]", "New String 1", stringArray[1]);
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ }
+
+ }
+
+
+ /**
+ * tests the string and int arrays of TestBean
+ */
+ public void testGetArrayProperty() {
+ try {
+ String arr[] = BeanUtils.getArrayProperty(bean, "stringArray");
+ String comp[] = (String[]) bean.get("stringArray");
+
+ assertTrue("String array length = " + comp.length,
+ (comp.length == arr.length));
+
+ arr = BeanUtils.getArrayProperty(bean, "intArray");
+ int iarr[] = (int[]) bean.get("intArray");
+
+ assertTrue("String array length = " + iarr.length,
+ (iarr.length == arr.length));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * tests getting an indexed property
+ */
+ public void testGetIndexedProperty1() {
+ try {
+ String val = BeanUtils.getIndexedProperty(bean, "intIndexed[3]");
+ String comp = String.valueOf(bean.get("intIndexed", 3));
+ assertTrue("intIndexed[3] == " + comp, val.equals(comp));
+
+ val = BeanUtils.getIndexedProperty(bean, "stringIndexed[3]");
+ comp = (String) bean.get("stringIndexed", 3);
+ assertTrue("stringIndexed[3] == " + comp, val.equals(comp));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+ }
+
+
+ /**
+ * tests getting an indexed property
+ */
+ public void testGetIndexedProperty2() {
+ try {
+ String val = BeanUtils.getIndexedProperty(bean, "intIndexed", 3);
+ String comp = String.valueOf(bean.get("intIndexed", 3));
+
+ assertTrue("intIndexed,3 == " + comp, val.equals(comp));
+
+ val = BeanUtils.getIndexedProperty(bean, "stringIndexed", 3);
+ comp = (String) bean.get("stringIndexed", 3);
+
+ assertTrue("stringIndexed,3 == " + comp, val.equals(comp));
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+ }
+
+
+ /**
+ * tests getting a nested property
+ */
+ public void testGetNestedProperty() {
+ try {
+ String val = BeanUtils.getNestedProperty(bean, "nested.stringProperty");
+ String comp = nested.getStringProperty();
+ assertTrue("nested.StringProperty == " + comp,
+ val.equals(comp));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+ }
+
+
+ /**
+ * tests getting a 'whatever' property
+ */
+ public void testGetGeneralProperty() {
+ try {
+ String val = BeanUtils.getProperty(bean, "nested.intIndexed[2]");
+ String comp = String.valueOf(bean.get("intIndexed", 2));
+
+ assertTrue("nested.intIndexed[2] == " + comp,
+ val.equals(comp));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+ }
+
+
+ /**
+ * tests getting a 'whatever' property
+ */
+ public void testGetSimpleProperty() {
+ try {
+ String val = BeanUtils.getSimpleProperty(bean, "shortProperty");
+ String comp = String.valueOf(bean.get("shortProperty"));
+
+ assertTrue("shortProperty == " + comp,
+ val.equals(comp));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+ }
+
+
+ /**
+ * Test populate() method on individual array elements.
+ */
+ public void testPopulateArrayElements() {
+
+ try {
+
+ HashMap map = new HashMap();
+ map.put("intIndexed[0]", "100");
+ map.put("intIndexed[2]", "120");
+ map.put("intIndexed[4]", "140");
+
+ BeanUtils.populate(bean, map);
+ Integer intIndexed0 = (Integer) bean.get("intIndexed", 0);
+ assertEquals("intIndexed[0] is 100",
+ 100, intIndexed0.intValue());
+ Integer intIndexed1 = (Integer) bean.get("intIndexed", 1);
+ assertEquals("intIndexed[1] is 10",
+ 10, intIndexed1.intValue());
+ Integer intIndexed2 = (Integer) bean.get("intIndexed", 2);
+ assertEquals("intIndexed[2] is 120",
+ 120, intIndexed2.intValue());
+ Integer intIndexed3 = (Integer) bean.get("intIndexed", 3);
+ assertEquals("intIndexed[3] is 30",
+ 30, intIndexed3.intValue());
+ Integer intIndexed4 = (Integer) bean.get("intIndexed", 4);
+ assertEquals("intIndexed[4] is 140",
+ 140, intIndexed4.intValue());
+
+ map.clear();
+ map.put("stringIndexed[1]", "New String 1");
+ map.put("stringIndexed[3]", "New String 3");
+
+ BeanUtils.populate(bean, map);
+
+ assertEquals("stringIndexed[0] is \"String 0\"",
+ "String 0",
+ (String) bean.get("stringIndexed", 0));
+ assertEquals("stringIndexed[1] is \"New String 1\"",
+ "New String 1",
+ (String) bean.get("stringIndexed", 1));
+ assertEquals("stringIndexed[2] is \"String 2\"",
+ "String 2",
+ (String) bean.get("stringIndexed", 2));
+ assertEquals("stringIndexed[3] is \"New String 3\"",
+ "New String 3",
+ (String) bean.get("stringIndexed", 3));
+ assertEquals("stringIndexed[4] is \"String 4\"",
+ "String 4",
+ (String) bean.get("stringIndexed", 4));
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ }
+
+ }
+
+
+ /**
+ * Test populate() on mapped properties.
+ */
+ public void testPopulateMapped() {
+
+ try {
+
+ HashMap map = new HashMap();
+ map.put("mappedProperty(First Key)", "New First Value");
+ map.put("mappedProperty(Third Key)", "New Third Value");
+
+ BeanUtils.populate(bean, map);
+
+ assertEquals("mappedProperty(First Key)",
+ "New First Value",
+ (String) bean.get("mappedProperty", "First Key"));
+ assertEquals("mappedProperty(Second Key)",
+ "Second Value",
+ (String) bean.get("mappedProperty", "Second Key"));
+ assertEquals("mappedProperty(Third Key)",
+ "New Third Value",
+ (String) bean.get("mappedProperty", "Third Key"));
+ assertNull("mappedProperty(Fourth Key",
+ (String) bean.get("mappedProperty", "Fourth Key"));
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ }
+
+ }
+
+
+ /**
+ * Test populate() method on nested properties.
+ */
+ public void testPopulateNested() {
+
+ try {
+
+ HashMap map = new HashMap();
+ map.put("nested.booleanProperty", "false");
+ // booleanSecond is left at true
+ map.put("nested.doubleProperty", "432.0");
+ // floatProperty is left at 123.0
+ map.put("nested.intProperty", "543");
+ // longProperty is left at 321
+ map.put("nested.shortProperty", "654");
+ // stringProperty is left at "This is a string"
+
+ BeanUtils.populate(bean, map);
+
+ TestBean nested = (TestBean) bean.get("nested");
+ assertTrue("booleanProperty is false",
+ !nested.getBooleanProperty());
+ assertTrue("booleanSecond is true",
+ nested.isBooleanSecond());
+ assertEquals("doubleProperty is 432.0",
+ (double) 432.0,
+ nested.getDoubleProperty(),
+ (double) 0.005);
+ assertEquals("floatProperty is 123.0",
+ (float) 123.0,
+ nested.getFloatProperty(),
+ (float) 0.005);
+ assertEquals("intProperty is 543",
+ 543, nested.getIntProperty());
+ assertEquals("longProperty is 321",
+ (long) 321, nested.getLongProperty());
+ assertEquals("shortProperty is 654",
+ (short) 654, nested.getShortProperty());
+ assertEquals("stringProperty is \"This is a string\"",
+ "This is a string",
+ nested.getStringProperty());
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ }
+
+ }
+
+
+ /**
+ * Test populate() method on scalar properties.
+ */
+ public void testPopulateScalar() {
+
+ try {
+
+ bean.set("nullProperty", "non-null value");
+
+ HashMap map = new HashMap();
+ map.put("booleanProperty", "false");
+ // booleanSecond is left at true
+ map.put("doubleProperty", "432.0");
+ // floatProperty is left at 123.0
+ map.put("intProperty", "543");
+ // longProperty is left at 321
+ map.put("nullProperty", null);
+ map.put("shortProperty", "654");
+ // stringProperty is left at "This is a string"
+
+ BeanUtils.populate(bean, map);
+
+ Boolean booleanProperty = (Boolean) bean.get("booleanProperty");
+ assertTrue("booleanProperty is false", !booleanProperty.booleanValue());
+ Boolean booleanSecond = (Boolean) bean.get("booleanSecond");
+ assertTrue("booleanSecond is true", booleanSecond.booleanValue());
+ Double doubleProperty = (Double) bean.get("doubleProperty");
+ assertEquals("doubleProperty is 432.0",
+ (double) 432.0, doubleProperty.doubleValue(),
+ (double) 0.005);
+ Float floatProperty = (Float) bean.get("floatProperty");
+ assertEquals("floatProperty is 123.0",
+ (float) 123.0, floatProperty.floatValue(),
+ (float) 0.005);
+ Integer intProperty = (Integer) bean.get("intProperty");
+ assertEquals("intProperty is 543",
+ 543, intProperty.intValue());
+ Long longProperty = (Long) bean.get("longProperty");
+ assertEquals("longProperty is 321",
+ (long) 321, longProperty.longValue());
+ assertNull("nullProperty is null", bean.get("nullProperty"));
+ Short shortProperty = (Short) bean.get("shortProperty");
+ assertEquals("shortProperty is 654",
+ (short) 654, shortProperty.shortValue());
+ assertEquals("stringProperty is \"This is a string\"",
+ "This is a string",
+ (String) bean.get("stringProperty"));
+
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ }
+
+ }
+
+
+ /**
+ * Test calling setProperty() with null property values.
+ */
+ public void testSetPropertyNullValues() throws Exception {
+
+ Object oldValue = null;
+ Object newValue = null;
+
+ // Scalar value into array
+ oldValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
+ BeanUtils.setProperty(bean, "stringArray", (String) null);
+ newValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
+ assertNotNull("stringArray is not null", newValue);
+ assertTrue("stringArray of correct type",
+ newValue instanceof String[]);
+ assertEquals("stringArray length",
+ 1, ((String[]) newValue).length);
+ assertTrue("stringArray[0] is null",
+ ((String[]) newValue)[0] == null);
+ PropertyUtils.setProperty(bean, "stringArray", oldValue);
+
+ // Indexed value into array
+ oldValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
+ BeanUtils.setProperty(bean, "stringArray[2]", (String) null);
+ newValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
+ assertNotNull("stringArray is not null", newValue);
+ assertTrue("stringArray of correct type",
+ newValue instanceof String[]);
+ assertEquals("stringArray length",
+ 5, ((String[]) newValue).length);
+ assertTrue("stringArray[2] is null",
+ ((String[]) newValue)[2] == null);
+ PropertyUtils.setProperty(bean, "stringArray", oldValue);
+
+ // Value into scalar
+ BeanUtils.setProperty(bean, "stringProperty", null);
+ assertTrue("stringProperty is now null",
+ BeanUtils.getProperty(bean, "stringProperty") == null);
+
+ }
+
+
+ /**
+ * Test converting to and from primitive wrapper types.
+ */
+ public void testSetPropertyOnPrimitiveWrappers() throws Exception {
+
+ BeanUtils.setProperty(bean,"intProperty", new Integer(1));
+ assertEquals(1,((Integer) bean.get("intProperty")).intValue());
+ BeanUtils.setProperty(bean,"stringProperty", new Integer(1));
+ assertEquals(1, Integer.parseInt((String) bean.get("stringProperty")));
+
+ }
+
+
+ /**
+ * Test setting a null property value.
+ */
+ public void testSetPropertyNull() throws Exception {
+
+ bean.set("nullProperty", "non-null value");
+ BeanUtils.setProperty(bean, "nullProperty", null);
+ assertNull("nullProperty is null", bean.get("nullProperty"));
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on byte.
+ */
+ public void testCopyPropertyByte() throws Exception {
+
+ BeanUtils.setProperty(bean, "byteProperty", new Byte((byte) 123));
+ assertEquals((byte) 123, ((Byte) bean.get("byteProperty")).byteValue());
+/*
+ BeanUtils.setProperty(bean, "byteProperty", new Double((double) 123));
+ assertEquals((byte) 123, ((Byte) bean.get("byteProperty")).byteValue());
+ BeanUtils.setProperty(bean, "byteProperty", new Float((float) 123));
+ assertEquals((byte) 123, ((Byte) bean.get("byteProperty")).byteValue());
+*/
+ BeanUtils.setProperty(bean, "byteProperty", new Integer((int) 123));
+ assertEquals((byte) 123, ((Byte) bean.get("byteProperty")).byteValue());
+ BeanUtils.setProperty(bean, "byteProperty", new Long((long) 123));
+ assertEquals((byte) 123, ((Byte) bean.get("byteProperty")).byteValue());
+ BeanUtils.setProperty(bean, "byteProperty", new Short((short) 123));
+ assertEquals((byte) 123, ((Byte) bean.get("byteProperty")).byteValue());
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on double.
+ */
+ public void testCopyPropertyDouble() throws Exception {
+
+ BeanUtils.setProperty(bean, "doubleProperty", new Byte((byte) 123));
+ assertEquals((double) 123, ((Double) bean.get("doubleProperty")).doubleValue(), 0.005);
+ BeanUtils.setProperty(bean, "doubleProperty", new Double((double) 123));
+ assertEquals((double) 123, ((Double) bean.get("doubleProperty")).doubleValue(), 0.005);
+ BeanUtils.setProperty(bean, "doubleProperty", new Float((float) 123));
+ assertEquals((double) 123, ((Double) bean.get("doubleProperty")).doubleValue(), 0.005);
+ BeanUtils.setProperty(bean, "doubleProperty", new Integer((int) 123));
+ assertEquals((double) 123, ((Double) bean.get("doubleProperty")).doubleValue(), 0.005);
+ BeanUtils.setProperty(bean, "doubleProperty", new Long((long) 123));
+ assertEquals((double) 123, ((Double) bean.get("doubleProperty")).doubleValue(), 0.005);
+ BeanUtils.setProperty(bean, "doubleProperty", new Short((short) 123));
+ assertEquals((double) 123, ((Double) bean.get("doubleProperty")).doubleValue(), 0.005);
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on float.
+ */
+ public void testCopyPropertyFloat() throws Exception {
+
+ BeanUtils.setProperty(bean, "floatProperty", new Byte((byte) 123));
+ assertEquals((float) 123, ((Float) bean.get("floatProperty")).floatValue(), 0.005);
+ BeanUtils.setProperty(bean, "floatProperty", new Double((double) 123));
+ assertEquals((float) 123, ((Float) bean.get("floatProperty")).floatValue(), 0.005);
+ BeanUtils.setProperty(bean, "floatProperty", new Float((float) 123));
+ assertEquals((float) 123, ((Float) bean.get("floatProperty")).floatValue(), 0.005);
+ BeanUtils.setProperty(bean, "floatProperty", new Integer((int) 123));
+ assertEquals((float) 123, ((Float) bean.get("floatProperty")).floatValue(), 0.005);
+ BeanUtils.setProperty(bean, "floatProperty", new Long((long) 123));
+ assertEquals((float) 123, ((Float) bean.get("floatProperty")).floatValue(), 0.005);
+ BeanUtils.setProperty(bean, "floatProperty", new Short((short) 123));
+ assertEquals((float) 123, ((Float) bean.get("floatProperty")).floatValue(), 0.005);
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on int.
+ */
+ public void testCopyPropertyInteger() throws Exception {
+
+ BeanUtils.setProperty(bean, "longProperty", new Byte((byte) 123));
+ assertEquals((int) 123, ((Integer) bean.get("intProperty")).intValue());
+/*
+ BeanUtils.setProperty(bean, "longProperty", new Double((double) 123));
+ assertEquals((int) 123, ((Integer) bean.get("intProperty")).intValue());
+ BeanUtils.setProperty(bean, "longProperty", new Float((float) 123));
+ assertEquals((int) 123, ((Integer) bean.get("intProperty")).intValue());
+*/
+ BeanUtils.setProperty(bean, "longProperty", new Integer((int) 123));
+ assertEquals((int) 123, ((Integer) bean.get("intProperty")).intValue());
+ BeanUtils.setProperty(bean, "longProperty", new Long((long) 123));
+ assertEquals((int) 123, ((Integer) bean.get("intProperty")).intValue());
+ BeanUtils.setProperty(bean, "longProperty", new Short((short) 123));
+ assertEquals((int) 123, ((Integer) bean.get("intProperty")).intValue());
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on long.
+ */
+ public void testCopyPropertyLong() throws Exception {
+
+ BeanUtils.setProperty(bean, "longProperty", new Byte((byte) 123));
+ assertEquals((long) 123, ((Long) bean.get("longProperty")).longValue());
+/*
+ BeanUtils.setProperty(bean, "longProperty", new Double((double) 123));
+ assertEquals((long) 123, ((Long) bean.get("longProperty")).longValue());
+ BeanUtils.setProperty(bean, "longProperty", new Float((float) 123));
+ assertEquals((long) 123, ((Long) bean.get("longProperty")).longValue());
+*/
+ BeanUtils.setProperty(bean, "longProperty", new Integer((int) 123));
+ assertEquals((long) 123, ((Long) bean.get("longProperty")).longValue());
+ BeanUtils.setProperty(bean, "longProperty", new Long((long) 123));
+ assertEquals((long) 123, ((Long) bean.get("longProperty")).longValue());
+ BeanUtils.setProperty(bean, "longProperty", new Short((short) 123));
+ assertEquals((long) 123, ((Long) bean.get("longProperty")).longValue());
+
+ }
+
+
+ /**
+ * Test copying a null property value.
+ */
+ public void testCopyPropertyNull() throws Exception {
+
+ bean.set("nullProperty", "non-null value");
+ BeanUtils.copyProperty(bean, "nullProperty", null);
+ assertNull("nullProperty is null", bean.get("nullProperty"));
+
+ }
+
+
+ /**
+ * Test narrowing and widening conversions on short.
+ */
+ public void testCopyPropertyShort() throws Exception {
+
+ BeanUtils.setProperty(bean, "shortProperty", new Byte((byte) 123));
+ assertEquals((short) 123, ((Short) bean.get("shortProperty")).shortValue());
+/*
+ BeanUtils.setProperty(bean, "shortProperty", new Double((double) 123));
+ assertEquals((short) 123, ((Short) bean.get("shortProperty")).shortValue());
+ BeanUtils.setProperty(bean, "shortProperty", new Float((float) 123));
+ assertEquals((short) 123, ((Short) bean.get("shortProperty")).shortValue());
+*/
+ BeanUtils.setProperty(bean, "shortProperty", new Integer((int) 123));
+ assertEquals((short) 123, ((Short) bean.get("shortProperty")).shortValue());
+ BeanUtils.setProperty(bean, "shortProperty", new Long((long) 123));
+ assertEquals((short) 123, ((Short) bean.get("shortProperty")).shortValue());
+ BeanUtils.setProperty(bean, "shortProperty", new Short((short) 123));
+ assertEquals((short) 123, ((Short) bean.get("shortProperty")).shortValue());
+
+ }
+
+
+ /**
+ * Test copying a property using a nested indexed array expression,
+ * with and without conversions.
+ */
+ public void testCopyPropertyNestedIndexedArray() throws Exception {
+
+ int origArray[] = { 0, 10, 20, 30, 40};
+ int intArray[] = { 0, 0, 0 };
+ ((TestBean) bean.get("nested")).setIntArray(intArray);
+ int intChanged[] = { 0, 0, 0 };
+
+ // No conversion required
+ BeanUtils.copyProperty(bean, "nested.intArray[1]", new Integer(1));
+ checkIntArray((int[]) bean.get("intArray"), origArray);
+ intChanged[1] = 1;
+ checkIntArray(((TestBean) bean.get("nested")).getIntArray(),
+ intChanged);
+
+ // Widening conversion required
+ BeanUtils.copyProperty(bean, "nested.intArray[1]", new Byte((byte) 2));
+ checkIntArray((int[]) bean.get("intArray"), origArray);
+ intChanged[1] = 2;
+ checkIntArray(((TestBean) bean.get("nested")).getIntArray(),
+ intChanged);
+
+ // Narrowing conversion required
+ BeanUtils.copyProperty(bean, "nested.intArray[1]", new Long((long) 3));
+ checkIntArray((int[]) bean.get("intArray"), origArray);
+ intChanged[1] = 3;
+ checkIntArray(((TestBean) bean.get("nested")).getIntArray(),
+ intChanged);
+
+ // String conversion required
+ BeanUtils.copyProperty(bean, "nested.intArray[1]", "4");
+ checkIntArray((int[]) bean.get("intArray"), origArray);
+ intChanged[1] = 4;
+ checkIntArray(((TestBean) bean.get("nested")).getIntArray(),
+ intChanged);
+
+ }
+
+
+ /**
+ * Test copying a property using a nested mapped map property.
+ */
+ public void testCopyPropertyNestedMappedMap() throws Exception {
+
+ Map origMap = new HashMap();
+ origMap.put("First Key", "First Value");
+ origMap.put("Second Key", "Second Value");
+ Map changedMap = new HashMap();
+ changedMap.put("First Key", "First Value");
+ changedMap.put("Second Key", "Second Value");
+
+ // No conversion required
+ BeanUtils.copyProperty(bean, "nested.mapProperty(Second Key)",
+ "New Second Value");
+ checkMap((Map) bean.get("mapProperty"), origMap);
+ changedMap.put("Second Key", "New Second Value");
+ checkMap(((TestBean) bean.get("nested")).getMapProperty(), changedMap);
+
+ }
+
+
+ /**
+ * Test copying a property using a nested simple expression, with and
+ * without conversions.
+ */
+ public void testCopyPropertyNestedSimple() throws Exception {
+
+ bean.set("intProperty", new Integer(0));
+ nested.setIntProperty(0);
+
+ // No conversion required
+ BeanUtils.copyProperty(bean, "nested.intProperty", new Integer(1));
+ assertEquals(0, ((Integer) bean.get("intProperty")).intValue());
+ assertEquals(1, nested.getIntProperty());
+
+ // Widening conversion required
+ BeanUtils.copyProperty(bean, "nested.intProperty", new Byte((byte) 2));
+ assertEquals(0, ((Integer) bean.get("intProperty")).intValue());
+ assertEquals(2, nested.getIntProperty());
+
+ // Narrowing conversion required
+ BeanUtils.copyProperty(bean, "nested.intProperty", new Long((long) 3));
+ assertEquals(0, ((Integer) bean.get("intProperty")).intValue());
+ assertEquals(3, nested.getIntProperty());
+
+ // String conversion required
+ BeanUtils.copyProperty(bean, "nested.intProperty", "4");
+ assertEquals(0, ((Integer) bean.get("intProperty")).intValue());
+ assertEquals(4, nested.getIntProperty());
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ // Ensure that the nested intArray matches the specified values
+ protected void checkIntArray(int actual[], int expected[]) {
+ assertNotNull("actual array not null", actual);
+ assertEquals("actual array length", expected.length, actual.length);
+ for (int i = 0; i < actual.length; i++) {
+ assertEquals("actual array value[" + i + "]",
+ expected[i], actual[i]);
+ }
+ }
+
+
+ // Ensure that the actual Map matches the expected Map
+ protected void checkMap(Map actual, Map expected) {
+ assertNotNull("actual map not null", actual);
+ assertEquals("actual map size", expected.size(), actual.size());
+ Iterator keys = expected.keySet().iterator();
+ while (keys.hasNext()) {
+ Object key = keys.next();
+ assertEquals("actual map value(" + key + ")",
+ expected.get(key), actual.get(key));
+ }
+ }
+
+
+ /**
+ * Create and return a <code>DynaClass</code> instance for our test
+ * <code>DynaBean</code>.
+ */
+ protected static DynaClass createDynaClass() {
+
+ int intArray[] = new int[0];
+ String stringArray[] = new String[0];
+
+ DynaClass dynaClass = new BasicDynaClass
+ ("TestDynaClass", null,
+ new DynaProperty[]{
+ new DynaProperty("booleanProperty", Boolean.TYPE),
+ new DynaProperty("booleanSecond", Boolean.TYPE),
+ new DynaProperty("byteProperty", Byte.TYPE),
+ new DynaProperty("doubleProperty", Double.TYPE),
+ new DynaProperty("dupProperty", stringArray.getClass()),
+ new DynaProperty("floatProperty", Float.TYPE),
+ new DynaProperty("intArray", intArray.getClass()),
+ new DynaProperty("intIndexed", intArray.getClass()),
+ new DynaProperty("intProperty", Integer.TYPE),
+ new DynaProperty("listIndexed", List.class),
+ new DynaProperty("longProperty", Long.TYPE),
+ new DynaProperty("mapProperty", Map.class),
+ new DynaProperty("mappedProperty", Map.class),
+ new DynaProperty("mappedIntProperty", Map.class),
+ new DynaProperty("nested", TestBean.class),
+ new DynaProperty("nullProperty", String.class),
+ new DynaProperty("shortProperty", Short.TYPE),
+ new DynaProperty("stringArray", stringArray.getClass()),
+ new DynaProperty("stringIndexed", stringArray.getClass()),
+ new DynaProperty("stringProperty", String.class),
+ });
+ return (dynaClass);
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaPropertyUtilsTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaPropertyUtilsTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaPropertyUtilsTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,2648 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * Test accessing DynaBeans transparently via PropertyUtils.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.12 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class DynaPropertyUtilsTestCase extends TestCase {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The basic test bean for each test.
+ */
+ protected DynaBean bean = null;
+
+
+ /**
+ * The set of properties that should be described.
+ */
+ protected String describes[] =
+ { "booleanProperty",
+ "booleanSecond",
+ "doubleProperty",
+ "floatProperty",
+ "intArray",
+ "intIndexed",
+ "intProperty",
+ "listIndexed",
+ "longProperty",
+ "mappedObjects",
+ "mappedProperty",
+ "mappedIntProperty",
+ "nested",
+ "nullProperty",
+ // "readOnlyProperty",
+ "shortProperty",
+ "stringArray",
+ "stringIndexed",
+ "stringProperty"
+ };
+
+
+ /**
+ * The nested bean pointed at by the "nested" property.
+ */
+ protected TestBean nested = null;
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public DynaPropertyUtilsTestCase(String name) {
+
+ super(name);
+
+ }
+
+
+ // --------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+
+ // Instantiate a new DynaBean instance
+ DynaClass dynaClass = createDynaClass();
+ bean = dynaClass.newInstance();
+
+ // Initialize the DynaBean's property values (like TestBean)
+ bean.set("booleanProperty", new Boolean(true));
+ bean.set("booleanSecond", new Boolean(true));
+ bean.set("doubleProperty", new Double(321.0));
+ bean.set("floatProperty", new Float((float) 123.0));
+ int intArray[] = { 0, 10, 20, 30, 40 };
+ bean.set("intArray", intArray);
+ int intIndexed[] = { 0, 10, 20, 30, 40 };
+ bean.set("intIndexed", intIndexed);
+ bean.set("intProperty", new Integer(123));
+ List listIndexed = new ArrayList();
+ listIndexed.add("String 0");
+ listIndexed.add("String 1");
+ listIndexed.add("String 2");
+ listIndexed.add("String 3");
+ listIndexed.add("String 4");
+ bean.set("listIndexed", listIndexed);
+ bean.set("longProperty", new Long((long) 321));
+ HashMap mapProperty = new HashMap();
+ mapProperty.put("First Key", "First Value");
+ mapProperty.put("Second Key", "Second Value");
+ bean.set("mapProperty", mapProperty);
+ HashMap mappedObjects = new HashMap();
+ mappedObjects.put("First Key", "First Value");
+ mappedObjects.put("Second Key", "Second Value");
+ bean.set("mappedObjects", mappedObjects);
+ HashMap mappedProperty = new HashMap();
+ mappedProperty.put("First Key", "First Value");
+ mappedProperty.put("Second Key", "Second Value");
+ bean.set("mappedProperty", mappedProperty);
+ HashMap mappedIntProperty = new HashMap();
+ mappedIntProperty.put("One", new Integer(1));
+ mappedIntProperty.put("Two", new Integer(2));
+ bean.set("mappedIntProperty", mappedIntProperty);
+ nested = new TestBean();
+ bean.set("nested", nested);
+ // Property "nullProperty" is not initialized, so it should return null
+ bean.set("shortProperty", new Short((short) 987));
+ String stringArray[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+ bean.set("stringArray", stringArray);
+ String stringIndexed[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+ bean.set("stringIndexed", stringIndexed);
+ bean.set("stringProperty", "This is a string");
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+
+ return (new TestSuite(DynaPropertyUtilsTestCase.class));
+
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+
+ bean = null;
+ nested = null;
+
+ }
+
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ /**
+ * Test copyProperties() when the origin is a a <code>Map</code>.
+ */
+ public void testCopyPropertiesMap() {
+
+ Map map = new HashMap();
+ map.put("booleanProperty", Boolean.FALSE);
+ map.put("doubleProperty", new Double(333.0));
+ map.put("dupProperty", new String[] { "New 0", "New 1", "New 2" });
+ map.put("floatProperty", new Float((float) 222.0));
+ map.put("intArray", new int[] { 0, 100, 200 });
+ map.put("intProperty", new Integer(111));
+ map.put("longProperty", new Long(444));
+ map.put("shortProperty", new Short((short) 555));
+ map.put("stringProperty", "New String Property");
+
+ try {
+ PropertyUtils.copyProperties(bean, map);
+ } catch (Throwable t) {
+ fail("Threw " + t.toString());
+ }
+
+ // Scalar properties
+ assertEquals("booleanProperty", false,
+ ((Boolean) bean.get("booleanProperty")).booleanValue());
+ assertEquals("doubleProperty", 333.0,
+ ((Double) bean.get("doubleProperty")).doubleValue(),
+ 0.005);
+ assertEquals("floatProperty", (float) 222.0,
+ ((Float) bean.get("floatProperty")).floatValue(),
+ (float) 0.005);
+ assertEquals("intProperty", 111,
+ ((Integer) bean.get("intProperty")).intValue());
+ assertEquals("longProperty", (long) 444,
+ ((Long) bean.get("longProperty")).longValue());
+ assertEquals("shortProperty", (short) 555,
+ ((Short) bean.get("shortProperty")).shortValue());
+ assertEquals("stringProperty", "New String Property",
+ (String) bean.get("stringProperty"));
+
+ // Indexed Properties
+ String dupProperty[] = (String[]) bean.get("dupProperty");
+ assertNotNull("dupProperty present", dupProperty);
+ assertEquals("dupProperty length", 3, dupProperty.length);
+ assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
+ assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
+ assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
+ int intArray[] = (int[]) bean.get("intArray");
+ assertNotNull("intArray present", intArray);
+ assertEquals("intArray length", 3, intArray.length);
+ assertEquals("intArray[0]", 0, intArray[0]);
+ assertEquals("intArray[1]", 100, intArray[1]);
+ assertEquals("intArray[2]", 200, intArray[2]);
+
+ }
+
+
+ /**
+ * Test the describe() method.
+ */
+ public void testDescribe() {
+
+ Map map = null;
+ try {
+ map = PropertyUtils.describe(bean);
+ } catch (Exception e) {
+ fail("Threw exception " + e);
+ }
+
+ // Verify existence of all the properties that should be present
+ for (int i = 0; i < describes.length; i++) {
+ assertTrue("Property '" + describes[i] + "' is present",
+ map.containsKey(describes[i]));
+ }
+ assertTrue("Property 'writeOnlyProperty' is not present",
+ !map.containsKey("writeOnlyProperty"));
+
+ // Verify the values of scalar properties
+ assertEquals("Value of 'booleanProperty'",
+ Boolean.TRUE,
+ (Boolean) map.get("booleanProperty"));
+ assertEquals("Value of 'doubleProperty'",
+ new Double(321.0),
+ (Double) map.get("doubleProperty"));
+ assertEquals("Value of 'floatProperty'",
+ new Float((float) 123.0),
+ (Float) map.get("floatProperty"));
+ assertEquals("Value of 'intProperty'",
+ new Integer(123),
+ (Integer) map.get("intProperty"));
+ assertEquals("Value of 'longProperty'",
+ new Long(321),
+ (Long) map.get("longProperty"));
+ assertEquals("Value of 'shortProperty'",
+ new Short((short) 987),
+ (Short) map.get("shortProperty"));
+ assertEquals("Value of 'stringProperty'",
+ "This is a string",
+ (String) map.get("stringProperty"));
+
+ }
+
+
+ /**
+ * Corner cases on getIndexedProperty invalid arguments.
+ */
+ public void testGetIndexedArguments() {
+
+ // Use explicit index argument
+
+ try {
+ PropertyUtils.getIndexedProperty(null, "intArray", 0);
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, null, 0);
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ // Use index expression
+
+ try {
+ PropertyUtils.getIndexedProperty(null,
+ "intArray[0]");
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, "[0]");
+ fail("Should throw NoSuchMethodException 4");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 4");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, "intArray");
+ fail("Should throw IllegalArgumentException 5");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 5");
+ }
+
+ // Use explicit index argument
+
+ try {
+ PropertyUtils.getIndexedProperty(null, "intIndexed", 0);
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, null, 0);
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ // Use index expression
+
+ try {
+ PropertyUtils.getIndexedProperty(null,
+ "intIndexed[0]");
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, "[0]");
+ fail("Should throw NoSuchMethodException 4");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 4");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, "intIndexed");
+ fail("Should throw IllegalArgumentException 5");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 5");
+ }
+
+ }
+
+
+ /**
+ * Positive and negative tests on getIndexedProperty valid arguments.
+ */
+ public void testGetIndexedValues() {
+
+ Object value = null;
+
+ // Use explicit key argument
+
+ for (int i = 0; i < 5; i++) {
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean, "intArray", i);
+ assertNotNull("intArray returned value " + i, value);
+ assertTrue("intArray returned Integer " + i,
+ value instanceof Integer);
+ assertEquals("intArray returned correct " + i, i * 10,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("intArray " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean, "intIndexed", i);
+ assertNotNull("intIndexed returned value " + i, value);
+ assertTrue("intIndexed returned Integer " + i,
+ value instanceof Integer);
+ assertEquals("intIndexed returned correct " + i, i * 10,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("intIndexed " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean, "listIndexed", i);
+ assertNotNull("listIndexed returned value " + i, value);
+ assertTrue("list returned String " + i,
+ value instanceof String);
+ assertEquals("listIndexed returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("listIndexed " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean, "stringArray", i);
+ assertNotNull("stringArray returned value " + i, value);
+ assertTrue("stringArray returned String " + i,
+ value instanceof String);
+ assertEquals("stringArray returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("stringArray " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean, "stringIndexed", i);
+ assertNotNull("stringIndexed returned value " + i, value);
+ assertTrue("stringIndexed returned String " + i,
+ value instanceof String);
+ assertEquals("stringIndexed returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("stringIndexed " + i + " threw " + t);
+ }
+
+ }
+
+ // Use key expression
+
+ for (int i = 0; i < 5; i++) {
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intArray[" + i + "]");
+ assertNotNull("intArray returned value " + i, value);
+ assertTrue("intArray returned Integer " + i,
+ value instanceof Integer);
+ assertEquals("intArray returned correct " + i, i * 10,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("intArray " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intIndexed[" + i + "]");
+ assertNotNull("intIndexed returned value " + i, value);
+ assertTrue("intIndexed returned Integer " + i,
+ value instanceof Integer);
+ assertEquals("intIndexed returned correct " + i, i * 10,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("intIndexed " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "listIndexed[" + i + "]");
+ assertNotNull("listIndexed returned value " + i, value);
+ assertTrue("listIndexed returned String " + i,
+ value instanceof String);
+ assertEquals("listIndexed returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("listIndexed " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray[" + i + "]");
+ assertNotNull("stringArray returned value " + i, value);
+ assertTrue("stringArray returned String " + i,
+ value instanceof String);
+ assertEquals("stringArray returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("stringArray " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringIndexed[" + i + "]");
+ assertNotNull("stringIndexed returned value " + i, value);
+ assertTrue("stringIndexed returned String " + i,
+ value instanceof String);
+ assertEquals("stringIndexed returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("stringIndexed " + i + " threw " + t);
+ }
+
+ }
+
+ // Index out of bounds tests
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intArray", -1);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intArray", 5);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intIndexed", -1);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intIndexed", 5);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "listIndexed", -1);
+ fail("Should have thrown IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "listIndexed", 5);
+ fail("Should have thrown IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray", -1);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray", 5);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringIndexed", -1);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringIndexed", 5);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getMappedProperty invalid arguments.
+ */
+ public void testGetMappedArguments() {
+
+ // Use explicit key argument
+
+ try {
+ PropertyUtils.getMappedProperty(null, "mappedProperty",
+ "First Key");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getMappedProperty(bean, null, "First Key");
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ try {
+ PropertyUtils.getMappedProperty(bean, "mappedProperty", null);
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ // Use key expression
+
+ try {
+ PropertyUtils.getMappedProperty(null,
+ "mappedProperty(First Key)");
+ fail("Should throw IllegalArgumentException 4");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 4");
+ }
+
+ try {
+ PropertyUtils.getMappedProperty(bean, "(Second Key)");
+ fail("Should throw IllegalArgumentException 5");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 5");
+ }
+
+ try {
+ PropertyUtils.getMappedProperty(bean, "mappedProperty");
+ fail("Should throw IllegalArgumentException 6");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 6");
+ }
+
+ }
+
+
+ /**
+ * Test getting mapped values with periods in the key.
+ */
+ public void testGetMappedPeriods() {
+
+ bean.set("mappedProperty", "key.with.a.dot", "Special Value");
+ assertEquals("Can retrieve directly",
+ "Special Value",
+ (String) bean.get("mappedProperty", "key.with.a.dot"));
+ try {
+ assertEquals("Can retrieve via getMappedProperty",
+ "Special Value",
+ PropertyUtils.getMappedProperty
+ (bean, "mappedProperty", "key.with.a.dot"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+ try {
+ assertEquals("Can retrieve via getNestedProperty",
+ "Special Value",
+ PropertyUtils.getNestedProperty
+ (bean, "mappedProperty(key.with.a.dot)"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+
+ bean.set("mappedObjects", "nested.property", new TestBean());
+ assertNotNull("Can retrieve directly",
+ bean.get("mappedObjects", "nested.property"));
+ try {
+ assertEquals("Can retrieve nested",
+ "This is a string",
+ PropertyUtils.getNestedProperty
+ (bean,
+ "mappedObjects(nested.property).stringProperty"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+
+ }
+
+
+ /**
+ * Test getting mapped values with slashes in the key. This is different
+ * from periods because slashes are not syntactically significant.
+ */
+ public void testGetMappedSlashes() {
+
+ bean.set("mappedProperty", "key/with/a/slash", "Special Value");
+ assertEquals("Can retrieve directly",
+ "Special Value",
+ bean.get("mappedProperty", "key/with/a/slash"));
+ try {
+ assertEquals("Can retrieve via getMappedProperty",
+ "Special Value",
+ PropertyUtils.getMappedProperty
+ (bean, "mappedProperty", "key/with/a/slash"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+ try {
+ assertEquals("Can retrieve via getNestedProperty",
+ "Special Value",
+ PropertyUtils.getNestedProperty
+ (bean, "mappedProperty(key/with/a/slash)"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+
+ bean.set("mappedObjects", "nested/property", new TestBean());
+ assertNotNull("Can retrieve directly",
+ bean.get("mappedObjects", "nested/property"));
+ try {
+ assertEquals("Can retrieve nested",
+ "This is a string",
+ PropertyUtils.getNestedProperty
+ (bean,
+ "mappedObjects(nested/property).stringProperty"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+
+ }
+
+
+ /**
+ * Positive and negative tests on getMappedProperty valid arguments.
+ */
+ public void testGetMappedValues() {
+
+ Object value = null;
+
+ // Use explicit key argument
+
+ try {
+ value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
+ "First Key");
+ assertEquals("Can find first value", "First Value", value);
+ } catch (Throwable t) {
+ fail("Finding first value threw " + t);
+ }
+
+ try {
+ value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
+ "Second Key");
+ assertEquals("Can find second value", "Second Value", value);
+ } catch (Throwable t) {
+ fail("Finding second value threw " + t);
+ }
+
+ try {
+ value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
+ "Third Key");
+ assertNull("Can not find third value", value);
+ } catch (Throwable t) {
+ fail("Finding third value threw " + t);
+ }
+
+ // Use key expression with parentheses
+
+ try {
+ value =
+ PropertyUtils.getMappedProperty(bean,
+ "mappedProperty(First Key)");
+ assertEquals("Can find first value", "First Value", value);
+ } catch (Throwable t) {
+ fail("Finding first value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getMappedProperty(bean,
+ "mappedProperty(Second Key)");
+ assertEquals("Can find second value", "Second Value", value);
+ } catch (Throwable t) {
+ fail("Finding second value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getMappedProperty(bean,
+ "mappedProperty(Third Key)");
+ assertNull("Can not find third value", value);
+ } catch (Throwable t) {
+ fail("Finding third value threw " + t);
+ }
+
+ // Use key expression with dotted syntax
+
+ try {
+ value =
+ PropertyUtils.getNestedProperty(bean,
+ "mapProperty.First Key");
+ assertEquals("Can find first value", "First Value", value);
+ } catch (Throwable t) {
+ fail("Finding first value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getNestedProperty(bean,
+ "mapProperty.Second Key");
+ assertEquals("Can find second value", "Second Value", value);
+ } catch (Throwable t) {
+ fail("Finding second value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getNestedProperty(bean,
+ "mapProperty.Third Key");
+ assertNull("Can not find third value", value);
+ } catch (Throwable t) {
+ fail("Finding third value threw " + t);
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getNestedProperty invalid arguments.
+ */
+ public void testGetNestedArguments() {
+
+ try {
+ PropertyUtils.getNestedProperty(null, "stringProperty");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getNestedProperty(bean, null);
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a boolean property.
+ */
+ public void testGetNestedBoolean() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.booleanProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Boolean));
+ TestBean nested = (TestBean) bean.get("nested");
+ assertTrue("Got correct value",
+ ((Boolean) value).booleanValue() ==
+ nested.getBooleanProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a double property.
+ */
+ public void testGetNestedDouble() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.doubleProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Double));
+ TestBean nested = (TestBean) bean.get("nested");
+ assertEquals("Got correct value",
+ ((Double) value).doubleValue(),
+ nested.getDoubleProperty(),
+ 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a float property.
+ */
+ public void testGetNestedFloat() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.floatProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Float));
+ TestBean nested = (TestBean) bean.get("nested");
+ assertEquals("Got correct value",
+ ((Float) value).floatValue(),
+ nested.getFloatProperty(),
+ (float) 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on an int property.
+ */
+ public void testGetNestedInt() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.intProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Integer));
+ TestBean nested = (TestBean) bean.get("nested");
+ assertEquals("Got correct value",
+ ((Integer) value).intValue(),
+ nested.getIntProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a long property.
+ */
+ public void testGetNestedLong() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.longProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Long));
+ TestBean nested = (TestBean) bean.get("nested");
+ assertEquals("Got correct value",
+ ((Long) value).longValue(),
+ nested.getLongProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a read-only String property.
+ */
+ public void testGetNestedReadOnly() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.readOnlyProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof String));
+ TestBean nested = (TestBean) bean.get("nested");
+ assertEquals("Got correct value",
+ (String) value,
+ nested.getReadOnlyProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a short property.
+ */
+ public void testGetNestedShort() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.shortProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Short));
+ TestBean nested = (TestBean) bean.get("nested");
+ assertEquals("Got correct value",
+ ((Short) value).shortValue(),
+ nested.getShortProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a String property.
+ */
+ public void testGetNestedString() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.stringProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof String));
+ TestBean nested = (TestBean) bean.get("nested");
+ assertEquals("Got correct value",
+ ((String) value),
+ nested.getStringProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test getNestedProperty on an unknown property.
+ */
+ public void testGetNestedUnknown() {
+
+ try {
+ PropertyUtils.getNestedProperty(bean, "nested.unknown");
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getSimpleProperty invalid arguments.
+ */
+ public void testGetSimpleArguments() {
+
+ try {
+ PropertyUtils.getSimpleProperty(null, "stringProperty");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getSimpleProperty(bean, null);
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a boolean property.
+ */
+ public void testGetSimpleBoolean() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "booleanProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Boolean));
+ assertTrue("Got correct value",
+ ((Boolean) value).booleanValue() == true);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a double property.
+ */
+ public void testGetSimpleDouble() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "doubleProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Double));
+ assertEquals("Got correct value",
+ ((Double) value).doubleValue(),
+ (double) 321.0,
+ (double) 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a float property.
+ */
+ public void testGetSimpleFloat() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "floatProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Float));
+ assertEquals("Got correct value",
+ ((Float) value).floatValue(),
+ (float) 123.0,
+ (float) 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test getSimpleProperty on an indexed property.
+ */
+ public void testGetSimpleIndexed() {
+
+ Object value = null;
+ try {
+ value = PropertyUtils.getSimpleProperty(bean,
+ "intIndexed[0]");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ ; // Correct result for this test
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on an int property.
+ */
+ public void testGetSimpleInt() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "intProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Integer));
+ assertEquals("Got correct value",
+ ((Integer) value).intValue(),
+ 123);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a long property.
+ */
+ public void testGetSimpleLong() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "longProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Long));
+ assertEquals("Got correct value",
+ ((Long) value).longValue(),
+ (long) 321);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test getSimpleProperty on a nested property.
+ */
+ public void testGetSimpleNested() {
+
+ Object value = null;
+ try {
+ value = PropertyUtils.getSimpleProperty(bean,
+ "nested.stringProperty");
+ fail("Should have thrown IllegaArgumentException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ ; // Correct result for this test
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a short property.
+ */
+ public void testGetSimpleShort() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "shortProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Short));
+ assertEquals("Got correct value",
+ ((Short) value).shortValue(),
+ (short) 987);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a String property.
+ */
+ public void testGetSimpleString() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "stringProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof String));
+ assertEquals("Got correct value",
+ (String) value,
+ "This is a string");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test getSimpleProperty on an unknown property.
+ */
+ public void testGetSimpleUnknown() {
+
+ try {
+ PropertyUtils.getSimpleProperty(bean, "unknown");
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Corner cases on setIndexedProperty invalid arguments.
+ */
+ public void testSetIndexedArguments() {
+
+ // Use explicit index argument
+
+ try {
+ PropertyUtils.setIndexedProperty(null, "intArray", 0,
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, null, 0,
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ // Use index expression
+
+ try {
+ PropertyUtils.setIndexedProperty(null,
+ "intArray[0]",
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, "[0]",
+ new Integer(1));
+ fail("Should throw NoSuchMethodException 4");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 4");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, "intArray",
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 5");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 5");
+ }
+
+ // Use explicit index argument
+
+ try {
+ PropertyUtils.setIndexedProperty(null, "intIndexed", 0,
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, null, 0,
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ // Use index expression
+
+ try {
+ PropertyUtils.setIndexedProperty(null,
+ "intIndexed[0]",
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, "[0]",
+ new Integer(1));
+ fail("Should throw NoSuchMethodException 4");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 4");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, "intIndexed",
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 5");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 5");
+ }
+
+ }
+
+
+ /**
+ * Positive and negative tests on setIndexedProperty valid arguments.
+ */
+ public void testSetIndexedValues() {
+
+ Object value = null;
+
+ // Use explicit index argument
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intArray", 0,
+ new Integer(1));
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intArray", 0);
+ assertNotNull("Returned new value 0", value);
+ assertTrue("Returned Integer new value 0",
+ value instanceof Integer);
+ assertEquals("Returned correct new value 0", 1,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intIndexed", 1,
+ new Integer(11));
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intIndexed", 1);
+ assertNotNull("Returned new value 1", value);
+ assertTrue("Returned Integer new value 1",
+ value instanceof Integer);
+ assertEquals("Returned correct new value 1", 11,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "listIndexed", 2,
+ "New Value 2");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "listIndexed", 2);
+ assertNotNull("Returned new value 2", value);
+ assertTrue("Returned String new value 2",
+ value instanceof String);
+ assertEquals("Returned correct new value 2", "New Value 2",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray", 2,
+ "New Value 2");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray", 2);
+ assertNotNull("Returned new value 2", value);
+ assertTrue("Returned String new value 2",
+ value instanceof String);
+ assertEquals("Returned correct new value 2", "New Value 2",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray", 3,
+ "New Value 3");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray", 3);
+ assertNotNull("Returned new value 3", value);
+ assertTrue("Returned String new value 3",
+ value instanceof String);
+ assertEquals("Returned correct new value 3", "New Value 3",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ // Use index expression
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intArray[4]",
+ new Integer(1));
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intArray[4]");
+ assertNotNull("Returned new value 4", value);
+ assertTrue("Returned Integer new value 4",
+ value instanceof Integer);
+ assertEquals("Returned correct new value 4", 1,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intIndexed[3]",
+ new Integer(11));
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intIndexed[3]");
+ assertNotNull("Returned new value 5", value);
+ assertTrue("Returned Integer new value 5",
+ value instanceof Integer);
+ assertEquals("Returned correct new value 5", 11,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "listIndexed[1]",
+ "New Value 2");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "listIndexed[1]");
+ assertNotNull("Returned new value 6", value);
+ assertTrue("Returned String new value 6",
+ value instanceof String);
+ assertEquals("Returned correct new value 6", "New Value 2",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray[1]",
+ "New Value 2");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray[2]");
+ assertNotNull("Returned new value 6", value);
+ assertTrue("Returned String new value 6",
+ value instanceof String);
+ assertEquals("Returned correct new value 6", "New Value 2",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray[0]",
+ "New Value 3");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray[0]");
+ assertNotNull("Returned new value 7", value);
+ assertTrue("Returned String new value 7",
+ value instanceof String);
+ assertEquals("Returned correct new value 7", "New Value 3",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ // Index out of bounds tests
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intArray", -1,
+ new Integer(0));
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intArray", 5,
+ new Integer(0));
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intIndexed", -1,
+ new Integer(0));
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intIndexed", 5,
+ new Integer(0));
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "listIndexed", 5,
+ "New String");
+ fail("Should have thrown IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "listIndexed", -1,
+ "New String");
+ fail("Should have thrown IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray", -1,
+ "New String");
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray", 5,
+ "New String");
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringIndexed", -1,
+ "New String");
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringIndexed", 5,
+ "New String");
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getMappedProperty invalid arguments.
+ */
+ public void testSetMappedArguments() {
+
+ // Use explicit key argument
+
+ try {
+ PropertyUtils.setMappedProperty(null, "mappedProperty",
+ "First Key", "First Value");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean, null, "First Key",
+ "First Value");
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean, "mappedProperty", null,
+ "First Value");
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ // Use key expression
+
+ try {
+ PropertyUtils.setMappedProperty(null,
+ "mappedProperty(First Key)",
+ "First Value");
+ fail("Should throw IllegalArgumentException 4");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 4");
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean, "(Second Key)",
+ "Second Value");
+ fail("Should throw IllegalArgumentException 5");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 5");
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean, "mappedProperty",
+ "Third Value");
+ fail("Should throw IllegalArgumentException 6");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 6");
+ }
+
+ }
+
+
+ /**
+ * Positive and negative tests on setMappedProperty valid arguments.
+ */
+ public void testSetMappedValues() {
+
+ Object value = null;
+
+ // Use explicit key argument
+
+ try {
+ value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
+ "Fourth Key");
+ assertNull("Can not find fourth value", value);
+ } catch (Throwable t) {
+ fail("Finding fourth value threw " + t);
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean, "mappedProperty",
+ "Fourth Key", "Fourth Value");
+ } catch (Throwable t) {
+ fail("Setting fourth value threw " + t);
+ }
+
+ try {
+ value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
+ "Fourth Key");
+ assertEquals("Can find fourth value", "Fourth Value", value);
+ } catch (Throwable t) {
+ fail("Finding fourth value threw " + t);
+ }
+
+ // Use key expression with parentheses
+
+ try {
+ value =
+ PropertyUtils.getMappedProperty(bean,
+ "mappedProperty(Fifth Key)");
+ assertNull("Can not find fifth value", value);
+ } catch (Throwable t) {
+ fail("Finding fifth value threw " + t);
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean,
+ "mappedProperty(Fifth Key)",
+ "Fifth Value");
+ } catch (Throwable t) {
+ fail("Setting fifth value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getMappedProperty(bean,
+ "mappedProperty(Fifth Key)");
+ assertEquals("Can find fifth value", "Fifth Value", value);
+ } catch (Throwable t) {
+ fail("Finding fifth value threw " + t);
+ }
+
+ // Use key expression with dotted expression
+
+ try {
+ value =
+ PropertyUtils.getNestedProperty(bean,
+ "mapProperty.Sixth Key");
+ assertNull("Can not find sixth value", value);
+ } catch (Throwable t) {
+ fail("Finding fifth value threw " + t);
+ }
+
+ try {
+ PropertyUtils.setNestedProperty(bean,
+ "mapProperty.Sixth Key",
+ "Sixth Value");
+ } catch (Throwable t) {
+ fail("Setting sixth value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getNestedProperty(bean,
+ "mapProperty.Sixth Key");
+ assertEquals("Can find sixth value", "Sixth Value", value);
+ } catch (Throwable t) {
+ fail("Finding sixth value threw " + t);
+ }
+
+ }
+
+
+ /**
+ * Corner cases on setNestedProperty invalid arguments.
+ */
+ public void testSetNestedArguments() {
+
+ try {
+ PropertyUtils.setNestedProperty(null, "stringProperty", "");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.setNestedProperty(bean, null, "");
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ }
+
+
+ /**
+ * Test setNextedProperty on a boolean property.
+ */
+ public void testSetNestedBoolean() {
+
+ try {
+ boolean oldValue = nested.getBooleanProperty();
+ boolean newValue = !oldValue;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.booleanProperty",
+ new Boolean(newValue));
+ assertTrue("Matched new value",
+ newValue ==
+ nested.getBooleanProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a double property.
+ */
+ public void testSetNestedDouble() {
+
+ try {
+ double oldValue = nested.getDoubleProperty();
+ double newValue = oldValue + 1.0;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.doubleProperty",
+ new Double(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ nested.getDoubleProperty(),
+ 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a float property.
+ */
+ public void testSetNestedFloat() {
+
+ try {
+ float oldValue = nested.getFloatProperty();
+ float newValue = oldValue + (float) 1.0;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.floatProperty",
+ new Float(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ nested.getFloatProperty(),
+ (float) 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a int property.
+ */
+ public void testSetNestedInt() {
+
+ try {
+ int oldValue = nested.getIntProperty();
+ int newValue = oldValue + 1;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.intProperty",
+ new Integer(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ nested.getIntProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a long property.
+ */
+ public void testSetNestedLong() {
+
+ try {
+ long oldValue = nested.getLongProperty();
+ long newValue = oldValue + 1;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.longProperty",
+ new Long(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ nested.getLongProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a read-only String property.
+ */
+ public void testSetNestedReadOnly() {
+
+ try {
+ String oldValue = nested.getWriteOnlyPropertyValue();
+ String newValue = oldValue + " Extra Value";
+ PropertyUtils.setNestedProperty(bean,
+ "nested.readOnlyProperty",
+ newValue);
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a short property.
+ */
+ public void testSetNestedShort() {
+
+ try {
+ short oldValue = nested.getShortProperty();
+ short newValue = oldValue;
+ newValue++;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.shortProperty",
+ new Short(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ nested.getShortProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a String property.
+ */
+ public void testSetNestedString() {
+
+ try {
+ String oldValue = nested.getStringProperty();
+ String newValue = oldValue + " Extra Value";
+ PropertyUtils.setNestedProperty(bean,
+ "nested.stringProperty",
+ newValue);
+ assertEquals("Matched new value",
+ newValue,
+ nested.getStringProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on an unknown property name.
+ */
+ public void testSetNestedUnknown() {
+
+ try {
+ String newValue = "New String Value";
+ PropertyUtils.setNestedProperty(bean,
+ "nested.unknown",
+ newValue);
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a write-only String property.
+ */
+ public void testSetNestedWriteOnly() {
+
+ try {
+ String oldValue = nested.getWriteOnlyPropertyValue();
+ String newValue = oldValue + " Extra Value";
+ PropertyUtils.setNestedProperty(bean,
+ "nested.writeOnlyProperty",
+ newValue);
+ assertEquals("Matched new value",
+ newValue,
+ nested.getWriteOnlyPropertyValue());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Corner cases on setSimpleProperty invalid arguments.
+ */
+ public void testSetSimpleArguments() {
+
+ try {
+ PropertyUtils.setSimpleProperty(null, "stringProperty", "");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.setSimpleProperty(bean, null, "");
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a boolean property.
+ */
+ public void testSetSimpleBoolean() {
+
+ try {
+ boolean oldValue = ((Boolean) bean.get("booleanProperty")).booleanValue();
+ boolean newValue = !oldValue;
+ PropertyUtils.setSimpleProperty(bean,
+ "booleanProperty",
+ new Boolean(newValue));
+ assertTrue("Matched new value",
+ newValue ==
+ ((Boolean) bean.get("booleanProperty")).booleanValue());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a double property.
+ */
+ public void testSetSimpleDouble() {
+
+ try {
+ double oldValue = ((Double) bean.get("doubleProperty")).doubleValue();
+ double newValue = oldValue + 1.0;
+ PropertyUtils.setSimpleProperty(bean,
+ "doubleProperty",
+ new Double(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ ((Double) bean.get("doubleProperty")).doubleValue(),
+ 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a float property.
+ */
+ public void testSetSimpleFloat() {
+
+ try {
+ float oldValue = ((Float) bean.get("floatProperty")).floatValue();
+ float newValue = oldValue + (float) 1.0;
+ PropertyUtils.setSimpleProperty(bean,
+ "floatProperty",
+ new Float(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ ((Float) bean.get("floatProperty")).floatValue(),
+ (float) 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test setSimpleProperty on an indexed property.
+ */
+ public void testSetSimpleIndexed() {
+
+ try {
+ PropertyUtils.setSimpleProperty(bean,
+ "stringIndexed[0]",
+ "New String Value");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ ; // Correct result for this test
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a int property.
+ */
+ public void testSetSimpleInt() {
+
+ try {
+ int oldValue = ((Integer) bean.get("intProperty")).intValue();
+ int newValue = oldValue + 1;
+ PropertyUtils.setSimpleProperty(bean,
+ "intProperty",
+ new Integer(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ ((Integer) bean.get("intProperty")).intValue());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a long property.
+ */
+ public void testSetSimpleLong() {
+
+ try {
+ long oldValue = ((Long) bean.get("longProperty")).longValue();
+ long newValue = oldValue + 1;
+ PropertyUtils.setSimpleProperty(bean,
+ "longProperty",
+ new Long(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ ((Long) bean.get("longProperty")).longValue());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test setSimpleProperty on a nested property.
+ */
+ public void testSetSimpleNested() {
+
+ try {
+ PropertyUtils.setSimpleProperty(bean,
+ "nested.stringProperty",
+ "New String Value");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ ; // Correct result for this test
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a short property.
+ */
+ public void testSetSimpleShort() {
+
+ try {
+ short oldValue = ((Short) bean.get("shortProperty")).shortValue();
+ short newValue = oldValue;
+ newValue++;
+ PropertyUtils.setSimpleProperty(bean,
+ "shortProperty",
+ new Short(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ ((Short) bean.get("shortProperty")).shortValue());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a String property.
+ */
+ public void testSetSimpleString() {
+
+ try {
+ String oldValue = (String) bean.get("stringProperty");
+ String newValue = oldValue + " Extra Value";
+ PropertyUtils.setSimpleProperty(bean,
+ "stringProperty",
+ newValue);
+ assertEquals("Matched new value",
+ newValue,
+ (String) bean.get("stringProperty"));
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on an unknown property name.
+ */
+ public void testSetSimpleUnknown() {
+
+ try {
+ String newValue = "New String Value";
+ PropertyUtils.setSimpleProperty(bean,
+ "unknown",
+ newValue);
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Create and return a <code>DynaClass</code> instance for our test
+ * <code>DynaBean</code>.
+ */
+ protected DynaClass createDynaClass() {
+
+ int intArray[] = new int[0];
+ String stringArray[] = new String[0];
+
+ DynaClass dynaClass = new BasicDynaClass
+ ("TestDynaClass", null,
+ new DynaProperty[]{
+ new DynaProperty("booleanProperty", Boolean.TYPE),
+ new DynaProperty("booleanSecond", Boolean.TYPE),
+ new DynaProperty("doubleProperty", Double.TYPE),
+ new DynaProperty("dupProperty", stringArray.getClass()),
+ new DynaProperty("floatProperty", Float.TYPE),
+ new DynaProperty("intArray", intArray.getClass()),
+ new DynaProperty("intIndexed", intArray.getClass()),
+ new DynaProperty("intProperty", Integer.TYPE),
+ new DynaProperty("listIndexed", List.class),
+ new DynaProperty("longProperty", Long.TYPE),
+ new DynaProperty("mapProperty", Map.class),
+ new DynaProperty("mappedObjects", Map.class),
+ new DynaProperty("mappedProperty", Map.class),
+ new DynaProperty("mappedIntProperty", Map.class),
+ new DynaProperty("nested", TestBean.class),
+ new DynaProperty("nullProperty", String.class),
+ new DynaProperty("shortProperty", Short.TYPE),
+ new DynaProperty("stringArray", stringArray.getClass()),
+ new DynaProperty("stringIndexed", stringArray.getClass()),
+ new DynaProperty("stringProperty", String.class),
+ });
+ return (dynaClass);
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaResultSetTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaResultSetTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaResultSetTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * Test accessing ResultSets via DynaBeans.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.5 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class DynaResultSetTestCase extends TestCase {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The mock result set DynaClass to be tested.
+ */
+ protected ResultSetDynaClass dynaClass = null;
+
+
+ /**
+ * Names of the columns for this test. Must match the order they are
+ * defined in {@link TestResultSetMetaData}, and must be all lower case.
+ */
+ protected String columns[] =
+ { "bigdecimalproperty", "booleanproperty",
+ "byteproperty", "dateproperty",
+ "doubleproperty", "floatproperty",
+ "intproperty", "longproperty",
+ "nullproperty", "shortproperty",
+ "stringproperty", "timeproperty",
+ "timestampproperty" };
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public DynaResultSetTestCase(String name) {
+
+ super(name);
+
+ }
+
+
+ // --------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+
+ dynaClass = new ResultSetDynaClass(new TestResultSet());
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+
+ return (new TestSuite(DynaResultSetTestCase.class));
+
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+
+ dynaClass = null;
+
+ }
+
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ public void testGetName() {
+
+ assertEquals("DynaClass name",
+ "org.apache.commons.beanutils.ResultSetDynaClass",
+ dynaClass.getName());
+
+
+ }
+
+
+ public void testGetDynaProperty() {
+
+ // Invalid argument test
+ try {
+ dynaClass.getDynaProperty(null);
+ fail("Did not throw IllegaArgumentException");
+ } catch (IllegalArgumentException e) {
+ ; // Expected result
+ }
+
+ // Negative test
+ DynaProperty dynaProp = dynaClass.getDynaProperty("unknownProperty");
+ assertTrue("unknown property returns null",
+ (dynaProp == null));
+
+ // Positive test
+ dynaProp = dynaClass.getDynaProperty("stringproperty");
+ assertNotNull("string property exists", dynaProp);
+ assertEquals("string property name", "stringproperty",
+ dynaProp.getName());
+ assertEquals("string property class", String.class,
+ dynaProp.getType());
+
+ }
+
+
+ public void testGetDynaProperties() {
+
+ DynaProperty dynaProps[] = dynaClass.getDynaProperties();
+ assertNotNull("dynaProps exists", dynaProps);
+ assertEquals("dynaProps length", columns.length, dynaProps.length);
+ for (int i = 0; i < columns.length; i++) {
+ assertEquals("Property " + columns[i],
+ columns[i], dynaProps[i].getName());
+ }
+
+ }
+
+
+ public void testNewInstance() {
+
+ try {
+ dynaClass.newInstance();
+ fail("Did not throw UnsupportedOperationException()");
+ } catch (UnsupportedOperationException e) {
+ ; // Expected result
+ } catch (Exception e) {
+ fail("Threw exception " + e);
+ }
+
+ }
+
+
+ public void testIteratorCount() {
+
+ Iterator rows = dynaClass.iterator();
+ assertNotNull("iterator exists", rows);
+ int n = 0;
+ while (rows.hasNext()) {
+ rows.next();
+ n++;
+ if (n > 10) {
+ fail("Returned too many rows");
+ }
+ }
+ assertEquals("iterator rows", 5, n);
+
+ }
+
+
+ public void testIteratorResults() {
+
+ // Grab the third row
+ Iterator rows = dynaClass.iterator();
+ rows.next();
+ rows.next();
+ DynaBean row = (DynaBean) rows.next();
+
+ // Invalid argument test
+ try {
+ row.get("unknownProperty");
+ fail("Did not throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ ; // Expected result
+ }
+
+ // Verify property values
+
+ Object bigDecimalProperty = row.get("bigdecimalproperty");
+ assertNotNull("bigDecimalProperty exists", bigDecimalProperty);
+ assertTrue("bigDecimalProperty type",
+ bigDecimalProperty instanceof BigDecimal);
+ assertEquals("bigDecimalProperty value",
+ 123.45,
+ ((BigDecimal) bigDecimalProperty).doubleValue(),
+ 0.005);
+
+ Object intProperty = row.get("intproperty");
+ assertNotNull("intProperty exists", intProperty);
+ assertTrue("intProperty type",
+ intProperty instanceof Integer);
+ assertEquals("intProperty value",
+ 103,
+ ((Integer) intProperty).intValue());
+
+ Object nullProperty = row.get("nullproperty");
+ assertNull("nullProperty null", nullProperty);
+
+ Object stringProperty = row.get("stringproperty");
+ assertNotNull("stringProperty exists", stringProperty);
+ assertTrue("stringProperty type",
+ stringProperty instanceof String);
+ assertEquals("stringProperty value",
+ "This is a string",
+ (String) stringProperty);
+
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaRowSetTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaRowSetTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/DynaRowSetTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * Test accessing RowSets via DynaBeans.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.5 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class DynaRowSetTestCase extends TestCase {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The mock result set DynaClass to be tested.
+ */
+ protected RowSetDynaClass dynaClass = null;
+
+
+ /**
+ * Names of the columns for this test. Must match the order they are
+ * defined in {@link TestResultSetMetaData}, and must be all lower case.
+ */
+ protected String columns[] =
+ { "bigdecimalproperty", "booleanproperty",
+ "byteproperty", "dateproperty",
+ "doubleproperty", "floatproperty",
+ "intproperty", "longproperty",
+ "nullproperty", "shortproperty",
+ "stringproperty", "timeproperty",
+ "timestampproperty" };
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public DynaRowSetTestCase(String name) {
+
+ super(name);
+
+ }
+
+
+ // --------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+
+ dynaClass = new RowSetDynaClass(new TestResultSet());
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+
+ return (new TestSuite(DynaRowSetTestCase.class));
+
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+
+ dynaClass = null;
+
+ }
+
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ public void testGetName() {
+
+ assertEquals("DynaClass name",
+ "org.apache.commons.beanutils.RowSetDynaClass",
+ dynaClass.getName());
+
+
+ }
+
+
+ public void testGetDynaProperty() {
+
+ // Invalid argument test
+ try {
+ dynaClass.getDynaProperty(null);
+ fail("Did not throw IllegaArgumentException");
+ } catch (IllegalArgumentException e) {
+ ; // Expected result
+ }
+
+ // Negative test
+ DynaProperty dynaProp = dynaClass.getDynaProperty("unknownProperty");
+ assertTrue("unknown property returns null",
+ (dynaProp == null));
+
+ // Positive test
+ dynaProp = dynaClass.getDynaProperty("stringproperty");
+ assertNotNull("string property exists", dynaProp);
+ assertEquals("string property name", "stringproperty",
+ dynaProp.getName());
+ assertEquals("string property class", String.class,
+ dynaProp.getType());
+
+ }
+
+
+ public void testGetDynaProperties() {
+
+ DynaProperty dynaProps[] = dynaClass.getDynaProperties();
+ assertNotNull("dynaProps exists", dynaProps);
+ assertEquals("dynaProps length", columns.length, dynaProps.length);
+ for (int i = 0; i < columns.length; i++) {
+ assertEquals("Property " + columns[i],
+ columns[i], dynaProps[i].getName());
+ }
+
+ }
+
+
+ public void testNewInstance() {
+
+ try {
+ dynaClass.newInstance();
+ fail("Did not throw UnsupportedOperationException()");
+ } catch (UnsupportedOperationException e) {
+ ; // Expected result
+ } catch (Exception e) {
+ fail("Threw exception " + e);
+ }
+
+ }
+
+
+ public void testListCount() {
+
+ List rows = dynaClass.getRows();
+ assertNotNull("list exists", rows);
+ assertEquals("list row count", 5, rows.size());
+
+ }
+
+
+ public void testListResults() {
+
+ // Grab the third row
+ List rows = dynaClass.getRows();
+ DynaBean row = (DynaBean) rows.get(2);
+
+ // Invalid argument test
+ try {
+ row.get("unknownProperty");
+ fail("Did not throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ ; // Expected result
+ }
+
+ // Verify property values
+
+ Object bigDecimalProperty = row.get("bigdecimalproperty");
+ assertNotNull("bigDecimalProperty exists", bigDecimalProperty);
+ assertTrue("bigDecimalProperty type",
+ bigDecimalProperty instanceof BigDecimal);
+ assertEquals("bigDecimalProperty value",
+ 123.45,
+ ((BigDecimal) bigDecimalProperty).doubleValue(),
+ 0.005);
+
+ Object intProperty = row.get("intproperty");
+ assertNotNull("intProperty exists", intProperty);
+ assertTrue("intProperty type",
+ intProperty instanceof Integer);
+ assertEquals("intProperty value",
+ 103,
+ ((Integer) intProperty).intValue());
+
+ Object nullProperty = row.get("nullproperty");
+ assertNull("nullProperty null", nullProperty);
+
+ Object stringProperty = row.get("stringproperty");
+ assertNotNull("stringProperty exists", stringProperty);
+ assertTrue("stringProperty type",
+ stringProperty instanceof String);
+ assertEquals("stringProperty value",
+ "This is a string",
+ (String) stringProperty);
+
+
+ }
+
+ public void testLimitedRows() throws Exception {
+
+ // created one with low limit
+ RowSetDynaClass limitedDynaClass = new RowSetDynaClass(new TestResultSet(), 3);
+ List rows = limitedDynaClass.getRows();
+ assertNotNull("list exists", rows);
+ assertEquals("limited row count", 3, rows.size());
+
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ExtendMapBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ExtendMapBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ExtendMapBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+import java.util.Hashtable;
+
+
+/**
+ * Used to test
+ *
+ * @author Robert Burrell
+ */
+
+public class ExtendMapBean extends Hashtable {
+
+ private String dbName = "[UNSET]";
+
+ public ExtendMapBean() {}
+
+ public String getUnusuallyNamedProperty()
+ {
+ return dbName;
+ }
+
+ public void setUnusuallyNamedProperty(String dbName)
+ {
+ this.dbName = dbName;
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaBeanTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaBeanTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaBeanTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,483 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.beanutils;
+
+import java.util.HashMap;
+import java.util.TreeMap;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.lang.reflect.InvocationTargetException;
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * <p>Test Case for the <code>LazyDynaBean</code> implementation class.</p>
+ *
+ * @author Niall Pemberton
+ */
+public class LazyDynaBeanTestCase extends TestCase {
+
+ protected LazyDynaBean bean = null;
+ protected LazyDynaClass dynaClass = null;
+ protected String testProperty = "myProperty";
+ protected String testPropertyA = "myProperty-A";
+ protected String testPropertyB = "myProperty-B";
+ protected String testString1 = "myStringValue-1";
+ protected String testString2 = "myStringValue-2";
+ protected Integer testInteger1 = new Integer(30);
+ protected Integer testInteger2 = new Integer(40);
+ protected String testKey = "myKey";
+
+ // ---------------------------------------------------------- Constructors
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public LazyDynaBeanTestCase(String name) {
+ super(name);
+ }
+
+ // -------------------------------------------------- Overall Test Methods
+
+ /**
+ * Run thus Test
+ */
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(LazyDynaBeanTestCase.class));
+ }
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+ bean = new LazyDynaBean();
+ dynaClass = (LazyDynaClass)bean.getDynaClass();
+ dynaClass.setReturnNull(true);
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ bean = null;
+ }
+
+ // ------------------------------------------------ Individual Test Methods
+
+ /**
+ * Test Getting/Setting a Simple Property
+ */
+ public void testSimpleProperty() {
+
+ // Check the property & value doesn't exist
+ assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+ assertNull("Check Value is null", bean.get(testProperty));
+
+ // Set a new property - should add new property and set value
+ bean.set(testProperty, testInteger1);
+ assertEquals("Check First Value is correct", testInteger1, bean.get(testProperty));
+ assertEquals("Check Property type is correct", Integer.class, dynaClass.getDynaProperty(testProperty).getType());
+
+ // Set the property again - should set the new value
+ bean.set(testProperty, testInteger2);
+ assertEquals("Check Second Value is correct", testInteger2, bean.get(testProperty));
+
+ // Set the property again - with a different type, should fail
+ try {
+ bean.set(testProperty, testString1);
+ fail("expected ConversionException trying to set an Integer property to a String");
+ } catch (ConversionException expected) {
+ // expected result
+ }
+
+ }
+
+ /**
+ * Test Setting a Simple Property when MutableDynaClass is set to restricted
+ */
+ public void testSimplePropertyRestricted() {
+
+ // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
+ dynaClass.setRestricted(true);
+ assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());
+
+ // Check the property & value doesn't exist
+ assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+ assertNull("Check Value is null", bean.get(testProperty));
+
+ // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
+ try {
+ bean.set(testProperty, testString1);
+ fail("expected IllegalArgumentException trying to add new property to restricted DynaClass");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+
+ }
+
+ /**
+ * Test Getting/Setting a 'Mapped' Property - default HashMap property
+ */
+ public void testMappedPropertyDefault() {
+
+ // Check the property & value doesn't exist
+ assertNull("Check Mapped Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+ assertNull("Check Map is null", bean.get(testProperty));
+ assertNull("Check Mapped Value is null", bean.get(testProperty, testKey));
+
+ // Set a new mapped property - should add new HashMap property and set the mapped value
+ bean.set(testProperty, testKey, testInteger1);
+ assertEquals("Check Mapped Property exists", HashMap.class, bean.get(testProperty).getClass());
+ assertEquals("Check First Mapped Value is correct(a)", testInteger1, bean.get(testProperty, testKey));
+ assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((HashMap)bean.get(testProperty)).get(testKey));
+
+ // Set the property again - should set the new value
+ bean.set(testProperty, testKey, testInteger2);
+ assertEquals("Check Second Mapped Value is correct(a)", testInteger2, bean.get(testProperty, testKey));
+ assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((HashMap)bean.get(testProperty)).get(testKey));
+ }
+
+ /**
+ * Test Getting/Setting a 'Mapped' Property - use TreeMap property
+ */
+ public void testMappedPropertyTreeMap() {
+
+ // Check the property & value doesn't exist
+ assertNull("Check Mapped Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+
+ // Add a 'TreeMap' property to the DynaClass
+ dynaClass.add(testProperty, TreeMap.class);
+ assertTrue("Check Property is mapped", dynaClass.getDynaProperty(testProperty).isMapped());
+ assertEquals("Check Property is correct type", TreeMap.class, dynaClass.getDynaProperty(testProperty).getType());
+ assertEquals("Check Mapped Property exists", TreeMap.class, bean.get(testProperty).getClass());
+// assertNull("Check mapped property is null", bean.get(testProperty));
+
+ // Set a new mapped property - should instatiate a new TreeMap property and set the mapped value
+ bean.set(testProperty, testKey, testInteger1);
+ assertEquals("Check Mapped Property exists", TreeMap.class, bean.get(testProperty).getClass());
+ assertEquals("Check First Mapped Value is correct(a)", testInteger1, bean.get(testProperty, testKey));
+ assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((TreeMap)bean.get(testProperty)).get(testKey));
+
+ // Set the property again - should set the new value
+ bean.set(testProperty, testKey, testInteger2);
+ assertEquals("Check Second Mapped Value is correct(a)", testInteger2, bean.get(testProperty, testKey));
+ assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((TreeMap)bean.get(testProperty)).get(testKey));
+ }
+
+ /**
+ * Test Setting a 'Mapped' Property using PropertyUtils
+ */
+ public void testMappedPropertyUtils() {
+
+ dynaClass.setReturnNull(false);
+
+ // Check the property & value doesn't exist
+ assertFalse("Check Mapped Property doesn't exist", dynaClass.isDynaProperty(testProperty));
+ assertNull("Check Map is null", bean.get(testProperty));
+ assertNull("Check Mapped Value is null", bean.get(testProperty, testKey));
+
+ // Set the mapped property using PropertyUtils
+ try {
+ PropertyUtils.setProperty(bean, testProperty+"("+testKey+")", testString1);
+ }
+ catch (NoSuchMethodException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+ catch (InvocationTargetException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+ catch (IllegalAccessException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+
+ // Check property value correctly set
+ assertEquals("Check Mapped Bean Value is correct", testString1, bean.get(testProperty, testKey));
+
+ }
+
+ /**
+ * Test Setting a Mapped Property when MutableDynaClass is set to restricted
+ */
+ public void testMappedPropertyRestricted() {
+
+ // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
+ dynaClass.setRestricted(true);
+ assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());
+
+ // Check the property & value doesn't exist
+ assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+ assertNull("Check Value is null", bean.get(testProperty));
+
+ // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
+ try {
+ bean.set(testProperty, testKey, testInteger1);
+ fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+
+ }
+
+ /**
+ * Test setting mapped property for type which is not Map
+ */
+ public void testMappedInvalidType() {
+ dynaClass.add(testProperty, String.class);
+ assertFalse("Check Property is not mapped", dynaClass.getDynaProperty(testProperty).isMapped());
+ try {
+ bean.set(testProperty, testKey, testInteger1);
+ fail("set(property, key, value) should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test Getting/Setting an 'Indexed' Property - default ArrayList property
+ */
+ public void testIndexedPropertyDefault() {
+
+ int index = 3;
+
+ // Check the property & value doesn't exist
+ assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", bean.get(testProperty));
+ assertNull("Check Indexed value is null", bean.get(testProperty, index));
+
+ // Set the property, should create new ArrayList and set appropriate indexed value
+ bean.set(testProperty, index, testInteger1);
+ assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
+ assertEquals("Check Indexed Property is correct type", ArrayList.class, bean.get(testProperty).getClass());
+ assertEquals("Check First Indexed Value is correct", testInteger1, bean.get(testProperty, index));
+ assertEquals("Check First Array length is correct", new Integer(index+1), new Integer(((ArrayList)bean.get(testProperty)).size()));
+
+ // Set a second indexed value, should automatically grow the ArrayList and set appropriate indexed value
+ index = index + 2;
+ bean.set(testProperty, index, testString1);
+ assertEquals("Check Second Indexed Value is correct", testString1, bean.get(testProperty, index));
+ assertEquals("Check Second Array length is correct", new Integer(index+1), new Integer(((ArrayList)bean.get(testProperty)).size()));
+ }
+
+ /**
+ * Test Getting/Setting a List 'Indexed' Property - use alternative List (LinkedList)
+ */
+ public void testIndexedLinkedList() {
+
+ int index = 3;
+
+ // Check the property & value doesn't exist
+ assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", bean.get(testProperty));
+
+ // Add a 'LinkedList' property to the DynaClass
+ dynaClass.add(testProperty, LinkedList.class);
+ assertTrue("Check Property is indexed", dynaClass.getDynaProperty(testProperty).isIndexed());
+ assertEquals("Check Property is correct type", LinkedList.class, dynaClass.getDynaProperty(testProperty).getType());
+ assertEquals("Check Property type is correct", LinkedList.class, bean.get(testProperty).getClass());
+
+ // Set the property, should instantiate a new LinkedList and set appropriate indexed value
+ bean.set(testProperty, index, testString1);
+ assertEquals("Check Property type is correct", LinkedList.class, bean.get(testProperty).getClass());
+ assertEquals("Check First Indexed Value is correct", testString1, bean.get(testProperty, index));
+ assertEquals("Check First Array length is correct", new Integer(index+1), new Integer(((LinkedList)bean.get(testProperty)).size()));
+
+ // Set a second indexed value, should automatically grow the LinkedList and set appropriate indexed value
+ index = index + 2;
+ bean.set(testProperty, index, testInteger1);
+ assertEquals("Check Second Indexed Value is correct", testInteger1, bean.get(testProperty, index));
+ assertEquals("Check Second Array length is correct", new Integer(index+1), new Integer(((LinkedList)bean.get(testProperty)).size()));
+ }
+
+ /**
+ * Test Getting/Setting a primitive array 'Indexed' Property - use int[]
+ */
+ public void testIndexedPrimitiveArray() {
+
+ int index = 3;
+ int[] primitiveArray = new int[0];
+
+ // Check the property & value doesn't exist
+ assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", bean.get(testProperty));
+
+ // Add a DynaProperty of type int[]
+ dynaClass.add(testProperty, primitiveArray.getClass());
+ assertEquals("Check Indexed Property exists", primitiveArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
+ assertEquals("Check Indexed Property is correct type", primitiveArray.getClass(), bean.get(testProperty).getClass());
+
+ // Set an indexed value
+ bean.set(testProperty, index, testInteger1);
+ assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
+ assertEquals("Check Indexed Property is correct type", primitiveArray.getClass(), bean.get(testProperty).getClass());
+ assertEquals("Check First Indexed Value is correct(a)", testInteger1, bean.get(testProperty, index));
+ assertEquals("Check First Indexed Value is correct(b)", testInteger1, new Integer(((int[])bean.get(testProperty))[index]));
+ assertEquals("Check Array length is correct", new Integer(index+1), new Integer(((int[])bean.get(testProperty)).length));
+
+ // Set a second indexed value, should automatically grow the int[] and set appropriate indexed value
+ index = index + 2;
+ bean.set(testProperty, index, testInteger2);
+ assertEquals("Check Second Indexed Value is correct(a)", testInteger2, bean.get(testProperty, index));
+ assertEquals("Check Second Indexed Value is correct(b)", testInteger2, new Integer(((int[])bean.get(testProperty))[index]));
+ assertEquals("Check Second Array length is correct", new Integer(index+1), new Integer(((int[])bean.get(testProperty)).length));
+
+ }
+
+ /**
+ * Test Getting/Setting an Object array 'Indexed' Property - use String[]
+ */
+ public void testIndexedObjectArray() {
+
+ int index = 3;
+ Object objectArray = new String[0];
+
+ // Check the property & value doesn't exist
+ assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", bean.get(testProperty));
+
+ // Add a DynaProperty of type String[]
+ dynaClass.add(testProperty, objectArray.getClass());
+ assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
+ assertEquals("Check Indexed Property is correct type", objectArray.getClass(), bean.get(testProperty).getClass());
+
+ // Set an indexed value
+ bean.set(testProperty, index, testString1);
+ assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
+ assertEquals("Check Indexed Property is correct type", objectArray.getClass(), bean.get(testProperty).getClass());
+ assertEquals("Check First Indexed Value is correct(a)", testString1, bean.get(testProperty, index));
+ assertEquals("Check First Indexed Value is correct(b)", testString1, ((String[])bean.get(testProperty))[index]);
+ assertEquals("Check Array length is correct", new Integer(index+1), new Integer(((String[])bean.get(testProperty)).length));
+
+ // Set a second indexed value, should automatically grow the String[] and set appropriate indexed value
+ index = index + 2;
+ bean.set(testProperty, index, testString2);
+ assertEquals("Check Second Indexed Value is correct(a)", testString2, bean.get(testProperty, index));
+ assertEquals("Check Second Indexed Value is correct(b)", testString2, ((String[])bean.get(testProperty))[index]);
+ assertEquals("Check Second Array length is correct", new Integer(index+1), new Integer(((String[])bean.get(testProperty)).length));
+ }
+
+ /**
+ * Test Getting/Setting an DynaBean[] array
+ */
+ public void testIndexedDynaBeanArray() {
+
+ int index = 3;
+ Object objectArray = new LazyDynaMap[0];
+
+ // Check the property & value doesn't exist
+ assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", bean.get(testProperty));
+
+ // Add a DynaProperty of type String[]
+ dynaClass.add(testProperty, objectArray.getClass());
+ assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
+ assertEquals("Check Indexed Property is correct type", objectArray.getClass(), bean.get(testProperty).getClass());
+
+ // Retrieving from Array should initialize DynaBean
+ for (int i = index; i >= 0; i--) {
+ assertEquals("Check Array Components initialized", LazyDynaMap.class, bean.get(testProperty, index).getClass());
+ }
+
+ dynaClass.add(testPropertyB, objectArray.getClass());
+ LazyDynaMap newMap = new LazyDynaMap();
+ newMap.set(testPropertyB, testString2);
+ bean.set(testPropertyA, index, newMap);
+ assertEquals("Check Indexed Value is correct(a)", testString2, ((DynaBean)bean.get(testPropertyA, index)).get(testPropertyB));
+
+ }
+
+ /**
+ * Test Setting an 'Indexed' Property using PropertyUtils
+ */
+ public void testIndexedPropertyUtils() {
+
+ int index = 3;
+ dynaClass.setReturnNull(false);
+
+ // Check the property & value doesn't exist
+ assertFalse("Check Indexed Property doesn't exist", dynaClass.isDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", bean.get(testProperty));
+ assertNull("Check Indexed value is null", bean.get(testProperty, index));
+
+ // Use PropertyUtils to set the indexed value
+ try {
+ PropertyUtils.setProperty(bean, testProperty+"["+index+"]", testString1);
+ }
+ catch (NoSuchMethodException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+ catch (InvocationTargetException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+ catch (IllegalAccessException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+
+ // Check property value correctly set
+ assertEquals("Check Indexed Bean Value is correct", testString1, bean.get(testProperty, index));
+
+ }
+
+ /**
+ * Test Setting an Indexed Property when MutableDynaClass is set to restricted
+ */
+ public void testIndexedPropertyRestricted() {
+
+ int index = 3;
+
+ // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
+ dynaClass.setRestricted(true);
+ assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());
+
+ // Check the property & value doesn't exist
+ assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
+ assertNull("Check Value is null", bean.get(testProperty));
+
+ // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
+ try {
+ bean.set(testProperty, index, testInteger1);
+ fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+
+ }
+
+ /**
+ * Test setting indexed property for type which is not List or Array
+ */
+ public void testIndexedInvalidType() {
+ int index = 3;
+ dynaClass.add(testProperty, String.class);
+ assertFalse("Check Property is not indexed", dynaClass.getDynaProperty(testProperty).isIndexed());
+ try {
+ bean.set(testProperty, index, testString1);
+ fail("set(property, index, value) should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+ }
+
+}
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaClassTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaClassTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaClassTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.beanutils;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * <p>Test Case for the <code>LazyDynaClass</code> implementation class.</p>
+ *
+ * @author Niall Pemberton
+ */
+public class LazyDynaClassTestCase extends TestCase {
+
+ protected LazyDynaClass dynaClass = null;
+ protected String testProperty = "myProperty";
+
+ // ---------------------------------------------------------- Constructors
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public LazyDynaClassTestCase(String name) {
+ super(name);
+ }
+
+ // -------------------------------------------------- Overall Test Methods
+
+ /**
+ * Run this Test
+ */
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+ dynaClass = new LazyDynaClass();
+ }
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(LazyDynaClassTestCase.class));
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ dynaClass = null;
+ }
+
+ // ------------------------------------------------ Individual Test Methods
+
+ /**
+ * Test add(name) method
+ */
+ public void testAddProperty1() {
+ dynaClass.add(testProperty);
+ DynaProperty dynaProperty = dynaClass.getDynaProperty(testProperty);
+ assertEquals("name is correct", testProperty, dynaProperty.getName());
+ assertEquals("type is correct", Object.class, dynaProperty.getType());
+ }
+
+ /**
+ * Test add(name, type) method
+ */
+ public void testAddProperty2() {
+ dynaClass.add(testProperty, String.class);
+ DynaProperty dynaProperty = dynaClass.getDynaProperty(testProperty);
+ assertEquals("name is correct", testProperty, dynaProperty.getName());
+ assertEquals("type is correct", String.class, dynaProperty.getType());
+ }
+
+ /**
+ * Test add(name, type, readable, writable) method
+ */
+ public void testAddProperty3() {
+ try {
+ dynaClass.add(testProperty, String.class, true, true);
+ fail("add(name, type, readable, writable) did not throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test add(name) method with 'null' name
+ */
+ public void testAddPropertyNullName1() {
+ try {
+ dynaClass.add((String)null);
+ fail("null property name not prevented");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test add(name, type) method with 'null' name
+ */
+ public void testAddPropertyNullName2() {
+ try {
+ dynaClass.add(null, String.class);
+ fail("null property name not prevented");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test add(name, type, readable, writable) method with 'null' name
+ */
+ public void testAddPropertyNullName3() {
+ try {
+ dynaClass.add(null, String.class, true, true);
+ fail("add(name, type, readable, writable) did not throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test add(name) method when restricted is set to 'true'
+ */
+ public void testAddPropertyRestricted1() {
+ dynaClass.setRestricted(true);
+ assertTrue("MutableDynaClass is restricted", dynaClass.isRestricted());
+ try {
+ dynaClass.add(testProperty);
+ fail("add(name) did not throw IllegalStateException");
+ } catch (IllegalStateException expected) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test add(name, type) method when restricted is set to 'true'
+ */
+ public void testAddPropertyRestricted2() {
+ dynaClass.setRestricted(true);
+ assertTrue("MutableDynaClass is restricted", dynaClass.isRestricted());
+ try {
+ dynaClass.add(testProperty, String.class);
+ fail("add(name, type) did not throw IllegalStateException");
+ } catch (IllegalStateException expected) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test add(name, type, readable, writable) method when restricted is set to 'true'
+ */
+ public void testAddPropertyRestricted3() {
+ dynaClass.setRestricted(true);
+ assertTrue("MutableDynaClass is restricted", dynaClass.isRestricted());
+ try {
+ dynaClass.add(testProperty, String.class, true, true);
+ fail("add(name, type, readable, writable) did not throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException t) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test retrieving a property which doesn't exist (returnNull is 'false')
+ */
+ public void testGetPropertyDoesntExist1() {
+ dynaClass.setReturnNull(false);
+ assertFalse("returnNull is 'false'", dynaClass.isReturnNull());
+ DynaProperty dynaProperty = dynaClass.getDynaProperty(testProperty);
+ assertEquals("name is correct", testProperty, dynaProperty.getName());
+ assertEquals("type is correct", Object.class, dynaProperty.getType());
+ assertFalse("property doesnt exist", dynaClass.isDynaProperty(testProperty));
+ }
+
+
+ /**
+ * Test retrieving a property which doesn't exist (returnNull is 'true')
+ */
+ public void testGetPropertyDoesntExist2() {
+ dynaClass.setReturnNull(true);
+ assertTrue("returnNull is 'true'", dynaClass.isReturnNull());
+ assertNull("property is null", dynaClass.getDynaProperty(testProperty));
+ }
+
+ /**
+ * Test removing a property
+ */
+ public void testRemoveProperty() {
+ dynaClass.setReturnNull(true);
+ dynaClass.add(testProperty);
+ assertTrue("Property exists", dynaClass.isDynaProperty(testProperty));
+ assertNotNull("property is Not null", dynaClass.getDynaProperty(testProperty));
+ dynaClass.remove(testProperty);
+ assertFalse("Property doesn't exist", dynaClass.isDynaProperty(testProperty));
+ assertNull("property is null", dynaClass.getDynaProperty(testProperty));
+ }
+
+ /**
+ * Test removing a property, name is null
+ */
+ public void testRemovePropertyNullName() {
+ try {
+ dynaClass.remove(null);
+ fail("remove(null) did not throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test removing a property, DynaClass is restricted
+ */
+ public void testRemovePropertyRestricted() {
+ dynaClass.add(testProperty);
+ assertTrue("Property exists", dynaClass.isDynaProperty(testProperty));
+ dynaClass.setRestricted(true);
+ assertTrue("MutableDynaClass is restricted", dynaClass.isRestricted());
+ try {
+ dynaClass.remove(testProperty);
+ fail("remove property when MutableDynaClassis restricted did not throw IllegalStateException");
+ } catch (IllegalStateException expected) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test removing a property which doesn't exist
+ */
+ public void testRemovePropertyDoesntExist() {
+ assertFalse("property doesn't exist", dynaClass.isDynaProperty(testProperty));
+ dynaClass.remove(testProperty);
+ assertFalse("property still doesn't exist", dynaClass.isDynaProperty(testProperty));
+ }
+}
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaMapTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaMapTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/LazyDynaMapTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,486 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.beanutils;
+
+import java.util.HashMap;
+import java.util.TreeMap;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.lang.reflect.InvocationTargetException;
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * <p>Test Case for the <code>LazyDynaMap</code> implementation class.</p>
+ *
+ * @author Niall Pemberton
+ */
+public class LazyDynaMapTestCase extends TestCase {
+
+ protected LazyDynaMap dynaMap = null;
+ protected String testProperty = "myProperty";
+ protected String testPropertyA = "myProperty-A";
+ protected String testPropertyB = "myProperty-B";
+ protected String testString1 = "myStringValue-1";
+ protected String testString2 = "myStringValue-2";
+ protected Integer testInteger1 = new Integer(30);
+ protected Integer testInteger2 = new Integer(40);
+ protected String testKey = "myKey";
+
+ // ---------------------------------------------------------- Constructors
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public LazyDynaMapTestCase(String name) {
+ super(name);
+ }
+
+ // -------------------------------------------------- Overall Test Methods
+
+ /**
+ * Run thus Test
+ */
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(LazyDynaMapTestCase.class));
+ }
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+ dynaMap = new LazyDynaMap();
+ dynaMap.setReturnNull(true);
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ dynaMap = null;
+ }
+
+ // ------------------------------------------------ Individual Test Methods
+
+ /**
+ * General Tests
+ */
+ public void testGeneral() {
+// LazyDynaMap bean = new LazyDynaMap("TestBean");
+ assertEquals("Check DynaClass name", "TestBean", new LazyDynaMap("TestBean").getName());
+
+ }
+
+ /**
+ * Test Getting/Setting a Simple Property
+ */
+ public void testSimpleProperty() {
+
+ // Check the property & value doesn't exist
+ assertNull("Check Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Value is null", dynaMap.get(testProperty));
+
+ // Set a new property - should add new property and set value
+ dynaMap.set(testProperty, testInteger1);
+ assertEquals("Check First Value is correct", testInteger1, dynaMap.get(testProperty));
+ assertEquals("Check Property type is correct", Integer.class, dynaMap.getDynaProperty(testProperty).getType());
+
+ // Set the property again - should set the new value
+ dynaMap.set(testProperty, testInteger2);
+ assertEquals("Check Second Value is correct", testInteger2, dynaMap.get(testProperty));
+
+ // Set the property again - with a different type, should succeed
+ dynaMap.set(testProperty, testString1);
+ assertEquals("Check Third Value is correct", testString1, dynaMap.get(testProperty));
+
+ }
+
+ /**
+ * Test Setting a Simple Property when MutableDynaClass is set to restricted
+ */
+ public void testSimplePropertyRestricted() {
+
+ // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
+ dynaMap.setRestricted(true);
+ assertTrue("Check MutableDynaClass is restricted", dynaMap.isRestricted());
+
+ // Check the property & value doesn't exist
+ assertNull("Check Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Value is null", dynaMap.get(testProperty));
+
+ // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
+ try {
+ dynaMap.set(testProperty, testString1);
+ fail("expected IllegalArgumentException trying to add new property to restricted DynaClass");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+
+ }
+
+ /**
+ * Test Getting/Setting a 'Mapped' Property - default HashMap property
+ */
+ public void testMappedPropertyDefault() {
+
+ // Check the property & value doesn't exist
+ assertNull("Check Mapped Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Map is null", dynaMap.get(testProperty));
+ assertNull("Check Mapped Value is null", dynaMap.get(testProperty, testKey));
+
+ // Set a new mapped property - should add new HashMap property and set the mapped value
+ dynaMap.set(testProperty, testKey, testInteger1);
+ assertEquals("Check Mapped Property exists", HashMap.class, dynaMap.get(testProperty).getClass());
+ assertEquals("Check First Mapped Value is correct(a)", testInteger1, dynaMap.get(testProperty, testKey));
+ assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((HashMap)dynaMap.get(testProperty)).get(testKey));
+
+ // Set the property again - should set the new value
+ dynaMap.set(testProperty, testKey, testInteger2);
+ assertEquals("Check Second Mapped Value is correct(a)", testInteger2, dynaMap.get(testProperty, testKey));
+ assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((HashMap)dynaMap.get(testProperty)).get(testKey));
+ }
+
+ /**
+ * Test Getting/Setting a 'Mapped' Property - use TreeMap property
+ */
+ public void testMappedPropertyTreeMap() {
+
+ // Check the property & value doesn't exist
+ assertNull("Check Mapped Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Map is null", dynaMap.get(testProperty));
+
+ // Add a 'TreeMap' property to the DynaClass
+ dynaMap.add(testProperty, TreeMap.class);
+ assertTrue("Check Property is mapped", dynaMap.getDynaProperty(testProperty).isMapped());
+ assertEquals("Check Property is correct type", TreeMap.class, dynaMap.getDynaProperty(testProperty).getType());
+ assertEquals("Check Mapped Property now exists", TreeMap.class, dynaMap.get(testProperty).getClass());
+
+ // Set a new mapped property - should instatiate a new TreeMap property and set the mapped value
+ dynaMap.set(testProperty, testKey, testInteger1);
+ assertEquals("Check Mapped Property exists", TreeMap.class, dynaMap.get(testProperty).getClass());
+ assertEquals("Check First Mapped Value is correct(a)", testInteger1, dynaMap.get(testProperty, testKey));
+ assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((TreeMap)dynaMap.get(testProperty)).get(testKey));
+
+ // Set the property again - should set the new value
+ dynaMap.set(testProperty, testKey, testInteger2);
+ assertEquals("Check Second Mapped Value is correct(a)", testInteger2, dynaMap.get(testProperty, testKey));
+ assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((TreeMap)dynaMap.get(testProperty)).get(testKey));
+ }
+
+ /**
+ * Test Setting a 'Mapped' Property using PropertyUtils
+ */
+ public void testMappedPropertyUtils() {
+
+ dynaMap.setReturnNull(false);
+
+ // Check the property & value doesn't exist
+ assertFalse("Check Mapped Property doesn't exist", dynaMap.isDynaProperty(testProperty));
+ assertNull("Check Map is null", dynaMap.get(testProperty));
+ assertNull("Check Mapped Value is null", dynaMap.get(testProperty, testKey));
+
+ // Set the mapped property using PropertyUtils
+ try {
+ PropertyUtils.setProperty(dynaMap, testProperty+"("+testKey+")", testString1);
+ }
+ catch (NoSuchMethodException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+ catch (InvocationTargetException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+ catch (IllegalAccessException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+
+ // Check property value correctly set
+ assertEquals("Check Mapped Bean Value is correct", testString1, dynaMap.get(testProperty, testKey));
+
+ }
+
+ /**
+ * Test Setting a Mapped Property when MutableDynaClass is set to restricted
+ */
+ public void testMappedPropertyRestricted() {
+
+ // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
+ dynaMap.setRestricted(true);
+ assertTrue("Check MutableDynaClass is restricted", dynaMap.isRestricted());
+
+ // Check the property & value doesn't exist
+ assertNull("Check Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Value is null", dynaMap.get(testProperty));
+
+ // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
+ try {
+ dynaMap.set(testProperty, testKey, testInteger1);
+ fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+
+ }
+
+ /**
+ * Test setting mapped property for type which is not Map
+ */
+ public void testMappedInvalidType() {
+ dynaMap.set(testProperty, new Integer(1));
+ assertFalse("Check Property is not mapped", dynaMap.getDynaProperty(testProperty).isMapped());
+ try {
+ dynaMap.set(testProperty, testKey, testInteger1);
+ fail("set(property, key, value) should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+ }
+
+ /**
+ * Test Getting/Setting an 'Indexed' Property - default ArrayList property
+ */
+ public void testIndexedPropertyDefault() {
+
+ int index = 3;
+
+ // Check the property & value doesn't exist
+ assertNull("Check Indexed Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
+ assertNull("Check Indexed value is null", dynaMap.get(testProperty, index));
+
+ // Set the property, should create new ArrayList and set appropriate indexed value
+ dynaMap.set(testProperty, index, testInteger1);
+ assertNotNull("Check Indexed Property is not null", dynaMap.get(testProperty));
+ assertEquals("Check Indexed Property is correct type", ArrayList.class, dynaMap.get(testProperty).getClass());
+ assertEquals("Check First Indexed Value is correct", testInteger1, dynaMap.get(testProperty, index));
+ assertEquals("Check First Array length is correct", new Integer(index+1), new Integer(((ArrayList)dynaMap.get(testProperty)).size()));
+
+ // Set a second indexed value, should automatically grow the ArrayList and set appropriate indexed value
+ index = index + 2;
+ dynaMap.set(testProperty, index, testString1);
+ assertEquals("Check Second Indexed Value is correct", testString1, dynaMap.get(testProperty, index));
+ assertEquals("Check Second Array length is correct", new Integer(index+1), new Integer(((ArrayList)dynaMap.get(testProperty)).size()));
+ }
+
+ /**
+ * Test Getting/Setting a List 'Indexed' Property - use alternative List (LinkedList)
+ */
+ public void testIndexedLinkedList() {
+
+ int index = 3;
+
+ // Check the property & value doesn't exist
+ assertNull("Check Indexed Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
+
+ // Add a 'LinkedList' property to the DynaClass - should instantiate a new LinkedList
+ dynaMap.add(testProperty, LinkedList.class);
+ assertTrue("Check Property is indexed", dynaMap.getDynaProperty(testProperty).isIndexed());
+ assertEquals("Check Property is correct type", LinkedList.class, dynaMap.getDynaProperty(testProperty).getType());
+ assertEquals("Check Indexed Property now exists", LinkedList.class, dynaMap.get(testProperty).getClass());
+
+ // Set the Indexed property, should grow the list to the correct size
+ dynaMap.set(testProperty, index, testString1);
+ assertEquals("Check Property type is correct", LinkedList.class, dynaMap.get(testProperty).getClass());
+ assertEquals("Check First Indexed Value is correct", testString1, dynaMap.get(testProperty, index));
+ assertEquals("Check First Array length is correct", new Integer(index+1), new Integer(((LinkedList)dynaMap.get(testProperty)).size()));
+
+ // Set a second indexed value, should automatically grow the LinkedList and set appropriate indexed value
+ index = index + 2;
+ dynaMap.set(testProperty, index, testInteger1);
+ assertEquals("Check Second Indexed Value is correct", testInteger1, dynaMap.get(testProperty, index));
+ assertEquals("Check Second Array length is correct", new Integer(index+1), new Integer(((LinkedList)dynaMap.get(testProperty)).size()));
+ }
+
+ /**
+ * Test Getting/Setting a primitive array 'Indexed' Property - use int[]
+ */
+ public void testIndexedPrimitiveArray() {
+
+ int index = 3;
+ int[] primitiveArray = new int[0];
+
+ // Check the property & value doesn't exist
+ assertNull("Check Indexed Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
+
+ // Add a DynaProperty of type int[]
+ dynaMap.add(testProperty, primitiveArray.getClass());
+ assertEquals("Check Indexed Property exists", primitiveArray.getClass(), dynaMap.getDynaProperty(testProperty).getType());
+ assertTrue("Check Indexed Property exists", dynaMap.get(testProperty).getClass().isInstance(primitiveArray));
+
+ // Set an indexed value
+ dynaMap.set(testProperty, index, testInteger1);
+ assertNotNull("Check Indexed Property is not null", dynaMap.get(testProperty));
+ assertEquals("Check Indexed Property is correct type", primitiveArray.getClass(), dynaMap.get(testProperty).getClass());
+ assertEquals("Check First Indexed Value is correct(a)", testInteger1, dynaMap.get(testProperty, index));
+ assertEquals("Check First Indexed Value is correct(b)", testInteger1, new Integer(((int[])dynaMap.get(testProperty))[index]));
+ assertEquals("Check Array length is correct", new Integer(index+1), new Integer(((int[])dynaMap.get(testProperty)).length));
+
+ // Set a second indexed value, should automatically grow the int[] and set appropriate indexed value
+ index = index + 2;
+ dynaMap.set(testProperty, index, testInteger2);
+ assertEquals("Check Second Indexed Value is correct(a)", testInteger2, dynaMap.get(testProperty, index));
+ assertEquals("Check Second Indexed Value is correct(b)", testInteger2, new Integer(((int[])dynaMap.get(testProperty))[index]));
+ assertEquals("Check Second Array length is correct", new Integer(index+1), new Integer(((int[])dynaMap.get(testProperty)).length));
+
+ }
+
+ /**
+ * Test Getting/Setting an Object array 'Indexed' Property - use String[]
+ */
+ public void testIndexedObjectArray() {
+
+ int index = 3;
+ Object objectArray = new String[0];
+
+ // Check the property & value doesn't exist
+ assertNull("Check Indexed Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
+
+ // Add a DynaProperty of type String[]
+ dynaMap.add(testProperty, objectArray.getClass());
+ assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaMap.getDynaProperty(testProperty).getType());
+ assertTrue("Check Indexed Property exists", dynaMap.get(testProperty).getClass().isInstance(objectArray));
+
+ // Set an indexed value
+ dynaMap.set(testProperty, index, testString1);
+ assertNotNull("Check Indexed Property is not null", dynaMap.get(testProperty));
+ assertEquals("Check Indexed Property is correct type", objectArray.getClass(), dynaMap.get(testProperty).getClass());
+ assertEquals("Check First Indexed Value is correct(a)", testString1, dynaMap.get(testProperty, index));
+ assertEquals("Check First Indexed Value is correct(b)", testString1, ((String[])dynaMap.get(testProperty))[index]);
+ assertEquals("Check Array length is correct", new Integer(index+1), new Integer(((String[])dynaMap.get(testProperty)).length));
+
+ // Set a second indexed value, should automatically grow the String[] and set appropriate indexed value
+ index = index + 2;
+ dynaMap.set(testProperty, index, testString2);
+ assertEquals("Check Second Indexed Value is correct(a)", testString2, dynaMap.get(testProperty, index));
+ assertEquals("Check Second Indexed Value is correct(b)", testString2, ((String[])dynaMap.get(testProperty))[index]);
+ assertEquals("Check Second Array length is correct", new Integer(index+1), new Integer(((String[])dynaMap.get(testProperty)).length));
+ }
+
+ /**
+ * Test Getting/Setting an DynaBean[] array
+ */
+ public void testIndexedDynaBeanArray() {
+
+ int index = 3;
+ Object objectArray = new LazyDynaBean[0];
+
+ // Check the property & value doesn't exist
+ assertNull("Check Indexed Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
+
+ // Add a DynaProperty of type String[]
+ dynaMap.add(testProperty, objectArray.getClass());
+ assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaMap.getDynaProperty(testProperty).getType());
+ assertEquals("Check Indexed Property is correct type", objectArray.getClass(), dynaMap.get(testProperty).getClass());
+
+ // Retrieving from Array should initialize DynaBean
+ for (int i = index; i >= 0; i--) {
+ assertEquals("Check Array Components initialized", LazyDynaBean.class, dynaMap.get(testProperty, index).getClass());
+ }
+
+ dynaMap.add(testPropertyB, objectArray.getClass());
+ LazyDynaBean newBean = new LazyDynaBean();
+ newBean.set(testPropertyB, testString2);
+ dynaMap.set(testPropertyA, index, newBean);
+ assertEquals("Check Indexed Value is correct(a)", testString2, ((DynaBean)dynaMap.get(testPropertyA, index)).get(testPropertyB));
+
+ }
+
+ /**
+ * Test Setting an 'Indexed' Property using PropertyUtils
+ */
+ public void testIndexedPropertyUtils() {
+
+ int index = 3;
+ dynaMap.setReturnNull(false);
+
+ // Check the property & value doesn't exist
+ assertFalse("Check Indexed Property doesn't exist", dynaMap.isDynaProperty(testProperty));
+ assertNull("Check Indexed Property is null", dynaMap.get(testProperty));
+ assertNull("Check Indexed value is null", dynaMap.get(testProperty, index));
+
+ // Use PropertyUtils to set the indexed value
+ try {
+ PropertyUtils.setProperty(dynaMap, testProperty+"["+index+"]", testString1);
+ }
+ catch (NoSuchMethodException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+ catch (InvocationTargetException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+ catch (IllegalAccessException ex) {
+ fail("testIndexedPropertyUtils threw "+ex);
+ }
+
+ // Check property value correctly set
+ assertEquals("Check Indexed Bean Value is correct", testString1, dynaMap.get(testProperty, index));
+
+ }
+
+ /**
+ * Test Setting an Indexed Property when MutableDynaClass is set to restricted
+ */
+ public void testIndexedPropertyRestricted() {
+
+ int index = 3;
+
+ // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
+ dynaMap.setRestricted(true);
+ assertTrue("Check MutableDynaClass is restricted", dynaMap.isRestricted());
+
+ // Check the property & value doesn't exist
+ assertNull("Check Property doesn't exist", dynaMap.getDynaProperty(testProperty));
+ assertNull("Check Value is null", dynaMap.get(testProperty));
+
+ // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
+ try {
+ dynaMap.set(testProperty, index, testInteger1);
+ fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+
+ }
+
+ /**
+ * Test setting indexed property for type which is not List or Array
+ */
+ public void testIndexedInvalidType() {
+ int index = 3;
+ dynaMap.set(testProperty, "Test String");
+ assertFalse("Check Property is not indexed", dynaMap.getDynaProperty(testProperty).isIndexed());
+ try {
+ dynaMap.set(testProperty, index, testString1);
+ fail("set(property, index, value) should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ // expected result
+ }
+ }
+
+}
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/MappedPropertyTestBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/MappedPropertyTestBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/MappedPropertyTestBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Just a java bean (JAJB) to try to replicate a reported bug
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class MappedPropertyTestBean {
+
+ private Map map = new HashMap();
+
+ // -------------------------------------------------------------- Properties
+
+ public String getMapproperty(String key) {
+ return (String) map.get(key);
+ }
+
+ public void setMapproperty(String key, String value) {
+ map.put(key, value);
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/MethodUtilsTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/MethodUtilsTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/MethodUtilsTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,560 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.beanutils.priv.PrivateBeanFactory;
+import org.apache.commons.beanutils.priv.PublicSubBean;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * <p> Test case for <code>MethodUtils</code> </p>
+ *
+ */
+public class MethodUtilsTestCase extends TestCase {
+
+ // ---------------------------------------------------- Instance Variables
+
+ protected PrivateBeanFactory privateBeanFactory;
+
+ // ---------------------------------------------------------- Constructors
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public MethodUtilsTestCase(String name) {
+ super(name);
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+ privateBeanFactory = new PrivateBeanFactory();
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(MethodUtilsTestCase.class));
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ privateBeanFactory = null;
+ }
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+ /**
+ * <p> Test <code>getAccessibleMethod</code>.
+ */
+ public void testGetAccessibleMethod() {
+ // test MethodUtils.getAccessibleMethod
+ // we'll make things easier by using the convenience methods
+
+ // easy bit first - find a public method
+ // METHOD ONE
+ Method method = MethodUtils.getAccessibleMethod
+ (TestBean.class, "setStringProperty", String.class);
+
+ // check that we've found one that matches
+ assertNotNull(method);
+ assertEquals("method ONE is named correctly",
+ "setStringProperty", method.getName());
+ assertTrue("Method ONE is public",
+ Modifier.isPublic(method.getModifiers()));
+
+ // trickier this one - find a method in a direct interface
+ // METHOD TWO
+ method = MethodUtils.getAccessibleMethod
+ (privateBeanFactory.create().getClass(),
+ "methodBar",
+ String.class);
+
+ // check that we've found one that matches
+ assertNotNull(method);
+ assertEquals("Method TWO is named correctly",
+ "methodBar", method.getName());
+ assertTrue("Method TWO is public",
+ Modifier.isPublic(method.getModifiers()));
+
+ // trickier this one - find a method in a indirect interface
+ // METHOD THREE
+ method = MethodUtils.getAccessibleMethod
+ (privateBeanFactory.createSubclass().getClass(),
+ "methodBaz",
+ String.class);
+
+ // check that we've found one that matches
+ assertNotNull(method);
+ assertEquals("Method THREE is named correctly",
+ "methodBaz", method.getName());
+ assertTrue("Method THREE is public",
+ Modifier.isPublic(method.getModifiers()));
+
+ }
+
+
+ /**
+ * <p> Test <code>invokeExactMethod</code>.
+ */
+ public void testInvokeExactMethod() {
+ // test MethodUtils.invokeExactMethod
+ // easy bit first - invoke a public method
+ // METHOD ONE
+ try {
+
+ TestBean bean = new TestBean();
+ Object ret = MethodUtils.invokeExactMethod(bean, "setStringProperty", "TEST");
+ // check that the return's right and that the properties been set
+ assertNull(ret);
+ assertEquals("Method ONE was invoked", "TEST", bean.getStringProperty());
+
+ } catch (Throwable t) {
+ // ONE
+ fail("Exception in method ONE prevented invokation: " + t.toString());
+ }
+
+ // trickier this one - find a method in a direct interface
+ // METHOD TWO FAILURE
+ try {
+
+ Object ret = MethodUtils.invokeExactMethod(
+ privateBeanFactory.create(),
+ "methodBar",
+ "ANOTHER TEST");
+
+ // check that we've found one that matches
+ assertEquals("Method TWO was invoked correctly", "ANOTHER TEST", ret);
+
+ } catch (Throwable t) {
+ // METHOD TWO FAILURE
+ fail("Exception in method TWO prevented invokation: " + t.toString());
+ }
+
+
+ // trickier this one - find a method in a indirect interface
+ // METHOD THREE
+ try {
+
+ Object ret = MethodUtils.invokeExactMethod(
+ privateBeanFactory.createSubclass(),
+ "methodBaz",
+ "YET ANOTHER TEST");
+
+
+ // check that we've found one that matches
+ assertEquals("Method TWO was invoked correctly", "YET ANOTHER TEST", ret);
+
+
+ } catch (Throwable t) {
+ // METHOD THREE FAILURE
+ fail("Exception in method THREE prevented invokation: " + t.toString());
+
+ }
+ }
+
+ /**
+ * <p> Test <code>invokeMethod</code>.
+ */
+ public void testInvokeMethod() throws Exception {
+ // i'm going to test that the actual calls work first and then try them via reflection
+
+ AbstractParent parent = new AlphaBean("parent");
+
+ // try testAddChild through abstract superclass
+ BetaBean childOne = new BetaBean("ChildOne");
+
+ assertEquals("Oh no! Badly coded test case! (1)", "ChildOne", parent.testAddChild(childOne));
+
+ // let's try MethodUtils version
+ assertEquals(
+ "Cannot invoke through abstract class (1)",
+ "ChildOne",
+ MethodUtils.invokeMethod(parent, "testAddChild", childOne));
+
+
+ // try adding through interface
+ AlphaBean childTwo = new AlphaBean("ChildTwo");
+
+ assertEquals("Oh no! Badly coded test case! (2)", "ChildTwo", parent.testAddChild(childTwo));
+
+ // let's try MethodUtils version
+ assertEquals(
+ "Cannot invoke through interface (1)",
+ "ChildTwo",
+ MethodUtils.invokeMethod(parent, "testAddChild", childTwo));
+
+
+ Object[] params = new Object[2];
+
+ assertEquals("Oh no! Badly coded test case! (3)", "ChildOne", parent.testAddChild2("parameter", childOne));
+
+
+ // let's try MethodUtils version
+ params[0] = "parameter";
+ params[1] = childOne;
+
+ assertEquals(
+ "Cannot invoke through abstract class (1)",
+ "ChildOne",
+ MethodUtils.invokeMethod(parent, "testAddChild2", params));
+
+ assertEquals("Oh no! Badly coded test case! (4)", "ChildTwo", parent.testAddChild2("parameter", childTwo));
+
+ // let's try MethodUtils version
+ params[0] = "parameter";
+ params[1] = childTwo;
+
+ assertEquals(
+ "Cannot invoke through abstract class (1)",
+ "ChildTwo",
+ MethodUtils.invokeMethod(parent, "testAddChild2", params));
+
+ // test that exception is correctly thrown when a method cannot be found with matching params
+ try {
+ // the next line
+ parent = new AlphaBean("parent");
+ childOne = new BetaBean("ChildOne");
+ MethodUtils.invokeMethod(parent, "bogus", childOne);
+ // should get here!
+ fail("No exception thrown when no appropriate method exists");
+
+ } catch (NoSuchMethodException e) {
+ // this is what we're expecting!
+ }
+
+ MethodUtils.invokeMethod(parent, "getName", null);
+ MethodUtils.invokeMethod(parent, "getName", null, null);
+ MethodUtils.invokeExactMethod(parent, "getName", null);
+ MethodUtils.invokeExactMethod(parent, "getName", null, null);
+ }
+
+
+ /**
+ * <p> Test <code>invokeMethod</code> with a primitive.
+ */
+ public void testInvokeMethodWithPrimitives() throws Exception {
+ // first test that the bean works
+ PrimitiveBean bean = new PrimitiveBean();
+ bean.setFloat(20.0f);
+ bean.setLong(10l);
+ bean.setBoolean(true);
+ bean.setInt(12);
+ bean.setDouble(25.5d);
+
+ assertEquals("Bug in PrimitiveBean (1)", 20.0f, bean.getFloat(), 0.01f);
+ assertEquals("Bug in PrimitiveBean (2)", 10, bean.getLong());
+ assertEquals("Bug in PrimitiveBean (3)", true, bean.getBoolean());
+ assertEquals("Bug in PrimitiveBean (4)", 12, bean.getInt());
+ assertEquals("Bug in PrimitiveBean (5)", 25.5d, bean.getDouble(), 0.01f);
+
+ bean = new PrimitiveBean();
+ MethodUtils.invokeMethod(bean, "setBoolean", new Boolean(true));
+ assertEquals("Call boolean property using invokeMethod", true, bean.getBoolean());
+
+ bean = new PrimitiveBean();
+ MethodUtils.invokeMethod(bean, "setFloat", new Float(20.0f));
+ assertEquals("Call float property using invokeMethod", 20.0f, bean.getFloat(), 0.01f);
+
+ bean = new PrimitiveBean();
+ MethodUtils.invokeMethod(bean, "setLong", new Long(10));
+ assertEquals("Call float property using invokeMethod", 10, bean.getLong());
+
+ bean = new PrimitiveBean();
+ MethodUtils.invokeMethod(bean, "setInt", new Integer(12));
+ assertEquals("Set float property using invokeMethod", 12, bean.getInt());
+
+ bean = new PrimitiveBean();
+ MethodUtils.invokeMethod(bean, "setDouble", new Double(25.5d));
+ assertEquals("Set float property using invokeMethod", 25.5d, bean.getDouble(), 0.01d);
+ }
+
+
+ /**
+ * Simple tests for accessing static methods via invokeMethod().
+ */
+ public void testSimpleStatic1() {
+
+ TestBean bean = new TestBean();
+ Object value = null;
+ int current = TestBean.currentCounter();
+
+ try {
+
+ // Return initial value of the counter
+ value = MethodUtils.invokeMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via no-arguments version
+ MethodUtils.invokeMethod
+ (bean, "incrementCounter", new Object[0], new Class[0]);
+
+ // Validate updated value
+ current++;
+ value = MethodUtils.invokeMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via specified-argument version
+ MethodUtils.invokeMethod
+ (bean, "incrementCounter",
+ new Object[] { new Integer(5) },
+ new Class[] { Integer.TYPE });
+
+ // Validate updated value
+ current += 5;
+ value = MethodUtils.invokeMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ } catch (Exception e) {
+ fail("Threw exception" + e);
+ }
+
+ }
+
+
+ /**
+ * Simple tests for accessing static methods via invokeExactMethod().
+ */
+ public void testSimpleStatic2() {
+
+ TestBean bean = new TestBean();
+ Object value = null;
+ int current = TestBean.currentCounter();
+
+ try {
+
+ // Return initial value of the counter
+ value = MethodUtils.invokeExactMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via no-arguments version
+ MethodUtils.invokeExactMethod
+ (bean, "incrementCounter", new Object[0], new Class[0]);
+
+ // Validate updated value
+ current++;
+ value = MethodUtils.invokeExactMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via specified-argument version
+ MethodUtils.invokeExactMethod
+ (bean, "incrementCounter",
+ new Object[] { new Integer(5) },
+ new Class[] { Integer.TYPE });
+
+ // Validate updated value
+ current += 5;
+ value = MethodUtils.invokeExactMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+
+ } catch (Exception e) {
+ fail("Threw exception" + e);
+ }
+
+ }
+
+
+ /**
+ * Simple tests for accessing static methods via getAccessibleMethod()
+ */
+ public void testSimpleStatic3() {
+
+ Object value = null;
+ int current = TestBean.currentCounter();
+
+ try {
+
+ // Acquire the methods we need
+ Method currentCounterMethod = MethodUtils.getAccessibleMethod
+ (TestBean.class, "currentCounter",
+ new Class[0]);
+ assertNotNull("currentCounterMethod exists",
+ currentCounterMethod);
+ assertEquals("currentCounterMethod name",
+ "currentCounter",
+ currentCounterMethod.getName());
+ assertEquals("currentCounterMethod args",
+ 0,
+ currentCounterMethod.getParameterTypes().length);
+ assertTrue("currentCounterMethod public",
+ Modifier.isPublic(currentCounterMethod.getModifiers()));
+ assertTrue("currentCounterMethod static",
+ Modifier.isStatic(currentCounterMethod.getModifiers()));
+ Method incrementCounterMethod1 = MethodUtils.getAccessibleMethod
+ (TestBean.class, "incrementCounter",
+ new Class[0]);
+ assertNotNull("incrementCounterMethod1 exists",
+ incrementCounterMethod1);
+ assertEquals("incrementCounterMethod1 name",
+ "incrementCounter",
+ incrementCounterMethod1.getName());
+ assertEquals("incrementCounterMethod1 args",
+ 0,
+ incrementCounterMethod1.getParameterTypes().length);
+ assertTrue("incrementCounterMethod1 public",
+ Modifier.isPublic(incrementCounterMethod1.getModifiers()));
+ assertTrue("incrementCounterMethod1 static",
+ Modifier.isStatic(incrementCounterMethod1.getModifiers()));
+ Method incrementCounterMethod2 = MethodUtils.getAccessibleMethod
+ (TestBean.class, "incrementCounter",
+ new Class[] { Integer.TYPE });
+ assertNotNull("incrementCounterMethod2 exists",
+ incrementCounterMethod2);
+ assertEquals("incrementCounterMethod2 name",
+ "incrementCounter",
+ incrementCounterMethod2.getName());
+ assertEquals("incrementCounterMethod2 args",
+ 1,
+ incrementCounterMethod2.getParameterTypes().length);
+ assertTrue("incrementCounterMethod2 public",
+ Modifier.isPublic(incrementCounterMethod2.getModifiers()));
+ assertTrue("incrementCounterMethod2 static",
+ Modifier.isStatic(incrementCounterMethod2.getModifiers()));
+
+ // Return initial value of the counter
+ value = currentCounterMethod.invoke(null, new Object[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via no-arguments version
+ incrementCounterMethod1.invoke(null, new Object[0]);
+
+ // Validate updated value
+ current++;
+ value = currentCounterMethod.invoke(null, new Object[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via specified-argument version
+ incrementCounterMethod2.invoke(null,
+ new Object[] { new Integer(5) });
+
+ // Validate updated value
+ current += 5;
+ value = currentCounterMethod.invoke(null, new Object[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ } catch (Exception e) {
+ fail("Threw exception" + e);
+ }
+
+ }
+
+ public void testPublicSub() throws Exception {
+ // make sure that bean does what it should
+ PublicSubBean bean = new PublicSubBean();
+ assertEquals("Start value (foo)", bean.getFoo(), "This is foo");
+ assertEquals("Start value (bar)", bean.getBar(), "This is bar");
+ bean.setFoo("new foo");
+ bean.setBar("new bar");
+ assertEquals("Set value (foo)", bean.getFoo(), "new foo");
+ assertEquals("Set value (bar)", bean.getBar(), "new bar");
+
+ // see if we can access public methods in a default access superclass
+ // from a public access subclass instance
+ MethodUtils.invokeMethod(bean, "setFoo", "alpha");
+ assertEquals("Set value (foo:2)", bean.getFoo(), "alpha");
+ MethodUtils.invokeMethod(bean, "setBar", "beta");
+ assertEquals("Set value (bar:2)", bean.getFoo(), "alpha");
+ }
+
+ public void testParentMethod() throws Exception {
+ OutputStream os = new PrintStream(System.out);
+ PrintStream ps = new PrintStream(System.out);
+
+ A a = new A();
+ MethodUtils.invokeMethod(a, "foo", os);
+ assertTrue("Method Invoked(1)", a.called);
+
+ a = new A();
+ MethodUtils.invokeMethod(a, "foo", ps);
+ assertTrue("Method Invoked(2)", a.called);
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/NestedTestBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/NestedTestBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/NestedTestBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Specialist test bean for complex nested properties.
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class NestedTestBean {
+
+
+ // ------------------------------------------------------------- Constructors
+ public NestedTestBean(String name) {
+ setName(name);
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+ private String testString = "NOT SET";
+
+ public String getTestString() {
+ return testString;
+ }
+
+ public void setTestString(String testString) {
+ this.testString = testString;
+ }
+
+
+ private boolean testBoolean = false;
+
+ public boolean getTestBoolean() {
+ return testBoolean;
+ }
+
+ public void setTestBoolean(boolean testBoolean) {
+ this.testBoolean = testBoolean;
+ }
+
+
+ private NestedTestBean indexedBeans[];
+
+ public void init() {
+ indexedBeans = new NestedTestBean[5];
+ indexedBeans[0] = new NestedTestBean("Bean at 0");
+ indexedBeans[1] = new NestedTestBean("Bean at 1");
+ indexedBeans[2] = new NestedTestBean("Bean at 2");
+ indexedBeans[3] = new NestedTestBean("Bean at 3");
+ indexedBeans[4] = new NestedTestBean("Bean at 4");
+
+ simpleBean = new NestedTestBean("Simple Property Bean");
+ };
+
+ public NestedTestBean getIndexedProperty(int index) {
+ return (this.indexedBeans[index]);
+ }
+
+ public void setIndexedProperty(int index, NestedTestBean value) {
+ this.indexedBeans[index] = value;
+ }
+
+ private NestedTestBean simpleBean;
+
+ public NestedTestBean getSimpleBeanProperty() {
+ return simpleBean;
+ }
+
+ // ------------------------------------------------------- Static Variables
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PassTestException.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PassTestException.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PassTestException.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+
+/**
+ * Just a runtime exception. Useful for check that a method is called.
+ *
+ * @author Robert Burrell Donkin
+ */
+
+public class PassTestException extends RuntimeException {
+}
\ No newline at end of file
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PrimitiveBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PrimitiveBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PrimitiveBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+/**
+ * Bean that has primitive properties
+ */
+public class PrimitiveBean {
+
+ private float _float;
+ private double _double;
+ private boolean _boolean;
+ private long _long;
+ private int _int;
+
+ public float getFloat() {
+ return _float;
+ }
+
+ public void setFloat(float _float) {
+ this._float = _float;
+ }
+
+ public double getDouble() {
+ return _double;
+ }
+
+ public void setDouble(double _double) {
+ this._double = _double;
+ }
+
+ public boolean getBoolean() {
+ return _boolean;
+ }
+
+ public void setBoolean(boolean _boolean) {
+ this._boolean = _boolean;
+ }
+
+ public long getLong() {
+ return _long;
+ }
+
+ public void setLong(long _long) {
+ this._long = _long;
+ }
+
+ public int getInt() {
+ return _int;
+ }
+
+ public void setInt(int _int) {
+ this._int = _int;
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PropertyUtilsBenchCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PropertyUtilsBenchCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PropertyUtilsBenchCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * JUnit Test Case containing microbenchmarks for PropertyUtils.
+ */
+
+public class PropertyUtilsBenchCase extends TestCase {
+
+
+ // ------------------------------------------------------------ Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public PropertyUtilsBenchCase(String name) {
+
+ super(name);
+
+ }
+
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ // Basic loop counter
+ private long counter = 100000;
+
+ // DynaClass for inDyna and outDyna
+ private DynaClass dynaClass = null;
+
+ // Input objects that have identical sets of properties and values.
+ private BenchBean inBean = null;
+ private DynaBean inDyna = null;
+ private Map inMap = null;
+
+ // Output objects that have identical sets of properties.
+ private BenchBean outBean = null;
+ private DynaBean outDyna = null;
+
+ // PropertyUtilsBean instance to be used
+ private PropertyUtilsBean pu = null;
+
+
+ // ---------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+
+ // Set up loop counter (if property specified)
+ String prop = System.getProperty("counter");
+ if (prop != null) {
+ counter = Long.parseLong(prop);
+ }
+
+ // Set up DynaClass for our DynaBean instances
+ dynaClass = new BasicDynaClass
+ ("BenchDynaClass", null,
+ new DynaProperty[]{
+ new DynaProperty("booleanProperty", Boolean.TYPE),
+ new DynaProperty("byteProperty", Byte.TYPE),
+ new DynaProperty("doubleProperty", Double.TYPE),
+ new DynaProperty("floatProperty", Float.TYPE),
+ new DynaProperty("intProperty", Integer.TYPE),
+ new DynaProperty("longProperty", Long.TYPE),
+ new DynaProperty("shortProperty", Short.TYPE),
+ new DynaProperty("stringProperty", String.class),
+ });
+
+ // Create input instances
+ inBean = new BenchBean();
+ inMap = new HashMap();
+ inMap.put("booleanProperty", new Boolean(inBean.getBooleanProperty()));
+ inMap.put("byteProperty", new Byte(inBean.getByteProperty()));
+ inMap.put("doubleProperty", new Double(inBean.getDoubleProperty()));
+ inMap.put("floatProperty", new Float(inBean.getFloatProperty()));
+ inMap.put("intProperty", new Integer(inBean.getIntProperty()));
+ inMap.put("longProperty", new Long(inBean.getLongProperty()));
+ inMap.put("shortProperty", new Short(inBean.getShortProperty()));
+ inMap.put("stringProperty", inBean.getStringProperty());
+ inDyna = dynaClass.newInstance();
+ Iterator inKeys = inMap.keySet().iterator();
+ while (inKeys.hasNext()) {
+ String inKey = (String) inKeys.next();
+ inDyna.set(inKey, inMap.get(inKey));
+ }
+
+ // Create output instances
+ outBean = new BenchBean();
+ outDyna = dynaClass.newInstance();
+ Iterator outKeys = inMap.keySet().iterator();
+ while (outKeys.hasNext()) {
+ String outKey = (String) outKeys.next();
+ outDyna.set(outKey, inMap.get(outKey));
+ }
+
+ // Set up PropertyUtilsBean instance we will use
+ pu = PropertyUtilsBean.getInstance();
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+
+ return (new TestSuite(PropertyUtilsBenchCase.class));
+
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+
+ dynaClass = null;
+ inBean = null;
+ inDyna = null;
+ inMap = null;
+ outBean = null;
+ outDyna = null;
+ pu = null;
+
+ }
+
+
+
+ // ------------------------------------------------- Individual Test Methods
+
+
+ // Time copyProperties() from a bean
+ public void testCopyPropertiesBean() throws Exception {
+
+ long start;
+ long stop;
+
+ // Bean->Bean
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outBean, inBean);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outBean, inBean);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("PU.copyProperties(bean,bean), count=" + counter +
+ ", time=" + (stop - start));
+
+ // Bean->Dyna
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outDyna, inBean);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outDyna, inBean);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("PU.copyProperties(dyna,bean), count=" + counter +
+ ", time=" + (stop - start));
+
+ }
+
+
+ // Time copyProperties() from a DynaBean
+ public void testCopyPropertiesDyna() throws Exception {
+
+ long start;
+ long stop;
+
+ // Dyna->Bean
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outBean, inDyna);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outBean, inDyna);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("PU.copyProperties(bean,dyna), count=" + counter +
+ ", time=" + (stop - start));
+
+ // Dyna->Dyna
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outDyna, inDyna);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outDyna, inDyna);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("PU.copyProperties(dyna,dyna), count=" + counter +
+ ", time=" + (stop - start));
+
+ }
+
+
+ // Time copyProperties() from a Map
+ public void testCopyPropertiesMap() throws Exception {
+
+ long start;
+ long stop;
+
+ // Dyna->Bean
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outBean, inMap);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outBean, inMap);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("PU.copyProperties(bean, map), count=" + counter +
+ ", time=" + (stop - start));
+
+ // Dyna->Dyna
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outDyna, inMap);
+ }
+ start = System.currentTimeMillis();
+ for (long i = 0; i < counter; i++) {
+ pu.copyProperties(outDyna, inMap);
+ }
+ stop = System.currentTimeMillis();
+ System.err.println("PU.copyProperties(dyna, map), count=" + counter +
+ ", time=" + (stop - start));
+
+ }
+
+
+ // --------------------------------------------------------- Support Methods
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PropertyUtilsTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PropertyUtilsTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PropertyUtilsTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,3665 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.beanutils.priv.PrivateBeanFactory;
+import org.apache.commons.beanutils.priv.PrivateDirect;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * <p>Test Case for the PropertyUtils class. The majority of these tests use
+ * instances of the TestBean class, so be sure to update the tests if you
+ * change the characteristics of that class.</p>
+ *
+ * <p>So far, this test case has tests for the following methods of the
+ * <code>PropertyUtils</code> class:</p>
+ * <ul>
+ * <li>getIndexedProperty(Object,String)</li>
+ * <li>getIndexedProperty(Object,String,int)</li>
+ * <li>getMappedProperty(Object,String)</li>
+ * <li>getMappedProperty(Object,String,String</li>
+ * <li>getNestedProperty(Object,String)</li>
+ * <li>getPropertyDescriptor(Object,String)</li>
+ * <li>getPropertyDescriptors(Object)</li>
+ * <li>getPropertyType(Object,String)</li>
+ * <li>getSimpleProperty(Object,String)</li>
+ * <li>setIndexedProperty(Object,String,Object)</li>
+ * <li>setIndexedProperty(Object,String,String,Object)</li>
+ * <li>setMappedProperty(Object,String,Object)</li>
+ * <li>setMappedProperty(Object,String,String,Object)</li>
+ * <li>setNestedProperty(Object,String,Object)</li>
+ * <li>setSimpleProperty(Object,String,Object)</li>
+ * </ul>
+ *
+ * @author Craig R. McClanahan
+ * @author Jan Sorensen
+ * @version $Revision: 1.34 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class PropertyUtilsTestCase extends TestCase {
+
+
+ // ---------------------------------------------------- Instance Variables
+
+
+ /**
+ * The fully qualified class name of our private directly
+ * implemented interface.
+ */
+ private static final String PRIVATE_DIRECT_CLASS =
+ "org.apache.commons.beanutils.priv.PrivateDirect";
+
+
+ /**
+ * The fully qualified class name of our private indirectly
+ * implemented interface.
+ */
+ private static final String PRIVATE_INDIRECT_CLASS =
+ "org.apache.commons.beanutils.priv.PrivateIndirect";
+
+
+ /**
+ * The fully qualified class name of our test bean class.
+ */
+ private static final String TEST_BEAN_CLASS =
+ "org.apache.commons.beanutils.TestBean";
+
+
+ /**
+ * The basic test bean for each test.
+ */
+ protected TestBean bean = null;
+
+
+ /**
+ * The "package private subclass" test bean for each test.
+ */
+ protected TestBeanPackageSubclass beanPackageSubclass = null;
+
+
+ /**
+ * The test bean for private access tests.
+ */
+ protected PrivateDirect beanPrivate = null;
+
+
+ /**
+ * The test bean for private access tests of subclasses.
+ */
+ protected PrivateDirect beanPrivateSubclass = null;
+
+
+ /**
+ * The "public subclass" test bean for each test.
+ */
+ protected TestBeanPublicSubclass beanPublicSubclass = null;
+
+
+ /**
+ * The set of properties that should be described.
+ */
+ protected String describes[] =
+ { "booleanProperty",
+ "booleanSecond",
+ "doubleProperty",
+ "floatProperty",
+ "intArray",
+ // "intIndexed",
+ "intProperty",
+ "listIndexed",
+ "longProperty",
+ // "mappedObjects",
+ // "mappedProperty",
+ // "mappedIntProperty",
+ "nested",
+ "nullProperty",
+ // "readOnlyProperty",
+ "shortProperty",
+ "stringArray",
+ // "stringIndexed",
+ "stringProperty"
+ };
+
+
+ /**
+ * The set of property names we expect to have returned when calling
+ * <code>getPropertyDescriptors()</code>. You should update this list
+ * when new properties are added to TestBean.
+ */
+ protected final static String[] properties = {
+ "booleanProperty",
+ "booleanSecond",
+ "doubleProperty",
+ "dupProperty",
+ "floatProperty",
+ "intArray",
+ "intIndexed",
+ "intProperty",
+ "listIndexed",
+ "longProperty",
+ "nested",
+ "nullProperty",
+ "readOnlyProperty",
+ "shortProperty",
+ "stringArray",
+ "stringIndexed",
+ "stringProperty",
+ "writeOnlyProperty",
+ };
+
+
+ // ---------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public PropertyUtilsTestCase(String name) {
+
+ super(name);
+
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+
+ bean = new TestBean();
+ beanPackageSubclass = new TestBeanPackageSubclass();
+ beanPrivate = PrivateBeanFactory.create();
+ beanPrivateSubclass = PrivateBeanFactory.createSubclass();
+ beanPublicSubclass = new TestBeanPublicSubclass();
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+
+ return (new TestSuite(PropertyUtilsTestCase.class));
+
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+
+ bean = null;
+ beanPackageSubclass = null;
+ beanPrivate = null;
+ beanPrivateSubclass = null;
+ beanPublicSubclass = null;
+
+ }
+
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ /**
+ * Test copyProperties() when the origin is a a <code>Map</code>.
+ */
+ public void testCopyPropertiesMap() {
+
+ Map map = new HashMap();
+ map.put("booleanProperty", Boolean.FALSE);
+ map.put("doubleProperty", new Double(333.0));
+ map.put("dupProperty", new String[] { "New 0", "New 1", "New 2" });
+ map.put("floatProperty", new Float((float) 222.0));
+ map.put("intArray", new int[] { 0, 100, 200 });
+ map.put("intProperty", new Integer(111));
+ map.put("longProperty", new Long(444));
+ map.put("shortProperty", new Short((short) 555));
+ map.put("stringProperty", "New String Property");
+
+ try {
+ PropertyUtils.copyProperties(bean, map);
+ } catch (Throwable t) {
+ fail("Threw " + t.toString());
+ }
+
+ // Scalar properties
+ assertEquals("booleanProperty", false,
+ bean.getBooleanProperty());
+ assertEquals("doubleProperty", 333.0,
+ bean.getDoubleProperty(), 0.005);
+ assertEquals("floatProperty", (float) 222.0,
+ bean.getFloatProperty(), (float) 0.005);
+ assertEquals("intProperty", 111,
+ bean.getIntProperty());
+ assertEquals("longProperty", (long) 444,
+ bean.getLongProperty());
+ assertEquals("shortProperty", (short) 555,
+ bean.getShortProperty());
+ assertEquals("stringProperty", "New String Property",
+ bean.getStringProperty());
+
+ // Indexed Properties
+ String dupProperty[] = bean.getDupProperty();
+ assertNotNull("dupProperty present", dupProperty);
+ assertEquals("dupProperty length", 3, dupProperty.length);
+ assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
+ assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
+ assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
+ int intArray[] = bean.getIntArray();
+ assertNotNull("intArray present", intArray);
+ assertEquals("intArray length", 3, intArray.length);
+ assertEquals("intArray[0]", 0, intArray[0]);
+ assertEquals("intArray[1]", 100, intArray[1]);
+ assertEquals("intArray[2]", 200, intArray[2]);
+
+ }
+
+
+ /**
+ * Test the describe() method.
+ */
+ public void testDescribe() {
+
+ Map map = null;
+ try {
+ map = PropertyUtils.describe(bean);
+ } catch (Exception e) {
+ fail("Threw exception " + e);
+ }
+
+ // Verify existence of all the properties that should be present
+ for (int i = 0; i < describes.length; i++) {
+ assertTrue("Property '" + describes[i] + "' is present",
+ map.containsKey(describes[i]));
+ }
+ assertTrue("Property 'writeOnlyProperty' is not present",
+ !map.containsKey("writeOnlyProperty"));
+
+ // Verify the values of scalar properties
+ assertEquals("Value of 'booleanProperty'",
+ Boolean.TRUE,
+ (Boolean) map.get("booleanProperty"));
+ assertEquals("Value of 'doubleProperty'",
+ new Double(321.0),
+ (Double) map.get("doubleProperty"));
+ assertEquals("Value of 'floatProperty'",
+ new Float((float) 123.0),
+ (Float) map.get("floatProperty"));
+ assertEquals("Value of 'intProperty'",
+ new Integer(123),
+ (Integer) map.get("intProperty"));
+ assertEquals("Value of 'longProperty'",
+ new Long(321),
+ (Long) map.get("longProperty"));
+ assertEquals("Value of 'shortProperty'",
+ new Short((short) 987),
+ (Short) map.get("shortProperty"));
+ assertEquals("Value of 'stringProperty'",
+ "This is a string",
+ (String) map.get("stringProperty"));
+
+ }
+
+
+ /**
+ * Corner cases on getPropertyDescriptor invalid arguments.
+ */
+ public void testGetDescriptorArguments() {
+
+ try {
+ PropertyUtils.getPropertyDescriptor(null, "stringProperty");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getPropertyDescriptor(bean, null);
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ }
+
+
+ /**
+ * Positive getPropertyDescriptor on property <code>booleanProperty</code>.
+ */
+ public void testGetDescriptorBoolean() {
+
+ testGetDescriptorBase("booleanProperty", "getBooleanProperty",
+ "setBooleanProperty");
+
+ }
+
+
+ /**
+ * Positive getPropertyDescriptor on property <code>doubleProperty</code>.
+ */
+ public void testGetDescriptorDouble() {
+
+ testGetDescriptorBase("doubleProperty", "getDoubleProperty",
+ "setDoubleProperty");
+
+ }
+
+
+ /**
+ * Positive getPropertyDescriptor on property <code>floatProperty</code>.
+ */
+ public void testGetDescriptorFloat() {
+
+ testGetDescriptorBase("floatProperty", "getFloatProperty",
+ "setFloatProperty");
+
+ }
+
+
+ /**
+ * Positive getPropertyDescriptor on property <code>intProperty</code>.
+ */
+ public void testGetDescriptorInt() {
+
+ testGetDescriptorBase("intProperty", "getIntProperty",
+ "setIntProperty");
+
+ }
+
+
+ /**
+ * <p>Negative tests on an invalid property with two different boolean
+ * getters (which is fine, according to the JavaBeans spec) but a
+ * String setter instead of a boolean setter.</p>
+ *
+ * <p>Although one could logically argue that this combination of method
+ * signatures should not identify a property at all, there is a sentence
+ * in Section 8.3.1 making it clear that the behavior tested for here
+ * is correct: "If we find only one of these methods, then we regard
+ * it as defining either a read-only or write-only property called
+ * <em><property-name></em>.</p>
+ */
+ public void testGetDescriptorInvalidBoolean() throws Exception {
+
+ PropertyDescriptor pd =
+ PropertyUtils.getPropertyDescriptor(bean, "invalidBoolean");
+ assertNotNull("invalidBoolean is a property", pd);
+ assertNotNull("invalidBoolean has a getter method",
+ pd.getReadMethod());
+ assertNull("invalidBoolean has no write method",
+ pd.getWriteMethod());
+ assertTrue("invalidBoolean getter method is isInvalidBoolean",
+ "isInvalidBoolean".equals(pd.getReadMethod().getName()));
+
+ }
+
+
+ /**
+ * Positive getPropertyDescriptor on property <code>longProperty</code>.
+ */
+ public void testGetDescriptorLong() {
+
+ testGetDescriptorBase("longProperty", "getLongProperty",
+ "setLongProperty");
+
+ }
+
+
+ /**
+ * Positive getPropertyDescriptor on property
+ * <code>readOnlyProperty</code>.
+ */
+ public void testGetDescriptorReadOnly() {
+
+ testGetDescriptorBase("readOnlyProperty", "getReadOnlyProperty",
+ null);
+
+ }
+
+
+ /**
+ * Positive getPropertyDescriptor on property <code>booleanSecond</code>
+ * that uses an "is" method as the getter.
+ */
+ public void testGetDescriptorSecond() {
+
+ testGetDescriptorBase("booleanSecond", "isBooleanSecond",
+ "setBooleanSecond");
+
+ }
+
+
+ /**
+ * Positive getPropertyDescriptor on property <code>shortProperty</code>.
+ */
+ public void testGetDescriptorShort() {
+
+ testGetDescriptorBase("shortProperty", "getShortProperty",
+ "setShortProperty");
+
+ }
+
+
+ /**
+ * Positive getPropertyDescriptor on property <code>stringProperty</code>.
+ */
+ public void testGetDescriptorString() {
+
+ testGetDescriptorBase("stringProperty", "getStringProperty",
+ "setStringProperty");
+
+ }
+
+
+ /**
+ * Negative getPropertyDescriptor on property <code>unknown</code>.
+ */
+ public void testGetDescriptorUnknown() {
+
+ testGetDescriptorBase("unknown", null, null);
+
+ }
+
+
+ /**
+ * Positive getPropertyDescriptor on property
+ * <code>writeOnlyProperty</code>.
+ */
+ public void testGetDescriptorWriteOnly() {
+
+ testGetDescriptorBase("writeOnlyProperty", null,
+ "setWriteOnlyProperty");
+
+ }
+
+
+ /**
+ * Positive test for getPropertyDescriptors(). Each property name
+ * listed in <code>properties</code> should be returned exactly once.
+ */
+ public void testGetDescriptors() {
+
+ PropertyDescriptor pd[] =
+ PropertyUtils.getPropertyDescriptors(bean);
+ assertNotNull("Got descriptors", pd);
+ int count[] = new int[properties.length];
+ for (int i = 0; i < pd.length; i++) {
+ String name = pd[i].getName();
+ for (int j = 0; j < properties.length; j++) {
+ if (name.equals(properties[j]))
+ count[j]++;
+ }
+ }
+ for (int j = 0; j < properties.length; j++) {
+ if (count[j] < 0)
+ fail("Missing property " + properties[j]);
+ else if (count[j] > 1)
+ fail("Duplicate property " + properties[j]);
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getPropertyDescriptors invalid arguments.
+ */
+ public void testGetDescriptorsArguments() {
+
+ try {
+ PropertyUtils.getPropertyDescriptors(null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException");
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getIndexedProperty invalid arguments.
+ */
+ public void testGetIndexedArguments() {
+
+ // Use explicit index argument
+
+ try {
+ PropertyUtils.getIndexedProperty(null, "intArray", 0);
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, null, 0);
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ // Use index expression
+
+ try {
+ PropertyUtils.getIndexedProperty(null,
+ "intArray[0]");
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, "[0]");
+ fail("Should throw NoSuchMethodException 4");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 4");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, "intArray");
+ fail("Should throw IllegalArgumentException 5");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 5");
+ }
+
+ // Use explicit index argument
+
+ try {
+ PropertyUtils.getIndexedProperty(null, "intIndexed", 0);
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, null, 0);
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ // Use index expression
+
+ try {
+ PropertyUtils.getIndexedProperty(null,
+ "intIndexed[0]");
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, "[0]");
+ fail("Should throw NoSuchMethodException 4");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 4");
+ }
+
+ try {
+ PropertyUtils.getIndexedProperty(bean, "intIndexed");
+ fail("Should throw IllegalArgumentException 5");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 5");
+ }
+
+ }
+
+
+ /**
+ * Positive and negative tests on getIndexedProperty valid arguments.
+ */
+ public void testGetIndexedValues() {
+
+ Object value = null;
+
+ // Use explicit key argument
+
+ for (int i = 0; i < 5; i++) {
+
+ try {
+ value = PropertyUtils.getIndexedProperty
+ (bean, "dupProperty", i);
+ assertNotNull("dupProperty returned value " + i, value);
+ assertTrue("dupProperty returned String " + i,
+ value instanceof String);
+ assertEquals("dupProperty returned correct " + i,
+ "Dup " + i,
+ (String) value);
+ } catch (Throwable t) {
+ fail("dupProperty " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean, "intArray", i);
+ assertNotNull("intArray returned value " + i, value);
+ assertTrue("intArray returned Integer " + i,
+ value instanceof Integer);
+ assertEquals("intArray returned correct " + i, i * 10,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("intArray " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean, "intIndexed", i);
+ assertNotNull("intIndexed returned value " + i, value);
+ assertTrue("intIndexed returned Integer " + i,
+ value instanceof Integer);
+ assertEquals("intIndexed returned correct " + i, i * 10,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("intIndexed " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean, "listIndexed", i);
+ assertNotNull("listIndexed returned value " + i, value);
+ assertTrue("list returned String " + i,
+ value instanceof String);
+ assertEquals("listIndexed returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("listIndexed " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean, "stringArray", i);
+ assertNotNull("stringArray returned value " + i, value);
+ assertTrue("stringArray returned String " + i,
+ value instanceof String);
+ assertEquals("stringArray returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("stringArray " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean, "stringIndexed", i);
+ assertNotNull("stringIndexed returned value " + i, value);
+ assertTrue("stringIndexed returned String " + i,
+ value instanceof String);
+ assertEquals("stringIndexed returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("stringIndexed " + i + " threw " + t);
+ }
+
+ }
+
+ // Use key expression
+
+ for (int i = 0; i < 5; i++) {
+
+ try {
+ value = PropertyUtils.getIndexedProperty
+ (bean, "dupProperty[" + i + "]");
+ assertNotNull("dupProperty returned value " + i, value);
+ assertTrue("dupProperty returned String " + i,
+ value instanceof String);
+ assertEquals("dupProperty returned correct " + i,
+ "Dup " + i,
+ (String) value);
+ } catch (Throwable t) {
+ fail("dupProperty " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intArray[" + i + "]");
+ assertNotNull("intArray returned value " + i, value);
+ assertTrue("intArray returned Integer " + i,
+ value instanceof Integer);
+ assertEquals("intArray returned correct " + i, i * 10,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("intArray " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intIndexed[" + i + "]");
+ assertNotNull("intIndexed returned value " + i, value);
+ assertTrue("intIndexed returned Integer " + i,
+ value instanceof Integer);
+ assertEquals("intIndexed returned correct " + i, i * 10,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("intIndexed " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "listIndexed[" + i + "]");
+ assertNotNull("listIndexed returned value " + i, value);
+ assertTrue("listIndexed returned String " + i,
+ value instanceof String);
+ assertEquals("listIndexed returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("listIndexed " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray[" + i + "]");
+ assertNotNull("stringArray returned value " + i, value);
+ assertTrue("stringArray returned String " + i,
+ value instanceof String);
+ assertEquals("stringArray returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("stringArray " + i + " threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringIndexed[" + i + "]");
+ assertNotNull("stringIndexed returned value " + i, value);
+ assertTrue("stringIndexed returned String " + i,
+ value instanceof String);
+ assertEquals("stringIndexed returned correct " + i,
+ "String " + i, (String) value);
+ } catch (Throwable t) {
+ fail("stringIndexed " + i + " threw " + t);
+ }
+
+ }
+
+ // Index out of bounds tests
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "dupProperty", -1);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "dupProperty", 5);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intArray", -1);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intArray", 5);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intIndexed", -1);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intIndexed", 5);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "listIndexed", -1);
+ fail("Should have thrown IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "listIndexed", 5);
+ fail("Should have thrown IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray", -1);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray", 5);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringIndexed", -1);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringIndexed", 5);
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getMappedProperty invalid arguments.
+ */
+ public void testGetMappedArguments() {
+
+ // Use explicit key argument
+
+ try {
+ PropertyUtils.getMappedProperty(null, "mappedProperty",
+ "First Key");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getMappedProperty(bean, null, "First Key");
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ try {
+ PropertyUtils.getMappedProperty(bean, "mappedProperty", null);
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ // Use key expression
+
+ try {
+ PropertyUtils.getMappedProperty(null,
+ "mappedProperty(First Key)");
+ fail("Should throw IllegalArgumentException 4");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 4");
+ }
+
+ try {
+ PropertyUtils.getMappedProperty(bean, "(Second Key)");
+ fail("Should throw IllegalArgumentException 5");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 5");
+ }
+
+ try {
+ PropertyUtils.getMappedProperty(bean, "mappedProperty");
+ fail("Should throw IllegalArgumentException 6");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 6");
+ }
+
+ }
+
+
+ /**
+ * Test getting mapped values with periods in the key.
+ */
+ public void testGetMappedPeriods() {
+
+ bean.setMappedProperty("key.with.a.dot", "Special Value");
+ assertEquals("Can retrieve directly",
+ "Special Value",
+ bean.getMappedProperty("key.with.a.dot"));
+ try {
+ assertEquals("Can retrieve via getMappedProperty",
+ "Special Value",
+ PropertyUtils.getMappedProperty
+ (bean, "mappedProperty", "key.with.a.dot"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+ try {
+ assertEquals("Can retrieve via getNestedProperty",
+ "Special Value",
+ PropertyUtils.getNestedProperty
+ (bean, "mappedProperty(key.with.a.dot)"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+
+ bean.setMappedObjects("nested.property", new TestBean());
+ assertNotNull("Can retrieve directly",
+ bean.getMappedObjects("nested.property"));
+ try {
+ assertEquals("Can retrieve nested",
+ "This is a string",
+ PropertyUtils.getNestedProperty
+ (bean,
+ "mappedObjects(nested.property).stringProperty"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+
+ try
+ {
+ assertEquals("Can't retrieved nested with mapped property",
+ "Mapped Value",
+ PropertyUtils.getNestedProperty(
+ bean,"mappedNested.value(Mapped Key)"));
+ } catch (Exception e)
+ {
+ fail("Thew exception: " + e);
+ }
+ }
+
+
+ /**
+ * Test getting mapped values with slashes in the key. This is different
+ * from periods because slashes are not syntactically significant.
+ */
+ public void testGetMappedSlashes() {
+
+ bean.setMappedProperty("key/with/a/slash", "Special Value");
+ assertEquals("Can retrieve directly",
+ "Special Value",
+ bean.getMappedProperty("key/with/a/slash"));
+ try {
+ assertEquals("Can retrieve via getMappedProperty",
+ "Special Value",
+ PropertyUtils.getMappedProperty
+ (bean, "mappedProperty", "key/with/a/slash"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+ try {
+ assertEquals("Can retrieve via getNestedProperty",
+ "Special Value",
+ PropertyUtils.getNestedProperty
+ (bean, "mappedProperty(key/with/a/slash)"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+
+ bean.setMappedObjects("nested/property", new TestBean());
+ assertNotNull("Can retrieve directly",
+ bean.getMappedObjects("nested/property"));
+ try {
+ assertEquals("Can retrieve nested",
+ "This is a string",
+ PropertyUtils.getNestedProperty
+ (bean,
+ "mappedObjects(nested/property).stringProperty"));
+ } catch (Exception e) {
+ fail("Thew exception: " + e);
+ }
+
+ }
+
+
+ /**
+ * Positive and negative tests on getMappedProperty valid arguments.
+ */
+ public void testGetMappedValues() {
+
+ Object value = null;
+
+ // Use explicit key argument
+
+ try {
+ value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
+ "First Key");
+ assertEquals("Can find first value", "First Value", value);
+ } catch (Throwable t) {
+ fail("Finding first value threw " + t);
+ }
+
+ try {
+ value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
+ "Second Key");
+ assertEquals("Can find second value", "Second Value", value);
+ } catch (Throwable t) {
+ fail("Finding second value threw " + t);
+ }
+
+ try {
+ value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
+ "Third Key");
+ assertNull("Can not find third value", value);
+ } catch (Throwable t) {
+ fail("Finding third value threw " + t);
+ }
+
+ // Use key expression with parentheses
+
+ try {
+ value =
+ PropertyUtils.getMappedProperty(bean,
+ "mappedProperty(First Key)");
+ assertEquals("Can find first value", "First Value", value);
+ } catch (Throwable t) {
+ fail("Finding first value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getMappedProperty(bean,
+ "mappedProperty(Second Key)");
+ assertEquals("Can find second value", "Second Value", value);
+ } catch (Throwable t) {
+ fail("Finding second value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getMappedProperty(bean,
+ "mappedProperty(Third Key)");
+ assertNull("Can not find third value", value);
+ } catch (Throwable t) {
+ fail("Finding third value threw " + t);
+ }
+
+ // Use key expression with dotted syntax
+
+ try {
+ value =
+ PropertyUtils.getNestedProperty(bean,
+ "mapProperty.First Key");
+ assertEquals("Can find first value", "First Value", value);
+ } catch (Throwable t) {
+ fail("Finding first value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getNestedProperty(bean,
+ "mapProperty.Second Key");
+ assertEquals("Can find second value", "Second Value", value);
+ } catch (Throwable t) {
+ fail("Finding second value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getNestedProperty(bean,
+ "mapProperty.Third Key");
+ assertNull("Can not find third value", value);
+ } catch (Throwable t) {
+ fail("Finding third value threw " + t);
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getNestedProperty invalid arguments.
+ */
+ public void testGetNestedArguments() {
+
+ try {
+ PropertyUtils.getNestedProperty(null, "stringProperty");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getNestedProperty(bean, null);
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a boolean property.
+ */
+ public void testGetNestedBoolean() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.booleanProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Boolean));
+ assertTrue("Got correct value",
+ ((Boolean) value).booleanValue() ==
+ bean.getNested().getBooleanProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a double property.
+ */
+ public void testGetNestedDouble() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.doubleProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Double));
+ assertEquals("Got correct value",
+ ((Double) value).doubleValue(),
+ bean.getNested().getDoubleProperty(),
+ 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a float property.
+ */
+ public void testGetNestedFloat() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.floatProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Float));
+ assertEquals("Got correct value",
+ ((Float) value).floatValue(),
+ bean.getNested().getFloatProperty(),
+ (float) 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on an int property.
+ */
+ public void testGetNestedInt() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.intProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Integer));
+ assertEquals("Got correct value",
+ ((Integer) value).intValue(),
+ bean.getNested().getIntProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a long property.
+ */
+ public void testGetNestedLong() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.longProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Long));
+ assertEquals("Got correct value",
+ ((Long) value).longValue(),
+ bean.getNested().getLongProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a read-only String property.
+ */
+ public void testGetNestedReadOnly() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.readOnlyProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof String));
+ assertEquals("Got correct value",
+ (String) value,
+ bean.getReadOnlyProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a short property.
+ */
+ public void testGetNestedShort() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.shortProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Short));
+ assertEquals("Got correct value",
+ ((Short) value).shortValue(),
+ bean.getNested().getShortProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getNestedProperty on a String property.
+ */
+ public void testGetNestedString() {
+
+ try {
+ Object value =
+ PropertyUtils.getNestedProperty
+ (bean, "nested.stringProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof String));
+ assertEquals("Got correct value",
+ ((String) value),
+ bean.getNested().getStringProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test getNestedProperty on an unknown property.
+ */
+ public void testGetNestedUnknown() {
+
+ try {
+ PropertyUtils.getNestedProperty(bean, "nested.unknown");
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+ /**
+ * When a bean has a null property which is reference by the standard access language,
+ * this should throw a NestedNullException.
+ */
+ public void testThrowNestedNull() throws Exception {
+ NestedTestBean nestedBean = new NestedTestBean("base");
+ // don't init!
+
+ try {
+ NestedTestBean value = (NestedTestBean) PropertyUtils.getProperty(
+ nestedBean,
+ "simpleBeanProperty.indexedProperty[0]");
+ fail("NestedNullException not thrown");
+ } catch (NestedNullException e) {
+ // that's what we wanted!
+ }
+ }
+
+ /**
+ * Test getNestedProperty on a write-only String property.
+ */
+ public void testGetNestedWriteOnly() {
+
+ try {
+ PropertyUtils.getNestedProperty(bean, "writeOnlyProperty");
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Test getPropertyType() on all kinds of properties.
+ */
+ public void testGetPropertyType() {
+
+ Class clazz = null;
+ int intArray[] = new int[0];
+ String stringArray[] = new String[0];
+
+ try {
+
+ // Scalar and Indexed Properties
+ clazz = PropertyUtils.getPropertyType(bean, "booleanProperty");
+ assertEquals("booleanProperty type", Boolean.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "booleanSecond");
+ assertEquals("booleanSecond type", Boolean.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "doubleProperty");
+ assertEquals("doubleProperty type", Double.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "dupProperty");
+ assertEquals("dupProperty type", String.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "floatProperty");
+ assertEquals("floatProperty type", Float.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "intArray");
+ assertEquals("intArray type", intArray.getClass(), clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "intIndexed");
+ assertEquals("intIndexed type", Integer.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "intProperty");
+ assertEquals("intProperty type", Integer.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "listIndexed");
+ assertEquals("listIndexed type", List.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "longProperty");
+ assertEquals("longProperty type", Long.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "mappedProperty");
+ assertEquals("mappedProperty type", String.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "mappedIntProperty");
+ assertEquals("mappedIntProperty type", Integer.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "readOnlyProperty");
+ assertEquals("readOnlyProperty type", String.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "shortProperty");
+ assertEquals("shortProperty type", Short.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "stringArray");
+ assertEquals("stringArray type", stringArray.getClass(), clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "stringIndexed");
+ assertEquals("stringIndexed type", String.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "stringProperty");
+ assertEquals("stringProperty type", String.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "writeOnlyProperty");
+ assertEquals("writeOnlyProperty type", String.class, clazz);
+
+ // Nested Properties
+ clazz = PropertyUtils.getPropertyType(bean, "nested.booleanProperty");
+ assertEquals("booleanProperty type", Boolean.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.booleanSecond");
+ assertEquals("booleanSecond type", Boolean.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.doubleProperty");
+ assertEquals("doubleProperty type", Double.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.dupProperty");
+ assertEquals("dupProperty type", String.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.floatProperty");
+ assertEquals("floatProperty type", Float.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.intArray");
+ assertEquals("intArray type", intArray.getClass(), clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.intIndexed");
+ assertEquals("intIndexed type", Integer.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.intProperty");
+ assertEquals("intProperty type", Integer.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.listIndexed");
+ assertEquals("listIndexed type", List.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.longProperty");
+ assertEquals("longProperty type", Long.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.mappedProperty");
+ assertEquals("mappedProperty type", String.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.mappedIntProperty");
+ assertEquals("mappedIntProperty type", Integer.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.readOnlyProperty");
+ assertEquals("readOnlyProperty type", String.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.shortProperty");
+ assertEquals("shortProperty type", Short.TYPE, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.stringArray");
+ assertEquals("stringArray type", stringArray.getClass(), clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.stringIndexed");
+ assertEquals("stringIndexed type", String.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.stringProperty");
+ assertEquals("stringProperty type", String.class, clazz);
+ clazz = PropertyUtils.getPropertyType(bean, "nested.writeOnlyProperty");
+ assertEquals("writeOnlyProperty type", String.class, clazz);
+
+ } catch (Exception e) {
+ fail("Exception: " + e.getMessage());
+ }
+
+ }
+
+
+ /**
+ * Test getting accessible property reader methods for a specified
+ * list of properties of our standard test bean.
+ */
+ public void testGetReadMethodBasic() {
+
+ testGetReadMethod(bean, properties, TEST_BEAN_CLASS);
+
+ }
+
+
+ /**
+ * Test getting accessible property reader methods for a specified
+ * list of properties of a package private subclass of our standard
+ * test bean.
+ */
+ public void testGetReadMethodPackageSubclass() {
+
+ testGetReadMethod(beanPackageSubclass, properties, TEST_BEAN_CLASS);
+
+ }
+
+
+ /**
+ * Test getting accessible property reader methods for a specified
+ * list of properties that are declared either directly or via
+ * implemented interfaces.
+ */
+ public void testGetReadMethodPublicInterface() {
+
+ // Properties "bar" and "baz" are visible via implemented interfaces
+ // (one direct and one indirect)
+ testGetReadMethod(beanPrivate,
+ new String[]{ "bar" },
+ PRIVATE_DIRECT_CLASS);
+ testGetReadMethod(beanPrivate,
+ new String[]{ "baz" },
+ PRIVATE_INDIRECT_CLASS);
+
+ // Properties "bar" and "baz" are visible via implemented interfaces
+ // (one direct and one indirect). The interface is implemented in
+ // a superclass
+ testGetReadMethod(beanPrivateSubclass,
+ new String[]{ "bar" },
+ PRIVATE_DIRECT_CLASS);
+ testGetReadMethod(beanPrivateSubclass,
+ new String[]{ "baz" },
+ PRIVATE_INDIRECT_CLASS);
+
+ // Property "foo" is not accessible because the underlying
+ // class has package scope
+ PropertyDescriptor pd[] =
+ PropertyUtils.getPropertyDescriptors(beanPrivate);
+ int n = -1;
+ for (int i = 0; i < pd.length; i++) {
+ if ("foo".equals(pd[i].getName())) {
+ n = i;
+ break;
+ }
+ }
+ assertTrue("Found foo descriptor", n >= 0);
+ Method reader = pd[n].getReadMethod();
+ assertNotNull("Found foo read method", reader);
+ Object value = null;
+ try {
+ value = reader.invoke(beanPrivate, new Class[0]);
+ fail("Foo reader did throw IllegalAccessException");
+ } catch (IllegalAccessException e) {
+ ; // Expected result for this test
+ } catch (Throwable t) {
+ fail("Invoke foo reader: " + t);
+ }
+
+ }
+
+
+ /**
+ * Test getting accessible property reader methods for a specified
+ * list of properties of a public subclass of our standard test bean.
+ */
+ public void testGetReadMethodPublicSubclass() {
+
+ testGetReadMethod(beanPublicSubclass, properties, TEST_BEAN_CLASS);
+
+ }
+
+
+ /**
+ * Corner cases on getSimpleProperty invalid arguments.
+ */
+ public void testGetSimpleArguments() {
+
+ try {
+ PropertyUtils.getSimpleProperty(null, "stringProperty");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.getSimpleProperty(bean, null);
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a boolean property.
+ */
+ public void testGetSimpleBoolean() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "booleanProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Boolean));
+ assertTrue("Got correct value",
+ ((Boolean) value).booleanValue() ==
+ bean.getBooleanProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a double property.
+ */
+ public void testGetSimpleDouble() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "doubleProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Double));
+ assertEquals("Got correct value",
+ ((Double) value).doubleValue(),
+ bean.getDoubleProperty(),
+ (double) 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a float property.
+ */
+ public void testGetSimpleFloat() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "floatProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Float));
+ assertEquals("Got correct value",
+ ((Float) value).floatValue(),
+ bean.getFloatProperty(),
+ (float) 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test getSimpleProperty on an indexed property.
+ */
+ public void testGetSimpleIndexed() {
+
+ Object value = null;
+ try {
+ value = PropertyUtils.getSimpleProperty(bean,
+ "intIndexed[0]");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ ; // Correct result for this test
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on an int property.
+ */
+ public void testGetSimpleInt() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "intProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Integer));
+ assertEquals("Got correct value",
+ ((Integer) value).intValue(),
+ bean.getIntProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a long property.
+ */
+ public void testGetSimpleLong() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "longProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Long));
+ assertEquals("Got correct value",
+ ((Long) value).longValue(),
+ bean.getLongProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test getSimpleProperty on a nested property.
+ */
+ public void testGetSimpleNested() {
+
+ Object value = null;
+ try {
+ value = PropertyUtils.getSimpleProperty(bean,
+ "nested.stringProperty");
+ fail("Should have thrown IllegaArgumentException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ ; // Correct result for this test
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a read-only String property.
+ */
+ public void testGetSimpleReadOnly() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "readOnlyProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof String));
+ assertEquals("Got correct value",
+ (String) value,
+ bean.getReadOnlyProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a short property.
+ */
+ public void testGetSimpleShort() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "shortProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof Short));
+ assertEquals("Got correct value",
+ ((Short) value).shortValue(),
+ bean.getShortProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a String property.
+ */
+ public void testGetSimpleString() {
+
+ try {
+ Object value =
+ PropertyUtils.getSimpleProperty(bean,
+ "stringProperty");
+ assertNotNull("Got a value", value);
+ assertTrue("Got correct type", (value instanceof String));
+ assertEquals("Got correct value",
+ (String) value,
+ bean.getStringProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test getSimpleProperty on an unknown property.
+ */
+ public void testGetSimpleUnknown() {
+
+ try {
+ PropertyUtils.getSimpleProperty(bean, "unknown");
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Test getSimpleProperty on a write-only String property.
+ */
+ public void testGetSimpleWriteOnly() {
+
+ try {
+ PropertyUtils.getSimpleProperty(bean, "writeOnlyProperty");
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Test getting accessible property writer methods for a specified
+ * list of properties of our standard test bean.
+ */
+ public void testGetWriteMethodBasic() {
+
+ testGetWriteMethod(bean, properties, TEST_BEAN_CLASS);
+
+ }
+
+
+ /**
+ * Test getting accessible property writer methods for a specified
+ * list of properties of a package private subclass of our standard
+ * test bean.
+ */
+ public void testGetWriteMethodPackageSubclass() {
+
+ testGetWriteMethod(beanPackageSubclass, properties, TEST_BEAN_CLASS);
+
+ }
+
+
+ /**
+ * Test getting accessible property writer methods for a specified
+ * list of properties of a public subclass of our standard test bean.
+ */
+ public void testGetWriteMethodPublicSubclass() {
+
+ testGetWriteMethod(beanPublicSubclass, properties, TEST_BEAN_CLASS);
+
+ }
+
+
+ /**
+ * Test the mappedPropertyType of MappedPropertyDescriptor.
+ */
+ public void testMappedPropertyType() throws Exception {
+
+ MappedPropertyDescriptor desc;
+
+ // Check a String property
+ desc = (MappedPropertyDescriptor)
+ PropertyUtils.getPropertyDescriptor(bean,
+ "mappedProperty");
+ assertEquals(String.class, desc.getMappedPropertyType());
+
+ // Check an int property
+ desc = (MappedPropertyDescriptor)
+ PropertyUtils.getPropertyDescriptor(bean,
+ "mappedIntProperty");
+ assertEquals(Integer.TYPE, desc.getMappedPropertyType());
+
+ }
+
+
+ /**
+ * Corner cases on setIndexedProperty invalid arguments.
+ */
+ public void testSetIndexedArguments() {
+
+ // Use explicit index argument
+
+ try {
+ PropertyUtils.setIndexedProperty(null, "intArray", 0,
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, null, 0,
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ // Use index expression
+
+ try {
+ PropertyUtils.setIndexedProperty(null,
+ "intArray[0]",
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, "[0]",
+ new Integer(1));
+ fail("Should throw NoSuchMethodException 4");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 4");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, "intArray",
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 5");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 5");
+ }
+
+ // Use explicit index argument
+
+ try {
+ PropertyUtils.setIndexedProperty(null, "intIndexed", 0,
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, null, 0,
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ // Use index expression
+
+ try {
+ PropertyUtils.setIndexedProperty(null,
+ "intIndexed[0]",
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, "[0]",
+ new Integer(1));
+ fail("Should throw NoSuchMethodException 4");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 4");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean, "intIndexed",
+ new Integer(1));
+ fail("Should throw IllegalArgumentException 5");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 5");
+ }
+
+ }
+
+
+ /**
+ * Positive and negative tests on setIndexedProperty valid arguments.
+ */
+ public void testSetIndexedValues() {
+
+ Object value = null;
+
+ // Use explicit index argument
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "dupProperty", 0,
+ "New 0");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "dupProperty", 0);
+ assertNotNull("Returned new value 0", value);
+ assertTrue("Returned String new value 0",
+ value instanceof String);
+ assertEquals("Returned correct new value 0", "New 0",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intArray", 0,
+ new Integer(1));
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intArray", 0);
+ assertNotNull("Returned new value 0", value);
+ assertTrue("Returned Integer new value 0",
+ value instanceof Integer);
+ assertEquals("Returned correct new value 0", 1,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intIndexed", 1,
+ new Integer(11));
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intIndexed", 1);
+ assertNotNull("Returned new value 1", value);
+ assertTrue("Returned Integer new value 1",
+ value instanceof Integer);
+ assertEquals("Returned correct new value 1", 11,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "listIndexed", 2,
+ "New Value 2");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "listIndexed", 2);
+ assertNotNull("Returned new value 2", value);
+ assertTrue("Returned String new value 2",
+ value instanceof String);
+ assertEquals("Returned correct new value 2", "New Value 2",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray", 2,
+ "New Value 2");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray", 2);
+ assertNotNull("Returned new value 2", value);
+ assertTrue("Returned String new value 2",
+ value instanceof String);
+ assertEquals("Returned correct new value 2", "New Value 2",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray", 3,
+ "New Value 3");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray", 3);
+ assertNotNull("Returned new value 3", value);
+ assertTrue("Returned String new value 3",
+ value instanceof String);
+ assertEquals("Returned correct new value 3", "New Value 3",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ // Use index expression
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "dupProperty[4]",
+ "New 4");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "dupProperty[4]");
+ assertNotNull("Returned new value 4", value);
+ assertTrue("Returned String new value 4",
+ value instanceof String);
+ assertEquals("Returned correct new value 4", "New 4",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intArray[4]",
+ new Integer(1));
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intArray[4]");
+ assertNotNull("Returned new value 4", value);
+ assertTrue("Returned Integer new value 4",
+ value instanceof Integer);
+ assertEquals("Returned correct new value 4", 1,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intIndexed[3]",
+ new Integer(11));
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "intIndexed[3]");
+ assertNotNull("Returned new value 5", value);
+ assertTrue("Returned Integer new value 5",
+ value instanceof Integer);
+ assertEquals("Returned correct new value 5", 11,
+ ((Integer) value).intValue());
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "listIndexed[1]",
+ "New Value 2");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "listIndexed[1]");
+ assertNotNull("Returned new value 6", value);
+ assertTrue("Returned String new value 6",
+ value instanceof String);
+ assertEquals("Returned correct new value 6", "New Value 2",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray[1]",
+ "New Value 2");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray[2]");
+ assertNotNull("Returned new value 6", value);
+ assertTrue("Returned String new value 6",
+ value instanceof String);
+ assertEquals("Returned correct new value 6", "New Value 2",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray[0]",
+ "New Value 3");
+ value =
+ PropertyUtils.getIndexedProperty(bean,
+ "stringArray[0]");
+ assertNotNull("Returned new value 7", value);
+ assertTrue("Returned String new value 7",
+ value instanceof String);
+ assertEquals("Returned correct new value 7", "New Value 3",
+ (String) value);
+ } catch (Throwable t) {
+ fail("Threw " + t);
+ }
+
+ // Index out of bounds tests
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "dupProperty", -1,
+ "New -1");
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "dupProperty", 5,
+ "New 5");
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intArray", -1,
+ new Integer(0));
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intArray", 5,
+ new Integer(0));
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intIndexed", -1,
+ new Integer(0));
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "intIndexed", 5,
+ new Integer(0));
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "listIndexed", 5,
+ "New String");
+ fail("Should have thrown IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "listIndexed", -1,
+ "New String");
+ fail("Should have thrown IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray", -1,
+ "New String");
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringArray", 5,
+ "New String");
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringIndexed", -1,
+ "New String");
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ try {
+ PropertyUtils.setIndexedProperty(bean,
+ "stringIndexed", 5,
+ "New String");
+ fail("Should have thrown ArrayIndexOutOfBoundsException");
+ } catch (ArrayIndexOutOfBoundsException t) {
+ ; // Expected results
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
+ }
+
+ }
+
+
+ /**
+ * Corner cases on getMappedProperty invalid arguments.
+ */
+ public void testSetMappedArguments() {
+
+ // Use explicit key argument
+
+ try {
+ PropertyUtils.setMappedProperty(null, "mappedProperty",
+ "First Key", "First Value");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean, null, "First Key",
+ "First Value");
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean, "mappedProperty", null,
+ "First Value");
+ fail("Should throw IllegalArgumentException 3");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 3");
+ }
+
+ // Use key expression
+
+ try {
+ PropertyUtils.setMappedProperty(null,
+ "mappedProperty(First Key)",
+ "First Value");
+ fail("Should throw IllegalArgumentException 4");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 4");
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean, "(Second Key)",
+ "Second Value");
+ fail("Should throw IllegalArgumentException 5");
+ } catch (NoSuchMethodException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of NoSuchMethodException 5");
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean, "mappedProperty",
+ "Third Value");
+ fail("Should throw IllegalArgumentException 6");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 6");
+ }
+
+ }
+
+
+ /**
+ * Positive and negative tests on setMappedProperty valid arguments.
+ */
+ public void testSetMappedValues() {
+
+ Object value = null;
+
+ // Use explicit key argument
+
+ try {
+ value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
+ "Fourth Key");
+ assertNull("Can not find fourth value", value);
+ } catch (Throwable t) {
+ fail("Finding fourth value threw " + t);
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean, "mappedProperty",
+ "Fourth Key", "Fourth Value");
+ } catch (Throwable t) {
+ fail("Setting fourth value threw " + t);
+ }
+
+ try {
+ value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
+ "Fourth Key");
+ assertEquals("Can find fourth value", "Fourth Value", value);
+ } catch (Throwable t) {
+ fail("Finding fourth value threw " + t);
+ }
+
+ // Use key expression with parentheses
+
+ try {
+ value =
+ PropertyUtils.getMappedProperty(bean,
+ "mappedProperty(Fifth Key)");
+ assertNull("Can not find fifth value", value);
+ } catch (Throwable t) {
+ fail("Finding fifth value threw " + t);
+ }
+
+ try {
+ PropertyUtils.setMappedProperty(bean,
+ "mappedProperty(Fifth Key)",
+ "Fifth Value");
+ } catch (Throwable t) {
+ fail("Setting fifth value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getMappedProperty(bean,
+ "mappedProperty(Fifth Key)");
+ assertEquals("Can find fifth value", "Fifth Value", value);
+ } catch (Throwable t) {
+ fail("Finding fifth value threw " + t);
+ }
+
+ // Use key expression with dotted expression
+
+ try {
+ value =
+ PropertyUtils.getNestedProperty(bean,
+ "mapProperty.Sixth Key");
+ assertNull("Can not find sixth value", value);
+ } catch (Throwable t) {
+ fail("Finding fifth value threw " + t);
+ }
+
+ try {
+ PropertyUtils.setNestedProperty(bean,
+ "mapProperty.Sixth Key",
+ "Sixth Value");
+ } catch (Throwable t) {
+ fail("Setting sixth value threw " + t);
+ }
+
+ try {
+ value =
+ PropertyUtils.getNestedProperty(bean,
+ "mapProperty.Sixth Key");
+ assertEquals("Can find sixth value", "Sixth Value", value);
+ } catch (Throwable t) {
+ fail("Finding sixth value threw " + t);
+ }
+
+ }
+
+
+ /**
+ * Corner cases on setNestedProperty invalid arguments.
+ */
+ public void testSetNestedArguments() {
+
+ try {
+ PropertyUtils.setNestedProperty(null, "stringProperty", "");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.setNestedProperty(bean, null, "");
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ }
+
+
+ /**
+ * Test setNextedProperty on a boolean property.
+ */
+ public void testSetNestedBoolean() {
+
+ try {
+ boolean oldValue = bean.getNested().getBooleanProperty();
+ boolean newValue = !oldValue;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.booleanProperty",
+ new Boolean(newValue));
+ assertTrue("Matched new value",
+ newValue ==
+ bean.getNested().getBooleanProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a double property.
+ */
+ public void testSetNestedDouble() {
+
+ try {
+ double oldValue = bean.getNested().getDoubleProperty();
+ double newValue = oldValue + 1.0;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.doubleProperty",
+ new Double(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ bean.getNested().getDoubleProperty(),
+ 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a float property.
+ */
+ public void testSetNestedFloat() {
+
+ try {
+ float oldValue = bean.getNested().getFloatProperty();
+ float newValue = oldValue + (float) 1.0;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.floatProperty",
+ new Float(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ bean.getNested().getFloatProperty(),
+ (float) 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a int property.
+ */
+ public void testSetNestedInt() {
+
+ try {
+ int oldValue = bean.getNested().getIntProperty();
+ int newValue = oldValue + 1;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.intProperty",
+ new Integer(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ bean.getNested().getIntProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a long property.
+ */
+ public void testSetNestedLong() {
+
+ try {
+ long oldValue = bean.getNested().getLongProperty();
+ long newValue = oldValue + 1;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.longProperty",
+ new Long(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ bean.getNested().getLongProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a read-only String property.
+ */
+ public void testSetNestedReadOnly() {
+
+ try {
+ String oldValue = bean.getNested().getWriteOnlyPropertyValue();
+ String newValue = oldValue + " Extra Value";
+ PropertyUtils.setNestedProperty(bean,
+ "nested.readOnlyProperty",
+ newValue);
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a short property.
+ */
+ public void testSetNestedShort() {
+
+ try {
+ short oldValue = bean.getNested().getShortProperty();
+ short newValue = oldValue;
+ newValue++;
+ PropertyUtils.setNestedProperty(bean,
+ "nested.shortProperty",
+ new Short(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ bean.getNested().getShortProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a String property.
+ */
+ public void testSetNestedString() {
+
+ try {
+ String oldValue = bean.getNested().getStringProperty();
+ String newValue = oldValue + " Extra Value";
+ PropertyUtils.setNestedProperty(bean,
+ "nested.stringProperty",
+ newValue);
+ assertEquals("Matched new value",
+ newValue,
+ bean.getNested().getStringProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on an unknown property name.
+ */
+ public void testSetNestedUnknown() {
+
+ try {
+ String newValue = "New String Value";
+ PropertyUtils.setNestedProperty(bean,
+ "nested.unknown",
+ newValue);
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Test setNestedProperty on a write-only String property.
+ */
+ public void testSetNestedWriteOnly() {
+
+ try {
+ String oldValue = bean.getNested().getWriteOnlyPropertyValue();
+ String newValue = oldValue + " Extra Value";
+ PropertyUtils.setNestedProperty(bean,
+ "nested.writeOnlyProperty",
+ newValue);
+ assertEquals("Matched new value",
+ newValue,
+ bean.getNested().getWriteOnlyPropertyValue());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Corner cases on setSimpleProperty invalid arguments.
+ */
+ public void testSetSimpleArguments() {
+
+ try {
+ PropertyUtils.setSimpleProperty(null, "stringProperty", "");
+ fail("Should throw IllegalArgumentException 1");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 1");
+ }
+
+ try {
+ PropertyUtils.setSimpleProperty(bean, null, "");
+ fail("Should throw IllegalArgumentException 2");
+ } catch (IllegalArgumentException e) {
+ ; // Expected response
+ } catch (Throwable t) {
+ fail("Threw " + t + " instead of IllegalArgumentException 2");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a boolean property.
+ */
+ public void testSetSimpleBoolean() {
+
+ try {
+ boolean oldValue = bean.getBooleanProperty();
+ boolean newValue = !oldValue;
+ PropertyUtils.setSimpleProperty(bean,
+ "booleanProperty",
+ new Boolean(newValue));
+ assertTrue("Matched new value",
+ newValue ==
+ bean.getBooleanProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a double property.
+ */
+ public void testSetSimpleDouble() {
+
+ try {
+ double oldValue = bean.getDoubleProperty();
+ double newValue = oldValue + 1.0;
+ PropertyUtils.setSimpleProperty(bean,
+ "doubleProperty",
+ new Double(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ bean.getDoubleProperty(),
+ 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a float property.
+ */
+ public void testSetSimpleFloat() {
+
+ try {
+ float oldValue = bean.getFloatProperty();
+ float newValue = oldValue + (float) 1.0;
+ PropertyUtils.setSimpleProperty(bean,
+ "floatProperty",
+ new Float(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ bean.getFloatProperty(),
+ (float) 0.005);
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test setSimpleProperty on an indexed property.
+ */
+ public void testSetSimpleIndexed() {
+
+ try {
+ PropertyUtils.setSimpleProperty(bean,
+ "stringIndexed[0]",
+ "New String Value");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ ; // Correct result for this test
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a int property.
+ */
+ public void testSetSimpleInt() {
+
+ try {
+ int oldValue = bean.getIntProperty();
+ int newValue = oldValue + 1;
+ PropertyUtils.setSimpleProperty(bean,
+ "intProperty",
+ new Integer(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ bean.getIntProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a long property.
+ */
+ public void testSetSimpleLong() {
+
+ try {
+ long oldValue = bean.getLongProperty();
+ long newValue = oldValue + 1;
+ PropertyUtils.setSimpleProperty(bean,
+ "longProperty",
+ new Long(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ bean.getLongProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Negative test setSimpleProperty on a nested property.
+ */
+ public void testSetSimpleNested() {
+
+ try {
+ PropertyUtils.setSimpleProperty(bean,
+ "nested.stringProperty",
+ "New String Value");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ ; // Correct result for this test
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a read-only String property.
+ */
+ public void testSetSimpleReadOnly() {
+
+ try {
+ String oldValue = bean.getWriteOnlyPropertyValue();
+ String newValue = oldValue + " Extra Value";
+ PropertyUtils.setSimpleProperty(bean,
+ "readOnlyProperty",
+ newValue);
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a short property.
+ */
+ public void testSetSimpleShort() {
+
+ try {
+ short oldValue = bean.getShortProperty();
+ short newValue = oldValue;
+ newValue++;
+ PropertyUtils.setSimpleProperty(bean,
+ "shortProperty",
+ new Short(newValue));
+ assertEquals("Matched new value",
+ newValue,
+ bean.getShortProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a String property.
+ */
+ public void testSetSimpleString() {
+
+ try {
+ String oldValue = bean.getStringProperty();
+ String newValue = oldValue + " Extra Value";
+ PropertyUtils.setSimpleProperty(bean,
+ "stringProperty",
+ newValue);
+ assertEquals("Matched new value",
+ newValue,
+ bean.getStringProperty());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on an unknown property name.
+ */
+ public void testSetSimpleUnknown() {
+
+ try {
+ String newValue = "New String Value";
+ PropertyUtils.setSimpleProperty(bean,
+ "unknown",
+ newValue);
+ fail("Should have thrown NoSuchMethodException");
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ ; // Correct result for this test
+ }
+
+ }
+
+
+ /**
+ * Test setSimpleProperty on a write-only String property.
+ */
+ public void testSetSimpleWriteOnly() {
+
+ try {
+ String oldValue = bean.getWriteOnlyPropertyValue();
+ String newValue = oldValue + " Extra Value";
+ PropertyUtils.setSimpleProperty(bean,
+ "writeOnlyProperty",
+ newValue);
+ assertEquals("Matched new value",
+ newValue,
+ bean.getWriteOnlyPropertyValue());
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (IllegalArgumentException e) {
+ fail("IllegalArgumentException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Base for testGetDescriptorXxxxx() series of tests.
+ *
+ * @param name Name of the property to be retrieved
+ * @param read Expected name of the read method (or null)
+ * @param write Expected name of the write method (or null)
+ */
+ protected void testGetDescriptorBase(String name, String read,
+ String write) {
+
+ try {
+ PropertyDescriptor pd =
+ PropertyUtils.getPropertyDescriptor(bean, name);
+ if ((read != null) || (write != null)) {
+ assertNotNull("Got descriptor", pd);
+ } else {
+ assertNull("Got descriptor", pd);
+ return;
+ }
+ Method rm = pd.getReadMethod();
+ if (read != null) {
+ assertNotNull("Got read method", rm);
+ assertEquals("Got correct read method",
+ rm.getName(), read);
+ } else {
+ assertNull("Got read method", rm);
+ }
+ Method wm = pd.getWriteMethod();
+ if (write != null) {
+ assertNotNull("Got write method", wm);
+ assertEquals("Got correct write method",
+ wm.getName(), write);
+ } else {
+ assertNull("Got write method", wm);
+ }
+ } catch (IllegalAccessException e) {
+ fail("IllegalAccessException");
+ } catch (InvocationTargetException e) {
+ fail("InvocationTargetException");
+ } catch (NoSuchMethodException e) {
+ fail("NoSuchMethodException");
+ }
+
+ }
+
+
+ /**
+ * Base for testGetReadMethod() series of tests.
+ *
+ * @param bean Bean for which to retrieve read methods.
+ * @param properties Property names to search for
+ * @param className Class name where this method should be defined
+ */
+ protected void testGetReadMethod(Object bean, String properties[],
+ String className) {
+
+ PropertyDescriptor pd[] =
+ PropertyUtils.getPropertyDescriptors(bean);
+ for (int i = 0; i < properties.length; i++) {
+
+ // Identify the property descriptor for this property
+ if (properties[i].equals("intIndexed"))
+ continue;
+ if (properties[i].equals("stringIndexed"))
+ continue;
+ if (properties[i].equals("writeOnlyProperty"))
+ continue;
+ int n = -1;
+ for (int j = 0; j < pd.length; j++) {
+ if (properties[i].equals(pd[j].getName())) {
+ n = j;
+ break;
+ }
+ }
+ assertTrue("PropertyDescriptor for " + properties[i],
+ n >= 0);
+
+ // Locate an accessible property reader method for it
+ Method reader = PropertyUtils.getReadMethod(pd[n]);
+ assertNotNull("Reader for " + properties[i],
+ reader);
+ Class clazz = reader.getDeclaringClass();
+ assertNotNull("Declaring class for " + properties[i],
+ clazz);
+ assertEquals("Correct declaring class for " + properties[i],
+ clazz.getName(),
+ className);
+
+ // Actually call the reader method we received
+ try {
+ reader.invoke(bean, new Class[0]);
+ } catch (Throwable t) {
+ fail("Call for " + properties[i] + ": " + t);
+ }
+
+ }
+
+ }
+
+
+ /**
+ * Base for testGetWriteMethod() series of tests.
+ *
+ * @param bean Bean for which to retrieve write methods.
+ * @param properties Property names to search for
+ * @param className Class name where this method should be defined
+ */
+ protected void testGetWriteMethod(Object bean, String properties[],
+ String className) {
+
+
+ PropertyDescriptor pd[] =
+ PropertyUtils.getPropertyDescriptors(bean);
+ for (int i = 0; i < properties.length; i++) {
+
+ // Identify the property descriptor for this property
+ if (properties[i].equals("intIndexed"))
+ continue;
+ if (properties[i].equals("listIndexed"))
+ continue;
+ if (properties[i].equals("nested"))
+ continue; // This property is read only
+ if (properties[i].equals("readOnlyProperty"))
+ continue;
+ if (properties[i].equals("stringIndexed"))
+ continue;
+ int n = -1;
+ for (int j = 0; j < pd.length; j++) {
+ if (properties[i].equals(pd[j].getName())) {
+ n = j;
+ break;
+ }
+ }
+ assertTrue("PropertyDescriptor for " + properties[i],
+ n >= 0);
+
+ // Locate an accessible property reader method for it
+ Method writer = PropertyUtils.getWriteMethod(pd[n]);
+ assertNotNull("Writer for " + properties[i],
+ writer);
+ Class clazz = writer.getDeclaringClass();
+ assertNotNull("Declaring class for " + properties[i],
+ clazz);
+ assertEquals("Correct declaring class for " + properties[i],
+ clazz.getName(),
+ className);
+
+ }
+
+ }
+
+ public void testNestedWithIndex() throws Exception
+ {
+ NestedTestBean nestedBean = new NestedTestBean("base");
+ nestedBean.init();
+ nestedBean.getSimpleBeanProperty().init();
+
+ NestedTestBean
+
+ // test first calling properties on indexed beans
+
+ value = (NestedTestBean) PropertyUtils.getProperty(
+ nestedBean,
+ "indexedProperty[0]");
+ assertEquals("Cannot get simple index(1)", "Bean at 0", value.getName());
+ assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
+
+ value = (NestedTestBean) PropertyUtils.getProperty(
+ nestedBean,
+ "indexedProperty[1]");
+ assertEquals("Cannot get simple index(1)", "Bean at 1", value.getName());
+ assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
+
+ String
+ prop = (String) PropertyUtils.getProperty(
+ nestedBean,
+ "indexedProperty[0].testString");
+ assertEquals("Get property on indexes failed (1)", "NOT SET", prop);
+
+ prop = (String) PropertyUtils.getProperty(
+ nestedBean,
+ "indexedProperty[1].testString");
+ assertEquals("Get property on indexes failed (2)", "NOT SET", prop);
+
+ PropertyUtils.setProperty(
+ nestedBean,
+ "indexedProperty[0].testString",
+ "Test#1");
+ assertEquals(
+ "Cannot set property on indexed bean (1)",
+ "Test#1",
+ nestedBean.getIndexedProperty(0).getTestString());
+
+ PropertyUtils.setProperty(
+ nestedBean,
+ "indexedProperty[1].testString",
+ "Test#2");
+ assertEquals(
+ "Cannot set property on indexed bean (2)",
+ "Test#2",
+ nestedBean.getIndexedProperty(1).getTestString());
+
+
+ // test first calling indexed properties on a simple property
+
+ value = (NestedTestBean) PropertyUtils.getProperty(
+ nestedBean,
+ "simpleBeanProperty");
+ assertEquals("Cannot get simple bean", "Simple Property Bean", value.getName());
+ assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
+
+ value = (NestedTestBean) PropertyUtils.getProperty(
+ nestedBean,
+ "simpleBeanProperty.indexedProperty[3]");
+ assertEquals("Cannot get index property on property", "Bean at 3", value.getName());
+ assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
+
+ PropertyUtils.setProperty(
+ nestedBean,
+ "simpleBeanProperty.indexedProperty[3].testString",
+ "Test#3");
+ assertEquals(
+ "Cannot set property on indexed property on property",
+ "Test#3",
+ nestedBean.getSimpleBeanProperty().getIndexedProperty(3).getTestString());
+ }
+
+ /** Text case for setting properties on inner classes */
+ public void testGetSetInnerBean() throws Exception {
+ BeanWithInnerBean bean = new BeanWithInnerBean();
+
+ PropertyUtils.setProperty(bean, "innerBean.fish(loiterTimer)", "5");
+ String out = (String) PropertyUtils.getProperty(bean.getInnerBean(), "fish(loiterTimer)");
+ assertEquals(
+ "(1) Inner class property set/get property failed.",
+ "5",
+ out);
+
+ out = (String) PropertyUtils.getProperty(bean, "innerBean.fish(loiterTimer)");
+
+ assertEquals(
+ "(2) Inner class property set/get property failed.",
+ "5",
+ out);
+ }
+
+ /** Text case for setting properties on parent */
+ public void testGetSetParentBean() throws Exception {
+
+ SonOfAlphaBean bean = new SonOfAlphaBean("Roger");
+
+ String out = (String) PropertyUtils.getProperty(bean, "name");
+ assertEquals(
+ "(1) Get/Set On Parent.",
+ "Roger",
+ out);
+
+ PropertyUtils.setProperty(bean, "name", "abcd");
+ assertEquals(
+ "(2) Get/Set On Parent.",
+ "abcd",
+ bean.getName());
+ }
+
+ public void testSetNoGetter() throws Exception
+ {
+ BetaBean bean = new BetaBean("Cedric");
+
+ // test standard no getter
+ bean.setNoGetterProperty("Sigma");
+ assertEquals("BetaBean test failed", "Sigma", bean.getSecret());
+
+ assertNotNull("Descriptor is null", PropertyUtils.getPropertyDescriptor(bean, "noGetterProperty"));
+
+ BeanUtils.setProperty(bean, "noGetterProperty", "Omega");
+ assertEquals("Cannot set no-getter property", "Omega", bean.getSecret());
+
+ // test mapped no getter descriptor
+ MappedPropertyDescriptor descriptor
+ = new MappedPropertyDescriptor("noGetterMappedProperty", BetaBean.class);
+
+ assertNotNull("Map Descriptor is null", PropertyUtils.getPropertyDescriptor(bean, "noGetterMappedProperty"));
+
+ PropertyUtils.setMappedProperty(bean, "noGetterMappedProperty", "Epsilon", "Epsilon");
+ assertEquals("Cannot set mapped no-getter property", "MAP:Epsilon", bean.getSecret());
+ }
+
+ /**
+ * This tests to see that classes that implement Map can have
+ * their standard properties set.
+ */
+ public void testSetMapExtension() throws Exception {
+ ExtendMapBean bean = new ExtendMapBean();
+
+ bean.setUnusuallyNamedProperty("bean value");
+ assertEquals("Set property direct failed", "bean value", bean.getUnusuallyNamedProperty());
+
+ PropertyUtils.setSimpleProperty(bean, "unusuallyNamedProperty", "new value");
+ assertEquals("Set property on map failed (1)", "new value", bean.getUnusuallyNamedProperty());
+
+ PropertyUtils.setProperty(bean, "unusuallyNamedProperty", "next value");
+ assertEquals("Set property on map failed (2)", "next value", bean.getUnusuallyNamedProperty());
+ }
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/PropertyUtilsTestCase.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/SonOfAlphaBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/SonOfAlphaBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/SonOfAlphaBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils;
+
+/** @author Robert Burrell Donkin */
+public class SonOfAlphaBean extends AlphaBean {
+
+ public SonOfAlphaBean(String name) {
+ super(name);
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,572 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * General purpose test bean for JUnit tests for the "beanutils" component.
+ *
+ * @author Craig R. McClanahan
+ * @author Rodney Waldhoff
+ * @version $Revision: 1.20 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class TestBean {
+
+ // ----------------------------------------------------------- Constructors
+
+ public TestBean() {
+ }
+
+ public TestBean(String stringProperty) {
+ setStringProperty(stringProperty);
+ }
+
+ public TestBean(float floatProperty) {
+ setFloatProperty(floatProperty);
+ }
+
+ public TestBean(boolean booleanProperty) {
+ setBooleanProperty(booleanProperty);
+ }
+
+ public TestBean(Boolean booleanSecond) {
+ setBooleanSecond(booleanSecond.booleanValue());
+ }
+
+ public TestBean(float floatProperty, String stringProperty) {
+ setFloatProperty(floatProperty);
+ setStringProperty(stringProperty);
+ }
+
+ public TestBean(boolean booleanProperty, String stringProperty) {
+ setBooleanProperty(booleanProperty);
+ setStringProperty(stringProperty);
+ }
+
+ public TestBean(Boolean booleanSecond, String stringProperty) {
+ setBooleanSecond(booleanSecond.booleanValue());
+ setStringProperty(stringProperty);
+ }
+
+ public TestBean(Integer intProperty) {
+ setIntProperty(intProperty.intValue());
+ }
+
+ public TestBean(double doubleProperty) {
+ setDoubleProperty(doubleProperty);
+ }
+
+ TestBean(int intProperty) {
+ setIntProperty(intProperty);
+ }
+
+ protected TestBean(boolean booleanProperty, boolean booleanSecond, String stringProperty) {
+ setBooleanProperty(booleanProperty);
+ setBooleanSecond(booleanSecond);
+ setStringProperty(stringProperty);
+ }
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A boolean property.
+ */
+ private boolean booleanProperty = true;
+
+ public boolean getBooleanProperty() {
+ return (booleanProperty);
+ }
+
+ public void setBooleanProperty(boolean booleanProperty) {
+ this.booleanProperty = booleanProperty;
+ }
+
+
+ /**
+ * A boolean property that uses an "is" method for the getter.
+ */
+ private boolean booleanSecond = true;
+
+ public boolean isBooleanSecond() {
+ return (booleanSecond);
+ }
+
+ public void setBooleanSecond(boolean booleanSecond) {
+ this.booleanSecond = booleanSecond;
+ }
+
+
+ /**
+ * A byte property.
+ */
+ private byte byteProperty = (byte) 121;
+
+ public byte getByteProperty() {
+ return (this.byteProperty);
+ }
+
+ public void setByteProperty(byte byteProperty) {
+ this.byteProperty = byteProperty;
+ }
+
+
+ /**
+ * A double property.
+ */
+ private double doubleProperty = 321.0;
+
+ public double getDoubleProperty() {
+ return (this.doubleProperty);
+ }
+
+ public void setDoubleProperty(double doubleProperty) {
+ this.doubleProperty = doubleProperty;
+ }
+
+
+ /**
+ * An "indexed property" accessible via both array and subscript
+ * based getters and setters.
+ */
+ private String dupProperty[] =
+ { "Dup 0", "Dup 1", "Dup 2", "Dup 3", "Dup 4" };
+
+ public String[] getDupProperty() {
+ return (this.dupProperty);
+ }
+
+ public String getDupProperty(int index) {
+ return (this.dupProperty[index]);
+ }
+
+ public void setDupProperty(int index, String value) {
+ this.dupProperty[index] = value;
+ }
+
+ public void setDupProperty(String dupProperty[]) {
+ this.dupProperty = dupProperty;
+ }
+
+
+ /**
+ * A float property.
+ */
+ private float floatProperty = (float) 123.0;
+
+ public float getFloatProperty() {
+ return (this.floatProperty);
+ }
+
+ public void setFloatProperty(float floatProperty) {
+ this.floatProperty = floatProperty;
+ }
+
+
+ /**
+ * An integer array property accessed as an array.
+ */
+ private int intArray[] = { 0, 10, 20, 30, 40 };
+
+ public int[] getIntArray() {
+ return (this.intArray);
+ }
+
+ public void setIntArray(int intArray[]) {
+ this.intArray = intArray;
+ }
+
+
+ /**
+ * An integer array property accessed as an indexed property.
+ */
+ private int intIndexed[] = { 0, 10, 20, 30, 40 };
+
+ public int getIntIndexed(int index) {
+ return (intIndexed[index]);
+ }
+
+ public void setIntIndexed(int index, int value) {
+ intIndexed[index] = value;
+ }
+
+
+ /**
+ * An integer property.
+ */
+ private int intProperty = 123;
+
+ public int getIntProperty() {
+ return (this.intProperty);
+ }
+
+ public void setIntProperty(int intProperty) {
+ this.intProperty = intProperty;
+ }
+
+
+ /**
+ * A List property accessed as an indexed property.
+ */
+ private static List listIndexed = new ArrayList();
+
+ static {
+ listIndexed.add("String 0");
+ listIndexed.add("String 1");
+ listIndexed.add("String 2");
+ listIndexed.add("String 3");
+ listIndexed.add("String 4");
+ }
+
+ public List getListIndexed() {
+ return (listIndexed);
+ }
+
+
+ /**
+ * A long property.
+ */
+ private long longProperty = 321;
+
+ public long getLongProperty() {
+ return (this.longProperty);
+ }
+
+ public void setLongProperty(long longProperty) {
+ this.longProperty = longProperty;
+ }
+
+
+ /**
+ * A mapped property with only a getter and setter for a Map.
+ */
+ private Map mapProperty = null;
+
+ public Map getMapProperty() {
+ // Create the map the very first time
+ if (mapProperty == null) {
+ mapProperty = new HashMap();
+ mapProperty.put("First Key", "First Value");
+ mapProperty.put("Second Key", "Second Value");
+ }
+ return (mapProperty);
+ }
+
+ public void setMapProperty(Map mapProperty) {
+ // Create the map the very first time
+ if (mapProperty == null) {
+ mapProperty = new HashMap();
+ mapProperty.put("First Key", "First Value");
+ mapProperty.put("Second Key", "Second Value");
+ }
+ this.mapProperty = mapProperty;
+ }
+
+
+ /**
+ * A mapped property that has String keys and Object values.
+ */
+ private HashMap mappedObjects = null;
+
+ public Object getMappedObjects(String key) {
+ // Create the map the very first time
+ if (mappedObjects == null) {
+ mappedObjects = new HashMap();
+ mappedObjects.put("First Key", "First Value");
+ mappedObjects.put("Second Key", "Second Value");
+ }
+ return (mappedObjects.get(key));
+ }
+
+ public void setMappedObjects(String key, Object value) {
+ // Create the map the very first time
+ if (mappedObjects == null) {
+ mappedObjects = new HashMap();
+ mappedObjects.put("First Key", "First Value");
+ mappedObjects.put("Second Key", "Second Value");
+ }
+ mappedObjects.put(key, value);
+ }
+
+
+ /**
+ * A mapped property that has String keys and String values.
+ */
+ private HashMap mappedProperty = null;
+
+ public String getMappedProperty(String key) {
+ // Create the map the very first time
+ if (mappedProperty == null) {
+ mappedProperty = new HashMap();
+ mappedProperty.put("First Key", "First Value");
+ mappedProperty.put("Second Key", "Second Value");
+ }
+ return ((String) mappedProperty.get(key));
+ }
+
+ public void setMappedProperty(String key, String value) {
+ // Create the map the very first time
+ if (mappedProperty == null) {
+ mappedProperty = new HashMap();
+ mappedProperty.put("First Key", "First Value");
+ mappedProperty.put("Second Key", "Second Value");
+ }
+ mappedProperty.put(key, value);
+ }
+
+
+ /**
+ * A mapped property that has String keys and int values.
+ */
+ private HashMap mappedIntProperty = null;
+
+ public int getMappedIntProperty(String key) {
+ // Create the map the very first time
+ if (mappedProperty == null) {
+ mappedProperty = new HashMap();
+ mappedProperty.put("One", new Integer(1));
+ mappedProperty.put("Two", new Integer(2));
+ }
+ Integer x = (Integer) mappedIntProperty.get(key);
+ return ((x == null) ? 0 : x.intValue());
+ }
+
+ public void setMappedIntProperty(String key, int value) {
+ mappedIntProperty.put(key, new Integer(value));
+ }
+
+
+ /**
+ * A nested reference to another test bean (populated as needed).
+ */
+ private TestBean nested = null;
+
+ public TestBean getNested() {
+ if (nested == null)
+ nested = new TestBean();
+ return (nested);
+ }
+
+ /**
+ * Another nested reference to another test bean,
+ */
+ private TestBean anotherNested = null;
+
+ public TestBean getAnotherNested() {
+ return anotherNested;
+ }
+
+ public void setAnotherNested( TestBean anotherNested ) {
+ this.anotherNested = anotherNested;
+ }
+
+ /*
+ * Another nested reference to a bean containing mapp properties
+ */
+ class MappedTestBean {
+ public void setValue(String key,String val) { }
+ public String getValue(String key) { return "Mapped Value"; }
+ }
+
+ private MappedTestBean mappedNested = null;
+
+ public MappedTestBean getMappedNested() {
+ if (mappedNested == null)
+ {
+ mappedNested = new MappedTestBean();
+ }
+ return mappedNested;
+ }
+
+ /**
+ * A String property with an initial value of null.
+ */
+ private String nullProperty = null;
+
+ public String getNullProperty() {
+ return (this.nullProperty);
+ }
+
+ public void setNullProperty(String nullProperty) {
+ this.nullProperty = nullProperty;
+ }
+
+
+ /**
+ * A read-only String property.
+ */
+ private String readOnlyProperty = "Read Only String Property";
+
+ public String getReadOnlyProperty() {
+ return (this.readOnlyProperty);
+ }
+
+
+ /**
+ * A short property.
+ */
+ private short shortProperty = (short) 987;
+
+ public short getShortProperty() {
+ return (this.shortProperty);
+ }
+
+ public void setShortProperty(short shortProperty) {
+ this.shortProperty = shortProperty;
+ }
+
+
+ /**
+ * A String array property accessed as a String.
+ */
+ private String stringArray[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+
+ public String[] getStringArray() {
+ return (this.stringArray);
+ }
+
+ public void setStringArray(String stringArray[]) {
+ this.stringArray = stringArray;
+ }
+
+
+ /**
+ * A String array property accessed as an indexed property.
+ */
+ private String stringIndexed[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+
+ public String getStringIndexed(int index) {
+ return (stringIndexed[index]);
+ }
+
+ public void setStringIndexed(int index, String value) {
+ stringIndexed[index] = value;
+ }
+
+
+ /**
+ * A String property.
+ */
+ private String stringProperty = "This is a string";
+
+ public String getStringProperty() {
+ return (this.stringProperty);
+ }
+
+ public void setStringProperty(String stringProperty) {
+ this.stringProperty = stringProperty;
+ }
+
+
+ /**
+ * A write-only String property.
+ */
+ private String writeOnlyProperty = "Write Only String Property";
+
+ public String getWriteOnlyPropertyValue() {
+ return (this.writeOnlyProperty);
+ }
+
+ public void setWriteOnlyProperty(String writeOnlyProperty) {
+ this.writeOnlyProperty = writeOnlyProperty;
+ }
+
+
+ // ------------------------------------------------------ Invalid Properties
+
+
+ /**
+ * <p>An invalid property that has two boolean getters (getInvalidBoolean
+ * and isInvalidBoolean) plus a String setter (setInvalidBoolean). By the
+ * rules described in the JavaBeans Specification, this will be considered
+ * a read-only boolean property, using isInvalidBoolean() as the getter.</p>
+ */
+ private boolean invalidBoolean = false;
+
+ public boolean getInvalidBoolean() {
+ return (this.invalidBoolean);
+ }
+
+ public boolean isInvalidBoolean() {
+ return (this.invalidBoolean);
+ }
+
+ public void setInvalidBoolean(String invalidBoolean) {
+ if ("true".equalsIgnoreCase(invalidBoolean) ||
+ "yes".equalsIgnoreCase(invalidBoolean) ||
+ "1".equalsIgnoreCase(invalidBoolean)) {
+ this.invalidBoolean = true;
+ } else {
+ this.invalidBoolean = false;
+ }
+ }
+
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * A static variable that is accessed and updated via static methods
+ * for MethodUtils testing.
+ */
+ private static int counter = 0;
+
+
+ /**
+ * Return the current value of the counter.
+ */
+ public static int currentCounter() {
+
+ return (counter);
+
+ }
+
+
+ /**
+ * Increment the current value of the counter by 1.
+ */
+ public static void incrementCounter() {
+
+ incrementCounter(1);
+
+ }
+
+
+ /**
+ * Increment the current value of the counter by the specified amount.
+ *
+ * @param amount Amount to be added to the current counter
+ */
+ public static void incrementCounter(int amount) {
+
+ counter += amount;
+
+ }
+
+
+}
Property changes on: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBean.java
___________________________________________________________________
Name: svn:executable
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBeanPackageSubclass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBeanPackageSubclass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBeanPackageSubclass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+/**
+ * This is a package private subclass of TestBean. All of our properties
+ * should still be accessible via reflection.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.5 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+class TestBeanPackageSubclass extends TestBean {
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBeanPublicSubclass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBeanPublicSubclass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestBeanPublicSubclass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+/**
+ * This is a public subclass of TestBean. All of our properties should still
+ * be accessible via reflection.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.5 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class TestBeanPublicSubclass extends TestBean {
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestResultSet.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestResultSet.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestResultSet.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,864 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Map;
+
+
+/**
+ * <p>Mock object that implements enough of <code>java.sql.ResultSet</code>
+ * to exercise the {@link ResultSetDyaClass} functionality.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.5 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class TestResultSet implements ResultSet {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * Current row number (0 means "before the first one").
+ */
+ protected int row = 0;
+
+
+ /**
+ * The constant (per run) value used to initialize date/time/timestamp.
+ */
+ protected long timestamp = System.currentTimeMillis();
+
+
+ // ---------------------------------------------------- Implemented Methods
+
+
+ public void close() throws SQLException {
+ ; // No action required
+ }
+
+
+ public ResultSetMetaData getMetaData() throws SQLException {
+ return (new TestResultSetMetaData());
+ }
+
+
+ public Object getObject(String columnName) throws SQLException {
+ if (row > 5) {
+ throw new SQLException("No current row");
+ }
+ if ("bigdecimalproperty".equals(columnName)) {
+ return (new BigDecimal(123.45));
+ } else if ("booleanproperty".equals(columnName)) {
+ if ((row % 2) == 0) {
+ return (Boolean.TRUE);
+ } else {
+ return (Boolean.FALSE);
+ }
+ } else if ("byteproperty".equals(columnName)) {
+ return (new Byte((byte) row));
+ } else if ("dateproperty".equals(columnName)) {
+ return (new Date(timestamp));
+ } else if ("doubleproperty".equals(columnName)) {
+ return (new Double(321.0));
+ } else if ("floatproperty".equals(columnName)) {
+ return (new Float((float) 123.0));
+ } else if ("intproperty".equals(columnName)) {
+ return (new Integer(100 + row));
+ } else if ("longproperty".equals(columnName)) {
+ return (new Long(200 + row));
+ } else if ("nullproperty".equals(columnName)) {
+ return (null);
+ } else if ("shortproperty".equals(columnName)) {
+ return (new Short((short) (300 + row)));
+ } else if ("stringproperty".equals(columnName)) {
+ return ("This is a string");
+ } else if ("timeproperty".equals(columnName)) {
+ return (new Time(timestamp));
+ } else if ("timestampproperty".equals(columnName)) {
+ return (new Timestamp(timestamp));
+ } else {
+ throw new SQLException("Unknown column name " + columnName);
+ }
+ }
+
+
+ public boolean next() throws SQLException {
+ if (row++ < 5) {
+ return (true);
+ } else {
+ return (false);
+ }
+ }
+
+
+ public void updateObject(String columnName, Object x)
+ throws SQLException {
+ if (row > 5) {
+ throw new SQLException("No current row");
+ }
+ ; // FIXME - updateObject()
+ }
+
+
+ // -------------------------------------------------- Unimplemented Methods
+
+
+ public boolean absolute(int row) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void afterLast() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void beforeFirst() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void cancelRowUpdates() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void clearWarnings() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void deleteRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int findColumn(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean first() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Array getArray(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Array getArray(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public InputStream getAsciiStream(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public InputStream getAsciiStream(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @deprecated */
+ public BigDecimal getBigDecimal(int columnIndex, int scale)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public BigDecimal getBigDecimal(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /** @deprecated */
+ public BigDecimal getBigDecimal(String columnName, int scale)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public InputStream getBinaryStream(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public InputStream getBinaryStream(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Blob getBlob(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Blob getBlob(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean getBoolean(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean getBoolean(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public byte getByte(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public byte getByte(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public byte[] getBytes(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public byte[] getBytes(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Reader getCharacterStream(int columnIndex)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Reader getCharacterStream(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Clob getClob(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Clob getClob(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getConcurrency() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public String getCursorName() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Date getDate(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Date getDate(int columnIndex, Calendar cal) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Date getDate(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Date getDate(String columnName, Calendar cal) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public double getDouble(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public double getDouble(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getFetchDirection() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getFetchSize() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public float getFloat(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public float getFloat(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getInt(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getInt(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public long getLong(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public long getLong(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Object getObject(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Object getObject(int columnIndex, Map map) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Object getObject(String columnName, Map map) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Ref getRef(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Ref getRef(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public short getShort(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public short getShort(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Statement getStatement() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public String getString(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public String getString(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Time getTime(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Time getTime(int columnIndex, Calendar cal) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Time getTime(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Time getTime(String columnName, Calendar cal) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Timestamp getTimestamp(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Timestamp getTimestamp(int columnIndex, Calendar cal)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Timestamp getTimestamp(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public Timestamp getTimestamp(String columnName, Calendar cal)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getType() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /** @deprecated */
+ public InputStream getUnicodeStream(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /** @deprecated */
+ public InputStream getUnicodeStream(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public URL getURL(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public URL getURL(String columnName) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public SQLWarning getWarnings() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void insertRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isAfterLast() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isBeforeFirst() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isFirst() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isLast() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean last() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void moveToCurrentRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void moveToInsertRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean previous() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void refreshRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean relative(int rows) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean rowDeleted() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean rowInserted() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean rowUpdated() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void setFetchDirection(int direction) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void setFetchSize(int size) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateArray(int columnPosition, Array x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateArray(String columnName, Array x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateAsciiStream(int columnPosition, InputStream x, int len)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateAsciiStream(String columnName, InputStream x, int len)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateBigDecimal(int columnPosition, BigDecimal x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateBigDecimal(String columnName, BigDecimal x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateBinaryStream(int columnPosition, InputStream x, int len)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateBinaryStream(String columnName, InputStream x, int len)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateBlob(int columnPosition, Blob x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateBlob(String columnName, Blob x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateBoolean(int columnPosition, boolean x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateBoolean(String columnName, boolean x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateByte(int columnPosition, byte x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateByte(String columnName, byte x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateBytes(int columnPosition, byte x[])
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateBytes(String columnName, byte x[])
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateCharacterStream(int columnPosition, Reader x, int len)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateCharacterStream(String columnName, Reader x, int len)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateClob(int columnPosition, Clob x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateClob(String columnName, Clob x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateDate(int columnPosition, Date x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateDate(String columnName, Date x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateDouble(int columnPosition, double x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateDouble(String columnName, double x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateFloat(int columnPosition, float x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateFloat(String columnName, float x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateInt(int columnPosition, int x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateInt(String columnName, int x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateLong(int columnPosition, long x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateLong(String columnName, long x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateNull(int columnPosition)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateNull(String columnName)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateObject(int columnPosition, Object x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateObject(int columnPosition, Object x, int scale)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateObject(String columnName, Object x, int scale)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateRef(int columnPosition, Ref x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateRef(String columnName, Ref x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateRow() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateShort(int columnPosition, short x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateShort(String columnName, short x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateString(int columnPosition, String x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateString(String columnName, String x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateTime(int columnPosition, Time x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateTime(String columnName, Time x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateTimestamp(int columnPosition, Timestamp x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public void updateTimestamp(String columnName, Timestamp x)
+ throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean wasNull() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestResultSetMetaData.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestResultSetMetaData.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/TestResultSetMetaData.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+
+/**
+ * <p>Mock object that implements enough of
+ * <code>java.sql.ResultSetMetaData</code>
+ * to exercise the {@link ResultSetDyaClass} functionality.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class TestResultSetMetaData implements ResultSetMetaData {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * <p>Array of column names and class names for metadata.</p>
+ */
+ protected String metadata[][] = {
+ { "bigDecimalProperty", "java.math.BigDecimal" },
+ { "booleanProperty", Boolean.class.getName() },
+ { "byteProperty", Byte.class.getName() },
+ { "dateProperty", "java.sql.Date" },
+ { "doubleProperty", Double.class.getName() },
+ { "floatProperty", Float.class.getName() },
+ { "intProperty", Integer.class.getName() },
+ { "longProperty", Long.class.getName() },
+ { "nullProperty", "java.lang.String" },
+ { "shortProperty", Short.class.getName() },
+ { "stringProperty", "java.lang.String" },
+ { "timeProperty", "java.sql.Time" },
+ { "timestampProperty", "java.sql.Timestamp" },
+ };
+
+
+ // ---------------------------------------------------- Implemented Methods
+
+
+ public String getColumnClassName(int columnIndex) throws SQLException {
+ return (metadata[columnIndex - 1][1]);
+ }
+
+
+ public int getColumnCount() throws SQLException {
+ return (metadata.length);
+ }
+
+ public String getColumnName(int columnIndex) throws SQLException {
+ return (metadata[columnIndex - 1][0]);
+ }
+
+
+ // -------------------------------------------------- Unimplemented Methods
+
+
+ public String getCatalogName(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getColumnDisplaySize(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public String getColumnLabel(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getColumnType(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public String getColumnTypeName(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getPrecision(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int getScale(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public String getSchemaName(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public String getTableName(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isAutoIncrement(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isCaseSensitive(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isCurrency(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isDefinitelyWritable(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public int isNullable(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isReadOnly(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isSearchable(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isSigned(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isWritable(int columnIndex) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ThrowExceptionConverter.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ThrowExceptionConverter.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/ThrowExceptionConverter.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+/**
+ * Converter implementation that throws a <code>PassTestException</code>
+ * when convert is called.
+ * The idea is that catching this exception is a clear signal that this method
+ * has been called.
+ *
+ * @author Robert Burrell Donkin
+ */
+
+public class ThrowExceptionConverter implements Converter {
+
+ public Object convert(Class type, Object value) {
+ throw new PassTestException();
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/WrapDynaBeanTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/WrapDynaBeanTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/WrapDynaBeanTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils;
+
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * <p>Test Case for the <code>WrapDynaBean</code> implementation class.
+ * These tests were based on the ones in <code>PropertyUtilsTestCase</code>
+ * because the two classes provide similar levels of functionality.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.9 $ $Date: 2004/02/28 13:18:36 $
+ */
+
+public class WrapDynaBeanTestCase extends BasicDynaBeanTestCase {
+
+
+ // ---------------------------------------------------- Instance Variables
+
+
+ // ---------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public WrapDynaBeanTestCase(String name) {
+
+ super(name);
+
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() throws Exception {
+
+ bean = new WrapDynaBean(new TestBean());
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+
+ return (new TestSuite(WrapDynaBeanTestCase.class));
+
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+
+ bean = null;
+
+ }
+
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ /**
+ * The <code>contains()</code> method is not supported by the
+ * <code>WrapDynaBean</code> implementation class.
+ */
+ public void testMappedContains() {
+
+ try {
+ assertTrue("Can see first key",
+ bean.contains("mappedProperty", "First Key"));
+ fail("Should have thrown UnsupportedOperationException");
+ } catch (UnsupportedOperationException t) {
+ ; // Expected result
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+
+ try {
+ assertTrue("Can not see unknown key",
+ !bean.contains("mappedProperty", "Unknown Key"));
+ fail("Should have thrown UnsupportedOperationException");
+ } catch (UnsupportedOperationException t) {
+ ; // Expected result
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ }
+
+
+ /**
+ * The <code>remove()</code> method is not supported by the
+ * <code>WrapDynaBean</code> implementation class.
+ */
+ public void testMappedRemove() {
+
+ try {
+ assertTrue("Can see first key",
+ bean.contains("mappedProperty", "First Key"));
+ bean.remove("mappedProperty", "First Key");
+ fail("Should have thrown UnsupportedOperationException");
+ // assertTrue("Can not see first key",
+ // !bean.contains("mappedProperty", "First Key"));
+ } catch (UnsupportedOperationException t) {
+ ; // Expected result
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ try {
+ assertTrue("Can not see unknown key",
+ !bean.contains("mappedProperty", "Unknown Key"));
+ bean.remove("mappedProperty", "Unknown Key");
+ fail("Should have thrown UnsupportedOperationException");
+ // assertTrue("Can not see unknown key",
+ // !bean.contains("mappedProperty", "Unknown Key"));
+ } catch (UnsupportedOperationException t) {
+ ; // Expected result
+ } catch (Throwable t) {
+ fail("Exception: " + t);
+ }
+
+ }
+
+
+ /**
+ * Suppress serialization and deserialization tests. WrapDynaClass
+ * is not serializable.
+ */
+ public void testSerialization() { }
+
+ /** Tests getInstance method */
+ public void testGetInstance() {
+ AlphaBean alphaBean = new AlphaBean("Now On Air... John Peel");
+ WrapDynaBean dynaBean = new WrapDynaBean(alphaBean);
+ Object wrappedInstance = dynaBean.getInstance();
+ assertTrue("Object type is AlphaBean", wrappedInstance instanceof AlphaBean);
+ AlphaBean wrappedAlphaBean = (AlphaBean) wrappedInstance;
+ assertTrue("Same Object", wrappedAlphaBean == alphaBean);
+ }
+
+ /** Tests the newInstance implementation for WrapDynaClass */
+ public void testNewInstance() throws Exception {
+ WrapDynaClass dynaClass = WrapDynaClass.createDynaClass(AlphaBean.class);
+ Object createdInstance = dynaClass.newInstance();
+ assertTrue("Object type is WrapDynaBean", createdInstance instanceof WrapDynaBean);
+ WrapDynaBean dynaBean = (WrapDynaBean) createdInstance;
+ assertTrue("Object type is AlphaBean", dynaBean.getInstance() instanceof AlphaBean);
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ByteConverterTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ByteConverterTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ByteConverterTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import junit.framework.TestSuite;
+
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * Test Case for the ByteConverter class.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class ByteConverterTestCase extends NumberConverterTestBase {
+
+ private Converter converter = null;
+
+ // ------------------------------------------------------------------------
+
+ public ByteConverterTestCase(String name) {
+ super(name);
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void setUp() throws Exception {
+ converter = makeConverter();
+ }
+
+ public static TestSuite suite() {
+ return new TestSuite(ByteConverterTestCase.class);
+ }
+
+ public void tearDown() throws Exception {
+ converter = null;
+ }
+
+ // ------------------------------------------------------------------------
+
+ protected Converter makeConverter() {
+ return new ByteConverter();
+ }
+
+ protected Class getExpectedType() {
+ return Byte.class;
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void testSimpleConversion() throws Exception {
+ String[] message= {
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from Byte",
+ "from Short",
+ "from Integer",
+ "from Long",
+ "from Float",
+ "from Double"
+ };
+
+ Object[] input = {
+ String.valueOf(Byte.MIN_VALUE),
+ "-17",
+ "-1",
+ "0",
+ "1",
+ "17",
+ String.valueOf(Byte.MAX_VALUE),
+ new Byte((byte)7),
+ new Short((short)8),
+ new Integer(9),
+ new Long(10),
+ new Float(11.1),
+ new Double(12.2)
+ };
+
+ Byte[] expected = {
+ new Byte(Byte.MIN_VALUE),
+ new Byte((byte)-17),
+ new Byte((byte)-1),
+ new Byte((byte)0),
+ new Byte((byte)1),
+ new Byte((byte)17),
+ new Byte(Byte.MAX_VALUE),
+ new Byte((byte)7),
+ new Byte((byte)8),
+ new Byte((byte)9),
+ new Byte((byte)10),
+ new Byte((byte)11),
+ new Byte((byte)12)
+ };
+
+ for(int i=0;i<expected.length;i++) {
+ assertEquals(message[i] + " to Byte",expected[i],converter.convert(Byte.class,input[i]));
+ assertEquals(message[i] + " to byte",expected[i],converter.convert(Byte.TYPE,input[i]));
+ assertEquals(message[i] + " to null type",expected[i],converter.convert(null,input[i]));
+ }
+ }
+
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ConverterTestSuite.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ConverterTestSuite.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ConverterTestSuite.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * <p>
+ * Created a test suite so that new test cases can be added here without having to
+ * edit the build.xml.
+ * </p>
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class ConverterTestSuite {
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ TestSuite testSuite = new TestSuite();
+ testSuite.addTestSuite(ByteConverterTestCase.class);
+ testSuite.addTestSuite(DoubleConverterTestCase.class);
+ testSuite.addTestSuite(FloatConverterTestCase.class);
+ testSuite.addTestSuite(IntegerConverterTestCase.class);
+ testSuite.addTestSuite(LongConverterTestCase.class);
+ testSuite.addTestSuite(ShortConverterTestCase.class);
+ testSuite.addTestSuite(StringArrayConverterTestCase.class);
+ return testSuite;
+ }
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/DoubleConverterTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/DoubleConverterTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/DoubleConverterTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import junit.framework.TestSuite;
+
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * Test Case for the DoubleConverter class.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class DoubleConverterTestCase extends NumberConverterTestBase {
+
+ private Converter converter = null;
+
+ // ------------------------------------------------------------------------
+
+ public DoubleConverterTestCase(String name) {
+ super(name);
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void setUp() throws Exception {
+ converter = makeConverter();
+ }
+
+ public static TestSuite suite() {
+ return new TestSuite(DoubleConverterTestCase.class);
+ }
+
+ public void tearDown() throws Exception {
+ converter = null;
+ }
+
+ // ------------------------------------------------------------------------
+
+ protected Converter makeConverter() {
+ return new DoubleConverter();
+ }
+
+ protected Class getExpectedType() {
+ return Double.class;
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void testSimpleConversion() throws Exception {
+ String[] message= {
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from Byte",
+ "from Short",
+ "from Integer",
+ "from Long",
+ "from Float",
+ "from Double"
+ };
+
+ Object[] input = {
+ String.valueOf(Double.MIN_VALUE),
+ "-17.2",
+ "-1.1",
+ "0.0",
+ "1.1",
+ "17.2",
+ String.valueOf(Double.MAX_VALUE),
+ new Byte((byte)7),
+ new Short((short)8),
+ new Integer(9),
+ new Long(10),
+ new Float(11.1),
+ new Double(12.2)
+ };
+
+ Double[] expected = {
+ new Double(Double.MIN_VALUE),
+ new Double(-17.2),
+ new Double(-1.1),
+ new Double(0.0),
+ new Double(1.1),
+ new Double(17.2),
+ new Double(Double.MAX_VALUE),
+ new Double(7),
+ new Double(8),
+ new Double(9),
+ new Double(10),
+ new Double(11.1),
+ new Double(12.2)
+ };
+
+ for(int i=0;i<expected.length;i++) {
+ assertEquals(
+ message[i] + " to Double",
+ expected[i].doubleValue(),
+ ((Double)(converter.convert(Double.class,input[i]))).doubleValue(),
+ 0.00001D);
+ assertEquals(
+ message[i] + " to double",
+ expected[i].doubleValue(),
+ ((Double)(converter.convert(Double.TYPE,input[i]))).doubleValue(),
+ 0.00001D);
+ assertEquals(
+ message[i] + " to null type",
+ expected[i].doubleValue(),
+ ((Double)(converter.convert(null,input[i]))).doubleValue(),
+ 0.00001D);
+ }
+ }
+
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/FileConverterTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/FileConverterTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/FileConverterTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * Test Case for the FileConverter class.
+ *
+ * @author James Strachan
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class FileConverterTestCase extends TestCase {
+
+ private Converter converter = null;
+
+ // ------------------------------------------------------------------------
+
+ public FileConverterTestCase(String name) {
+ super(name);
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void setUp() throws Exception {
+ converter = makeConverter();
+ }
+
+ public static TestSuite suite() {
+ return new TestSuite(FileConverterTestCase.class);
+ }
+
+ public void tearDown() throws Exception {
+ converter = null;
+ }
+
+ // ------------------------------------------------------------------------
+
+ protected Converter makeConverter() {
+ return new FileConverter();
+ }
+
+ protected Class getExpectedType() {
+ return File.class;
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void testSimpleConversion() throws Exception {
+ String[] message= {
+ "from String",
+ "from String",
+ "from String"
+ };
+
+ Object[] input = {
+ "/tmp",
+ "/tmp/foo.txt",
+ "/tmp/does/not/exist.foo"
+ };
+
+ File[] expected = {
+ new File("/tmp"),
+ new File("/tmp/foo.txt"),
+ new File("/tmp/does/not/exist.foo")
+ };
+
+ for(int i=0;i<expected.length;i++) {
+ assertEquals(message[i] + " to File",expected[i],converter.convert(File.class,input[i]));
+ assertEquals(message[i] + " to null type",expected[i],converter.convert(null,input[i]));
+ }
+ }
+
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/FloatConverterTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/FloatConverterTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/FloatConverterTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import junit.framework.TestSuite;
+
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * Test Case for the FloatConverter class.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class FloatConverterTestCase extends NumberConverterTestBase {
+
+ private Converter converter = null;
+
+ // ------------------------------------------------------------------------
+
+ public FloatConverterTestCase(String name) {
+ super(name);
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void setUp() throws Exception {
+ converter = makeConverter();
+ }
+
+ public static TestSuite suite() {
+ return new TestSuite(FloatConverterTestCase.class);
+ }
+
+ public void tearDown() throws Exception {
+ converter = null;
+ }
+
+ // ------------------------------------------------------------------------
+
+ protected Converter makeConverter() {
+ return new FloatConverter();
+ }
+
+ protected Class getExpectedType() {
+ return Float.class;
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void testSimpleConversion() throws Exception {
+ String[] message= {
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from Byte",
+ "from Short",
+ "from Integer",
+ "from Long",
+ "from Float",
+ "from Double"
+ };
+
+ Object[] input = {
+ String.valueOf(Float.MIN_VALUE),
+ "-17.2",
+ "-1.1",
+ "0.0",
+ "1.1",
+ "17.2",
+ String.valueOf(Float.MAX_VALUE),
+ new Byte((byte)7),
+ new Short((short)8),
+ new Integer(9),
+ new Long(10),
+ new Float(11.1),
+ new Double(12.2)
+ };
+
+ Float[] expected = {
+ new Float(Float.MIN_VALUE),
+ new Float(-17.2),
+ new Float(-1.1),
+ new Float(0.0),
+ new Float(1.1),
+ new Float(17.2),
+ new Float(Float.MAX_VALUE),
+ new Float(7),
+ new Float(8),
+ new Float(9),
+ new Float(10),
+ new Float(11.1),
+ new Float(12.2)
+ };
+
+ for(int i=0;i<expected.length;i++) {
+ assertEquals(
+ message[i] + " to Float",
+ expected[i].floatValue(),
+ ((Float)(converter.convert(Float.class,input[i]))).floatValue(),
+ 0.00001);
+ assertEquals(
+ message[i] + " to float",
+ expected[i].floatValue(),
+ ((Float)(converter.convert(Float.TYPE,input[i]))).floatValue(),
+ 0.00001);
+ assertEquals(
+ message[i] + " to null type",
+ expected[i].floatValue(),
+ ((Float)(converter.convert(null,input[i]))).floatValue(),
+ 0.00001);
+ }
+ }
+
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/IntegerConverterTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/IntegerConverterTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/IntegerConverterTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import junit.framework.TestSuite;
+
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * Test Case for the IntegerConverter class.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class IntegerConverterTestCase extends NumberConverterTestBase {
+
+ private Converter converter = null;
+
+ // ------------------------------------------------------------------------
+
+ public IntegerConverterTestCase(String name) {
+ super(name);
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void setUp() throws Exception {
+ converter = makeConverter();
+ }
+
+ public static TestSuite suite() {
+ return new TestSuite(IntegerConverterTestCase.class);
+ }
+
+ public void tearDown() throws Exception {
+ converter = null;
+ }
+
+ // ------------------------------------------------------------------------
+
+ protected Converter makeConverter() {
+ return new IntegerConverter();
+ }
+
+ protected Class getExpectedType() {
+ return Integer.class;
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void testSimpleConversion() throws Exception {
+ String[] message= {
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from Byte",
+ "from Short",
+ "from Integer",
+ "from Long",
+ "from Float",
+ "from Double"
+ };
+
+ Object[] input = {
+ String.valueOf(Integer.MIN_VALUE),
+ "-17",
+ "-1",
+ "0",
+ "1",
+ "17",
+ String.valueOf(Integer.MAX_VALUE),
+ new Byte((byte)7),
+ new Short((short)8),
+ new Integer(9),
+ new Long(10),
+ new Float(11.1),
+ new Double(12.2)
+ };
+
+ Integer[] expected = {
+ new Integer(Integer.MIN_VALUE),
+ new Integer(-17),
+ new Integer(-1),
+ new Integer(0),
+ new Integer(1),
+ new Integer(17),
+ new Integer(Integer.MAX_VALUE),
+ new Integer(7),
+ new Integer(8),
+ new Integer(9),
+ new Integer(10),
+ new Integer(11),
+ new Integer(12)
+ };
+
+ for(int i=0;i<expected.length;i++) {
+ assertEquals(message[i] + " to Integer",expected[i],converter.convert(Integer.class,input[i]));
+ assertEquals(message[i] + " to int",expected[i],converter.convert(Integer.TYPE,input[i]));
+ assertEquals(message[i] + " to null type",expected[i],converter.convert(null,input[i]));
+ }
+ }
+
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/LongConverterTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/LongConverterTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/LongConverterTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import junit.framework.TestSuite;
+
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * Test Case for the LongConverter class.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class LongConverterTestCase extends NumberConverterTestBase {
+
+ private Converter converter = null;
+
+ // ------------------------------------------------------------------------
+
+ public LongConverterTestCase(String name) {
+ super(name);
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void setUp() throws Exception {
+ converter = makeConverter();
+ }
+
+ public static TestSuite suite() {
+ return new TestSuite(LongConverterTestCase.class);
+ }
+
+ public void tearDown() throws Exception {
+ converter = null;
+ }
+
+ // ------------------------------------------------------------------------
+
+ protected Converter makeConverter() {
+ return new LongConverter();
+ }
+
+ protected Class getExpectedType() {
+ return Long.class;
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void testSimpleConversion() throws Exception {
+ String[] message= {
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from Byte",
+ "from Short",
+ "from Integer",
+ "from Long",
+ "from Float",
+ "from Double"
+ };
+
+ Object[] input = {
+ String.valueOf(Long.MIN_VALUE),
+ "-17",
+ "-1",
+ "0",
+ "1",
+ "17",
+ String.valueOf(Long.MAX_VALUE),
+ new Byte((byte)7),
+ new Short((short)8),
+ new Integer(9),
+ new Long(10),
+ new Float(11.1),
+ new Double(12.2)
+ };
+
+ Long[] expected = {
+ new Long(Long.MIN_VALUE),
+ new Long(-17),
+ new Long(-1),
+ new Long(0),
+ new Long(1),
+ new Long(17),
+ new Long(Long.MAX_VALUE),
+ new Long(7),
+ new Long(8),
+ new Long(9),
+ new Long(10),
+ new Long(11),
+ new Long(12)
+ };
+
+ for(int i=0;i<expected.length;i++) {
+ assertEquals(message[i] + " to Long",expected[i],converter.convert(Long.class,input[i]));
+ assertEquals(message[i] + " to long",expected[i],converter.convert(Long.TYPE,input[i]));
+ assertEquals(message[i] + " to null type",expected[i],converter.convert(null,input[i]));
+ }
+ }
+
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/NumberConverterTestBase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/NumberConverterTestBase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/NumberConverterTestBase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * Abstract base for <Number>Converter classes.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public abstract class NumberConverterTestBase extends TestCase {
+
+ // ------------------------------------------------------------------------
+
+ public NumberConverterTestBase(String name) {
+ super(name);
+ }
+
+ // ------------------------------------------------------------------------
+
+ protected abstract Converter makeConverter();
+ protected abstract Class getExpectedType();
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Assumes ConversionException in response to covert(getExpectedType(),null).
+ */
+ public void testConvertNull() throws Exception {
+ try {
+ makeConverter().convert(getExpectedType(),null);
+ fail("Expected ConversionException");
+ } catch(ConversionException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Assumes convert(getExpectedType(),Number) returns some non-null
+ * instance of getExpectedType().
+ */
+ public void testConvertNumber() throws Exception {
+ String[] message= {
+ "from Byte",
+ "from Short",
+ "from Integer",
+ "from Long",
+ "from Float",
+ "from Double"
+ };
+
+ Object[] number = {
+ new Byte((byte)7),
+ new Short((short)8),
+ new Integer(9),
+ new Long(10),
+ new Float(11.1),
+ new Double(12.2)
+ };
+
+ for(int i=0;i<number.length;i++) {
+ Object val = makeConverter().convert(getExpectedType(),number[i]);
+ assertNotNull("Convert " + message[i] + " should not be null",val);
+ assertTrue(
+ "Convert " + message[i] + " should return a " + getExpectedType().getName(),
+ getExpectedType().isInstance(val));
+ }
+ }
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ShortConverterTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ShortConverterTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/ShortConverterTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import junit.framework.TestSuite;
+
+import org.apache.commons.beanutils.Converter;
+
+
+/**
+ * Test Case for the ShortConverter class.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class ShortConverterTestCase extends NumberConverterTestBase {
+
+ private Converter converter = null;
+
+ // ------------------------------------------------------------------------
+
+ public ShortConverterTestCase(String name) {
+ super(name);
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void setUp() throws Exception {
+ converter = makeConverter();
+ }
+
+ public static TestSuite suite() {
+ return new TestSuite(ShortConverterTestCase.class);
+ }
+
+ public void tearDown() throws Exception {
+ converter = null;
+ }
+
+ // ------------------------------------------------------------------------
+
+ protected Converter makeConverter() {
+ return new ShortConverter();
+ }
+
+ protected Class getExpectedType() {
+ return Short.class;
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void testSimpleConversion() throws Exception {
+ String[] message= {
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from Byte",
+ "from Short",
+ "from Integer",
+ "from Long",
+ "from Float",
+ "from Double"
+ };
+
+ Object[] input = {
+ String.valueOf(Short.MIN_VALUE),
+ "-17",
+ "-1",
+ "0",
+ "1",
+ "17",
+ String.valueOf(Short.MAX_VALUE),
+ new Byte((byte)7),
+ new Short((short)8),
+ new Integer(9),
+ new Long(10),
+ new Float(11.1),
+ new Double(12.2)
+ };
+
+ Short[] expected = {
+ new Short(Short.MIN_VALUE),
+ new Short((short)-17),
+ new Short((short)-1),
+ new Short((short)0),
+ new Short((short)1),
+ new Short((short)17),
+ new Short(Short.MAX_VALUE),
+ new Short((short)7),
+ new Short((short)8),
+ new Short((short)9),
+ new Short((short)10),
+ new Short((short)11),
+ new Short((short)12)
+ };
+
+ for(int i=0;i<expected.length;i++) {
+ assertEquals(message[i] + " to Short",expected[i],converter.convert(Short.class,input[i]));
+ assertEquals(message[i] + " to short",expected[i],converter.convert(Short.TYPE,input[i]));
+ assertEquals(message[i] + " to null type",expected[i],converter.convert(null,input[i]));
+ }
+ }
+
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/StringArrayConverterTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/StringArrayConverterTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/StringArrayConverterTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import junit.framework.TestCase;
+import junit.framework.TestCase;
+
+/**
+ * Test Case for StringArrayConverter
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class StringArrayConverterTestCase extends TestCase {
+
+ public StringArrayConverterTestCase(String name) {
+ super(name);
+ }
+
+ public void testIntToString() {
+
+ int[] testArray = {1, 2, 3, 4, 5};
+ String[] results = (String []) new StringArrayConverter().convert(String.class, testArray);
+
+ assertEquals("Incorrect results size", 5, results.length);
+ assertEquals("Entry one is wrong", "1", results[0]);
+ assertEquals("Entry two is wrong", "2", results[1]);
+ assertEquals("Entry three is wrong", "3", results[2]);
+ assertEquals("Entry four is wrong", "4", results[3]);
+ assertEquals("Entry five is wrong", "5", results[4]);
+ }
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/URLConverterTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/URLConverterTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/converters/URLConverterTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.converters;
+
+import junit.framework.TestSuite;
+import junit.framework.TestCase;
+
+import org.apache.commons.beanutils.Converter;
+
+import java.net.URL;
+
+
+/**
+ * Test Case for the URLConverter class.
+ *
+ * @author Henri Yandell
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class URLConverterTestCase extends TestCase {
+
+ private Converter converter = null;
+
+ // ------------------------------------------------------------------------
+
+ public URLConverterTestCase(String name) {
+ super(name);
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void setUp() throws Exception {
+ converter = makeConverter();
+ }
+
+ public static TestSuite suite() {
+ return new TestSuite(URLConverterTestCase.class);
+ }
+
+ public void tearDown() throws Exception {
+ converter = null;
+ }
+
+ // ------------------------------------------------------------------------
+
+ protected Converter makeConverter() {
+ return new URLConverter();
+ }
+
+ protected Class getExpectedType() {
+ return URL.class;
+ }
+
+ // ------------------------------------------------------------------------
+
+ public void testSimpleConversion() throws Exception {
+ String[] message= {
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ "from String",
+ };
+
+ Object[] input = {
+ "http://www.apache.org",
+ "http://www.apache.org/",
+ "ftp://cvs.apache.org",
+ "file://project.xml",
+ "http://208.185.179.12",
+ "http://www.apache.org:9999/test/thing",
+ "http://user:admin@www.apache.org:50/one/two.three",
+ "http://notreal.apache.org",
+ };
+
+ URL[] expected = {
+ new URL("http://www.apache.org"),
+ new URL("http://www.apache.org/"),
+ new URL("ftp://cvs.apache.org"),
+ new URL("file://project.xml"),
+ new URL("http://208.185.179.12"),
+ new URL("http://www.apache.org:9999/test/thing"),
+ new URL("http://user:admin@www.apache.org:50/one/two.three"),
+ new URL("http://notreal.apache.org")
+ };
+
+ for(int i=0;i<expected.length;i++) {
+ assertEquals(message[i] + " to URL",expected[i],converter.convert(URL.class,input[i]));
+ assertEquals(message[i] + " to null type",expected[i],converter.convert(null,input[i]));
+ }
+ }
+
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleBeanificationTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleBeanificationTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleBeanificationTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,533 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale;
+
+import java.util.*;
+
+import java.lang.ref.WeakReference;
+import java.lang.ref.ReferenceQueue;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.collections.ReferenceMap;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.commons.beanutils.ContextClassLoaderLocal;
+import org.apache.commons.beanutils.PrimitiveBean;
+
+/**
+ * <p>
+ * Test Case for changes made during LocaleBeanutils Beanification.
+ * This is basically a cut-and-correct version of the beanutils beanifications tests.
+ * </p>
+ *
+ * @author Robert Burrell Donkin
+ * @author Juozas Baliuka
+ * @version $Revision: 1.2 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class LocaleBeanificationTestCase extends TestCase {
+
+ // ---------------------------------------------------- Constants
+
+ /** Maximum number of iterations before our test fails */
+ public static final int MAX_GC_ITERATIONS = 50;
+
+ // ---------------------------------------------------- Instance Variables
+
+
+ // ---------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public LocaleBeanificationTestCase(String name) {
+ super(name);
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+
+ LocaleConvertUtils.deregister();
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(LocaleBeanificationTestCase.class));
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ ; // No action required
+ }
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+ /** Test of the methodology we'll use for some of the later tests */
+ public void testMemoryTestMethodology() throws Exception {
+ // test methodology
+ // many thanks to Juozas Baliuka for suggesting this method
+ ClassLoader loader = new ClassLoader() {};
+ WeakReference reference = new WeakReference(loader);
+ Class myClass = loader.loadClass("org.apache.commons.beanutils.BetaBean");
+
+ assertNotNull("Weak reference released early", reference.get());
+
+ // dereference class loader and class:
+ loader = null;
+ myClass = null;
+
+ int iterations = 0;
+ int bytz = 2;
+ while(true) {
+ System.gc();
+ if(iterations++ > MAX_GC_ITERATIONS){
+ fail("Max iterations reached before resource released.");
+ }
+ if( reference.get() == null ) {
+ break;
+
+ } else {
+ // create garbage:
+ byte[] b = new byte[bytz];
+ bytz = bytz * 2;
+ }
+ }
+ }
+
+ /** Tests whether classloaders and beans are released from memory by the map used by beanutils */
+ public void testMemoryLeak2() throws Exception {
+ // tests when the map used by beanutils has the right behaviour
+
+ if (isPre14JVM()) {
+ System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");
+ return;
+ }
+
+ // many thanks to Juozas Baliuka for suggesting this methodology
+ TestClassLoader loader = new TestClassLoader();
+ ReferenceQueue queue = new ReferenceQueue();
+ WeakReference loaderReference = new WeakReference(loader, queue);
+ Integer test = new Integer(1);
+
+ WeakReference testReference = new WeakReference(test, queue);
+ //Map map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD, true);
+ Map map = new WeakHashMap();
+ map.put(loader, test);
+
+ assertEquals("In map", test, map.get(loader));
+ assertNotNull("Weak reference released early (1)", loaderReference.get());
+ assertNotNull("Weak reference released early (2)", testReference.get());
+
+ // dereference strong references
+ loader = null;
+ test = null;
+
+ int iterations = 0;
+ int bytz = 2;
+ while(true) {
+ System.gc();
+ if(iterations++ > MAX_GC_ITERATIONS){
+ fail("Max iterations reached before resource released.");
+ }
+ map.isEmpty();
+
+ if(
+ loaderReference.get() == null &&
+ testReference.get() == null) {
+ break;
+
+ } else {
+ // create garbage:
+ byte[] b = new byte[bytz];
+ bytz = bytz * 2;
+ }
+ }
+ }
+
+ /** Tests whether classloaders and beans are released from memory */
+ public void testMemoryLeak() throws Exception {
+ if (isPre14JVM()) {
+ System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");
+ return;
+ }
+
+ // many thanks to Juozas Baliuka for suggesting this methodology
+ TestClassLoader loader = new TestClassLoader();
+ WeakReference loaderReference = new WeakReference(loader);
+ LocaleBeanUtilsBean.getLocaleBeanUtilsInstance();
+
+ class GetBeanUtilsBeanThread extends Thread {
+
+ LocaleBeanUtilsBean beanUtils;
+ LocaleConvertUtilsBean convertUtils;
+
+ GetBeanUtilsBeanThread() {}
+
+ public void run() {
+ beanUtils = LocaleBeanUtilsBean.getLocaleBeanUtilsInstance();
+ convertUtils = LocaleConvertUtilsBean.getInstance();
+ // XXX Log keeps a reference around!
+ LogFactory.releaseAll();
+ }
+
+ public String toString() {
+ return "GetBeanUtilsBeanThread";
+ }
+ }
+
+
+ GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread();
+ WeakReference threadWeakReference = new WeakReference(thread);
+ thread.setContextClassLoader(loader);
+
+ thread.start();
+ thread.join();
+
+ WeakReference beanUtilsReference = new WeakReference(thread.beanUtils);
+ WeakReference convertUtilsReference = new WeakReference(thread.convertUtils);
+
+ assertNotNull("Weak reference released early (1)", loaderReference.get());
+ assertNotNull("Weak reference released early (2)", beanUtilsReference.get());
+ assertNotNull("Weak reference released early (4)", convertUtilsReference.get());
+
+ // dereference strong references
+ loader = null;
+ thread.setContextClassLoader(null);
+ thread = null;
+
+ int iterations = 0;
+ int bytz = 2;
+ while(true) {
+ LocaleBeanUtilsBean.getLocaleBeanUtilsInstance();
+ System.gc();
+ if(iterations++ > MAX_GC_ITERATIONS){
+ fail("Max iterations reached before resource released.");
+ }
+
+ if(
+ loaderReference.get() == null &&
+ beanUtilsReference.get() == null &&
+ convertUtilsReference.get() == null) {
+ break;
+
+ } else {
+ // create garbage:
+ byte[] b = new byte[bytz];
+ bytz = bytz * 2;
+ }
+ }
+ }
+
+ /**
+ * Tests whether difference instances are loaded by different
+ * context classloaders.
+ */
+ public void testGetByContextClassLoader() throws Exception {
+
+ class GetBeanUtilsBeanThread extends Thread {
+
+ private Signal signal;
+
+ GetBeanUtilsBeanThread(Signal signal) {
+ this.signal = signal;
+ }
+
+ public void run() {
+ signal.setSignal(2);
+ signal.setBean(LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());
+ signal.setConvertUtils(LocaleConvertUtilsBean.getInstance());
+ }
+
+ public String toString() {
+ return "GetBeanUtilsBeanThread";
+ }
+ }
+
+ Signal signal = new Signal();
+ signal.setSignal(1);
+
+ GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread(signal);
+ thread.setContextClassLoader(new TestClassLoader());
+
+ thread.start();
+ thread.join();
+
+ assertEquals("Signal not set by test thread", 2, signal.getSignal());
+ assertTrue(
+ "Different LocaleBeanUtilsBean instances per context classloader",
+ LocaleBeanUtilsBean.getInstance() != signal.getBean());
+ assertTrue(
+ "Different LocaleConvertUtilsBean instances per context classloader",
+ LocaleConvertUtilsBean.getInstance() != signal.getConvertUtils());
+ }
+
+
+ /**
+ * Tests whether difference instances are loaded by different
+ * context classloaders.
+ */
+ public void testContextClassLoaderLocal() throws Exception {
+
+ class CCLLTesterThread extends Thread {
+
+ private Signal signal;
+ private ContextClassLoaderLocal ccll;
+
+ CCLLTesterThread(Signal signal, ContextClassLoaderLocal ccll) {
+ this.signal = signal;
+ this.ccll = ccll;
+ }
+
+ public void run() {
+ ccll.set(new Integer(1789));
+ signal.setSignal(2);
+ signal.setMarkerObject(ccll.get());
+ }
+
+ public String toString() {
+ return "CCLLTesterThread";
+ }
+ }
+
+ ContextClassLoaderLocal ccll = new ContextClassLoaderLocal();
+ ccll.set(new Integer(1776));
+ assertEquals("Start thread sets value", new Integer(1776), ccll.get());
+
+ Signal signal = new Signal();
+ signal.setSignal(1);
+
+ CCLLTesterThread thread = new CCLLTesterThread(signal, ccll);
+ thread.setContextClassLoader(new TestClassLoader());
+
+ thread.start();
+ thread.join();
+
+ assertEquals("Signal not set by test thread", 2, signal.getSignal());
+ assertEquals("Second thread preserves value", new Integer(1776), ccll.get());
+ assertEquals("Second thread gets value it set", new Integer(1789), signal.getMarkerObject());
+ }
+
+ /** Tests whether calls are independent for different classloaders */
+ public void testContextClassloaderIndependence() throws Exception {
+
+ class TestIndependenceThread extends Thread {
+ private Signal signal;
+ private PrimitiveBean bean;
+
+ TestIndependenceThread(Signal signal, PrimitiveBean bean) {
+ this.signal = signal;
+ this.bean = bean;
+ }
+
+ public void run() {
+ try {
+ signal.setSignal(3);
+ LocaleConvertUtils.register(new LocaleConverter() {
+ public Object convert(Class type, Object value) {
+ return new Integer(9);
+ }
+ public Object convert(Class type, Object value, String pattern) {
+ return new Integer(9);
+ }
+ }, Integer.TYPE, Locale.getDefault());
+ LocaleBeanUtils.setProperty(bean, "int", "1");
+ } catch (Exception e) {
+ e.printStackTrace();
+ signal.setException(e);
+ }
+ }
+
+ public String toString() {
+ return "TestIndependenceThread";
+ }
+ }
+
+ PrimitiveBean bean = new PrimitiveBean();
+ LocaleBeanUtils.setProperty(bean, "int", new Integer(1));
+ assertEquals("Wrong property value (1)", 1, bean.getInt());
+
+ LocaleConvertUtils.register(new LocaleConverter() {
+ public Object convert(Class type, Object value) {
+ return new Integer(5);
+ }
+ public Object convert(Class type, Object value, String pattern) {
+ return new Integer(5);
+ }
+ }, Integer.TYPE, Locale.getDefault());
+ LocaleBeanUtils.setProperty(bean, "int", "1");
+ assertEquals("Wrong property value(2)", 5, bean.getInt());
+
+ Signal signal = new Signal();
+ signal.setSignal(1);
+ TestIndependenceThread thread = new TestIndependenceThread(signal, bean);
+ thread.setContextClassLoader(new TestClassLoader());
+
+ thread.start();
+ thread.join();
+
+ assertNull("Exception thrown by test thread:" + signal.getException(), signal.getException());
+ assertEquals("Signal not set by test thread", 3, signal.getSignal());
+ assertEquals("Wrong property value(3)", 9, bean.getInt());
+
+ }
+
+ /** Tests whether different threads can set beanutils instances correctly */
+ public void testBeanUtilsBeanSetInstance() throws Exception {
+
+ class SetInstanceTesterThread extends Thread {
+
+ private Signal signal;
+ private LocaleBeanUtilsBean bean;
+
+ SetInstanceTesterThread(Signal signal, LocaleBeanUtilsBean bean) {
+ this.signal = signal;
+ this.bean = bean;
+ }
+
+ public void run() {
+ LocaleBeanUtilsBean.setInstance(bean);
+ signal.setSignal(21);
+ signal.setBean(LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());
+ }
+
+ public String toString() {
+ return "SetInstanceTesterThread";
+ }
+ }
+
+ Signal signal = new Signal();
+ signal.setSignal(1);
+
+ LocaleBeanUtilsBean beanOne = new LocaleBeanUtilsBean();
+ LocaleBeanUtilsBean beanTwo = new LocaleBeanUtilsBean();
+
+ SetInstanceTesterThread thread = new SetInstanceTesterThread(signal, beanTwo);
+ thread.setContextClassLoader(new TestClassLoader());
+
+ LocaleBeanUtilsBean.setInstance(beanOne);
+ assertEquals("Start thread gets right instance", beanOne, LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());
+
+ thread.start();
+ thread.join();
+
+ assertEquals("Signal not set by test thread", 21, signal.getSignal());
+ assertEquals("Second thread preserves value", beanOne, LocaleBeanUtilsBean.getLocaleBeanUtilsInstance());
+ assertEquals("Second thread gets value it set", beanTwo, signal.getBean());
+ }
+
+ /** Tests whether the unset method works*/
+ public void testContextClassLoaderUnset() throws Exception {
+ LocaleBeanUtilsBean beanOne = new LocaleBeanUtilsBean();
+ ContextClassLoaderLocal ccll = new ContextClassLoaderLocal();
+ ccll.set(beanOne);
+ assertEquals("Start thread gets right instance", beanOne, ccll.get());
+ ccll.unset();
+ assertTrue("Unset works", !beanOne.equals(ccll.get()));
+ }
+
+ private boolean isPre14JVM() {
+ // some pre 1.4 JVM have buggy WeakHashMap implementations
+ // this is used to test for those JVM
+ String version = System.getProperty("java.specification.version");
+ StringTokenizer tokenizer = new StringTokenizer(version,".");
+ if (tokenizer.nextToken().equals("1")) {
+ String minorVersion = tokenizer.nextToken();
+ if (minorVersion.equals("0")) return true;
+ if (minorVersion.equals("1")) return true;
+ if (minorVersion.equals("2")) return true;
+ if (minorVersion.equals("3")) return true;
+ }
+ return false;
+ }
+
+ // ---- Auxillary classes
+
+ class TestClassLoader extends ClassLoader {
+ public String toString() {
+ return "TestClassLoader";
+ }
+ }
+
+ class Signal {
+ private Exception e;
+ private int signal = 0;
+ private LocaleBeanUtilsBean bean;
+ private LocaleConvertUtilsBean convertUtils;
+ private Object marker;
+
+ public Exception getException() {
+ return e;
+ }
+
+ public void setException(Exception e) {
+ this.e = e;
+ }
+
+ public int getSignal() {
+ return signal;
+ }
+
+ public void setSignal(int signal) {
+ this.signal = signal;
+ }
+
+ public Object getMarkerObject() {
+ return marker;
+ }
+
+ public void setMarkerObject(Object marker) {
+ this.marker = marker;
+ }
+
+ public LocaleBeanUtilsBean getBean() {
+ return bean;
+ }
+
+ public void setBean(LocaleBeanUtilsBean bean) {
+ this.bean = bean;
+ }
+
+ public LocaleConvertUtilsBean getConvertUtils() {
+ return convertUtils;
+ }
+
+ public void setConvertUtils(LocaleConvertUtilsBean convertUtils) {
+ this.convertUtils = convertUtils;
+ }
+ }
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleConvertTestSuite.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleConvertTestSuite.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleConvertTestSuite.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.commons.beanutils.locale.converters.DateLocaleConverterTestCase;
+
+/**
+ * <p>
+ * Created a test suite so that new test cases can be added here without having to
+ * edit the build.xml.
+ * </p>
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 1.6 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class LocaleConvertTestSuite {
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ TestSuite testSuite = new TestSuite();
+ testSuite.addTestSuite(LocaleConvertUtilsTestCase.class);
+ testSuite.addTestSuite(DateLocaleConverterTestCase.class);
+ testSuite.addTestSuite(LocaleBeanificationTestCase.class);
+ return testSuite;
+ }
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleConvertUtilsTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleConvertUtilsTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/LocaleConvertUtilsTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,639 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.HashMap;
+import java.util.Locale;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.commons.beanutils.ConvertUtils;
+import org.apache.commons.beanutils.ConversionException;
+
+
+/**
+ * <p>
+ * Test Case for the LocaleConvertUtils class.
+ * See unimplemented functionality of the convert utils in the method begining with fixme
+ * </p>
+ *
+ * @author Michael Szlapa
+ * @author Paul Hamamnt & Rune Johannesen (pairing) - patches.
+ * @version $Revision: 1.7 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class LocaleConvertUtilsTestCase extends TestCase {
+
+ // ---------------------------------------------------- Instance Variables
+
+ private char m_decimalSeparator;
+
+ // ---------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public LocaleConvertUtilsTestCase(String name) {
+ super(name);
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+
+ LocaleConvertUtils.deregister();
+
+ NumberFormat nf = DecimalFormat.getNumberInstance();
+ String result = nf.format(1.1);
+
+ // could be commas instead of stops in Europe.
+ m_decimalSeparator = result.charAt(1);
+
+
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(LocaleConvertUtilsTestCase.class));
+ }
+
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ ; // No action required
+ }
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ /**
+ * Negative String to primitive integer array tests.
+ */
+ public void fixmetestNegativeIntegerArray() {
+
+ fail("Array conversions not implemented yet.");
+
+ Object value = null;
+ int intArray[] = new int[0];
+
+ value = LocaleConvertUtils.convert((String) null, intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = LocaleConvertUtils.convert("a", intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = LocaleConvertUtils.convert("{ a }", intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = LocaleConvertUtils.convert("1a3", intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = LocaleConvertUtils.convert("{ 1a3 }", intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = LocaleConvertUtils.convert("0,1a3", intArray.getClass());
+ checkIntegerArray(value, intArray);
+ value = LocaleConvertUtils.convert("{ 0, 1a3 }", intArray.getClass());
+ checkIntegerArray(value, intArray);
+
+ }
+
+
+ /**
+ * Negative scalar conversion tests. These rely on the standard
+ * default value conversions in LocaleConvertUtils.
+ */
+ public void fixmetestNegativeScalar() {
+
+ Object value = null;
+
+ /* fixme Boolean converters not implemented at this point
+ value = LocaleConvertUtils.convert("foo", Boolean.TYPE);
+ ...
+
+ value = LocaleConvertUtils.convert("foo", Boolean.class);
+ ...
+ */
+
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Byte.TYPE);
+ fail("Should have thrown conversion exception (1)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Byte.class);
+ fail("Should have thrown conversion exception (2)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ /* fixme - not implemented
+ try {
+ value = LocaleConvertUtils.convert("org.apache.commons.beanutils.Undefined", Class.class);
+ fail("Should have thrown conversion exception");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+ */
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Double.TYPE);
+ fail("Should have thrown conversion exception (3)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Double.class);
+ fail("Should have thrown conversion exception (4)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Float.TYPE);
+ fail("Should have thrown conversion exception (5)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Float.class);
+ fail("Should have thrown conversion exception (6)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Integer.TYPE);
+ fail("Should have thrown conversion exception (7)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Integer.class);
+ fail("Should have thrown conversion exception (8)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Byte.TYPE);
+ fail("Should have thrown conversion exception (9)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Long.class);
+ fail("Should have thrown conversion exception (10)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Short.TYPE);
+ fail("Should have thrown conversion exception (11)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ try {
+ value = LocaleConvertUtils.convert("foo", Short.class);
+ fail("Should have thrown conversion exception (12)");
+ } catch (ConversionException e) {
+ ; // Expected result
+ }
+
+ }
+
+
+ /**
+ * Negative String to String array tests.
+ */
+ public void fixmetestNegativeStringArray() {
+
+ fail("Array conversions not implemented yet.");
+
+ Object value = null;
+ String stringArray[] = new String[0];
+
+ value = LocaleConvertUtils.convert((String) null, stringArray.getClass());
+ checkStringArray(value, stringArray);
+ }
+
+
+ /**
+ * Test conversion of object to string for arrays - .
+ */
+ public void fixmetestObjectToStringArray() {
+
+ fail("Array conversions not implemented yet.");
+ int intArray0[] = new int[0];
+ int intArray1[] = {123};
+ int intArray2[] = {123, 456};
+ String stringArray0[] = new String[0];
+ String stringArray1[] = {"abc"};
+ String stringArray2[] = {"abc", "def"};
+
+ assertEquals("intArray0", null,
+ LocaleConvertUtils.convert(intArray0));
+ assertEquals("intArray1", "123",
+ LocaleConvertUtils.convert(intArray1));
+ assertEquals("intArray2", "123",
+ LocaleConvertUtils.convert(intArray2));
+
+ assertEquals("stringArray0", null,
+ LocaleConvertUtils.convert(stringArray0));
+ assertEquals("stringArray1", "abc",
+ LocaleConvertUtils.convert(stringArray1));
+ assertEquals("stringArray2", "abc",
+ LocaleConvertUtils.convert(stringArray2));
+
+ }
+
+
+ /**
+ * Test conversion of object to string for scalars.
+ */
+ public void testObjectToStringScalar() {
+
+ assertEquals("Boolean->String", "false",
+ LocaleConvertUtils.convert(Boolean.FALSE));
+ assertEquals("Boolean->String", "true",
+ LocaleConvertUtils.convert(Boolean.TRUE));
+ assertEquals("Byte->String", "123",
+ LocaleConvertUtils.convert(new Byte((byte) 123)));
+ assertEquals("Character->String", "a",
+ LocaleConvertUtils.convert(new Character('a')));
+ assertEquals("Double->String", "123" + m_decimalSeparator + "4",
+ LocaleConvertUtils.convert(new Double((double) 123.4)));
+ assertEquals("Float->String", "123" + m_decimalSeparator + "4",
+ LocaleConvertUtils.convert(new Float((float) 123.4)));
+ assertEquals("Integer->String", "123",
+ LocaleConvertUtils.convert(new Integer((int) 123)));
+ assertEquals("Long->String", "123",
+ LocaleConvertUtils.convert(new Long((long) 123)));
+ assertEquals("Short->String", "123",
+ LocaleConvertUtils.convert(new Short((short) 123)));
+ assertEquals("String->String", "abc",
+ LocaleConvertUtils.convert("abc"));
+ assertEquals("String->String null", null,
+ LocaleConvertUtils.convert(null));
+
+ }
+
+
+ /**
+ * Positive array conversion tests.
+ */
+ public void fixmetestPositiveArray() {
+
+ fail("Array conversions not implemented yet.");
+
+ String values1[] = {"10", "20", "30"};
+ Object value = LocaleConvertUtils.convert(values1, Integer.TYPE);
+ int shape[] = new int[0];
+ assertEquals(shape.getClass(), value.getClass());
+ int results1[] = (int[]) value;
+ assertEquals(results1[0], 10);
+ assertEquals(results1[1], 20);
+ assertEquals(results1[2], 30);
+
+ String values2[] = {"100", "200", "300"};
+ value = LocaleConvertUtils.convert(values2, shape.getClass());
+ assertEquals(shape.getClass(), value.getClass());
+ int results2[] = (int[]) value;
+ assertEquals(results2[0], 100);
+ assertEquals(results2[1], 200);
+ assertEquals(results2[2], 300);
+ }
+
+
+ /**
+ * Positive String to primitive integer array tests.
+ */
+ public void fixmetestPositiveIntegerArray() {
+
+ fail("Array conversions not implemented yet.");
+
+ Object value = null;
+ int intArray[] = new int[0];
+ int intArray1[] = new int[]{0};
+ int intArray2[] = new int[]{0, 10};
+
+ value = LocaleConvertUtils.convert("{ }", intArray.getClass());
+ checkIntegerArray(value, intArray);
+
+ value = LocaleConvertUtils.convert("0", intArray.getClass());
+ checkIntegerArray(value, intArray1);
+ value = LocaleConvertUtils.convert(" 0 ", intArray.getClass());
+ checkIntegerArray(value, intArray1);
+ value = LocaleConvertUtils.convert("{ 0 }", intArray.getClass());
+ checkIntegerArray(value, intArray1);
+
+ value = LocaleConvertUtils.convert("0,10", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ value = LocaleConvertUtils.convert("0 10", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ value = LocaleConvertUtils.convert("{0,10}", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ value = LocaleConvertUtils.convert("{0 10}", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ value = LocaleConvertUtils.convert("{ 0, 10 }", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ value = LocaleConvertUtils.convert("{ 0 10 }", intArray.getClass());
+ checkIntegerArray(value, intArray2);
+ }
+
+
+ /**
+ * Positive scalar conversion tests.
+ */
+ public void testPositiveScalar() {
+ Object value = null;
+
+ /* fixme Boolean converters not implemented
+ value = LocaleConvertUtils.convert("true", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = LocaleConvertUtils.convert("true", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = LocaleConvertUtils.convert("yes", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = LocaleConvertUtils.convert("yes", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = LocaleConvertUtils.convert("y", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = LocaleConvertUtils.convert("y", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = LocaleConvertUtils.convert("on", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = LocaleConvertUtils.convert("on", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), true);
+
+ value = LocaleConvertUtils.convert("false", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = LocaleConvertUtils.convert("false", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = LocaleConvertUtils.convert("no", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = LocaleConvertUtils.convert("no", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = LocaleConvertUtils.convert("n", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = LocaleConvertUtils.convert("n", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = LocaleConvertUtils.convert("off", Boolean.TYPE);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+
+ value = LocaleConvertUtils.convert("off", Boolean.class);
+ assertTrue(value instanceof Boolean);
+ assertEquals(((Boolean) value).booleanValue(), false);
+ */
+
+ value = LocaleConvertUtils.convert("123", Byte.TYPE);
+ assertTrue(value instanceof Byte);
+ assertEquals(((Byte) value).byteValue(), (byte) 123);
+
+ value = LocaleConvertUtils.convert("123", Byte.class);
+ assertTrue(value instanceof Byte);
+ assertEquals(((Byte) value).byteValue(), (byte) 123);
+
+ /*fixme Character conversion not implemented yet
+ value = LocaleConvertUtils.convert("a", Character.TYPE);
+ assertTrue(value instanceof Character);
+ assertEquals(((Character) value).charValue(), 'a');
+
+ value = LocaleConvertUtils.convert("a", Character.class);
+ assertTrue(value instanceof Character);
+ assertEquals(((Character) value).charValue(), 'a');
+ */
+ /* fixme - this is a discrepancy with standard converters ( probably not major issue )
+ value = LocaleConvertUtils.convert("java.lang.String", Class.class);
+ assertTrue(value instanceof Class);
+ assertEquals(String.class, (Class) value);
+ */
+
+ value = LocaleConvertUtils.convert("123" + m_decimalSeparator + "456", Double.TYPE);
+ assertTrue(value instanceof Double);
+ assertEquals(((Double) value).doubleValue(), (double) 123.456,
+ (double) 0.005);
+
+ value = LocaleConvertUtils.convert("123" + m_decimalSeparator + "456", Double.class);
+ assertTrue(value instanceof Double);
+ assertEquals(((Double) value).doubleValue(), (double) 123.456,
+ (double) 0.005);
+
+ value = LocaleConvertUtils.convert("123" + m_decimalSeparator + "456", Float.TYPE);
+ assertTrue(value instanceof Float);
+ assertEquals(((Float) value).floatValue(), (float) 123.456,
+ (float) 0.005);
+
+ value = LocaleConvertUtils.convert("123" + m_decimalSeparator + "456", Float.class);
+ assertTrue(value instanceof Float);
+ assertEquals(((Float) value).floatValue(), (float) 123.456,
+ (float) 0.005);
+
+ value = LocaleConvertUtils.convert("123", Integer.TYPE);
+ assertTrue(value instanceof Integer);
+ assertEquals(((Integer) value).intValue(), (int) 123);
+
+ value = LocaleConvertUtils.convert("123", Integer.class);
+ assertTrue(value instanceof Integer);
+ assertEquals(((Integer) value).intValue(), (int) 123);
+
+ value = LocaleConvertUtils.convert("123", Long.TYPE);
+ assertTrue(value instanceof Long);
+ assertEquals(((Long) value).longValue(), (long) 123);
+
+ value = LocaleConvertUtils.convert("123456", Long.class);
+ assertTrue(value instanceof Long);
+ assertEquals(((Long) value).longValue(), (long) 123456);
+
+ /* fixme - Short conversion not implemented at this point
+ value = LocaleConvertUtils.convert("123", Short.TYPE);
+ assertTrue(value instanceof Short);
+ assertEquals(((Short) value).shortValue(), (short) 123);
+
+ value = LocaleConvertUtils.convert("123", Short.class);
+ assertTrue(value instanceof Short);
+ assertEquals(((Short) value).shortValue(), (short) 123);
+ */
+
+ String input = null;
+
+ input = "2002-03-17";
+ value = LocaleConvertUtils.convert(input, Date.class);
+ assertTrue(value instanceof Date);
+ assertEquals(input, value.toString());
+
+ input = "20:30:40";
+ value = LocaleConvertUtils.convert(input, Time.class);
+ assertTrue(value instanceof Time);
+ assertEquals(input, value.toString());
+
+ input = "2002-03-17 20:30:40.0";
+ value = LocaleConvertUtils.convert(input, Timestamp.class);
+ assertTrue(value instanceof Timestamp);
+ assertEquals(input, value.toString());
+
+ }
+
+
+ /**
+ * Positive String to String array tests.
+ */
+ public void fixmetestPositiveStringArray() {
+
+ fail("Array conversions not implemented yet.");
+
+ Object value = null;
+ String stringArray[] = new String[0];
+ String stringArray1[] = new String[]
+ {"abc"};
+ String stringArray2[] = new String[]
+ {"abc", "de,f"};
+
+ value = LocaleConvertUtils.convert("", stringArray.getClass());
+ checkStringArray(value, stringArray);
+ value = LocaleConvertUtils.convert(" ", stringArray.getClass());
+ checkStringArray(value, stringArray);
+ value = LocaleConvertUtils.convert("{}", stringArray.getClass());
+ checkStringArray(value, stringArray);
+ value = LocaleConvertUtils.convert("{ }", stringArray.getClass());
+ checkStringArray(value, stringArray);
+
+ value = LocaleConvertUtils.convert("abc", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+ value = LocaleConvertUtils.convert("{abc}", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+ value = LocaleConvertUtils.convert("\"abc\"", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+ value = LocaleConvertUtils.convert("{\"abc\"}", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+ value = LocaleConvertUtils.convert("'abc'", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+ value = LocaleConvertUtils.convert("{'abc'}", stringArray.getClass());
+ checkStringArray(value, stringArray1);
+
+ value = LocaleConvertUtils.convert("abc 'de,f'",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+ value = LocaleConvertUtils.convert("{abc, 'de,f'}",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+ value = LocaleConvertUtils.convert("\"abc\",\"de,f\"",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+ value = LocaleConvertUtils.convert("{\"abc\" 'de,f'}",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+ value = LocaleConvertUtils.convert("'abc' 'de,f'",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+ value = LocaleConvertUtils.convert("{'abc', \"de,f\"}",
+ stringArray.getClass());
+ checkStringArray(value, stringArray2);
+
+ }
+
+
+ // -------------------------------------------------------- Private Methods
+
+
+ private void checkIntegerArray(Object value, int intArray[]) {
+
+ assertNotNull("Returned value is not null", value);
+ assertEquals("Returned value is int[]",
+ intArray.getClass(), value.getClass());
+ int results[] = (int[]) value;
+ assertEquals("Returned array length", intArray.length, results.length);
+ for (int i = 0; i < intArray.length; i++) {
+ assertEquals("Returned array value " + i,
+ intArray[i], results[i]);
+ }
+
+ }
+
+
+ private void checkStringArray(Object value, String stringArray[]) {
+
+ assertNotNull("Returned value is not null", value);
+ assertEquals("Returned value is String[]",
+ stringArray.getClass(), value.getClass());
+ String results[] = (String[]) value;
+ assertEquals("Returned array length",
+ stringArray.length, results.length);
+ for (int i = 0; i < stringArray.length; i++) {
+ assertEquals("Returned array value " + i,
+ stringArray[i], results[i]);
+ }
+
+ }
+
+
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/converters/DateLocaleConverterTestCase.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/converters/DateLocaleConverterTestCase.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/locale/converters/DateLocaleConverterTestCase.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.beanutils.locale.converters;
+
+import junit.framework.TestSuite;
+import junit.framework.TestCase;
+
+import java.text.SimpleDateFormat;
+import java.text.ParseException;
+
+import java.util.Locale;
+
+import org.apache.commons.beanutils.Converter;
+import org.apache.commons.beanutils.ConversionException;
+
+/**
+ * Test Case for the DateLocaleConverter class.
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class DateLocaleConverterTestCase extends TestCase {
+
+ // ------------------------------------------------------------------------
+
+ public DateLocaleConverterTestCase(String name) {
+ super(name);
+ }
+
+ // ------------------------------------------------------------------------
+
+ public static TestSuite suite() {
+ return new TestSuite(DateLocaleConverterTestCase.class);
+ }
+
+
+ // ------------------------------------------------------------------------
+
+ public void testSetLenient() {
+ // make sure that date format works as expected
+ SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd, yyyy", Locale.UK);
+
+ // test with no leniency
+ dateFormat.setLenient(false);
+
+ try {
+
+ dateFormat.parse("Feb 10, 2001");
+
+ } catch (ParseException e) {
+ fail("Could not parse date (1) - " + e.getMessage());
+ }
+
+ try {
+
+ dateFormat.parse("Feb 31, 2001");
+ fail("Parsed illegal date (1)");
+
+ } catch (ParseException e) {
+ // that's what we expected
+ }
+
+ // test with leniency
+ dateFormat.setLenient(true);
+
+ try {
+
+ dateFormat.parse("Feb 10, 2001");
+
+ } catch (ParseException e) {
+ fail("Could not parse date (2) - " + e.getMessage());
+ }
+
+ try {
+
+ dateFormat.parse("Feb 31, 2001");
+
+ } catch (ParseException e) {
+ fail("Could not parse date (3) - " + e.getMessage());
+ }
+
+ // now repeat tests for converter
+ DateLocaleConverter converter = new DateLocaleConverter(Locale.UK, "MMM dd, yyyy");
+
+ // test with no leniency
+ converter.setLenient(false);
+ assertEquals("Set lenient failed", converter.isLenient(), false);
+
+ try {
+
+ converter.convert("Feb 10, 2001");
+
+ } catch (ConversionException e) {
+ fail("Could not parse date (4) - " + e.getMessage());
+ }
+
+ try {
+
+ converter.convert("Feb 31, 2001");
+ assertEquals("Set lenient failed", converter.isLenient(), false);
+ fail("Parsed illegal date (2)");
+
+ } catch (ConversionException e) {
+ // that's what we expected
+ }
+
+ // test with leniency
+ converter.setLenient(true);
+ assertEquals("Set lenient failed", converter.isLenient(), true);
+
+ try {
+
+ converter.convert("Feb 10, 2001");
+
+ } catch (ConversionException e) {
+ fail("Could not parse date (5) - " + e.getMessage());
+ }
+
+ try {
+
+ converter.convert("Feb 31, 2001");
+
+ } catch (ConversionException e) {
+ fail("Could not parse date (6) - " + e.getMessage());
+ }
+ }
+}
+
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PackageBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PackageBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PackageBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.priv;
+
+
+/**
+ * <p>This class is designed to test the default access jvm problem workaround.
+ * The issue is that public methods of a public subclass contained in a default access
+ * superclass are returned by reflection but an IllegalAccessException is thrown
+ * when they are invoked.</p>
+ *
+ * <p>This is the default access superclass</p>
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+class PackageBean {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Package private constructor - can only use factory method to create
+ * beans.
+ */
+ PackageBean() {
+
+ super();
+
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ */
+ private String bar = "This is bar";
+
+ public String getBar() {
+
+ return (this.bar);
+
+ }
+
+ public void setBar(String bar) {
+
+ this.bar = bar;
+
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.priv;
+
+
+/**
+ * Bean that has a private constructor that exposes properties via
+ * various mechanisms (based on property name):
+ * <ul>
+ * <li><strong>foo</strong> - Via direct public method
+ * <li><strong>bar</strong> - Via directly implemented interface
+ * <li><strong>baz</strong> - Via indirectly implemented interface
+ * </ul>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.6 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+class PrivateBean implements PrivateDirect {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Package private constructor - can only use factory method to create
+ * beans.
+ */
+ PrivateBean() {
+
+ super();
+
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A directly implemented property.
+ */
+ private String foo = "This is foo";
+
+ public String getFoo() {
+
+ return (this.foo);
+
+ }
+
+
+ /**
+ * A property accessible via a directly implemented interface.
+ */
+ private String bar = "This is bar";
+
+ public String getBar() {
+
+ return (this.bar);
+
+ }
+
+
+ /**
+ * A method accessible via a directly implemented interface.
+ */
+ public String methodBar(String in) {
+
+ return (in);
+
+ }
+
+
+ /**
+ * A property accessible via an indirectly implemented interface.
+ */
+ private String baz = "This is baz";
+
+ public String getBaz() {
+
+ return (this.baz);
+
+ }
+
+
+ /**
+ * A method accessible via an indirectly implemented interface.
+ */
+ public String methodBaz(String in) {
+
+ return (in);
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBeanFactory.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBeanFactory.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBeanFactory.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.priv;
+
+
+/**
+ * Factory class for PrivateBean instances.
+ *
+ * @author Craig R. McClanahan
+ * @author Jan Sorensen
+ * @version $Revision: 1.6 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class PrivateBeanFactory {
+
+
+ /**
+ * Factory method to create new beans.
+ */
+ public static PrivateDirect create() {
+
+ return (new PrivateBean());
+
+ }
+
+
+ /**
+ * Factory method to create new beans.
+ */
+ public static PrivateDirect createSubclass() {
+
+ return (new PrivateBeanSubclass());
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBeanSubclass.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBeanSubclass.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateBeanSubclass.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.priv;
+
+
+/**
+ * Bean that exposes methods defined by an interface that is implemented
+ * in the superclass.
+ *
+ * @author Jan Sorensen
+ * @version $Revision: 1.5 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+class PrivateBeanSubclass extends PrivateBean {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a new PrivateBeanSubclass instance.
+ */
+ PrivateBeanSubclass() {
+
+ super();
+
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A property accessible via the superclass.
+ */
+ public String getBar() {
+
+ return (super.getBar());
+
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateDirect.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateDirect.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateDirect.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.priv;
+
+
+/**
+ * Interface that is directly implemented by PrivateBean.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.6 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public interface PrivateDirect extends PrivateIndirect {
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A property accessible via a directly implemented interface.
+ */
+ String getBar();
+
+
+ /**
+ * A method accessible via a directly implemented interface.
+ */
+ String methodBar(String in);
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateIndirect.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateIndirect.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PrivateIndirect.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.priv;
+
+
+/**
+ * Interface that is indirectly implemented by PrivateBean.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.6 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public interface PrivateIndirect {
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A property accessible via an indirectly implemented interface.
+ */
+ public String getBaz();
+
+
+ /**
+ * A method accessible via an indirectly implemented interface.
+ */
+ public String methodBaz(String in);
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PublicSubBean.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PublicSubBean.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/beanutils/priv/PublicSubBean.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.beanutils.priv;
+
+
+/**
+ * <p>This class is designed to test the default access jvm problem workaround.
+ * The issue is that public methods of a public subclass contained in a default access
+ * superclass are returned by reflection but an IllegalAccessException is thrown
+ * when they are invoked.</p>
+ *
+ * <p>This is the default access superclass</p>
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 1.4 $ $Date: 2004/02/28 13:18:37 $
+ */
+
+public class PublicSubBean extends PackageBean {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Package private constructor - can only use factory method to create
+ * beans.
+ */
+ public PublicSubBean() {
+
+ super();
+
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A directly implemented property.
+ */
+ private String foo = "This is foo";
+
+ public String getFoo() {
+
+ return (this.foo);
+
+ }
+
+ public void setFoo(String foo) {
+
+ this.foo = foo;
+
+ }
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/ReferenceMap.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/ReferenceMap.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/ReferenceMap.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,957 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.util.AbstractCollection;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.commons.collections.keyvalue.DefaultMapEntry;
+
+/**
+ * Hash-based {@link Map} implementation that allows
+ * mappings to be removed by the garbage collector.<p>
+ *
+ * When you construct a <code>ReferenceMap</code>, you can
+ * specify what kind of references are used to store the
+ * map's keys and values. If non-hard references are
+ * used, then the garbage collector can remove mappings
+ * if a key or value becomes unreachable, or if the
+ * JVM's memory is running low. For information on how
+ * the different reference types behave, see
+ * {@link Reference}.<p>
+ *
+ * Different types of references can be specified for keys
+ * and values. The keys can be configured to be weak but
+ * the values hard, in which case this class will behave
+ * like a <a href="http://java.sun.com/j2se/1.4/docs/api/java/util/WeakHashMap.html">
+ * <code>WeakHashMap</code></a>. However, you
+ * can also specify hard keys and weak values, or any other
+ * combination. The default constructor uses hard keys
+ * and soft values, providing a memory-sensitive cache.<p>
+ *
+ * The algorithms used are basically the same as those
+ * in {@link java.util.HashMap}. In particular, you
+ * can specify a load factor and capacity to suit your
+ * needs. All optional {@link Map} operations are
+ * supported.<p>
+ *
+ * However, this {@link Map} implementation does <I>not</I>
+ * allow null elements. Attempting to add a null key or
+ * or a null value to the map will raise a
+ * <code>NullPointerException</code>.<p>
+ *
+ * As usual, this implementation is not synchronized. You
+ * can use {@link java.util.Collections#synchronizedMap} to
+ * provide synchronized access to a <code>ReferenceMap</code>.
+ *
+ * @see java.lang.ref.Reference
+ *
+ * @deprecated Moved to map subpackage. Due to be removed in v4.0.
+ * @since Commons Collections 2.1
+ * @version $Revision: 1.1 $ $Date: 2004/05/10 19:52:42 $
+ *
+ * @author Paul Jack
+ */
+public class ReferenceMap extends AbstractMap {
+
+ /**
+ * For serialization.
+ */
+ final private static long serialVersionUID = -3370601314380922368L;
+
+
+ /**
+ * Constant indicating that hard references should be used.
+ */
+ final public static int HARD = 0;
+
+
+ /**
+ * Constant indicating that soft references should be used.
+ */
+ final public static int SOFT = 1;
+
+
+ /**
+ * Constant indicating that weak references should be used.
+ */
+ final public static int WEAK = 2;
+
+
+ // --- serialized instance variables:
+
+
+ /**
+ * The reference type for keys. Must be HARD, SOFT, WEAK.
+ * Note: I originally marked this field as final, but then this class
+ * didn't compile under JDK1.2.2.
+ * @serial
+ */
+ private int keyType;
+
+
+ /**
+ * The reference type for values. Must be HARD, SOFT, WEAK.
+ * Note: I originally marked this field as final, but then this class
+ * didn't compile under JDK1.2.2.
+ * @serial
+ */
+ private int valueType;
+
+
+ /**
+ * The threshold variable is calculated by multiplying
+ * table.length and loadFactor.
+ * Note: I originally marked this field as final, but then this class
+ * didn't compile under JDK1.2.2.
+ * @serial
+ */
+ private float loadFactor;
+
+ /**
+ * Should the value be automatically purged when the associated key has been collected?
+ */
+ private boolean purgeValues = false;
+
+
+ // -- Non-serialized instance variables
+
+ /**
+ * ReferenceQueue used to eliminate stale mappings.
+ * See purge.
+ */
+ private transient ReferenceQueue queue = new ReferenceQueue();
+
+
+ /**
+ * The hash table. Its length is always a power of two.
+ */
+ private transient Entry[] table;
+
+
+ /**
+ * Number of mappings in this map.
+ */
+ private transient int size;
+
+
+ /**
+ * When size reaches threshold, the map is resized.
+ * See resize().
+ */
+ private transient int threshold;
+
+
+ /**
+ * Number of times this map has been modified.
+ */
+ private transient volatile int modCount;
+
+
+ /**
+ * Cached key set. May be null if key set is never accessed.
+ */
+ private transient Set keySet;
+
+
+ /**
+ * Cached entry set. May be null if entry set is never accessed.
+ */
+ private transient Set entrySet;
+
+
+ /**
+ * Cached values. May be null if values() is never accessed.
+ */
+ private transient Collection values;
+
+
+ /**
+ * Constructs a new <code>ReferenceMap</code> that will
+ * use hard references to keys and soft references to values.
+ */
+ public ReferenceMap() {
+ this(HARD, SOFT);
+ }
+
+ /**
+ * Constructs a new <code>ReferenceMap</code> that will
+ * use the specified types of references.
+ *
+ * @param keyType the type of reference to use for keys;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param valueType the type of reference to use for values;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param purgeValues should the value be automatically purged when the
+ * key is garbage collected
+ */
+ public ReferenceMap(int keyType, int valueType, boolean purgeValues) {
+ this(keyType, valueType);
+ this.purgeValues = purgeValues;
+ }
+
+ /**
+ * Constructs a new <code>ReferenceMap</code> that will
+ * use the specified types of references.
+ *
+ * @param keyType the type of reference to use for keys;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param valueType the type of reference to use for values;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ */
+ public ReferenceMap(int keyType, int valueType) {
+ this(keyType, valueType, 16, 0.75f);
+ }
+
+ /**
+ * Constructs a new <code>ReferenceMap</code> with the
+ * specified reference types, load factor and initial
+ * capacity.
+ *
+ * @param keyType the type of reference to use for keys;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param valueType the type of reference to use for values;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param capacity the initial capacity for the map
+ * @param loadFactor the load factor for the map
+ * @param purgeValues should the value be automatically purged when the
+ * key is garbage collected
+ */
+ public ReferenceMap(
+ int keyType,
+ int valueType,
+ int capacity,
+ float loadFactor,
+ boolean purgeValues) {
+ this(keyType, valueType, capacity, loadFactor);
+ this.purgeValues = purgeValues;
+ }
+
+ /**
+ * Constructs a new <code>ReferenceMap</code> with the
+ * specified reference types, load factor and initial
+ * capacity.
+ *
+ * @param keyType the type of reference to use for keys;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param valueType the type of reference to use for values;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param capacity the initial capacity for the map
+ * @param loadFactor the load factor for the map
+ */
+ public ReferenceMap(int keyType, int valueType, int capacity, float loadFactor) {
+ super();
+
+ verify("keyType", keyType);
+ verify("valueType", valueType);
+
+ if (capacity <= 0) {
+ throw new IllegalArgumentException("capacity must be positive");
+ }
+ if ((loadFactor <= 0.0f) || (loadFactor >= 1.0f)) {
+ throw new IllegalArgumentException("Load factor must be greater than 0 and less than 1.");
+ }
+
+ this.keyType = keyType;
+ this.valueType = valueType;
+
+ int v = 1;
+ while (v < capacity) v *= 2;
+
+ this.table = new Entry[v];
+ this.loadFactor = loadFactor;
+ this.threshold = (int)(v * loadFactor);
+ }
+
+
+ // used by constructor
+ private static void verify(String name, int type) {
+ if ((type < HARD) || (type > WEAK)) {
+ throw new IllegalArgumentException(name +
+ " must be HARD, SOFT, WEAK.");
+ }
+ }
+
+
+ /**
+ * Writes this object to the given output stream.
+ *
+ * @param out the output stream to write to
+ * @throws IOException if the stream raises it
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ out.writeInt(table.length);
+
+ // Have to use null-terminated list because size might shrink
+ // during iteration
+
+ for (Iterator iter = entrySet().iterator(); iter.hasNext();) {
+ Map.Entry entry = (Map.Entry)iter.next();
+ out.writeObject(entry.getKey());
+ out.writeObject(entry.getValue());
+ }
+ out.writeObject(null);
+ }
+
+
+ /**
+ * Reads the contents of this object from the given input stream.
+ *
+ * @param inp the input stream to read from
+ * @throws IOException if the stream raises it
+ * @throws ClassNotFoundException if the stream raises it
+ */
+ private void readObject(ObjectInputStream inp) throws IOException, ClassNotFoundException {
+ inp.defaultReadObject();
+ table = new Entry[inp.readInt()];
+ threshold = (int)(table.length * loadFactor);
+ queue = new ReferenceQueue();
+ Object key = inp.readObject();
+ while (key != null) {
+ Object value = inp.readObject();
+ put(key, value);
+ key = inp.readObject();
+ }
+ }
+
+
+ /**
+ * Constructs a reference of the given type to the given
+ * referent. The reference is registered with the queue
+ * for later purging.
+ *
+ * @param type HARD, SOFT or WEAK
+ * @param referent the object to refer to
+ * @param hash the hash code of the <I>key</I> of the mapping;
+ * this number might be different from referent.hashCode() if
+ * the referent represents a value and not a key
+ */
+ private Object toReference(int type, Object referent, int hash) {
+ switch (type) {
+ case HARD: return referent;
+ case SOFT: return new SoftRef(hash, referent, queue);
+ case WEAK: return new WeakRef(hash, referent, queue);
+ default: throw new Error();
+ }
+ }
+
+
+ /**
+ * Returns the entry associated with the given key.
+ *
+ * @param key the key of the entry to look up
+ * @return the entry associated with that key, or null
+ * if the key is not in this map
+ */
+ private Entry getEntry(Object key) {
+ if (key == null) return null;
+ int hash = key.hashCode();
+ int index = indexFor(hash);
+ for (Entry entry = table[index]; entry != null; entry = entry.next) {
+ if ((entry.hash == hash) && key.equals(entry.getKey())) {
+ return entry;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Converts the given hash code into an index into the
+ * hash table.
+ */
+ private int indexFor(int hash) {
+ // mix the bits to avoid bucket collisions...
+ hash += ~(hash << 15);
+ hash ^= (hash >>> 10);
+ hash += (hash << 3);
+ hash ^= (hash >>> 6);
+ hash += ~(hash << 11);
+ hash ^= (hash >>> 16);
+ return hash & (table.length - 1);
+ }
+
+
+
+ /**
+ * Resizes this hash table by doubling its capacity.
+ * This is an expensive operation, as entries must
+ * be copied from the old smaller table to the new
+ * bigger table.
+ */
+ private void resize() {
+ Entry[] old = table;
+ table = new Entry[old.length * 2];
+
+ for (int i = 0; i < old.length; i++) {
+ Entry next = old[i];
+ while (next != null) {
+ Entry entry = next;
+ next = next.next;
+ int index = indexFor(entry.hash);
+ entry.next = table[index];
+ table[index] = entry;
+ }
+ old[i] = null;
+ }
+ threshold = (int)(table.length * loadFactor);
+ }
+
+
+
+ /**
+ * Purges stale mappings from this map.
+ * <p>
+ * Ordinarily, stale mappings are only removed during
+ * a write operation, although this method is called for both
+ * read and write operations to maintain a consistent state.
+ * <p>
+ * Note that this method is not synchronized! Special
+ * care must be taken if, for instance, you want stale
+ * mappings to be removed on a periodic basis by some
+ * background thread.
+ */
+ private void purge() {
+ Reference ref = queue.poll();
+ while (ref != null) {
+ purge(ref);
+ ref = queue.poll();
+ }
+ }
+
+
+ private void purge(Reference ref) {
+ // The hashCode of the reference is the hashCode of the
+ // mapping key, even if the reference refers to the
+ // mapping value...
+ int hash = ref.hashCode();
+ int index = indexFor(hash);
+ Entry previous = null;
+ Entry entry = table[index];
+ while (entry != null) {
+ if (entry.purge(ref)) {
+ if (previous == null) table[index] = entry.next;
+ else previous.next = entry.next;
+ this.size--;
+ return;
+ }
+ previous = entry;
+ entry = entry.next;
+ }
+
+ }
+
+
+ /**
+ * Returns the size of this map.
+ *
+ * @return the size of this map
+ */
+ public int size() {
+ purge();
+ return size;
+ }
+
+
+ /**
+ * Returns <code>true</code> if this map is empty.
+ *
+ * @return <code>true</code> if this map is empty
+ */
+ public boolean isEmpty() {
+ purge();
+ return size == 0;
+ }
+
+
+ /**
+ * Returns <code>true</code> if this map contains the given key.
+ *
+ * @return true if the given key is in this map
+ */
+ public boolean containsKey(Object key) {
+ purge();
+ Entry entry = getEntry(key);
+ if (entry == null) return false;
+ return entry.getValue() != null;
+ }
+
+
+ /**
+ * Returns the value associated with the given key, if any.
+ *
+ * @return the value associated with the given key, or <code>null</code>
+ * if the key maps to no value
+ */
+ public Object get(Object key) {
+ purge();
+ Entry entry = getEntry(key);
+ if (entry == null) return null;
+ return entry.getValue();
+ }
+
+
+ /**
+ * Associates the given key with the given value.<p>
+ * Neither the key nor the value may be null.
+ *
+ * @param key the key of the mapping
+ * @param value the value of the mapping
+ * @return the last value associated with that key, or
+ * null if no value was associated with the key
+ * @throws NullPointerException if either the key or value
+ * is null
+ */
+ public Object put(Object key, Object value) {
+ if (key == null) throw new NullPointerException("null keys not allowed");
+ if (value == null) throw new NullPointerException("null values not allowed");
+
+ purge();
+ if (size + 1 > threshold) resize();
+
+ int hash = key.hashCode();
+ int index = indexFor(hash);
+ Entry entry = table[index];
+ while (entry != null) {
+ if ((hash == entry.hash) && key.equals(entry.getKey())) {
+ Object result = entry.getValue();
+ entry.setValue(value);
+ return result;
+ }
+ entry = entry.next;
+ }
+ this.size++;
+ modCount++;
+ key = toReference(keyType, key, hash);
+ value = toReference(valueType, value, hash);
+ table[index] = new Entry(key, hash, value, table[index]);
+ return null;
+ }
+
+
+ /**
+ * Removes the key and its associated value from this map.
+ *
+ * @param key the key to remove
+ * @return the value associated with that key, or null if
+ * the key was not in the map
+ */
+ public Object remove(Object key) {
+ if (key == null) return null;
+ purge();
+ int hash = key.hashCode();
+ int index = indexFor(hash);
+ Entry previous = null;
+ Entry entry = table[index];
+ while (entry != null) {
+ if ((hash == entry.hash) && key.equals(entry.getKey())) {
+ if (previous == null) table[index] = entry.next;
+ else previous.next = entry.next;
+ this.size--;
+ modCount++;
+ return entry.getValue();
+ }
+ previous = entry;
+ entry = entry.next;
+ }
+ return null;
+ }
+
+
+ /**
+ * Clears this map.
+ */
+ public void clear() {
+ Arrays.fill(table, null);
+ size = 0;
+ while (queue.poll() != null); // drain the queue
+ }
+
+
+ /**
+ * Returns a set view of this map's entries.
+ *
+ * @return a set view of this map's entries
+ */
+ public Set entrySet() {
+ if (entrySet != null) {
+ return entrySet;
+ }
+ entrySet = new AbstractSet() {
+ public int size() {
+ return ReferenceMap.this.size();
+ }
+
+ public void clear() {
+ ReferenceMap.this.clear();
+ }
+
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ if (!(o instanceof Map.Entry)) return false;
+ Map.Entry e = (Map.Entry)o;
+ Entry e2 = getEntry(e.getKey());
+ return (e2 != null) && e.equals(e2);
+ }
+
+ public boolean remove(Object o) {
+ boolean r = contains(o);
+ if (r) {
+ Map.Entry e = (Map.Entry)o;
+ ReferenceMap.this.remove(e.getKey());
+ }
+ return r;
+ }
+
+ public Iterator iterator() {
+ return new EntryIterator();
+ }
+
+ public Object[] toArray() {
+ return toArray(new Object[0]);
+ }
+
+ public Object[] toArray(Object[] arr) {
+ ArrayList list = new ArrayList();
+ Iterator iterator = iterator();
+ while (iterator.hasNext()) {
+ Entry e = (Entry)iterator.next();
+ list.add(new DefaultMapEntry(e.getKey(), e.getValue()));
+ }
+ return list.toArray(arr);
+ }
+ };
+ return entrySet;
+ }
+
+
+ /**
+ * Returns a set view of this map's keys.
+ *
+ * @return a set view of this map's keys
+ */
+ public Set keySet() {
+ if (keySet != null) return keySet;
+ keySet = new AbstractSet() {
+ public int size() {
+ return ReferenceMap.this.size();
+ }
+
+ public Iterator iterator() {
+ return new KeyIterator();
+ }
+
+ public boolean contains(Object o) {
+ return containsKey(o);
+ }
+
+
+ public boolean remove(Object o) {
+ Object r = ReferenceMap.this.remove(o);
+ return r != null;
+ }
+
+ public void clear() {
+ ReferenceMap.this.clear();
+ }
+
+ public Object[] toArray() {
+ return toArray(new Object[0]);
+ }
+
+ public Object[] toArray(Object[] array) {
+ Collection c = new ArrayList(size());
+ for (Iterator it = iterator(); it.hasNext(); ) {
+ c.add(it.next());
+ }
+ return c.toArray(array);
+ }
+ };
+ return keySet;
+ }
+
+
+ /**
+ * Returns a collection view of this map's values.
+ *
+ * @return a collection view of this map's values.
+ */
+ public Collection values() {
+ if (values != null) return values;
+ values = new AbstractCollection() {
+ public int size() {
+ return ReferenceMap.this.size();
+ }
+
+ public void clear() {
+ ReferenceMap.this.clear();
+ }
+
+ public Iterator iterator() {
+ return new ValueIterator();
+ }
+
+ public Object[] toArray() {
+ return toArray(new Object[0]);
+ }
+
+ public Object[] toArray(Object[] array) {
+ Collection c = new ArrayList(size());
+ for (Iterator it = iterator(); it.hasNext(); ) {
+ c.add(it.next());
+ }
+ return c.toArray(array);
+ }
+ };
+ return values;
+ }
+
+
+ // If getKey() or getValue() returns null, it means
+ // the mapping is stale and should be removed.
+ private class Entry implements Map.Entry, KeyValue {
+
+ Object key;
+ Object value;
+ int hash;
+ Entry next;
+
+
+ public Entry(Object key, int hash, Object value, Entry next) {
+ this.key = key;
+ this.hash = hash;
+ this.value = value;
+ this.next = next;
+ }
+
+
+ public Object getKey() {
+ return (keyType > HARD) ? ((Reference)key).get() : key;
+ }
+
+
+ public Object getValue() {
+ return (valueType > HARD) ? ((Reference)value).get() : value;
+ }
+
+
+ public Object setValue(Object object) {
+ Object old = getValue();
+ if (valueType > HARD) ((Reference)value).clear();
+ value = toReference(valueType, object, hash);
+ return old;
+ }
+
+
+ public boolean equals(Object o) {
+ if (o == null) return false;
+ if (o == this) return true;
+ if (!(o instanceof Map.Entry)) return false;
+
+ Map.Entry entry = (Map.Entry)o;
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+ if ((key == null) || (value == null)) return false;
+ return key.equals(getKey()) && value.equals(getValue());
+ }
+
+
+ public int hashCode() {
+ Object v = getValue();
+ return hash ^ ((v == null) ? 0 : v.hashCode());
+ }
+
+
+ public String toString() {
+ return getKey() + "=" + getValue();
+ }
+
+
+ boolean purge(Reference ref) {
+ boolean r = (keyType > HARD) && (key == ref);
+ r = r || ((valueType > HARD) && (value == ref));
+ if (r) {
+ if (keyType > HARD) ((Reference)key).clear();
+ if (valueType > HARD) {
+ ((Reference)value).clear();
+ } else if (purgeValues) {
+ value = null;
+ }
+ }
+ return r;
+ }
+ }
+
+
+ private class EntryIterator implements Iterator {
+ // These fields keep track of where we are in the table.
+ int index;
+ Entry entry;
+ Entry previous;
+
+ // These Object fields provide hard references to the
+ // current and next entry; this assures that if hasNext()
+ // returns true, next() will actually return a valid element.
+ Object nextKey, nextValue;
+ Object currentKey, currentValue;
+
+ int expectedModCount;
+
+
+ public EntryIterator() {
+ index = (size() != 0 ? table.length : 0);
+ // have to do this here! size() invocation above
+ // may have altered the modCount.
+ expectedModCount = modCount;
+ }
+
+
+ public boolean hasNext() {
+ checkMod();
+ while (nextNull()) {
+ Entry e = entry;
+ int i = index;
+ while ((e == null) && (i > 0)) {
+ i--;
+ e = table[i];
+ }
+ entry = e;
+ index = i;
+ if (e == null) {
+ currentKey = null;
+ currentValue = null;
+ return false;
+ }
+ nextKey = e.getKey();
+ nextValue = e.getValue();
+ if (nextNull()) entry = entry.next;
+ }
+ return true;
+ }
+
+
+ private void checkMod() {
+ if (modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+
+ private boolean nextNull() {
+ return (nextKey == null) || (nextValue == null);
+ }
+
+ protected Entry nextEntry() {
+ checkMod();
+ if (nextNull() && !hasNext()) throw new NoSuchElementException();
+ previous = entry;
+ entry = entry.next;
+ currentKey = nextKey;
+ currentValue = nextValue;
+ nextKey = null;
+ nextValue = null;
+ return previous;
+ }
+
+
+ public Object next() {
+ return nextEntry();
+ }
+
+
+ public void remove() {
+ checkMod();
+ if (previous == null) throw new IllegalStateException();
+ ReferenceMap.this.remove(currentKey);
+ previous = null;
+ currentKey = null;
+ currentValue = null;
+ expectedModCount = modCount;
+ }
+
+ }
+
+
+ private class ValueIterator extends EntryIterator {
+ public Object next() {
+ return nextEntry().getValue();
+ }
+ }
+
+
+ private class KeyIterator extends EntryIterator {
+ public Object next() {
+ return nextEntry().getKey();
+ }
+ }
+
+
+
+ // These two classes store the hashCode of the key of
+ // of the mapping, so that after they're dequeued a quick
+ // lookup of the bucket in the table can occur.
+
+
+ private static class SoftRef extends SoftReference {
+ private int hash;
+
+
+ public SoftRef(int hash, Object r, ReferenceQueue q) {
+ super(r, q);
+ this.hash = hash;
+ }
+
+
+ public int hashCode() {
+ return hash;
+ }
+ }
+
+
+ private static class WeakRef extends WeakReference {
+ private int hash;
+
+
+ public WeakRef(int hash, Object r, ReferenceQueue q) {
+ super(r, q);
+ this.hash = hash;
+ }
+
+
+ public int hashCode() {
+ return hash;
+ }
+ }
+
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/AbstractKeyValue.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/AbstractKeyValue.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/AbstractKeyValue.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2003-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.keyvalue;
+
+import org.apache.commons.collections.KeyValue;
+
+/**
+ * Abstract pair class to assist with creating KeyValue and MapEntry implementations.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 1.1 $ $Date: 2004/05/10 19:53:54 $
+ *
+ * @author James Strachan
+ * @author Michael A. Smith
+ * @author Neil O'Toole
+ * @author Stephen Colebourne
+ */
+public abstract class AbstractKeyValue implements KeyValue {
+
+ /** The key */
+ protected Object key;
+ /** The value */
+ protected Object value;
+
+ /**
+ * Constructs a new pair with the specified key and given value.
+ *
+ * @param key the key for the entry, may be null
+ * @param value the value for the entry, may be null
+ */
+ protected AbstractKeyValue(Object key, Object value) {
+ super();
+ this.key = key;
+ this.value = value;
+ }
+
+ /**
+ * Gets the key from the pair.
+ *
+ * @return the key
+ */
+ public Object getKey() {
+ return key;
+ }
+
+ /**
+ * Gets the value from the pair.
+ *
+ * @return the value
+ */
+ public Object getValue() {
+ return value;
+ }
+
+ /**
+ * Gets a debugging String view of the pair.
+ *
+ * @return a String view of the entry
+ */
+ public String toString() {
+ return new StringBuffer()
+ .append(getKey())
+ .append('=')
+ .append(getValue())
+ .toString();
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/AbstractMapEntry.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/AbstractMapEntry.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/AbstractMapEntry.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2003-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.keyvalue;
+
+import java.util.Map;
+
+/**
+ * Abstract Pair class to assist with creating correct Map Entry implementations.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 1.1 $ $Date: 2004/05/10 19:53:36 $
+ *
+ * @author James Strachan
+ * @author Michael A. Smith
+ * @author Neil O'Toole
+ * @author Stephen Colebourne
+ */
+public abstract class AbstractMapEntry extends AbstractKeyValue implements Map.Entry {
+
+ /**
+ * Constructs a new entry with the given key and given value.
+ *
+ * @param key the key for the entry, may be null
+ * @param value the value for the entry, may be null
+ */
+ protected AbstractMapEntry(Object key, Object value) {
+ super(key, value);
+ }
+
+ // Map.Entry interface
+ //-------------------------------------------------------------------------
+ /**
+ * Sets the value stored in this Map Entry.
+ * <p>
+ * This Map Entry is not connected to a Map, so only the local data is changed.
+ *
+ * @param value the new value
+ * @return the previous value
+ */
+ public Object setValue(Object value) {
+ Object answer = this.value;
+ this.value = value;
+ return answer;
+ }
+
+ /**
+ * Compares this Map Entry with another Map Entry.
+ * <p>
+ * Implemented per API documentation of {@link java.util.Map.Entry#equals(Object)}
+ *
+ * @param obj the object to compare to
+ * @return true if equal key and value
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof Map.Entry == false) {
+ return false;
+ }
+ Map.Entry other = (Map.Entry) obj;
+ return
+ (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) &&
+ (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
+ }
+
+ /**
+ * Gets a hashCode compatible with the equals method.
+ * <p>
+ * Implemented per API documentation of {@link java.util.Map.Entry#hashCode()}
+ *
+ * @return a suitable hash code
+ */
+ public int hashCode() {
+ return (getKey() == null ? 0 : getKey().hashCode()) ^
+ (getValue() == null ? 0 : getValue().hashCode());
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/DefaultMapEntry.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/DefaultMapEntry.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/DefaultMapEntry.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.keyvalue;
+
+import java.util.Map;
+
+import org.apache.commons.collections.KeyValue;
+
+/**
+ * A restricted implementation of {@link java.util.Map.Entry} that prevents
+ * the MapEntry contract from being broken.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 1.1 $ $Date: 2004/05/10 19:53:16 $
+ *
+ * @author James Strachan
+ * @author Michael A. Smith
+ * @author Neil O'Toole
+ * @author Stephen Colebourne
+ */
+public final class DefaultMapEntry extends AbstractMapEntry {
+
+ /**
+ * Constructs a new entry with the specified key and given value.
+ *
+ * @param key the key for the entry, may be null
+ * @param value the value for the entry, may be null
+ */
+ public DefaultMapEntry(final Object key, final Object value) {
+ super(key, value);
+ }
+
+ /**
+ * Constructs a new entry from the specified KeyValue.
+ *
+ * @param pair the pair to copy, must not be null
+ * @throws NullPointerException if the entry is null
+ */
+ public DefaultMapEntry(final KeyValue pair) {
+ super(pair.getKey(), pair.getValue());
+ }
+
+ /**
+ * Constructs a new entry from the specified MapEntry.
+ *
+ * @param entry the entry to copy, must not be null
+ * @throws NullPointerException if the entry is null
+ */
+ public DefaultMapEntry(final Map.Entry entry) {
+ super(entry.getKey(), entry.getValue());
+ }
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/KeyValue.java
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/KeyValue.java 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/src/test/org/apache/commons/collections/keyvalue/KeyValue.java 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2003-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections;
+
+/**
+ * Defines a simple key value pair.
+ * <p>
+ * A Map Entry has considerable additional semantics over and above a simple
+ * key-value pair. This interface defines the minimum key value, with just the
+ * two get methods.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 1.1 $ $Date: 2004/05/10 19:52:59 $
+ *
+ * @author Stephen Colebourne
+ */
+public interface KeyValue {
+
+ /**
+ * Gets the key from the pair.
+ *
+ * @return the key
+ */
+ Object getKey();
+
+ /**
+ * Gets the value from the pair.
+ *
+ * @return the value
+ */
+ Object getValue();
+
+}
Added: trunk/commons-beanutils/branches/upstream/current/xdocs/.cvsignore
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/xdocs/.cvsignore 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/xdocs/.cvsignore 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1 @@
+stylesheets
Added: trunk/commons-beanutils/branches/upstream/current/xdocs/images/logo.png
===================================================================
(Binary files differ)
Property changes on: trunk/commons-beanutils/branches/upstream/current/xdocs/images/logo.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/commons-beanutils/branches/upstream/current/xdocs/index.xml
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/xdocs/index.xml 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/xdocs/index.xml 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,153 @@
+<?xml version="1.0"?>
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<document>
+
+ <properties>
+ <title>Commons</title>
+ <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+ </properties>
+
+ <body>
+
+<section name="Commons BeanUtils">
+
+<p>
+Most Java developers are used to creating Java classes that conform to the
+JavaBeans naming patterns for property getters and setters. It is natural to
+then access these methods directly, using calls to the corresponding
+<code>getXxx</code> and <code>setXxx</code> methods. However, there are some
+occasions where dynamic access to Java object properties (without compiled-in
+knowledge of the property getter and setter methods to be called) is needed.
+Example use cases include:</p>
+<ul>
+<li>Building scripting languages that interact with the Java object model
+ (such as the Bean Scripting Framework).</li>
+<li>Building template language processors for web presentation and similar
+ uses (such as JSP or Velocity).</li>
+<li>Building custom tag libraries for JSP and XSP environments (such as Jakarta
+ Taglibs, Struts, Cocoon).</li>
+<li>Consuming XML-based configuration resources (such as Ant build scripts, web
+ application deployment descriptors, Tomcat's <code>server.xml</code>
+ file).</li>
+</ul>
+
+<p>
+The Java language provides <em>Reflection</em> and <em>Introspection</em>
+APIs (see the <code>java.lang.reflect</code> and <code>java.beans</code>
+packages in the JDK Javadocs). However, these APIs can be quite complex to
+understand and utilize. The <em>BeanUtils</em> component provides
+easy-to-use wrappers around these capabilities.
+</p>
+ <subsection name='BeanUtils Core And Modules'>
+ <p>
+The next release will see a departure from the usual packaging strategy.
+Rather than just a single jar, BeanUtils will distribute a
+<code>commons-beanutils-core.jar</code> containing the essential parts of BeanUtils
+with minimal dependencies (for this release just
+<a href='http://jakarta.apache.org/commons/logging'>Commons Logging</a>).
+Other parts of BeanUtils (typically specialized modules) will be distributed as separate,
+modular jars with additional dependencies. Hopefully this will allow library and framework
+creators more finely grained control over their dependencies. It should also help with
+compatibility issues.
+ </p>
+ <p>
+For everyone else, don't worry :) There will be a single commons-beanutils-all.jar
+containing everything. Drop it in and add any dependencies your application needs.
+ </p>
+ </subsection>
+ <subsection name='Bean Collections'>
+ <p>
+Bean collections is a library combining BeanUtils with
+<a href='http://jakarta.apache.org/commons/collections'>Commons Collections</a>
+to provide services for collections of beans. Once class (<code>BeanComparator</code>)
+was previously released, the rest are new. This new distribution strategy should allow
+this sub-component to evolve naturally without the concerns about size and scope
+that might otherwise happen.
+ </p>
+ <p>
+Bean Collections has an additional dependency on
+<a href='http://jakarta.apache.org/commons/collections'>Commons Collections</a>.
+ </p>
+ </subsection>
+</section>
+
+
+<section name="Documentation">
+
+<p>The <a href="http://jakarta.apache.org/commons/beanutils/RELEASE-NOTES.txt">
+Release Notes</a> document the new features and bug fixes that have been
+included in this release.</p>
+
+<p>The <a href="http://jakarta.apache.org/commons/beanutils/api/index.html">
+JavaDoc API documents</a> are available online. In particular, you should
+note the property reference syntax options described in the
+<code>PropertyUtils</code> class description.</p>
+
+</section>
+
+
+<section name="Releases">
+ <subsection name='Mirrored Releases'>
+<p>
+Releases after 1.5 should be downloaded from a mirror. Please remember to verify the
+sigature of the release from the
+<a href='http://www.apache.org/dist/jakarta/commons/beanutils/'>main apache site</a>
+when downloading from a mirror.
+</p>
+<p>
+ Binary releases are available
+ <a href="http://jakarta.apache.org/site/binindex.cgi">here</a>.
+ Source releases are available
+ <a href="http://jakarta.apache.org/site/sourceindex.cgi">here</a>
+</p>
+</subsection>
+<subsection name='1.7.x Releases (Mirrored)'>
+ <p>
+<strong>BeanUtils 1.7.0</strong> is a service release which removes the dependency
+upon a specific commons-collection library version. It may be safely used together
+with either the 2.x or 3.x series of commons-collections releases.
+It also introduces a number of important enhancements. It is backward compatible
+with the 1.6 release.
+ </p>
+</subsection>
+<subsection name='1.6.x Releases (Mirrored)'>
+<ul>
+ <li>Version 1.6.1 (latest) - 18 Feb 2003</li>
+ <li>Version 1.6 - 21 Jan 2003</li>
+</ul>
+ </subsection>
+ <subsection name='Older Releases (Not Mirrored)'>
+ <p>
+ <ul>
+ <li><a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-beanutils/v1.5/">Version 1.5 </a> - 23 Oct 2002</li>
+ <li><a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-beanutils/v1.4.1/">Version 1.4.1</a> - 28 Aug 2002</li>
+ <li><a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-beanutils/v1.4/">Version 1.4</a> - 13 Aug 2002
+</li>
+ <li><a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-beanutils/v1.3/">Version 1.3</a> - 29 Apr 2002</li>
+ <li><a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-beanutils/v1.2/">Version 1.2</a> - 24 Dec 2001</li>
+ <li><a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-beanutils/v1.1/">Version 1.1</a> - 22 Sep 2001</li>
+ <li><a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-beanutils/v1.0/">Version 1.0</a> - 14 July 2001</li>
+ </ul>
+ </p>
+ </subsection>
+</section>
+
+
+
+</body>
+</document>
Added: trunk/commons-beanutils/branches/upstream/current/xdocs/navigation.xml
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/xdocs/navigation.xml 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/xdocs/navigation.xml 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!DOCTYPE org.apache.commons.menus SYSTEM '../../commons-build/menus/menus.dtd'>
+<project name="BeanUtils">
+
+ <title>BeanUtils</title>
+ <organizationLogo href="/images/jakarta-logo-blue.gif">
+ Jakarta
+ </organizationLogo>
+
+ <body>
+ <links>
+ <item name="Jakarta Commons"
+ href="http://jakarta.apache.org/commons/"/>
+ </links>
+
+ <menu name="Commons BeanUtils">
+ <item name="Overview" href="/index.html"/>
+ <item name="Javadoc (Release)" href="api/index.html"/>
+ <item name="Mailing lists" href="/mail-lists.html"/>
+ <item name="Team" href="/team-list.html"/>
+ <!--item name="Tasks" href="/tasks.html"/-->
+ <item name="CVS" href="http://cvs.apache.org/viewcvs/jakarta-commons/beanutils/"/>
+ <item name="Javadoc (CVS latest)" href="apidocs/index.html"/>
+ </menu>
+
+ <menu name='Modules'>
+ <item name="Bean Collections" href="bean-collections/index.html"/>
+ </menu>
+
+ &common-menus;
+
+ </body>
+</project>
Added: trunk/commons-beanutils/branches/upstream/current/xdocs/proposal.xml
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/xdocs/proposal.xml 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/xdocs/proposal.xml 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,136 @@
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<document>
+<properties>
+<title>Proposal for BeanUtils Package</title>
+</properties>
+<body>
+
+
+<section name="Proposal for BeanUtils Package">
+
+
+
+<subsection name="(0) Rationale">
+
+<p>Most Java developers are used to creating Java classes that conform to the
+JavaBeans naming patterns for property getters and setters. It is natural to
+then access these methods directly, using calls to the corresponding
+<code>getXxx</code> and <code>setXxx</code> methods. However, there are some
+occasions where dynamic access to Java object properties (without compiled-in
+knowledge of the property getter and setter methods to be called) is needed.
+Example use cases include:</p>
+<ul>
+<li>Building scripting languages that interact with the Java object model
+ (such as the Bean Scripting Framework).</li>
+<li>Building template language processors for web presentation and similar
+ uses (such as JSP or Velocity).</li>
+<li>Building custom tag libraries for JSP and XSP environments (such as Jakarta
+ Taglibs, Struts, Cocoon).</li>
+<li>Consuming XML-based configuration resources (such as Ant build scripts, web
+ application deployment descriptors, Tomcat's <code>server.xml</code>
+ file).</li>
+</ul>
+
+<p>The Java language provides <em>Reflection</em> and <em>Introspection</em>
+APIs (see the <code>java.lang.reflect</code> and <code>java.beans</code>
+packages in the JDK Javadocs). However, these APIs can be quite complex to
+understand and utilize. The proposed <em>BeanUtils</em> component provides
+easy-to-use wrappers around these capabilities.</p>
+
+
+</subsection>
+<subsection name="(1) Scope of the Package">
+
+<p>This proposal is to create a package of Java utility methods for accessing
+and modifying the properties of arbitrary JavaBeans. No dependencies outside
+of the JDK are required, so the use of this package is very lightweight.</p>
+
+<p>In addition to wrapping the reflection and introspection APIs of the
+standard JDK, <em>BeanUtils</em> components shall support a syntax for directly
+accessing <strong>nested</strong> and <strong>indexed</strong> properties, in a
+manner that will be familar to users of scripting languages like JavaScript.
+For example, the following property accessor expressions are supported:</p>
+<ul>
+<li><strong>customer</strong> - Equivalent to <code>getCustomer()</code>.</li>
+<li><strong>customer.address</strong> - Equivalent to
+ <code>getCustomer().getAddress()</code>.</li>
+<li><strong>customer.address[2].street</strong> - Equivalent to
+ <code>getCustomer().getAddress(2).getStreet()</code> (access to indexed
+ properties also works if the underlying property is an array rather than
+ providing indexed getter and setter methods).</li>
+</ul>
+
+
+</subsection>
+<subsection name="(1.5) Interaction With Other Packages">
+
+<p><em>BeanUtils</em> relies only on standard JDK 1.2 (or later) APIs for
+production deployment. It utilizes the JUnit unit testing framework for
+developing and executing unit tests, but this is of interest only to
+developers of the component. BeanUtils will also be a dependency for
+several future proposed components for the Jakarta Commons subproject.</p>
+
+<p>No external configuration files are utilized.</p>
+
+
+</subsection>
+<subsection name="(2) Initial Source of the Package">
+
+<p>The three original Java classes (<code>BeanUtils</code>,
+<code>ConvertUtils</code>, and <code>PropertyUtils</code>) are an integral
+part of the <a href="http://jakarta.apache.org/struts">Struts Framework</a>.
+However, they have very few dependencies on other aspects of Struts, and
+those dependencies have been removed in the proposed code base.
+Once accepted and released as a Jakarta Commons component, Struts will
+be modified to use the Commons version of these classes, and its internal
+versions will be deprecated.</p>
+
+<p>The proposed package name for the new component is
+<code>org.apache.commons.beanutils</code>.</p>
+
+
+</subsection>
+<subsection name="(3) Required Jakarta-Commons Resources">
+
+<ul>
+<li>CVS Repository - New directory <code>beanutils</code> in the
+ <code>jakarta-commons</code> CVS repository. All initial committers
+ are already committers on <code>jakarta-commons</code>, so no
+ additional user setups are required.</li>
+<li>Mailing List - Discussions will take place on the general
+ <em>jakarta-commons at jakarta.apache.org</em> mailing list. To help
+ list subscribers identify messages of interest, it is suggested that
+ the message subject of messages about this component be prefixed with
+ [BeanUtils].</li>
+<li>Bugzilla - New component "BeanUtils" under the "Commons" product
+ category, with appropriate version identifiers as needed.</li>
+<li>Jyve FAQ - New category "commons-beanutils" (when available). </li>
+</ul>
+
+
+</subsection>
+<subsection name="(4) Initial Committers">
+
+<p>The initial committers on the BeanUtils component shall be Craig
+McClanahan and Geir Magnusson Jr.</p>
+
+
+
+</subsection>
+</section>
+</body>
+</document>
Added: trunk/commons-beanutils/branches/upstream/current/xdocs/style/project.css
===================================================================
--- trunk/commons-beanutils/branches/upstream/current/xdocs/style/project.css 2006-03-09 22:01:25 UTC (rev 1957)
+++ trunk/commons-beanutils/branches/upstream/current/xdocs/style/project.css 2006-03-09 22:04:21 UTC (rev 1958)
@@ -0,0 +1,5 @@
+#banner, #banner td {
+ background: #fff;
+ color: #000;
+}
+
More information about the pkg-java-commits
mailing list