From 82607494229d96cdf64073b5a205ce1d5266ac96 Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Tue, 18 Dec 2018 21:46:12 +0100 Subject: [PATCH 01/10] Make MILLISECOND_FORMAT static final --- .../xwork2/conversion/impl/DefaultTypeConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java index e8fdb2c00..783c5a61e 100644 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java +++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java @@ -44,7 +44,7 @@ import java.util.Map; */ public abstract class DefaultTypeConverter implements TypeConverter { - protected static String MILLISECOND_FORMAT = ".SSS"; + protected static final String MILLISECOND_FORMAT = ".SSS"; private static final String NULL_STRING = "null"; From 0bad296cd265dce5f71d44d172135746fbdcaecd Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Tue, 18 Dec 2018 21:49:14 +0100 Subject: [PATCH 02/10] Remove the thrown NumberFormatException which is a runtime exception --- .../conversion/impl/DefaultTypeConverter.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java index 783c5a61e..c8b27b93b 100644 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java +++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java @@ -202,10 +202,8 @@ public abstract class DefaultTypeConverter implements TypeConverter { * @param value * an object to interpret as a long integer * @return the long integer value implied by the given object - * @throws NumberFormatException - * if the given object can't be understood as a long integer */ - public static long longValue(Object value) throws NumberFormatException { + public static long longValue(Object value) { if (value == null) return 0L; Class c = value.getClass(); @@ -224,10 +222,8 @@ public abstract class DefaultTypeConverter implements TypeConverter { * @param value * an object to interpret as a double * @return the double value implied by the given object - * @throws NumberFormatException - * if the given object can't be understood as a double */ - public static double doubleValue(Object value) throws NumberFormatException { + public static double doubleValue(Object value) { if (value == null) return 0.0; Class c = value.getClass(); @@ -252,11 +248,8 @@ public abstract class DefaultTypeConverter implements TypeConverter { * @param value * an object to interpret as a BigInteger * @return the BigInteger value implied by the given object - * @throws NumberFormatException - * if the given object can't be understood as a BigInteger */ - public static BigInteger bigIntValue(Object value) - throws NumberFormatException { + public static BigInteger bigIntValue(Object value) { if (value == null) return BigInteger.valueOf(0L); Class c = value.getClass(); @@ -279,11 +272,8 @@ public abstract class DefaultTypeConverter implements TypeConverter { * @param value * an object to interpret as a BigDecimal * @return the BigDecimal value implied by the given object - * @throws NumberFormatException - * if the given object can't be understood as a BigDecimal */ - public static BigDecimal bigDecValue(Object value) - throws NumberFormatException { + public static BigDecimal bigDecValue(Object value) { if (value == null) return BigDecimal.valueOf(0L); Class c = value.getClass(); From cb492377bf95e602a1f5a6cace2d5656597d0c9e Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Tue, 18 Dec 2018 21:50:06 +0100 Subject: [PATCH 03/10] Remove commented-out lines of code --- .../xwork2/conversion/impl/DefaultTypeConverter.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java index c8b27b93b..fc0ebc8d0 100644 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java +++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java @@ -236,10 +236,6 @@ public abstract class DefaultTypeConverter implements TypeConverter { String s = stringValue(value, true); return (s.length() == 0) ? 0.0 : Double.parseDouble(s); - /* - * For 1.1 parseDouble() is not available - */ - // return Double.valueOf( value.toString() ).doubleValue(); } /** From d99888da5e60c5ea8e7ba03ff3f0d42ac95b00dc Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Tue, 18 Dec 2018 21:52:31 +0100 Subject: [PATCH 04/10] Fix warning: Use "BigDecimal.valueOf" instead This method uses a string under the covers to eliminate floating point rounding errors. --- .../xwork2/conversion/impl/DefaultTypeConverter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java index fc0ebc8d0..93d0a46d9 100644 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java +++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java @@ -63,7 +63,7 @@ public abstract class DefaultTypeConverter implements TypeConverter { map.put(Float.TYPE, new Float(0.0f)); map.put(Double.TYPE, new Double(0.0)); map.put(BigInteger.class, new BigInteger("0")); - map.put(BigDecimal.class, new BigDecimal(0.0)); + map.put(BigDecimal.class, BigDecimal.valueOf(0.0)); primitiveDefaults = Collections.unmodifiableMap(map); } @@ -278,7 +278,7 @@ public abstract class DefaultTypeConverter implements TypeConverter { if (c == BigInteger.class) return new BigDecimal((BigInteger) value); if (c.getSuperclass() == Number.class) - return new BigDecimal(((Number) value).doubleValue()); + return BigDecimal.valueOf(((Number) value).doubleValue()); if (c == Boolean.class) return BigDecimal.valueOf((Boolean) value ? 1 : 0); if (c == Character.class) From e428d8d785102cc8236fddaa2b2e1fcf752608f2 Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Tue, 18 Dec 2018 21:53:04 +0100 Subject: [PATCH 05/10] Add the "@Override" annotation --- .../xwork2/conversion/impl/DefaultTypeConverter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java index 93d0a46d9..5209c13dd 100644 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java +++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java @@ -76,6 +76,7 @@ public abstract class DefaultTypeConverter implements TypeConverter { return convertValue(value, toType); } + @Override public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType) { return convertValue(context, value, toType); From 59e174e34f55db4764cc920547fd09cc609f148b Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Wed, 19 Dec 2018 21:13:32 +0100 Subject: [PATCH 06/10] Simplify nested else/if --- .../xwork2/conversion/impl/DefaultTypeConverter.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java index 5209c13dd..cc26f70c9 100644 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java +++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java @@ -153,10 +153,8 @@ public abstract class DefaultTypeConverter implements TypeConverter { if (Enum.class.isAssignableFrom(toType)) result = enumValue(toType, value); } - } else { - if (toType.isPrimitive()) { - result = primitiveDefaults.get(toType); - } + } else if (toType.isPrimitive()) { + result = primitiveDefaults.get(toType); } return result; } From 3d120f59aa866d90bf20ae0fbf92e57e6f161181 Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Wed, 19 Dec 2018 21:47:39 +0100 Subject: [PATCH 07/10] Add test for convertValue with BigDecimal --- .../impl/XWorkBasicConverterTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java index a0c66c69c..815489f12 100644 --- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java @@ -23,6 +23,7 @@ import com.opensymphony.xwork2.XWorkException; import com.opensymphony.xwork2.XWorkTestCase; import com.opensymphony.xwork2.test.annotations.Person; +import java.math.BigDecimal; import java.text.DateFormat; import java.util.*; @@ -228,6 +229,37 @@ public class XWorkBasicConverterTest extends XWorkTestCase { assertEquals(94.1231233d, (Double) convertedObject, 0.0001); } + public void testBigDecimal() { + Object convertedObject = basicConverter.convertValue(null, BigDecimal.class); + assertNull(convertedObject); + + convertedObject = basicConverter.convertValue(new BigDecimal(0), BigDecimal.class); + assertEquals(BigDecimal.ZERO, convertedObject); + assertTrue(convertedObject instanceof BigDecimal); + assertEquals(0, BigDecimal.ZERO.compareTo((BigDecimal) convertedObject)); + + convertedObject = basicConverter.convertValue(BigDecimal.valueOf(0), BigDecimal.class); + assertEquals(BigDecimal.ZERO, convertedObject); + assertTrue(convertedObject instanceof BigDecimal); + assertEquals(0, BigDecimal.ZERO.compareTo((BigDecimal) convertedObject)); + + convertedObject = basicConverter.convertValue(BigDecimal.valueOf(0.0), BigDecimal.class); + assertEquals(BigDecimal.valueOf(0.0), convertedObject); + assertTrue(convertedObject instanceof BigDecimal); + assertEquals(0, BigDecimal.ZERO.compareTo((BigDecimal) convertedObject)); + + convertedObject = basicConverter.convertValue(BigDecimal.valueOf(0.000), BigDecimal.class); + assertEquals(BigDecimal.valueOf(0.000), convertedObject); + assertTrue(convertedObject instanceof BigDecimal); + assertEquals(0, BigDecimal.ZERO.compareTo((BigDecimal) convertedObject)); + + convertedObject = basicConverter.convertValue(BigDecimal.valueOf(10), BigDecimal.class); + assertEquals(BigDecimal.TEN, convertedObject); + + convertedObject = basicConverter.convertValue(BigDecimal.valueOf(12345.67890), BigDecimal.class); + assertEquals(BigDecimal.valueOf(12345.67890), convertedObject); + } + public void testNestedEnumValue() throws Exception { Object convertedObject = basicConverter.convertValue(ParentClass.NestedEnum.TEST.name(), ParentClass.NestedEnum.class); assertTrue(convertedObject instanceof ParentClass.NestedEnum); From ba493b46c5c2c28a451a38270a65f3b6f85481c1 Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Fri, 21 Dec 2018 23:07:35 +0100 Subject: [PATCH 08/10] Use parameterized Class instead of raw type --- .../conversion/impl/DefaultTypeConverter.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java index cc26f70c9..38c1edfad 100644 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java +++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java @@ -48,12 +48,12 @@ public abstract class DefaultTypeConverter implements TypeConverter { private static final String NULL_STRING = "null"; - private static final Map primitiveDefaults; + private static final Map, Object> primitiveDefaults; private Container container; static { - Map map = new HashMap<>(); + Map, Object> map = new HashMap<>(); map.put(Boolean.TYPE, Boolean.FALSE); map.put(Byte.TYPE, Byte.valueOf((byte) 0)); map.put(Short.TYPE, Short.valueOf((short) 0)); @@ -119,7 +119,7 @@ public abstract class DefaultTypeConverter implements TypeConverter { if (value != null) { /* If array -> array then convert components of array individually */ if (value.getClass().isArray() && toType.isArray()) { - Class componentType = toType.getComponentType(); + final Class componentType = toType.getComponentType(); result = Array.newInstance(componentType, Array .getLength(value)); @@ -171,7 +171,7 @@ public abstract class DefaultTypeConverter implements TypeConverter { public static boolean booleanValue(Object value) { if (value == null) return false; - Class c = value.getClass(); + final Class c = value.getClass(); if (c == Boolean.class) return (Boolean) value; // if ( c == String.class ) @@ -205,7 +205,7 @@ public abstract class DefaultTypeConverter implements TypeConverter { public static long longValue(Object value) { if (value == null) return 0L; - Class c = value.getClass(); + final Class c = value.getClass(); if (c.getSuperclass() == Number.class) return ((Number) value).longValue(); if (c == Boolean.class) @@ -225,15 +225,14 @@ public abstract class DefaultTypeConverter implements TypeConverter { public static double doubleValue(Object value) { if (value == null) return 0.0; - Class c = value.getClass(); + final Class c = value.getClass(); if (c.getSuperclass() == Number.class) return ((Number) value).doubleValue(); if (c == Boolean.class) return (Boolean) value ? 1 : 0; if (c == Character.class) return (Character) value; - String s = stringValue(value, true); - + final String s = stringValue(value, true); return (s.length() == 0) ? 0.0 : Double.parseDouble(s); } @@ -247,7 +246,7 @@ public abstract class DefaultTypeConverter implements TypeConverter { public static BigInteger bigIntValue(Object value) { if (value == null) return BigInteger.valueOf(0L); - Class c = value.getClass(); + final Class c = value.getClass(); if (c == BigInteger.class) return (BigInteger) value; if (c == BigDecimal.class) @@ -271,7 +270,7 @@ public abstract class DefaultTypeConverter implements TypeConverter { public static BigDecimal bigDecValue(Object value) { if (value == null) return BigDecimal.valueOf(0L); - Class c = value.getClass(); + final Class c = value.getClass(); if (c == BigDecimal.class) return (BigDecimal) value; if (c == BigInteger.class) From b58dc38c5ca2067a71feb45301c3491a8e241d3e Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Fri, 21 Dec 2018 23:32:23 +0100 Subject: [PATCH 09/10] Add test for convertValue with BigInteger --- .../impl/XWorkBasicConverterTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java index 815489f12..be51879e2 100644 --- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java @@ -24,6 +24,7 @@ import com.opensymphony.xwork2.XWorkTestCase; import com.opensymphony.xwork2.test.annotations.Person; import java.math.BigDecimal; +import java.math.BigInteger; import java.text.DateFormat; import java.util.*; @@ -229,6 +230,24 @@ public class XWorkBasicConverterTest extends XWorkTestCase { assertEquals(94.1231233d, (Double) convertedObject, 0.0001); } + public void testBigInteger() { + Object convertedObject = basicConverter.convertValue(null, BigInteger.class); + assertEquals(BigInteger.ZERO, convertedObject); + assertEquals(0, BigInteger.ZERO.compareTo((BigInteger) convertedObject)); + + convertedObject = basicConverter.convertValue(BigInteger.ZERO, BigInteger.class); + assertEquals(BigInteger.ZERO, convertedObject); + assertEquals(0, BigInteger.ZERO.compareTo((BigInteger) convertedObject)); + + convertedObject = basicConverter.convertValue(new BigInteger("0"), BigInteger.class); + assertEquals(BigInteger.ZERO, convertedObject); + assertEquals(0, BigInteger.ZERO.compareTo((BigInteger) convertedObject)); + + convertedObject = basicConverter.convertValue(BigInteger.TEN, BigInteger.class); + assertEquals(BigInteger.TEN, convertedObject); + assertEquals(0, BigInteger.TEN.compareTo((BigInteger) convertedObject)); + } + public void testBigDecimal() { Object convertedObject = basicConverter.convertValue(null, BigDecimal.class); assertNull(convertedObject); From d09d3dcb3c16edd48a6484e93378c96b1b887df7 Mon Sep 17 00:00:00 2001 From: Sebastian Peters Date: Fri, 21 Dec 2018 23:42:03 +0100 Subject: [PATCH 10/10] Fix behaviour for convertValue with value null I insinuate that the non primitive BigInteger and BigDecimal types should also return default values for null input. Rename the map to `baseTypeDefaults for better understanding and remove the check for `isPrimitive` b/c this seemed to be kind of optimization but breaked the check for included non-primitive types. B/c the unit tests run successfully, we can use the existing default fields ZERO. --- .../xwork2/conversion/impl/DefaultTypeConverter.java | 12 ++++++------ .../conversion/impl/XWorkBasicConverterTest.java | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java index 38c1edfad..731b8f503 100644 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java +++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java @@ -48,7 +48,7 @@ public abstract class DefaultTypeConverter implements TypeConverter { private static final String NULL_STRING = "null"; - private static final Map, Object> primitiveDefaults; + private static final Map, Object> baseTypeDefaults; private Container container; @@ -62,9 +62,9 @@ public abstract class DefaultTypeConverter implements TypeConverter { map.put(Long.TYPE, Long.valueOf(0L)); map.put(Float.TYPE, new Float(0.0f)); map.put(Double.TYPE, new Double(0.0)); - map.put(BigInteger.class, new BigInteger("0")); - map.put(BigDecimal.class, BigDecimal.valueOf(0.0)); - primitiveDefaults = Collections.unmodifiableMap(map); + map.put(BigInteger.class, BigInteger.ZERO); + map.put(BigDecimal.class, BigDecimal.ZERO); + baseTypeDefaults = Collections.unmodifiableMap(map); } @Inject @@ -153,8 +153,8 @@ public abstract class DefaultTypeConverter implements TypeConverter { if (Enum.class.isAssignableFrom(toType)) result = enumValue(toType, value); } - } else if (toType.isPrimitive()) { - result = primitiveDefaults.get(toType); + } else { + result = baseTypeDefaults.get(toType); } return result; } diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java index be51879e2..f8c3e7e41 100644 --- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverterTest.java @@ -250,7 +250,9 @@ public class XWorkBasicConverterTest extends XWorkTestCase { public void testBigDecimal() { Object convertedObject = basicConverter.convertValue(null, BigDecimal.class); - assertNull(convertedObject); + assertEquals(BigDecimal.ZERO, convertedObject); + assertTrue(convertedObject instanceof BigDecimal); + assertEquals(0, BigDecimal.ZERO.compareTo((BigDecimal) convertedObject)); convertedObject = basicConverter.convertValue(new BigDecimal(0), BigDecimal.class); assertEquals(BigDecimal.ZERO, convertedObject);