The issue: I ran into a problem because I needed to handle the conversion going from my view beans to my dto beans differently than going from my dto beans to my view beans.
The Solution: I added a new class, called a ConverterSet, which maintains a set of converters. A programmer may create multiple ConverterSets, and then pass in the appropriate ConvertSet for the task at hand. Other Comments: This is more of a 'preview' patch- just to get a feel for suggestions/comments/etc. I can take suggestions and work them in, then submit a final patch -- assuming there happens to be some interest in this feature. I didn't update much (if any) of the existing javadoc- I'm waiting to get some feedback so I don't spend too much effort on things that may change. I also realize you are in the middle of a beanutils release, I hope my timing for submitting this does not interfere. ======================================================================= An overview of the changes: ConvertUtils: -removed the member variable "converters" and replaced it with a "converterSets" variable, which now holds ConverterSet objects. There is a default ConverterSet object created, which contains all the default Converters. -changed lookup/register/deregister/etc to operate on the Default ConverterSet object -Added methods "addConverterSet", "removeConverterSet", "getConverterSet" -moved default values to ConverterSet -removed deprecated getter/setters ( I will add these back in, if they are going to be in the next release.) ConverterSet -contains a FastHashMap which holds all of the converters associated with this ConverterSet -Each ConverterSet has a full set of converters (i.e. there is no hierarchy, if two ConverterSets share the same Converter object, it must be registered with both) -Converters are registered/deregistered directly on the ConverterSet BeanUtils -Added new method signatures for (almost) all methods, which takes an additional parameter- a ConverterSet. If the old method signature is used (w/o passing in a ConverterSet) the default ConverterSet is used. -Existing behavior of methods has not been altered LocaleBeanUtils -Added a (String) cast for method invocations involving the null parameter (needed due to changes made in BeanUtils) -Additional things may have to be added in this class to allow it to work with ConverterSets as well TestCases -I have some test cases that are coupled with my current application. I will break those away so they can be included. (all current tests still pass) ======================================================================= Example usage with a custom ConverterSet: ----------------------------------------- setup: ConverterSet toDto = new ConverterSet("TO_DTO"); ConvertUtils.addConverterSet(toDto); toDto.register(new CustomSqlDateConverter(), java.sql.Date.class); usage: ConverterSet toDto = ConvertUtils.getConverterSet("TO_DTO"); BeanUtils.copyProperties(dest, source, toDto); Old usage still works (uses the default ConverterSet): ------------------------------------------------------ setup: ConvertUtils.register(new CustomSqlDateConverter(), java.sql.Date.class); usage: BeanUtils.copyProperties(dest, source); which is also functionaly equivalent to: alternate setup: ConverterSet toDto = ConvertUtils.getDefaultConverterSet(); // same as: ConverterSet toDto = ConvertUtils.getConverterSet(ConverterSet.DEFAULT_CONVERTER_SET_NAME) toDto.register(new CustomSqlDateConverter(), java.sql.Date.class); alternate usage: ConverterSet toDto = ConvertUtils.getDefaultConverterSet(); BeanUtils.copyProperties(dest, source, toDto); ======================================================================= The Code: (The original files were taken from cvs HEAD about a week ago) --- BeanUtils.java.orig 2003-02-12 10:45:11.000000000 -0600 +++ BeanUtils.java 2003-02-12 10:45:13.000000000 -0600 @@ -215,6 +215,13 @@ public static void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException { + copyProperties(dest,orig, ConvertUtils.getDefaultConverterSet()); + + } + + public static void copyProperties(Object dest, Object orig, ConverterSet set) + throws IllegalAccessException, InvocationTargetException { + // Validate existence of the specified beans if (dest == null) { throw new IllegalArgumentException @@ -236,7 +243,7 @@ String name = origDescriptors[i].getName(); if (PropertyUtils.isWriteable(dest, name)) { Object value = ((DynaBean) orig).get(name); - copyProperty(dest, name, value); + copyProperty(dest, name, value, set); } } } else if (orig instanceof Map) { @@ -245,7 +252,7 @@ String name = (String) names.next(); if (PropertyUtils.isWriteable(dest, name)) { Object value = ((Map) orig).get(name); - copyProperty(dest, name, value); + copyProperty(dest, name, value, set); } } } else /* if (orig is a standard JavaBean) */ { @@ -261,7 +268,7 @@ try { Object value = PropertyUtils.getSimpleProperty(orig, name); - copyProperty(dest, name, value); + copyProperty(dest, name, value, set); } catch (NoSuchMethodException e) { ; // Should not happen } @@ -305,7 +312,11 @@ */ public static void copyProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException { + copyProperty(bean,name,value,ConvertUtils.getDefaultConverterSet() ); + } + public static void copyProperty(Object bean, String name, Object value, +ConverterSet set) + throws IllegalAccessException, InvocationTargetException { // Trace logging (if enabled) if (log.isTraceEnabled()) { StringBuffer sb = new StringBuffer(" copyProperty("); @@ -417,7 +428,7 @@ // Convert the specified value to the required type and store it if (index >= 0) { // Destination must be indexed - Converter converter = ConvertUtils.lookup(type.getComponentType()); + Converter converter = set.lookup(type.getComponentType()); if (converter != null) { log.trace(" USING CONVERTER " + converter); value = converter.convert(type, value); @@ -441,7 +452,7 @@ (e, "Cannot set " + propName); } } else { // Destination must be simple - Converter converter = ConvertUtils.lookup(type); + Converter converter = set.lookup(type); if (converter != null) { log.trace(" USING CONVERTER " + converter); value = converter.convert(type, value); @@ -477,22 +488,30 @@ throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + return describe(bean, ConvertUtils.getDefaultConverterSet()); + + } + + public static Map describe(Object bean, ConverterSet set) + 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)); + description.put(name, getProperty(bean, name,set)); } } else { PropertyDescriptor descriptors[] = @@ -500,7 +519,7 @@ for (int i = 0; i < descriptors.length; i++) { String name = descriptors[i].getName(); if (descriptors[i].getReadMethod() != null) - description.put(name, getProperty(bean, name)); + description.put(name, getProperty(bean, name,set)); } } return (description); @@ -583,9 +602,15 @@ public static String getIndexedProperty(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + return getIndexedProperty(bean,name,ConvertUtils.getDefaultConverterSet()); + } + + public static String getIndexedProperty(Object bean, String name, ConverterSet +set) + throws IllegalAccessException, InvocationTargetException, + NoSuchMethodException { Object value = PropertyUtils.getIndexedProperty(bean, name); - return (ConvertUtils.convert(value)); + return (ConvertUtils.convert(value, set)); } @@ -611,8 +636,17 @@ throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + return +getIndexedProperty(bean,name,index,ConvertUtils.getDefaultConverterSet()); + + } + + public static String getIndexedProperty(Object bean, + String name, int index, ConverterSet set) + throws IllegalAccessException, InvocationTargetException, + NoSuchMethodException { + Object value = PropertyUtils.getIndexedProperty(bean, name, index); - return (ConvertUtils.convert(value)); + return (ConvertUtils.convert(value,set)); } @@ -639,8 +673,16 @@ throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + return getMappedProperty(bean,name,ConvertUtils.getDefaultConverterSet()); + + } + + public static String getMappedProperty(Object bean, String name, ConverterSet set) + throws IllegalAccessException, InvocationTargetException, + NoSuchMethodException { + Object value = PropertyUtils.getMappedProperty(bean, name); - return (ConvertUtils.convert(value)); + return (ConvertUtils.convert(value,set)); } @@ -665,9 +707,16 @@ String name, String key) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + return getMappedProperty(bean,name,key,ConvertUtils.getDefaultConverterSet()); + } + + public static String getMappedProperty(Object bean, + String name, String key, ConverterSet set) + throws IllegalAccessException, InvocationTargetException, + NoSuchMethodException { Object value = PropertyUtils.getMappedProperty(bean, name, key); - return (ConvertUtils.convert(value)); + return (ConvertUtils.convert(value,set)); } @@ -691,9 +740,15 @@ public static String getNestedProperty(Object bean, String name) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + return getNestedProperty(bean,name,ConvertUtils.getDefaultConverterSet()); + } + + public static String getNestedProperty(Object bean, String name,ConverterSet set) + throws IllegalAccessException, InvocationTargetException, + NoSuchMethodException { Object value = PropertyUtils.getNestedProperty(bean, name); - return (ConvertUtils.convert(value)); + return (ConvertUtils.convert(value,set)); } @@ -717,7 +772,15 @@ throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - return (getNestedProperty(bean, name)); + return getProperty(bean,name,ConvertUtils.getDefaultConverterSet()); + + } + + public static String getProperty(Object bean, String name, ConverterSet set) + throws IllegalAccessException, InvocationTargetException, + NoSuchMethodException { + + return (getNestedProperty(bean, name,set)); } @@ -740,8 +803,16 @@ throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + return getSimpleProperty(bean,name,ConvertUtils.getDefaultConverterSet()); + + } + + public static String getSimpleProperty(Object bean, String name,ConverterSet set) + throws IllegalAccessException, InvocationTargetException, + NoSuchMethodException { + Object value = PropertyUtils.getSimpleProperty(bean, name); - return (ConvertUtils.convert(value)); + return (ConvertUtils.convert(value,set)); } @@ -754,14 +825,14 @@ * <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> @@ -784,6 +855,12 @@ public static void populate(Object bean, Map properties) throws IllegalAccessException, InvocationTargetException { + populate(bean, properties, ConvertUtils.getDefaultConverterSet()); + + } + + public static void populate(Object bean, Map properties, ConverterSet set) + throws IllegalAccessException, InvocationTargetException { // Do nothing unless both arguments have been specified if ((bean == null) || (properties == null)) { return; @@ -805,7 +882,7 @@ Object value = properties.get(name); // Perform the assignment for this property - setProperty(bean, name, value); + setProperty(bean, name, value, set); } @@ -816,7 +893,7 @@ * <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 + * <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, @@ -845,6 +922,13 @@ public static void setProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException { + setProperty(bean,name,value,ConvertUtils.getDefaultConverterSet()); + + } + + public static void setProperty(Object bean, String name, Object value, +ConverterSet set) + throws IllegalAccessException, InvocationTargetException { + // Trace logging (if enabled) if (log.isTraceEnabled()) { StringBuffer sb = new StringBuffer(" setProperty("); @@ -974,34 +1058,34 @@ if (value == null) { String values[] = new String[1]; values[0] = (String) value; - newValue = ConvertUtils.convert((String[]) values, type); + newValue = ConvertUtils.convert((String[]) values, type, set); } else if (value instanceof String) { String values[] = new String[1]; values[0] = (String) value; - newValue = ConvertUtils.convert((String[]) values, type); + newValue = ConvertUtils.convert((String[]) values, type, set); } else if (value instanceof String[]) { - newValue = ConvertUtils.convert((String[]) value, type); + newValue = ConvertUtils.convert((String[]) value, type, set); } else { newValue = value; } } else if (type.isArray()) { // Indexed value into array if (value instanceof String) { newValue = ConvertUtils.convert((String) value, - type.getComponentType()); + type.getComponentType(), set); } else if (value instanceof String[]) { newValue = ConvertUtils.convert(((String[]) value)[0], - type.getComponentType()); + type.getComponentType(), set); } else { newValue = value; } } else { // Value into scalar if ((value instanceof String) || (value == null)) { - newValue = ConvertUtils.convert((String) value, type); + newValue = ConvertUtils.convert((String) value, type, set); } else if (value instanceof String[]) { newValue = ConvertUtils.convert(((String[]) value)[0], - type); - } else if (ConvertUtils.lookup(value.getClass()) != null) { - newValue = ConvertUtils.convert(value.toString(), type); + type, set); + } else if (set.lookup(value.getClass()) != null) { + newValue = ConvertUtils.convert(value.toString(), type, set); } else { newValue = value; } --- ConverterSet.java.orig 2003-02-12 10:45:13.000000000 -0600 +++ ConverterSet.java 2003-02-12 10:45:14.000000000 -0600 @@ -0,0 +1,202 @@ +package org.apache.commons.beanutils; + +import org.apache.commons.collections.FastHashMap; +import org.apache.commons.beanutils.converters.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; + +public class ConverterSet { + + /** + * The name of the defaultConverter set. The default ConverterSet can be +retrieved by calling + * ConvertUtils.getDefaultConverterSet(), or +ConvertUtils.getConverterSet(ConverterSet.DEFAULT_CONVERTER_SET_NAME) + */ + public static final String DEFAULT_CONVERTER_SET_NAME = "DEFAULT"; + + + private static Log log = LogFactory.getLog(ConverterSet.class); + + + /** + * The default value for Boolean conversions. + * To change the default, create a new Converter: + * ConverterSet.register(Boolean.TYPE, new BooleanConverter(Boolean.TRUE)); + * ConverterSet.register(Boolean.class, new BooleanConverter(Boolean.TRUE)); + */ + private static Boolean defaultBoolean = Boolean.FALSE; + + /** + * The default value for Byte conversions. + */ + private static Byte defaultByte = new Byte((byte) 0); + + /** + * The default value for Character conversions. + */ + private static Character defaultCharacter = new Character(' '); + + /** + * The default value for Double conversions. + */ + private static Double defaultDouble = new Double((double) 0.0); + + /** + * The default value for Float conversions. + */ + private static Float defaultFloat = new Float((float) 0.0); + + /** + * The default value for Integer conversions. + */ + private static Integer defaultInteger = new Integer(0); + + /** + * The default value for Long conversions. + */ + private static Long defaultLong = new Long((long) 0); + + /** + * The default value for Short conversions. + */ + private static Short defaultShort = new Short((short) 0); + + + /** + * Name of this ConverterSet (immutable). + */ + private String name; + + public ConverterSet(String name) { + this.name = name; + converters.setFast(false); + deregister(); //initialize the data (maybe have a better method name?) + converters.setFast(true); + } + + public String getName() { + return name; + } + + + /** + * The set of converters associated with this ConverterSet + */ + private FastHashMap converters = new FastHashMap(); + + protected FastHashMap getConverters() { + return converters; + } + + + /** + * Return the converter associate with the given class (Converts TO this class) + * + * @param clazz + * @return + */ + public Converter lookup(Class clazz) { + return (Converter) converters.get(clazz); + } + + /** + * Register a new converter for the given class. + * + * @param clazz + * @param converter + */ + public void register(Converter converter, Class clazz) { + converters.put(clazz, converter); + } + + /** + * Removes the converter for the given class + * + * @param clazz + */ + public void deregister(Class clazz) { + converters.remove(clazz); + } + + /** + * removes all converters + */ + public void clear() { + getConverters().clear(); + } + + /** + * returns true if this ConverterSet represents the default converter set + * + * @return + */ + public boolean isDefaultConverterSet() { + return DEFAULT_CONVERTER_SET_NAME.equals(getName()); + } + + /** + * Remove all registered {@link Converter}s, and re-establish the + * standard Converters. + * + * //@todo There should be some synchronization here, but there wasn't any before +so do we worry about it? + * // i.e. if lookup() is called while in the middle of this method, on a class +type for which the + * // default converter has not yet been re-registered, it will either throw an +NPE or ?? depending on type + * // this whole block should be synchronized with lookup(); + * // unless if you assume that this method should only be called as a setup +procedure, and not be called during normal application runtime + */ + 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]; + + clear(); + + register(new BigDecimalConverter(), BigDecimal.class); + register(new BigIntegerConverter(), BigInteger.class); + register(new BooleanConverter(defaultBoolean), Boolean.TYPE); + register(new BooleanConverter(defaultBoolean), Boolean.class); + register(new BooleanArrayConverter(booleanArray), + booleanArray.getClass()); + register(new ByteConverter(defaultByte), Byte.TYPE); + register(new ByteConverter(defaultByte), Byte.class); + register(new ByteArrayConverter(byteArray), byteArray.getClass()); + register(new CharacterConverter(defaultCharacter), Character.TYPE); + register(new CharacterConverter(defaultCharacter), Character.class); + register(new CharacterArrayConverter(charArray), charArray.getClass()); + register(new ClassConverter(), Class.class); + register(new DoubleConverter(defaultDouble), Double.TYPE); + register(new DoubleConverter(defaultDouble), Double.class); + register(new DoubleArrayConverter(doubleArray), doubleArray.getClass()); + register(new FloatConverter(defaultFloat), Float.TYPE); + register(new FloatConverter(defaultFloat), Float.class); + register(new FloatArrayConverter(floatArray), floatArray.getClass()); + register(new IntegerConverter(defaultInteger), Integer.TYPE); + register(new IntegerConverter(defaultInteger), Integer.class); + register(new IntegerArrayConverter(intArray), intArray.getClass()); + register(new LongConverter(defaultLong), Long.TYPE); + register(new LongConverter(defaultLong), Long.class); + register(new LongArrayConverter(longArray), longArray.getClass()); + register(new ShortConverter(defaultShort), Short.TYPE); + register(new ShortConverter(defaultShort), Short.class); + register(new ShortArrayConverter(shortArray), shortArray.getClass()); + register(new StringConverter(), String.class); + register(new StringArrayConverter(stringArray), stringArray.getClass()); + register(new SqlDateConverter(), Date.class); + register(new SqlTimeConverter(), Time.class); + register(new SqlTimestampConverter(), Timestamp.class); + + } + +} --- ConvertUtils.java.orig 2003-02-12 10:45:12.000000000 -0600 +++ ConvertUtils.java 2003-02-12 10:45:14.000000000 -0600 @@ -64,35 +64,6 @@ 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 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.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.collections.FastHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -150,165 +121,59 @@ // ------------------------------------------------------ Static Properties - /** - * The default value for Boolean conversions. - * @deprecated Register replacement converters for Boolean.TYPE and - * Boolean.class instead - */ - private static Boolean defaultBoolean = Boolean.FALSE; - - public static boolean getDefaultBoolean() { - return (defaultBoolean.booleanValue()); - } - public static void setDefaultBoolean(boolean newDefaultBoolean) { - defaultBoolean = new Boolean(newDefaultBoolean); - converters.put(Boolean.TYPE, new BooleanConverter(defaultBoolean)); - converters.put(Boolean.class, new BooleanConverter(defaultBoolean)); - } - - - /** - * The default value for Byte conversions. - * @deprecated Register replacement converters for Byte.TYPE and - * Byte.class instead - */ - private static Byte defaultByte = new Byte((byte) 0); - public static byte getDefaultByte() { - return (defaultByte.byteValue()); - } - public static void setDefaultByte(byte newDefaultByte) { - defaultByte = new Byte(newDefaultByte); - converters.put(Byte.TYPE, new ByteConverter(defaultByte)); - converters.put(Byte.class, new ByteConverter(defaultByte)); - } + // ------------------------------------------------------- Static Variables /** - * The default value for Character conversions. - * @deprecated Register replacement converters for Character.TYPE and - * Character.class instead + * 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 static Character defaultCharacter = new Character(' '); + private static FastHashMap converterSets = new FastHashMap(); - public static char getDefaultCharacter() { - return (defaultCharacter.charValue()); - } + protected static FastHashMap getConverterSets() { - public static void setDefaultCharacter(char newDefaultCharacter) { - defaultCharacter = new Character(newDefaultCharacter); - converters.put(Character.TYPE, - new CharacterConverter(defaultCharacter)); - converters.put(Character.class, - new CharacterConverter(defaultCharacter)); - } + return converterSets; - - /** - * The default value for Double conversions. - * @deprecated Register replacement converters for Double.TYPE and - * Double.class instead - */ - private static Double defaultDouble = new Double((double) 0.0); - - public static double getDefaultDouble() { - return (defaultDouble.doubleValue()); - } - - public static void setDefaultDouble(double newDefaultDouble) { - defaultDouble = new Double(newDefaultDouble); - converters.put(Double.TYPE, new DoubleConverter(defaultDouble)); - converters.put(Double.class, new DoubleConverter(defaultDouble)); } + public static ConverterSet getDefaultConverterSet() { - /** - * The default value for Float conversions. - * @deprecated Register replacement converters for Float.TYPE and - * Float.class instead - */ - private static Float defaultFloat = new Float((float) 0.0); + return +(ConverterSet)getConverterSets().get(ConverterSet.DEFAULT_CONVERTER_SET_NAME); - public static float getDefaultFloat() { - return (defaultFloat.floatValue()); - } - - public static void setDefaultFloat(float newDefaultFloat) { - defaultFloat = new Float(newDefaultFloat); - converters.put(Float.TYPE, new FloatConverter(defaultFloat)); - converters.put(Float.class, new FloatConverter(defaultFloat)); } + public static ConverterSet getConverterSet(String name) { - /** - * The default value for Integer conversions. - * @deprecated Register replacement converters for Integer.TYPE and - * Integer.class instead - */ - private static Integer defaultInteger = new Integer(0); + return (ConverterSet)getConverterSets().get(name); - public static int getDefaultInteger() { - return (defaultInteger.intValue()); } - public static void setDefaultInteger(int newDefaultInteger) { - defaultInteger = new Integer(newDefaultInteger); - converters.put(Integer.TYPE, new IntegerConverter(defaultInteger)); - converters.put(Integer.class, new IntegerConverter(defaultInteger)); - } - - - /** - * The default value for Long conversions. - * @deprecated Register replacement converters for Long.TYPE and - * Long.class instead - */ - private static Long defaultLong = new Long((long) 0); + public static void addConverterSet(ConverterSet set) { + if (set.getName() == null) { + throw new IllegalArgumentException("ConverterSet must have a name in +order to add it"); + } - public static long getDefaultLong() { - return (defaultLong.longValue()); - } + getConverterSets().put(set.getName(), set); - public static void setDefaultLong(long newDefaultLong) { - defaultLong = new Long(newDefaultLong); - converters.put(Long.TYPE, new LongConverter(defaultLong)); - converters.put(Long.class, new LongConverter(defaultLong)); } + public static void removeConverterSet(String name) { + if (name == null) { + throw new IllegalArgumentException("ConverterSet must have a name in +order to add it"); + } - /** - * 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); - - public static short getDefaultShort() { - return (defaultShort.shortValue()); - } + getConverterSets().remove(name); - public static void setDefaultShort(short newDefaultShort) { - defaultShort = new Short(newDefaultShort); - converters.put(Short.TYPE, new ShortConverter(defaultShort)); - converters.put(Short.class, new ShortConverter(defaultShort)); } - // ------------------------------------------------------- Static 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 static FastHashMap converters = new FastHashMap(); - static { - converters.setFast(false); - deregister(); - converters.setFast(true); + //create the default ConverterSet instance + getConverterSets().put(ConverterSet.DEFAULT_CONVERTER_SET_NAME,new +ConverterSet(ConverterSet.DEFAULT_CONVERTER_SET_NAME) ); + } @@ -332,7 +197,10 @@ * @param value Value to be converted (may be null) */ public static String convert(Object value) { + return convert(value, getDefaultConverterSet()); + } + public static String convert(Object value, ConverterSet set) { if (value == null) { return ((String) null); } else if (value.getClass().isArray()) { @@ -343,11 +211,11 @@ if (value == null) { return ((String) null); } else { - Converter converter = (Converter) converters.get(String.class); + Converter converter = set.lookup(String.class); return ((String) converter.convert(String.class, value)); } } else { - Converter converter = (Converter) converters.get(String.class); + Converter converter = set.lookup(String.class); return ((String) converter.convert(String.class, value)); } @@ -364,14 +232,18 @@ * @exception ConversionException if thrown by an underlying Converter */ public static Object convert(String value, Class clazz) { + return convert(value, clazz, getDefaultConverterSet() ); + } + + public static Object convert(String value, Class clazz, ConverterSet set) { if (log.isDebugEnabled()) { log.debug("Convert string '" + value + "' to class '" + clazz.getName() + "'"); } - Converter converter = (Converter) converters.get(clazz); + Converter converter = set.lookup(clazz); if (converter == null) { - converter = (Converter) converters.get(String.class); + converter = set.lookup(String.class); } if (log.isTraceEnabled()) { log.trace(" Using converter " + converter); @@ -394,7 +266,10 @@ * @exception ConversionException if thrown by an underlying Converter */ public static Object convert(String values[], Class clazz) { + return convert(values, clazz, getDefaultConverterSet()); + } + public static Object convert(String values[], Class clazz, ConverterSet set) { Class type = clazz; if (clazz.isArray()) { type = clazz.getComponentType(); @@ -403,9 +278,9 @@ log.debug("Convert String[" + values.length + "] to class '" + type.getName() + "[]'"); } - Converter converter = (Converter) converters.get(type); + Converter converter = set.lookup(type); if (converter == null) { - converter = (Converter) converters.get(String.class); + converter = set.lookup(String.class); } if (log.isTraceEnabled()) { log.trace(" Using converter " + converter); @@ -419,68 +294,7 @@ } - /** - * Remove all registered {@link Converter}s, and re-establish the - * standard Converters. - */ - public static 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(); - converters.put(BigDecimal.class, new BigDecimalConverter()); - converters.put(BigInteger.class, new BigIntegerConverter()); - converters.put(Boolean.TYPE, new BooleanConverter(defaultBoolean)); - converters.put(Boolean.class, new BooleanConverter(defaultBoolean)); - converters.put(booleanArray.getClass(), - new BooleanArrayConverter(booleanArray)); - converters.put(Byte.TYPE, new ByteConverter(defaultByte)); - converters.put(Byte.class, new ByteConverter(defaultByte)); - converters.put(byteArray.getClass(), - new ByteArrayConverter(byteArray)); - converters.put(Character.TYPE, - new CharacterConverter(defaultCharacter)); - converters.put(Character.class, - new CharacterConverter(defaultCharacter)); - converters.put(charArray.getClass(), - new CharacterArrayConverter(charArray)); - converters.put(Class.class, new ClassConverter()); - converters.put(Double.TYPE, new DoubleConverter(defaultDouble)); - converters.put(Double.class, new DoubleConverter(defaultDouble)); - converters.put(doubleArray.getClass(), - new DoubleArrayConverter(doubleArray)); - converters.put(Float.TYPE, new FloatConverter(defaultFloat)); - converters.put(Float.class, new FloatConverter(defaultFloat)); - converters.put(floatArray.getClass(), - new FloatArrayConverter(floatArray)); - converters.put(Integer.TYPE, new IntegerConverter(defaultInteger)); - converters.put(Integer.class, new IntegerConverter(defaultInteger)); - converters.put(intArray.getClass(), - new IntegerArrayConverter(intArray)); - converters.put(Long.TYPE, new LongConverter(defaultLong)); - converters.put(Long.class, new LongConverter(defaultLong)); - converters.put(longArray.getClass(), - new LongArrayConverter(longArray)); - converters.put(Short.TYPE, new ShortConverter(defaultShort)); - converters.put(Short.class, new ShortConverter(defaultShort)); - converters.put(shortArray.getClass(), - new ShortArrayConverter(shortArray)); - converters.put(String.class, new StringConverter()); - converters.put(stringArray.getClass(), - new StringArrayConverter(stringArray)); - converters.put(Date.class, new SqlDateConverter()); - converters.put(Time.class, new SqlTimeConverter()); - converters.put(Timestamp.class, new SqlTimestampConverter()); - } /** @@ -491,10 +305,15 @@ */ public static void deregister(Class clazz) { - converters.remove(clazz); + getDefaultConverterSet().deregister(clazz); } + public static void deregister() { + + getDefaultConverterSet().deregister(); + + } /** * Look up and return any registered {@link Converter} for the specified @@ -505,7 +324,7 @@ */ public static Converter lookup(Class clazz) { - return ((Converter) converters.get(clazz)); + return getDefaultConverterSet().lookup(clazz); } @@ -520,7 +339,7 @@ */ public static void register(Converter converter, Class clazz) { - converters.put(clazz, converter); + getDefaultConverterSet().register(converter, clazz); } --- LocaleBeanUtils.java.orig 2003-02-12 10:45:12.000000000 -0600 +++ LocaleBeanUtils.java 2003-02-12 10:45:14.000000000 -0600 @@ -179,7 +179,7 @@ throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - return getIndexedProperty(bean, name, null); + return getIndexedProperty(bean, name, (String)null); } /** @@ -231,7 +231,7 @@ String name, int index) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - return getIndexedProperty(bean, name, index, null); + return getIndexedProperty(bean, name, index, (String)null); } /** @@ -277,7 +277,7 @@ throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - return getSimpleProperty(bean, name, null); + return getSimpleProperty(bean, name, (String)null); } /** @@ -329,7 +329,7 @@ throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - return getMappedProperty(bean, name, key, null); + return getMappedProperty(bean, name, key, (String)null); } @@ -436,7 +436,7 @@ throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - return getNestedProperty(bean, name, null); + return getNestedProperty(bean, name, (String)null); } /** @@ -504,7 +504,7 @@ public static void setProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException { - setProperty(bean, name, value, null); + setProperty(bean, name, value, (String)null); } /** --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]