You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by oh...@apache.org on 2006/06/01 21:52:54 UTC

svn commit: r410930 - in /jakarta/commons/proper/configuration/trunk: src/java/org/apache/commons/configuration/ src/test/org/apache/commons/configuration/ xdocs/

Author: oheger
Date: Thu Jun  1 12:52:53 2006
New Revision: 410930

URL: http://svn.apache.org/viewvc?rev=410930&view=rev
Log:
Added support for conversions between different Number types to PropertyConverter; fixes CONFIGURATION-214

Modified:
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertyConverter.java
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestBaseConfiguration.java
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertyConverter.java
    jakarta/commons/proper/configuration/trunk/xdocs/changes.xml

Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertyConverter.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertyConverter.java?rev=410930&r1=410929&r2=410930&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertyConverter.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertyConverter.java Thu Jun  1 12:52:53 2006
@@ -17,6 +17,8 @@
 package org.apache.commons.configuration;
 
 import java.awt.Color;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.net.MalformedURLException;
@@ -55,6 +57,11 @@
     /** Constant for the radix of hex numbers.*/
     private static final int HEX_RADIX = 16;
 
+    /** Constant for the argument classes of the Number constructor that takes
+     * a String.
+     */
+    private static final Class[] CONSTR_ARGS = { String.class };
+
     /**
      * Private constructor prevents instances from being created.
      */
@@ -100,32 +107,14 @@
      */
     public static Byte toByte(Object value) throws ConversionException
     {
-        if (value instanceof Byte)
+        Number n = toNumber(value, Byte.class);
+        if (n instanceof Byte)
         {
-            return (Byte) value;
-        }
-        else if (value instanceof String)
-        {
-            try
-            {
-                String string = (String) value;
-                if (string.startsWith(HEX_PREFIX))
-                {
-                    return new Byte((byte) Integer.parseInt(string.substring(2), HEX_RADIX));
-                }
-                else
-                {
-                    return new Byte(string);
-                }
-            }
-            catch (NumberFormatException e)
-            {
-                throw new ConversionException("The value " + value + " can't be converted to a Byte object", e);
-            }
+            return (Byte) n;
         }
         else
         {
-            throw new ConversionException("The value " + value + " can't be converted to a Byte object");
+            return new Byte(n.byteValue());
         }
     }
 
@@ -138,33 +127,14 @@
      */
     public static Short toShort(Object value) throws ConversionException
     {
-        if (value instanceof Short)
+        Number n = toNumber(value, Short.class);
+        if (n instanceof Short)
         {
-            return (Short) value;
-        }
-        else if (value instanceof String)
-        {
-            try
-            {
-                String string = (String) value;
-                if (string.startsWith(HEX_PREFIX))
-                {
-                    return new Short((short) Integer.parseInt(string.substring(2), HEX_RADIX));
-                }
-                else
-                {
-                    return new Short(string);
-                }
-
-            }
-            catch (NumberFormatException e)
-            {
-                throw new ConversionException("The value " + value + " can't be converted to a Short object", e);
-            }
+            return (Short) n;
         }
         else
         {
-            throw new ConversionException("The value " + value + " can't be converted to a Short object");
+            return new Short(n.shortValue());
         }
     }
 
@@ -177,32 +147,14 @@
      */
     public static Integer toInteger(Object value) throws ConversionException
     {
-        if (value instanceof Integer)
-        {
-            return (Integer) value;
-        }
-        else if (value instanceof String)
+        Number n = toNumber(value, Integer.class);
+        if (n instanceof Integer)
         {
-            try
-            {
-                String string = (String) value;
-                if (string.startsWith(HEX_PREFIX))
-                {
-                    return new Integer((int) Long.parseLong(string.substring(2), HEX_RADIX));
-                }
-                else
-                {
-                    return new Integer(string);
-                }
-            }
-            catch (NumberFormatException e)
-            {
-                throw new ConversionException("The value " + value + " can't be converted to an Integer object", e);
-            }
+            return (Integer) n;
         }
         else
         {
-            throw new ConversionException("The value " + value + " can't be converted to an Integer object");
+            return new Integer(n.intValue());
         }
     }
 
@@ -215,32 +167,14 @@
      */
     public static Long toLong(Object value) throws ConversionException
     {
-        if (value instanceof Long)
+        Number n = toNumber(value, Long.class);
+        if (n instanceof Long)
         {
-            return (Long) value;
-        }
-        else if (value instanceof String)
-        {
-            try
-            {
-                String string = (String) value;
-                if (string.startsWith(HEX_PREFIX))
-                {
-                    return new Long(new BigInteger(string.substring(2), HEX_RADIX).longValue());
-                }
-                else
-                {
-                    return new Long(string);
-                }
-            }
-            catch (NumberFormatException e)
-            {
-                throw new ConversionException("The value " + value + " can't be converted to a Long object", e);
-            }
+            return (Long) n;
         }
         else
         {
-            throw new ConversionException("The value " + value + " can't be converted to a Long object");
+            return new Long(n.longValue());
         }
     }
 
@@ -253,24 +187,14 @@
      */
     public static Float toFloat(Object value) throws ConversionException
     {
-        if (value instanceof Float)
+        Number n = toNumber(value, Float.class);
+        if (n instanceof Float)
         {
-            return (Float) value;
-        }
-        else if (value instanceof String)
-        {
-            try
-            {
-                return new Float((String) value);
-            }
-            catch (NumberFormatException e)
-            {
-                throw new ConversionException("The value " + value + " can't be converted to a Float object", e);
-            }
+            return (Float) n;
         }
         else
         {
-            throw new ConversionException("The value " + value + " can't be converted to a Float object");
+            return new Float(n.floatValue());
         }
     }
 
@@ -283,24 +207,14 @@
      */
     public static Double toDouble(Object value) throws ConversionException
     {
-        if (value instanceof Double)
-        {
-            return (Double) value;
-        }
-        else if (value instanceof String)
+        Number n = toNumber(value, Double.class);
+        if (n instanceof Double)
         {
-            try
-            {
-                return new Double((String) value);
-            }
-            catch (NumberFormatException e)
-            {
-                throw new ConversionException("The value " + value + " can't be converted to a Double object", e);
-            }
+            return (Double) n;
         }
         else
         {
-            throw new ConversionException("The value " + value + " can't be converted to a Double object");
+            return new Double(n.doubleValue());
         }
     }
 
@@ -313,32 +227,14 @@
      */
     public static BigInteger toBigInteger(Object value) throws ConversionException
     {
-        if (value instanceof BigInteger)
+        Number n = toNumber(value, BigInteger.class);
+        if (n instanceof BigInteger)
         {
-            return (BigInteger) value;
-        }
-        else if (value instanceof String)
-        {
-            try
-            {
-                String string = (String) value;
-                if (string.startsWith(HEX_PREFIX))
-                {
-                    return new BigInteger(string.substring(2), HEX_RADIX);
-                }
-                else
-                {
-                    return new BigInteger(string);
-                }
-            }
-            catch (NumberFormatException e)
-            {
-                throw new ConversionException("The value " + value + " can't be converted to a BigInteger object", e);
-            }
+            return (BigInteger) n;
         }
         else
         {
-            throw new ConversionException("The value " + value + " can't be converted to a BigInteger object");
+            return BigInteger.valueOf(n.longValue());
         }
     }
 
@@ -351,24 +247,73 @@
      */
     public static BigDecimal toBigDecimal(Object value) throws ConversionException
     {
-        if (value instanceof BigDecimal)
+        Number n = toNumber(value, BigDecimal.class);
+        if (n instanceof BigDecimal)
         {
-            return (BigDecimal) value;
+            return (BigDecimal) n;
         }
-        else if (value instanceof String)
+        else
         {
-            try
+            return new BigDecimal(n.doubleValue());
+        }
+    }
+
+    /**
+     * Tries to convert the specified object into a number object. This method
+     * is used by the conversion methods for number types. Note that the return
+     * value is not in always of the specified target class, but only if a new
+     * object has to be created.
+     *
+     * @param value the value to be converted (must not be <b>null</b>)
+     * @param targetClass the target class of the conversion (must be derived
+     * from <code>java.lang.Number</code>)
+     * @return the converted number
+     * @throws ConversionException if the object cannot be converted
+     */
+    static Number toNumber(Object value, Class targetClass)
+            throws ConversionException
+    {
+        if (value instanceof Number)
+        {
+            return (Number) value;
+        }
+        else
+        {
+            String str = value.toString();
+            if (str.startsWith(HEX_PREFIX))
             {
-                return new BigDecimal((String) value);
+                try
+                {
+                    return new BigInteger(str.substring(HEX_PREFIX.length()),
+                            HEX_RADIX);
+                }
+                catch (NumberFormatException nex)
+                {
+                    throw new ConversionException("Could not convert " + str
+                            + " to " + targetClass.getName()
+                            + "! Invalid hex number.", nex);
+                }
             }
-            catch (NumberFormatException e)
+
+            try
             {
-                throw new ConversionException("The value " + value + " can't be converted to a BigDecimal object", e);
+                Constructor constr = targetClass.getConstructor(CONSTR_ARGS);
+                return (Number) constr.newInstance(new Object[]
+                { str });
+            }
+            catch (InvocationTargetException itex)
+            {
+                throw new ConversionException("Could not convert " + str
+                        + " to " + targetClass.getName(), itex
+                        .getTargetException());
+            }
+            catch (Exception ex)
+            {
+                // Treat all possible exceptions the same way
+                throw new ConversionException(
+                        "Conversion error when trying to convert " + str
+                                + " to " + targetClass.getName(), ex);
             }
-        }
-        else
-        {
-            throw new ConversionException("The value " + value + " can't be converted to a BigDecimal object");
         }
     }
 

Modified: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestBaseConfiguration.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestBaseConfiguration.java?rev=410930&r1=410929&r2=410930&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestBaseConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestBaseConfiguration.java Thu Jun  1 12:52:53 2006
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2005 The Apache Software Foundation.
+ * Copyright 2001-2006 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.
@@ -38,6 +38,9 @@
  */
 public class TestBaseConfiguration extends TestCase
 {
+    /** Constant for the number key.*/
+    static final String KEY_NUMBER = "number";
+
     protected BaseConfiguration config = null;
 
     protected static Class missingElementException = NoSuchElementException.class;
@@ -709,5 +712,28 @@
 
         config.addPropertyDirect("array.double", new double[] { 1, 2 });
         assertEquals("first element of the 'array.double' property", 1, config.getDouble("array.double"), 0);
+    }
+
+    /**
+     * Tests if conversion between number types is possible.
+     */
+    public void testNumberConversions()
+    {
+        config.setProperty(KEY_NUMBER, new Integer(42));
+        assertEquals("Wrong int returned", 42, config.getInt(KEY_NUMBER));
+        assertEquals("Wrong long returned", 42L, config.getLong(KEY_NUMBER));
+        assertEquals("Wrong byte returned", (byte) 42, config
+                .getByte(KEY_NUMBER));
+        assertEquals("Wrong float returned", 42.0f,
+                config.getFloat(KEY_NUMBER), 0.01f);
+        assertEquals("Wrong double returned", 42.0, config
+                .getDouble(KEY_NUMBER), 0.001);
+
+        assertEquals("Wrong Long returned", new Long(42L), config.getLong(
+                KEY_NUMBER, null));
+        assertEquals("Wrong BigInt returned", new BigInteger("42"), config
+                .getBigInteger(KEY_NUMBER));
+        assertEquals("Wrong DigDecimal returned", new BigDecimal("42"), config
+                .getBigDecimal(KEY_NUMBER));
     }
 }

Modified: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertyConverter.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertyConverter.java?rev=410930&r1=410929&r2=410930&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertyConverter.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertyConverter.java Thu Jun  1 12:52:53 2006
@@ -15,6 +15,7 @@
  */
 package org.apache.commons.configuration;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Iterator;
 
@@ -162,5 +163,92 @@
                 "The quick brown fox jumps over ${target}.", PropertyConverter
                         .interpolate("The ${animal} jumps over ${target}.",
                                 config));
+    }
+
+    /**
+     * Tests conversion to numbers when the passed in objects are already
+     * numbers.
+     */
+    public void testToNumberDirect()
+    {
+        Integer i = new Integer(42);
+        assertSame("Wrong integer", i, PropertyConverter.toNumber(i,
+                Integer.class));
+        BigDecimal d = new BigDecimal("3.1415");
+        assertSame("Wrong BigDecimal", d, PropertyConverter.toNumber(d,
+                Integer.class));
+    }
+
+    /**
+     * Tests conversion to numbers when the passed in objects have a compatible
+     * string representation.
+     */
+    public void testToNumberFromString()
+    {
+        assertEquals("Incorrect Integer value", new Integer(42),
+                PropertyConverter.toNumber("42", Integer.class));
+        assertEquals("Incorrect Short value", new Short((short) 10),
+                PropertyConverter.toNumber(new StringBuffer("10"), Short.class));
+    }
+
+    /**
+     * Tests conversion to numbers when the passed in objects are strings with
+     * prefixes for special radices.
+     */
+    public void testToNumberFromHexString()
+    {
+        Number n = PropertyConverter.toNumber("0x10", Integer.class);
+        assertEquals("Incorrect Integer value", 16, n.intValue());
+    }
+
+    /**
+     * Tests conversion to numbers when an invalid Hex value is passed in. This
+     * should cause an exception.
+     */
+    public void testToNumberFromInvalidHexString()
+    {
+        try
+        {
+            PropertyConverter.toNumber("0xNotAHexValue", Integer.class);
+            fail("Could convert invalid hex value!");
+        }
+        catch (ConversionException cex)
+        {
+            // ok
+        }
+    }
+
+    /**
+     * Tests conversion to numbers when the passed in objects have no numeric
+     * String representation. This should cause an exception.
+     */
+    public void testToNumberFromInvalidString()
+    {
+        try
+        {
+            PropertyConverter.toNumber("Not a number", Byte.class);
+            fail("Could convert invalid String!");
+        }
+        catch (ConversionException cex)
+        {
+            // ok
+        }
+    }
+
+    /**
+     * Tests conversion to numbers when the passed in target class is invalid.
+     * This should cause an exception.
+     */
+    public void testToNumberWithInvalidClass()
+    {
+        try
+        {
+            PropertyConverter.toNumber("42", Object.class);
+            fail("Could convert to invalid target class!");
+        }
+        catch (ConversionException cex)
+        {
+            //ok
+        }
     }
 }

Modified: jakarta/commons/proper/configuration/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/xdocs/changes.xml?rev=410930&r1=410929&r2=410930&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/xdocs/changes.xml (original)
+++ jakarta/commons/proper/configuration/trunk/xdocs/changes.xml Thu Jun  1 12:52:53 2006
@@ -23,6 +23,11 @@
   <body>
 
     <release version="1.3-SNAPSHOT" date="in SVN">
+      <action dev="oheger" type="update" issue="CONFIGURATION-214">
+        The getter methods for numeric data types in AbstractConfiguration now
+        support conversions between different Number types, e.g. you can now
+        call getLong(key) when key points to an Integer value.
+      </action>
       <action dev="oheger" type="add">
         The new class DefaultConfigurationBuilder was added as an alternative to
         ConfigurationFactory. It provides some more features and creates a



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org