From aeb4195fbdb1b70cb2485cbdfb1b97d648bf2df2 Mon Sep 17 00:00:00 2001 From: Ravi Chodavarapu Date: Tue, 10 May 2016 16:43:08 +0100 Subject: [PATCH 1/2] Allow retrieving null column values, especially when setting them on the primitive wrapper class types --- .../chodavarapu/datamill/db/impl/RowImpl.java | 10 ++++ .../chodavarapu/datamill/json/JsonArray.java | 9 ++++ .../chodavarapu/datamill/json/JsonObject.java | 52 +++++++++++++++++++ .../datamill/reflection/impl/OutlineImpl.java | 32 +++++++++--- .../datamill/values/StringValue.java | 43 +++++++++++++++ .../chodavarapu/datamill/values/Value.java | 1 + 6 files changed, 139 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/chodavarapu/datamill/db/impl/RowImpl.java b/core/src/main/java/org/chodavarapu/datamill/db/impl/RowImpl.java index 3e2feaa..8fe8d0f 100644 --- a/core/src/main/java/org/chodavarapu/datamill/db/impl/RowImpl.java +++ b/core/src/main/java/org/chodavarapu/datamill/db/impl/RowImpl.java @@ -126,6 +126,11 @@ public boolean asBoolean() { return safeRetrieve(k -> resultSet.getBoolean(key)); } + @Override + public Object asObject(Class type) { + return safeRetrieve(k -> resultSet.getObject(key)); + } + @Override public short asShort() { return safeRetrieve(k -> resultSet.getShort(key)); @@ -194,6 +199,11 @@ public boolean asBoolean() { return safeRetrieve(k -> resultSet.getBoolean(key)); } + @Override + public Object asObject(Class type) { + return safeRetrieve(k -> resultSet.getObject(key)); + } + @Override public short asShort() { return safeRetrieve(k -> resultSet.getShort(key)); diff --git a/core/src/main/java/org/chodavarapu/datamill/json/JsonArray.java b/core/src/main/java/org/chodavarapu/datamill/json/JsonArray.java index a8f995a..2096d3a 100644 --- a/core/src/main/java/org/chodavarapu/datamill/json/JsonArray.java +++ b/core/src/main/java/org/chodavarapu/datamill/json/JsonArray.java @@ -102,6 +102,15 @@ public String asString() { return array.toString(); } + @Override + public Object asObject(Class type) { + if (type == String.class) { + return asString(); + } + + return this; + } + @Override public boolean isBoolean() { return false; diff --git a/core/src/main/java/org/chodavarapu/datamill/json/JsonObject.java b/core/src/main/java/org/chodavarapu/datamill/json/JsonObject.java index 7d9993b..ef19ef9 100644 --- a/core/src/main/java/org/chodavarapu/datamill/json/JsonObject.java +++ b/core/src/main/java/org/chodavarapu/datamill/json/JsonObject.java @@ -79,6 +79,15 @@ public long asLong() { throw new JsonException("A JSON object cannot be converted to a long!"); } + @Override + public Object asObject(Class type) { + if (type == String.class) { + return asString(); + } + + return this; + } + @Override public short asShort() { throw new JsonException("A JSON object cannot be converted to a short!"); @@ -281,6 +290,49 @@ public long asLong() { return object.getLong(name); } + @Override + public Object asObject(Class type) { + if (type == boolean.class) { + return object.has(name) ? asBoolean() : null; + } else if (type == Boolean.class) { + return object.has(name) ? asBoolean() : null; + } else if (type == byte.class) { + return object.has(name) ? asByte() : null; + } else if (type == Byte.class) { + return object.has(name) ? asByte() : null; + } else if (type == char.class) { + return object.has(name) ? asCharacter() : null; + } else if (type == Character.class) { + return object.has(name) ? asCharacter() : null; + } else if (type == short.class) { + return object.has(name) ? asShort() : null; + } else if (type == Short.class) { + return object.has(name) ? asShort() : null; + } else if (type == int.class) { + return object.has(name) ? asInteger() : null; + } else if (type == Integer.class) { + return object.has(name) ? asInteger() : null; + } else if (type == long.class) { + return object.has(name) ? asLong() : null; + } else if (type == Long.class) { + return object.has(name) ? asLong() : null; + } else if (type == float.class) { + return object.has(name) ? asFloat() : null; + } else if (type == Float.class) { + return object.has(name) ? asFloat() : null; + } else if (type == double.class) { + return object.has(name) ? asDouble() : null; + } else if (type == Double.class) { + return object.has(name) ? asDouble() : null; + } else if (type == LocalDateTime.class) { + return object.has(name) ? asLocalDateTime() : null; + } else if (type == byte[].class) { + return object.has(name) ? asByteArray() : null; + } else { + return asJson(); + } + } + @Override public short asShort() { return (short) (int) object.getInt(name); diff --git a/core/src/main/java/org/chodavarapu/datamill/reflection/impl/OutlineImpl.java b/core/src/main/java/org/chodavarapu/datamill/reflection/impl/OutlineImpl.java index 218664b..e1b5b29 100644 --- a/core/src/main/java/org/chodavarapu/datamill/reflection/impl/OutlineImpl.java +++ b/core/src/main/java/org/chodavarapu/datamill/reflection/impl/OutlineImpl.java @@ -294,22 +294,38 @@ public Outline outline() { public Bean set(Consumer propertyInvoker, Value value) { Property descriptor = OutlineImpl.this.property(propertyInvoker); Class type = descriptor.type(); - if (type == boolean.class || type == Boolean.class) { + if (type == boolean.class) { descriptor.set(instance, value.asBoolean()); - } else if (type == byte.class || type == Byte.class) { + } else if (type == Boolean.class) { + descriptor.set(instance, (Boolean) value.asObject(Boolean.class)); + } else if (type == byte.class) { descriptor.set(instance, value.asByte()); - } else if (type == char.class || type == Character.class) { + } else if (type == Byte.class) { + descriptor.set(instance, (Byte) value.asObject(Byte.class)); + } else if (type == char.class) { descriptor.set(instance, value.asCharacter()); - } else if (type == short.class || type == Short.class) { + } else if (type == Character.class) { + descriptor.set(instance, (Character) value.asObject(Character.class)); + } else if (type == short.class) { descriptor.set(instance, value.asShort()); - } else if (type == int.class || type == Integer.class) { + } else if (type == Short.class) { + descriptor.set(instance, (Short) value.asObject(Short.class)); + } else if (type == int.class) { descriptor.set(instance, value.asInteger()); - } else if (type == long.class || type == Long.class) { + } else if (type == Integer.class) { + descriptor.set(instance, (Integer) value.asObject(Integer.class)); + } else if (type == long.class) { descriptor.set(instance, value.asLong()); - } else if (type == float.class || type == Float.class) { + } else if (type == Long.class) { + descriptor.set(instance, (Long) value.asObject(Long.class)); + } else if (type == float.class) { descriptor.set(instance, value.asFloat()); - } else if (type == double.class || type == Double.class) { + } else if (type == Float.class) { + descriptor.set(instance, (Float) value.asObject(Float.class)); + } else if (type == double.class) { descriptor.set(instance, value.asDouble()); + } else if (type == Double.class) { + descriptor.set(instance, (Double) value.asObject(Double.class)); } else if (type == LocalDateTime.class) { descriptor.set(instance, value.asLocalDateTime()); } else if (type == byte[].class) { diff --git a/core/src/main/java/org/chodavarapu/datamill/values/StringValue.java b/core/src/main/java/org/chodavarapu/datamill/values/StringValue.java index 538348e..6964548 100644 --- a/core/src/main/java/org/chodavarapu/datamill/values/StringValue.java +++ b/core/src/main/java/org/chodavarapu/datamill/values/StringValue.java @@ -72,6 +72,49 @@ public int asInteger() { return Integer.parseInt(value); } + @Override + public Object asObject(Class type) { + if (type == boolean.class) { + return value != null ? asBoolean() : null; + } else if (type == Boolean.class) { + return value != null ? asBoolean() : null; + } else if (type == byte.class) { + return value != null ? asByte() : null; + } else if (type == Byte.class) { + return value != null ? asByte() : null; + } else if (type == char.class) { + return value != null ? asCharacter() : null; + } else if (type == Character.class) { + return value != null ? asCharacter() : null; + } else if (type == short.class) { + return value != null ? asShort() : null; + } else if (type == Short.class) { + return value != null ? asShort() : null; + } else if (type == int.class) { + return value != null ? asInteger() : null; + } else if (type == Integer.class) { + return value != null ? asInteger() : null; + } else if (type == long.class) { + return value != null ? asLong() : null; + } else if (type == Long.class) { + return value != null ? asLong() : null; + } else if (type == float.class) { + return value != null ? asFloat() : null; + } else if (type == Float.class) { + return value != null ? asFloat() : null; + } else if (type == double.class) { + return value != null ? asDouble() : null; + } else if (type == Double.class) { + return value != null ? asDouble() : null; + } else if (type == LocalDateTime.class) { + return value != null ? asLocalDateTime() : null; + } else if (type == byte[].class) { + return value != null ? asByteArray() : null; + } else { + return asString(); + } + } + @Override public short asShort() { return Short.parseShort(value); diff --git a/core/src/main/java/org/chodavarapu/datamill/values/Value.java b/core/src/main/java/org/chodavarapu/datamill/values/Value.java index f6bd885..28e9c52 100644 --- a/core/src/main/java/org/chodavarapu/datamill/values/Value.java +++ b/core/src/main/java/org/chodavarapu/datamill/values/Value.java @@ -15,6 +15,7 @@ public interface Value { float asFloat(); int asInteger(); LocalDateTime asLocalDateTime(); + Object asObject(Class type); long asLong(); short asShort(); String asString(); From 7bd78e88d51a13363d5ba931601994b408757cb6 Mon Sep 17 00:00:00 2001 From: Ravi Chodavarapu Date: Wed, 11 May 2016 00:05:36 +0100 Subject: [PATCH 2/2] Refactor to type switches so we have something re-usable that improves maintainability Add some tests --- .../chodavarapu/datamill/json/JsonObject.java | 99 ++++---- .../datamill/reflection/impl/OutlineImpl.java | 158 +++++++++---- .../impl/TripleArgumentTypeSwitch.java | 89 ++++++++ .../datamill/reflection/impl/TypeSwitch.java | 89 ++++++++ .../datamill/values/StringValue.java | 100 ++++---- .../impl/TripleArgumentTypeSwitchTest.java | 214 ++++++++++++++++++ .../reflection/impl/TypeSwitchTest.java | 212 +++++++++++++++++ .../datamill/values/StringValueTest.java | 33 +++ 8 files changed, 876 insertions(+), 118 deletions(-) create mode 100644 core/src/main/java/org/chodavarapu/datamill/reflection/impl/TripleArgumentTypeSwitch.java create mode 100644 core/src/main/java/org/chodavarapu/datamill/reflection/impl/TypeSwitch.java create mode 100644 core/src/test/java/org/chodavarapu/datamill/reflection/impl/TripleArgumentTypeSwitchTest.java create mode 100644 core/src/test/java/org/chodavarapu/datamill/reflection/impl/TypeSwitchTest.java diff --git a/core/src/main/java/org/chodavarapu/datamill/json/JsonObject.java b/core/src/main/java/org/chodavarapu/datamill/json/JsonObject.java index ef19ef9..0635084 100644 --- a/core/src/main/java/org/chodavarapu/datamill/json/JsonObject.java +++ b/core/src/main/java/org/chodavarapu/datamill/json/JsonObject.java @@ -1,6 +1,7 @@ package org.chodavarapu.datamill.json; import org.chodavarapu.datamill.reflection.Member; +import org.chodavarapu.datamill.reflection.impl.TripleArgumentTypeSwitch; import org.chodavarapu.datamill.values.ReflectableValue; import org.chodavarapu.datamill.values.Value; import org.json.JSONArray; @@ -16,6 +17,64 @@ * @author Ravi Chodavarapu (rchodava@gmail.com) */ public class JsonObject implements Json, ReflectableValue { + private static final TripleArgumentTypeSwitch propertyAsObjectSwitch = + new TripleArgumentTypeSwitch() { + @Override + protected Object caseBoolean(JSONObject value1, String value2, JsonProperty value3) { + return value1.has(value2) ? value3.asBoolean() : null; + } + + @Override + protected Object caseByte(JSONObject value1, String value2, JsonProperty value3) { + return value1.has(value2) ? value3.asByte() : null; + } + + @Override + protected Object caseCharacter(JSONObject value1, String value2, JsonProperty value3) { + return value1.has(value2) ? value3.asCharacter() : null; + } + + @Override + protected Object caseShort(JSONObject value1, String value2, JsonProperty value3) { + return value1.has(value2) ? value3.asShort() : null; + } + + @Override + protected Object caseInteger(JSONObject value1, String value2, JsonProperty value3) { + return value1.has(value2) ? value3.asInteger() : null; + } + + @Override + protected Object caseLong(JSONObject value1, String value2, JsonProperty value3) { + return value1.has(value2) ? value3.asLong() : null; + } + + @Override + protected Object caseFloat(JSONObject value1, String value2, JsonProperty value3) { + return value1.has(value2) ? value3.asFloat() : null; + } + + @Override + protected Object caseDouble(JSONObject value1, String value2, JsonProperty value3) { + return value1.has(value2) ? value3.asDouble() : null; + } + + @Override + protected Object caseLocalDateTime(JSONObject value1, String value2, JsonProperty value3) { + return value1.has(value2) ? value3.asLocalDateTime() : null; + } + + @Override + protected Object caseByteArray(JSONObject value1, String value2, JsonProperty value3) { + return value1.has(value2) ? value3.asByteArray() : null; + } + + @Override + protected Object defaultCase(JSONObject value1, String value2, JsonProperty value3) { + return value3.asJson(); + } + }; + final JSONObject object; private JsonObject(JSONObject object) { @@ -292,45 +351,7 @@ public long asLong() { @Override public Object asObject(Class type) { - if (type == boolean.class) { - return object.has(name) ? asBoolean() : null; - } else if (type == Boolean.class) { - return object.has(name) ? asBoolean() : null; - } else if (type == byte.class) { - return object.has(name) ? asByte() : null; - } else if (type == Byte.class) { - return object.has(name) ? asByte() : null; - } else if (type == char.class) { - return object.has(name) ? asCharacter() : null; - } else if (type == Character.class) { - return object.has(name) ? asCharacter() : null; - } else if (type == short.class) { - return object.has(name) ? asShort() : null; - } else if (type == Short.class) { - return object.has(name) ? asShort() : null; - } else if (type == int.class) { - return object.has(name) ? asInteger() : null; - } else if (type == Integer.class) { - return object.has(name) ? asInteger() : null; - } else if (type == long.class) { - return object.has(name) ? asLong() : null; - } else if (type == Long.class) { - return object.has(name) ? asLong() : null; - } else if (type == float.class) { - return object.has(name) ? asFloat() : null; - } else if (type == Float.class) { - return object.has(name) ? asFloat() : null; - } else if (type == double.class) { - return object.has(name) ? asDouble() : null; - } else if (type == Double.class) { - return object.has(name) ? asDouble() : null; - } else if (type == LocalDateTime.class) { - return object.has(name) ? asLocalDateTime() : null; - } else if (type == byte[].class) { - return object.has(name) ? asByteArray() : null; - } else { - return asJson(); - } + return propertyAsObjectSwitch.doSwitch(type, object, name, this); } @Override diff --git a/core/src/main/java/org/chodavarapu/datamill/reflection/impl/OutlineImpl.java b/core/src/main/java/org/chodavarapu/datamill/reflection/impl/OutlineImpl.java index e1b5b29..e31530f 100644 --- a/core/src/main/java/org/chodavarapu/datamill/reflection/impl/OutlineImpl.java +++ b/core/src/main/java/org/chodavarapu/datamill/reflection/impl/OutlineImpl.java @@ -20,7 +20,6 @@ import java.lang.reflect.Type; import java.security.AccessController; import java.security.PrivilegedAction; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -32,6 +31,123 @@ * @author Ravi Chodavarapu (rchodava@gmail.com) */ public class OutlineImpl implements Outline { + private final TripleArgumentTypeSwitch propertySetterSwitch = + new TripleArgumentTypeSwitch() { + @Override + protected Void caseBoolean(Property value1, T value2, Value value3) { + value1.set(value2, value3.asBoolean()); + return null; + } + + @Override + protected Void caseBooleanWrapper(Property value1, T value2, Value value3) { + value1.set(value2, (Boolean) value3.asObject(Boolean.class)); + return null; + } + + @Override + protected Void caseByte(Property value1, T value2, Value value3) { + value1.set(value2, value3.asByte()); + return null; + } + + @Override + protected Void caseByteWrapper(Property value1, T value2, Value value3) { + value1.set(value2, (Byte) value3.asObject(Byte.class)); + return null; + } + + @Override + protected Void caseCharacter(Property value1, T value2, Value value3) { + value1.set(value2, value3.asCharacter()); + return null; + } + + @Override + protected Void caseCharacterWrapper(Property value1, T value2, Value value3) { + value1.set(value2, (Character) value3.asObject(Character.class)); + return null; + } + + @Override + protected Void caseShort(Property value1, T value2, Value value3) { + value1.set(value2, value3.asShort()); + return null; + } + + @Override + protected Void caseShortWrapper(Property value1, T value2, Value value3) { + value1.set(value2, (Short) value3.asObject(Short.class)); + return null; + } + + @Override + protected Void caseInteger(Property value1, T value2, Value value3) { + value1.set(value2, value3.asInteger()); + return null; + } + + @Override + protected Void caseIntegerWrapper(Property value1, T value2, Value value3) { + value1.set(value2, (Integer) value3.asObject(Integer.class)); + return null; + } + + @Override + protected Void caseLong(Property value1, T value2, Value value3) { + value1.set(value2, value3.asLong()); + return null; + } + + @Override + protected Void caseLongWrapper(Property value1, T value2, Value value3) { + value1.set(value2, (Long) value3.asObject(Long.class)); + return null; + } + + @Override + protected Void caseFloat(Property value1, T value2, Value value3) { + value1.set(value2, value3.asFloat()); + return null; + } + + @Override + protected Void caseFloatWrapper(Property value1, T value2, Value value3) { + value1.set(value2, (Float) value3.asObject(Float.class)); + return null; + } + + @Override + protected Void caseDouble(Property value1, T value2, Value value3) { + value1.set(value2, value3.asDouble()); + return null; + } + + @Override + protected Void caseDoubleWrapper(Property value1, T value2, Value value3) { + value1.set(value2, (Double) value3.asObject(Double.class)); + return null; + } + + @Override + protected Void caseLocalDateTime(Property value1, T value2, Value value3) { + value1.set(value2, value3.asLocalDateTime()); + return null; + } + + @Override + protected Void caseByteArray(Property value1, T value2, Value value3) { + value1.set(value2, value3.asByteArray()); + return null; + } + + @Override + protected Void defaultCase(Property value1, T value2, Value value3) { + value1.set(value2, value3.asString()); + return null; + } + }; + private static Method OBJECT_GET_CLASS_METHOD; private static String capitalize(String string) { @@ -294,45 +410,7 @@ public Outline outline() { public Bean set(Consumer propertyInvoker, Value value) { Property descriptor = OutlineImpl.this.property(propertyInvoker); Class type = descriptor.type(); - if (type == boolean.class) { - descriptor.set(instance, value.asBoolean()); - } else if (type == Boolean.class) { - descriptor.set(instance, (Boolean) value.asObject(Boolean.class)); - } else if (type == byte.class) { - descriptor.set(instance, value.asByte()); - } else if (type == Byte.class) { - descriptor.set(instance, (Byte) value.asObject(Byte.class)); - } else if (type == char.class) { - descriptor.set(instance, value.asCharacter()); - } else if (type == Character.class) { - descriptor.set(instance, (Character) value.asObject(Character.class)); - } else if (type == short.class) { - descriptor.set(instance, value.asShort()); - } else if (type == Short.class) { - descriptor.set(instance, (Short) value.asObject(Short.class)); - } else if (type == int.class) { - descriptor.set(instance, value.asInteger()); - } else if (type == Integer.class) { - descriptor.set(instance, (Integer) value.asObject(Integer.class)); - } else if (type == long.class) { - descriptor.set(instance, value.asLong()); - } else if (type == Long.class) { - descriptor.set(instance, (Long) value.asObject(Long.class)); - } else if (type == float.class) { - descriptor.set(instance, value.asFloat()); - } else if (type == Float.class) { - descriptor.set(instance, (Float) value.asObject(Float.class)); - } else if (type == double.class) { - descriptor.set(instance, value.asDouble()); - } else if (type == Double.class) { - descriptor.set(instance, (Double) value.asObject(Double.class)); - } else if (type == LocalDateTime.class) { - descriptor.set(instance, value.asLocalDateTime()); - } else if (type == byte[].class) { - descriptor.set(instance, value.asByteArray()); - } else { - descriptor.set(instance, value.asString()); - } + propertySetterSwitch.doSwitch(type, descriptor, instance, value); return this; } diff --git a/core/src/main/java/org/chodavarapu/datamill/reflection/impl/TripleArgumentTypeSwitch.java b/core/src/main/java/org/chodavarapu/datamill/reflection/impl/TripleArgumentTypeSwitch.java new file mode 100644 index 0000000..8ec8e79 --- /dev/null +++ b/core/src/main/java/org/chodavarapu/datamill/reflection/impl/TripleArgumentTypeSwitch.java @@ -0,0 +1,89 @@ +package org.chodavarapu.datamill.reflection.impl; + +import rx.functions.Func3; + +import java.time.LocalDateTime; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author Ravi Chodavarapu (rchodava@gmail.com) + */ +public abstract class TripleArgumentTypeSwitch { + private final Map, Func3> cases = new ConcurrentHashMap<>(); + + public TripleArgumentTypeSwitch() { + cases.put(boolean.class, (v1, v2, v3) -> caseBoolean(v1, v2, v3)); + cases.put(Boolean.class, (v1, v2, v3) -> caseBooleanWrapper(v1, v2, v3)); + cases.put(byte.class, (v1, v2, v3) -> caseByte(v1, v2, v3)); + cases.put(Byte.class, (v1, v2, v3) -> caseByteWrapper(v1, v2, v3)); + cases.put(char.class, (v1, v2, v3) -> caseCharacter(v1, v2, v3)); + cases.put(Character.class, (v1, v2, v3) -> caseCharacterWrapper(v1, v2, v3)); + cases.put(short.class, (v1, v2, v3) -> caseShort(v1, v2, v3)); + cases.put(Short.class, (v1, v2, v3) -> caseShortWrapper(v1, v2, v3)); + cases.put(int.class, (v1, v2, v3) -> caseInteger(v1, v2, v3)); + cases.put(Integer.class, (v1, v2, v3) -> caseIntegerWrapper(v1, v2, v3)); + cases.put(long.class, (v1, v2, v3) -> caseLong(v1, v2, v3)); + cases.put(Long.class, (v1, v2, v3) -> caseLongWrapper(v1, v2, v3)); + cases.put(float.class, (v1, v2, v3) -> caseFloat(v1, v2, v3)); + cases.put(Float.class, (v1, v2, v3) -> caseFloatWrapper(v1, v2, v3)); + cases.put(double.class, (v1, v2, v3) -> caseDouble(v1, v2, v3)); + cases.put(Double.class, (v1, v2, v3) -> caseDoubleWrapper(v1, v2, v3)); + cases.put(LocalDateTime.class, (v1, v2, v3) -> caseLocalDateTime(v1, v2, v3)); + cases.put(byte[].class, (v1, v2, v3) -> caseByteArray(v1, v2, v3)); + } + + protected abstract R caseBoolean(T1 value1, T2 value2, T3 value3); + protected R caseBooleanWrapper(T1 value1, T2 value2, T3 value3) { + return caseBoolean(value1, value2, value3); + } + + protected abstract R caseByte(T1 value1, T2 value2, T3 value3); + protected R caseByteWrapper(T1 value1, T2 value2, T3 value3) { + return caseByte(value1, value2, value3); + } + + protected abstract R caseCharacter(T1 value1, T2 value2, T3 value3); + protected R caseCharacterWrapper(T1 value1, T2 value2, T3 value3) { + return caseCharacter(value1, value2, value3); + } + + protected abstract R caseShort(T1 value1, T2 value2, T3 value3); + protected R caseShortWrapper(T1 value1, T2 value2, T3 value3) { + return caseShort(value1, value2, value3); + } + + protected abstract R caseInteger(T1 value1, T2 value2, T3 value3); + protected R caseIntegerWrapper(T1 value1, T2 value2, T3 value3) { + return caseInteger(value1, value2, value3); + } + + protected abstract R caseLong(T1 value1, T2 value2, T3 value3); + protected R caseLongWrapper(T1 value1, T2 value2, T3 value3) { + return caseLong(value1, value2, value3); + } + + protected abstract R caseFloat(T1 value1, T2 value2, T3 value3); + protected R caseFloatWrapper(T1 value1, T2 value2, T3 value3) { + return caseFloat(value1, value2, value3); + } + + protected abstract R caseDouble(T1 value1, T2 value2, T3 value3); + protected R caseDoubleWrapper(T1 value1, T2 value2, T3 value3) { + return caseDouble(value1, value2, value3); + } + + protected abstract R caseLocalDateTime(T1 value1, T2 value2, T3 value3); + protected abstract R caseByteArray(T1 value1, T2 value2, T3 value3); + + protected abstract R defaultCase(T1 value1, T2 value2, T3 value3); + + public final R doSwitch(Class type, T1 value1, T2 value2, T3 value3) { + Func3 typeCase = cases.get(type); + if (typeCase != null) { + return typeCase.call(value1, value2, value3); + } else { + return defaultCase(value1, value2, value3); + } + } +} diff --git a/core/src/main/java/org/chodavarapu/datamill/reflection/impl/TypeSwitch.java b/core/src/main/java/org/chodavarapu/datamill/reflection/impl/TypeSwitch.java new file mode 100644 index 0000000..d5b6f4d --- /dev/null +++ b/core/src/main/java/org/chodavarapu/datamill/reflection/impl/TypeSwitch.java @@ -0,0 +1,89 @@ +package org.chodavarapu.datamill.reflection.impl; + +import rx.functions.Func2; + +import java.time.LocalDateTime; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author Ravi Chodavarapu (rchodava@gmail.com) + */ +public abstract class TypeSwitch { + private final Map, Func2> cases = new ConcurrentHashMap<>(); + + public TypeSwitch() { + cases.put(boolean.class, (v1, v2) -> caseBoolean(v1, v2)); + cases.put(Boolean.class, (v1, v2) -> caseBooleanWrapper(v1, v2)); + cases.put(byte.class, (v1, v2) -> caseByte(v1, v2)); + cases.put(Byte.class, (v1, v2) -> caseByteWrapper(v1, v2)); + cases.put(char.class, (v1, v2) -> caseCharacter(v1, v2)); + cases.put(Character.class, (v1, v2) -> caseCharacterWrapper(v1, v2)); + cases.put(short.class, (v1, v2) -> caseShort(v1, v2)); + cases.put(Short.class, (v1, v2) -> caseShortWrapper(v1, v2)); + cases.put(int.class, (v1, v2) -> caseInteger(v1, v2)); + cases.put(Integer.class, (v1, v2) -> caseIntegerWrapper(v1, v2)); + cases.put(long.class, (v1, v2) -> caseLong(v1, v2)); + cases.put(Long.class, (v1, v2) -> caseLongWrapper(v1, v2)); + cases.put(float.class, (v1, v2) -> caseFloat(v1, v2)); + cases.put(Float.class, (v1, v2) -> caseFloatWrapper(v1, v2)); + cases.put(double.class, (v1, v2) -> caseDouble(v1, v2)); + cases.put(Double.class, (v1, v2) -> caseDoubleWrapper(v1, v2)); + cases.put(LocalDateTime.class, (v1, v2) -> caseLocalDateTime(v1, v2)); + cases.put(byte[].class, (v1, v2) -> caseByteArray(v1, v2)); + } + + protected abstract R caseBoolean(T1 value1, T2 value2); + protected R caseBooleanWrapper(T1 value1, T2 value2) { + return caseBoolean(value1, value2); + } + + protected abstract R caseByte(T1 value1, T2 value2); + protected R caseByteWrapper(T1 value1, T2 value2) { + return caseByte(value1, value2); + } + + protected abstract R caseCharacter(T1 value1, T2 value2); + protected R caseCharacterWrapper(T1 value1, T2 value2) { + return caseCharacter(value1, value2); + } + + protected abstract R caseShort(T1 value1, T2 value2); + protected R caseShortWrapper(T1 value1, T2 value2) { + return caseShort(value1, value2); + } + + protected abstract R caseInteger(T1 value1, T2 value2); + protected R caseIntegerWrapper(T1 value1, T2 value2) { + return caseInteger(value1, value2); + } + + protected abstract R caseLong(T1 value1, T2 value2); + protected R caseLongWrapper(T1 value1, T2 value2) { + return caseLong(value1, value2); + } + + protected abstract R caseFloat(T1 value1, T2 value2); + protected R caseFloatWrapper(T1 value1, T2 value2) { + return caseFloat(value1, value2); + } + + protected abstract R caseDouble(T1 value1, T2 value2); + protected R caseDoubleWrapper(T1 value1, T2 value2) { + return caseDouble(value1, value2); + } + + protected abstract R caseLocalDateTime(T1 value1, T2 value2); + protected abstract R caseByteArray(T1 value1, T2 value2); + + protected abstract R defaultCase(T1 value1, T2 value2); + + public final R doSwitch(Class type, T1 value1, T2 value2) { + Func2 typeCase = cases.get(type); + if (typeCase != null) { + return typeCase.call(value1, value2); + } else { + return defaultCase(value1, value2); + } + } +} diff --git a/core/src/main/java/org/chodavarapu/datamill/values/StringValue.java b/core/src/main/java/org/chodavarapu/datamill/values/StringValue.java index 6964548..f8f1f10 100644 --- a/core/src/main/java/org/chodavarapu/datamill/values/StringValue.java +++ b/core/src/main/java/org/chodavarapu/datamill/values/StringValue.java @@ -1,5 +1,7 @@ package org.chodavarapu.datamill.values; +import org.chodavarapu.datamill.reflection.impl.TypeSwitch; + import java.time.LocalDateTime; import java.util.UnknownFormatConversionException; import java.util.function.Function; @@ -8,6 +10,64 @@ * @author Ravi Chodavarapu (rchodava@gmail.com) */ public class StringValue implements ReflectableValue { + private static final TypeSwitch stringCastSwitch = + new TypeSwitch() { + @Override + protected Object caseBoolean(StringValue value1, String value2) { + return value2 != null ? value1.asBoolean() : null; + } + + @Override + protected Object caseByte(StringValue value1, String value2) { + return value2 != null ? value1.asByte() : null; + } + + @Override + protected Object caseCharacter(StringValue value1, String value2) { + return value2 != null ? value1.asCharacter() : null; + } + + @Override + protected Object caseShort(StringValue value1, String value2) { + return value2 != null ? value1.asShort() : null; + } + + @Override + protected Object caseInteger(StringValue value1, String value2) { + return value2 != null ? value1.asInteger() : null; + } + + @Override + protected Object caseLong(StringValue value1, String value2) { + return value2 != null ? value1.asLong() : null; + } + + @Override + protected Object caseFloat(StringValue value1, String value2) { + return value2 != null ? value1.asFloat() : null; + } + + @Override + protected Object caseDouble(StringValue value1, String value2) { + return value2 != null ? value1.asDouble() : null; + } + + @Override + protected Object caseLocalDateTime(StringValue value1, String value2) { + return value2 != null ? value1.asLocalDateTime() : null; + } + + @Override + protected Object caseByteArray(StringValue value1, String value2) { + return value2 != null ? value1.asByteArray() : null; + } + + @Override + protected Object defaultCase(StringValue value1, String value2) { + return value1.asString(); + } + }; + private String value; public StringValue(String value) { @@ -74,45 +134,7 @@ public int asInteger() { @Override public Object asObject(Class type) { - if (type == boolean.class) { - return value != null ? asBoolean() : null; - } else if (type == Boolean.class) { - return value != null ? asBoolean() : null; - } else if (type == byte.class) { - return value != null ? asByte() : null; - } else if (type == Byte.class) { - return value != null ? asByte() : null; - } else if (type == char.class) { - return value != null ? asCharacter() : null; - } else if (type == Character.class) { - return value != null ? asCharacter() : null; - } else if (type == short.class) { - return value != null ? asShort() : null; - } else if (type == Short.class) { - return value != null ? asShort() : null; - } else if (type == int.class) { - return value != null ? asInteger() : null; - } else if (type == Integer.class) { - return value != null ? asInteger() : null; - } else if (type == long.class) { - return value != null ? asLong() : null; - } else if (type == Long.class) { - return value != null ? asLong() : null; - } else if (type == float.class) { - return value != null ? asFloat() : null; - } else if (type == Float.class) { - return value != null ? asFloat() : null; - } else if (type == double.class) { - return value != null ? asDouble() : null; - } else if (type == Double.class) { - return value != null ? asDouble() : null; - } else if (type == LocalDateTime.class) { - return value != null ? asLocalDateTime() : null; - } else if (type == byte[].class) { - return value != null ? asByteArray() : null; - } else { - return asString(); - } + return stringCastSwitch.doSwitch(type, this, value); } @Override diff --git a/core/src/test/java/org/chodavarapu/datamill/reflection/impl/TripleArgumentTypeSwitchTest.java b/core/src/test/java/org/chodavarapu/datamill/reflection/impl/TripleArgumentTypeSwitchTest.java new file mode 100644 index 0000000..c18a132 --- /dev/null +++ b/core/src/test/java/org/chodavarapu/datamill/reflection/impl/TripleArgumentTypeSwitchTest.java @@ -0,0 +1,214 @@ +package org.chodavarapu.datamill.reflection.impl; + +import org.junit.Test; + +import java.time.LocalDateTime; + +import static org.junit.Assert.assertEquals; + +/** + * @author Ravi Chodavarapu (rchodava@gmail.com) + */ +public class TripleArgumentTypeSwitchTest { + @Test + public void doSwitchWithoutWrappers() { + TripleArgumentTypeSwitch s = + new TripleArgumentTypeSwitch() { + @Override + protected String caseBoolean(String value1, String value2, String value3) { + return "bool" + value1 + value2 + value3; + } + + @Override + protected String caseByte(String value1, String value2, String value3) { + return "byte" + value1 + value2 + value3; + } + + @Override + protected String caseCharacter(String value1, String value2, String value3) { + return "c" + value1 + value2 + value3; + } + + @Override + protected String caseShort(String value1, String value2, String value3) { + return "s" + value1 + value2 + value3; + } + + @Override + protected String caseInteger(String value1, String value2, String value3) { + return "i" + value1 + value2 + value3; + } + + @Override + protected String caseLong(String value1, String value2, String value3) { + return "l" + value1 + value2 + value3; + } + + @Override + protected String caseFloat(String value1, String value2, String value3) { + return "f" + value1 + value2 + value3; + } + + @Override + protected String caseDouble(String value1, String value2, String value3) { + return "d" + value1 + value2 + value3; + } + + @Override + protected String caseLocalDateTime(String value1, String value2, String value3) { + return "ldt" + value1 + value2 + value3; + } + + @Override + protected String caseByteArray(String value1, String value2, String value3) { + return "ba" + value1 + value2 + value3; + } + + @Override + protected String defaultCase(String value1, String value2, String value3) { + return "def" + value1 + value2 + value3; + } + }; + + assertEquals("boolv1v2v3", s.doSwitch(boolean.class, "v1", "v2", "v3")); + assertEquals("boolv1v2v3", s.doSwitch(Boolean.class, "v1", "v2", "v3")); + assertEquals("bytev1v2v3", s.doSwitch(byte.class, "v1", "v2", "v3")); + assertEquals("bytev1v2v3", s.doSwitch(Byte.class, "v1", "v2", "v3")); + assertEquals("cv1v2v3", s.doSwitch(char.class, "v1", "v2", "v3")); + assertEquals("cv1v2v3", s.doSwitch(Character.class, "v1", "v2", "v3")); + assertEquals("sv1v2v3", s.doSwitch(short.class, "v1", "v2", "v3")); + assertEquals("sv1v2v3", s.doSwitch(Short.class, "v1", "v2", "v3")); + assertEquals("iv1v2v3", s.doSwitch(int.class, "v1", "v2", "v3")); + assertEquals("iv1v2v3", s.doSwitch(Integer.class, "v1", "v2", "v3")); + assertEquals("lv1v2v3", s.doSwitch(long.class, "v1", "v2", "v3")); + assertEquals("lv1v2v3", s.doSwitch(Long.class, "v1", "v2", "v3")); + assertEquals("fv1v2v3", s.doSwitch(float.class, "v1", "v2", "v3")); + assertEquals("fv1v2v3", s.doSwitch(Float.class, "v1", "v2", "v3")); + assertEquals("dv1v2v3", s.doSwitch(double.class, "v1", "v2", "v3")); + assertEquals("dv1v2v3", s.doSwitch(Double.class, "v1", "v2", "v3")); + assertEquals("ldtv1v2v3", s.doSwitch(LocalDateTime.class, "v1", "v2", "v3")); + assertEquals("bav1v2v3", s.doSwitch(byte[].class, "v1", "v2", "v3")); + assertEquals("defv1v2v3", s.doSwitch(String.class, "v1", "v2", "v3")); + } + + @Test + public void doSwitchWithWrappers() { + TripleArgumentTypeSwitch s = + new TripleArgumentTypeSwitch() { + @Override + protected String caseBoolean(String value1, String value2, String value3) { + return "bool" + value1 + value2 + value3; + } + + @Override + protected String caseBooleanWrapper(String value1, String value2, String value3) { + return "boolw" + value1 + value2 + value3; + } + + @Override + protected String caseByte(String value1, String value2, String value3) { + return "byte" + value1 + value2 + value3; + } + + @Override + protected String caseByteWrapper(String value1, String value2, String value3) { + return "bytew" + value1 + value2 + value3; + } + + @Override + protected String caseCharacter(String value1, String value2, String value3) { + return "c" + value1 + value2 + value3; + } + + @Override + protected String caseCharacterWrapper(String value1, String value2, String value3) { + return "cw" + value1 + value2 + value3; + } + + @Override + protected String caseShort(String value1, String value2, String value3) { + return "s" + value1 + value2 + value3; + } + + @Override + protected String caseShortWrapper(String value1, String value2, String value3) { + return "sw" + value1 + value2 + value3; + } + + @Override + protected String caseInteger(String value1, String value2, String value3) { + return "i" + value1 + value2 + value3; + } + + @Override + protected String caseIntegerWrapper(String value1, String value2, String value3) { + return "iw" + value1 + value2 + value3; + } + + @Override + protected String caseLong(String value1, String value2, String value3) { + return "l" + value1 + value2 + value3; + } + + @Override + protected String caseLongWrapper(String value1, String value2, String value3) { + return "lw" + value1 + value2 + value3; + } + + @Override + protected String caseFloat(String value1, String value2, String value3) { + return "f" + value1 + value2 + value3; + } + + @Override + protected String caseFloatWrapper(String value1, String value2, String value3) { + return "fw" + value1 + value2 + value3; + } + + @Override + protected String caseDouble(String value1, String value2, String value3) { + return "d" + value1 + value2 + value3; + } + + @Override + protected String caseDoubleWrapper(String value1, String value2, String value3) { + return "dw" + value1 + value2 + value3; + } + + @Override + protected String caseLocalDateTime(String value1, String value2, String value3) { + return "ldt" + value1 + value2 + value3; + } + + @Override + protected String caseByteArray(String value1, String value2, String value3) { + return "ba" + value1 + value2 + value3; + } + + @Override + protected String defaultCase(String value1, String value2, String value3) { + return "def" + value1 + value2 + value3; + } + }; + + assertEquals("boolv1v2v3", s.doSwitch(boolean.class, "v1", "v2", "v3")); + assertEquals("boolwv1v2v3", s.doSwitch(Boolean.class, "v1", "v2", "v3")); + assertEquals("bytev1v2v3", s.doSwitch(byte.class, "v1", "v2", "v3")); + assertEquals("bytewv1v2v3", s.doSwitch(Byte.class, "v1", "v2", "v3")); + assertEquals("cv1v2v3", s.doSwitch(char.class, "v1", "v2", "v3")); + assertEquals("cwv1v2v3", s.doSwitch(Character.class, "v1", "v2", "v3")); + assertEquals("sv1v2v3", s.doSwitch(short.class, "v1", "v2", "v3")); + assertEquals("swv1v2v3", s.doSwitch(Short.class, "v1", "v2", "v3")); + assertEquals("iv1v2v3", s.doSwitch(int.class, "v1", "v2", "v3")); + assertEquals("iwv1v2v3", s.doSwitch(Integer.class, "v1", "v2", "v3")); + assertEquals("lv1v2v3", s.doSwitch(long.class, "v1", "v2", "v3")); + assertEquals("lwv1v2v3", s.doSwitch(Long.class, "v1", "v2", "v3")); + assertEquals("fv1v2v3", s.doSwitch(float.class, "v1", "v2", "v3")); + assertEquals("fwv1v2v3", s.doSwitch(Float.class, "v1", "v2", "v3")); + assertEquals("dv1v2v3", s.doSwitch(double.class, "v1", "v2", "v3")); + assertEquals("dwv1v2v3", s.doSwitch(Double.class, "v1", "v2", "v3")); + assertEquals("ldtv1v2v3", s.doSwitch(LocalDateTime.class, "v1", "v2", "v3")); + assertEquals("bav1v2v3", s.doSwitch(byte[].class, "v1", "v2", "v3")); + assertEquals("defv1v2v3", s.doSwitch(String.class, "v1", "v2", "v3")); + } +} diff --git a/core/src/test/java/org/chodavarapu/datamill/reflection/impl/TypeSwitchTest.java b/core/src/test/java/org/chodavarapu/datamill/reflection/impl/TypeSwitchTest.java new file mode 100644 index 0000000..c7742b3 --- /dev/null +++ b/core/src/test/java/org/chodavarapu/datamill/reflection/impl/TypeSwitchTest.java @@ -0,0 +1,212 @@ +package org.chodavarapu.datamill.reflection.impl; + +import org.junit.Test; + +import java.time.LocalDateTime; + +import static org.junit.Assert.assertEquals; + +/** + * @author Ravi Chodavarapu (rchodava@gmail.com) + */ +public class TypeSwitchTest { + @Test + public void doSwitchWithoutWrappers() { + TypeSwitch s = new TypeSwitch() { + @Override + protected String caseBoolean(String value1, String value2) { + return "bool" + value1 + value2; + } + + @Override + protected String caseByte(String value1, String value2) { + return "byte" + value1 + value2; + } + + @Override + protected String caseCharacter(String value1, String value2) { + return "c" + value1 + value2; + } + + @Override + protected String caseShort(String value1, String value2) { + return "s" + value1 + value2; + } + + @Override + protected String caseInteger(String value1, String value2) { + return "i" + value1 + value2; + } + + @Override + protected String caseLong(String value1, String value2) { + return "l" + value1 + value2; + } + + @Override + protected String caseFloat(String value1, String value2) { + return "f" + value1 + value2; + } + + @Override + protected String caseDouble(String value1, String value2) { + return "d" + value1 + value2; + } + + @Override + protected String caseLocalDateTime(String value1, String value2) { + return "ldt" + value1 + value2; + } + + @Override + protected String caseByteArray(String value1, String value2) { + return "ba" + value1 + value2; + } + + @Override + protected String defaultCase(String value1, String value2) { + return "def" + value1 + value2; + } + }; + + assertEquals("boolv1v2", s.doSwitch(boolean.class, "v1", "v2")); + assertEquals("boolv1v2", s.doSwitch(Boolean.class, "v1", "v2")); + assertEquals("bytev1v2", s.doSwitch(byte.class, "v1", "v2")); + assertEquals("bytev1v2", s.doSwitch(Byte.class, "v1", "v2")); + assertEquals("cv1v2", s.doSwitch(char.class, "v1", "v2")); + assertEquals("cv1v2", s.doSwitch(Character.class, "v1", "v2")); + assertEquals("sv1v2", s.doSwitch(short.class, "v1", "v2")); + assertEquals("sv1v2", s.doSwitch(Short.class, "v1", "v2")); + assertEquals("iv1v2", s.doSwitch(int.class, "v1", "v2")); + assertEquals("iv1v2", s.doSwitch(Integer.class, "v1", "v2")); + assertEquals("lv1v2", s.doSwitch(long.class, "v1", "v2")); + assertEquals("lv1v2", s.doSwitch(Long.class, "v1", "v2")); + assertEquals("fv1v2", s.doSwitch(float.class, "v1", "v2")); + assertEquals("fv1v2", s.doSwitch(Float.class, "v1", "v2")); + assertEquals("dv1v2", s.doSwitch(double.class, "v1", "v2")); + assertEquals("dv1v2", s.doSwitch(Double.class, "v1", "v2")); + assertEquals("ldtv1v2", s.doSwitch(LocalDateTime.class, "v1", "v2")); + assertEquals("bav1v2", s.doSwitch(byte[].class, "v1", "v2")); + assertEquals("defv1v2", s.doSwitch(String.class, "v1", "v2")); + } + + @Test + public void doSwitchWithWrappers() { + TypeSwitch s = new TypeSwitch() { + @Override + protected String caseBoolean(String value1, String value2) { + return "bool" + value1 + value2; + } + + @Override + protected String caseBooleanWrapper(String value1, String value2) { + return "boolw" + value1 + value2; + } + + @Override + protected String caseByte(String value1, String value2) { + return "byte" + value1 + value2; + } + + @Override + protected String caseByteWrapper(String value1, String value2) { + return "bytew" + value1 + value2; + } + + @Override + protected String caseCharacter(String value1, String value2) { + return "c" + value1 + value2; + } + + @Override + protected String caseCharacterWrapper(String value1, String value2) { + return "cw" + value1 + value2; + } + + @Override + protected String caseShort(String value1, String value2) { + return "s" + value1 + value2; + } + + @Override + protected String caseShortWrapper(String value1, String value2) { + return "sw" + value1 + value2; + } + + @Override + protected String caseInteger(String value1, String value2) { + return "i" + value1 + value2; + } + + @Override + protected String caseIntegerWrapper(String value1, String value2) { + return "iw" + value1 + value2; + } + + @Override + protected String caseLong(String value1, String value2) { + return "l" + value1 + value2; + } + + @Override + protected String caseLongWrapper(String value1, String value2) { + return "lw" + value1 + value2; + } + + @Override + protected String caseFloat(String value1, String value2) { + return "f" + value1 + value2; + } + + @Override + protected String caseFloatWrapper(String value1, String value2) { + return "fw" + value1 + value2; + } + + @Override + protected String caseDouble(String value1, String value2) { + return "d" + value1 + value2; + } + + @Override + protected String caseDoubleWrapper(String value1, String value2) { + return "dw" + value1 + value2; + } + + @Override + protected String caseLocalDateTime(String value1, String value2) { + return "ldt" + value1 + value2; + } + + @Override + protected String caseByteArray(String value1, String value2) { + return "ba" + value1 + value2; + } + + @Override + protected String defaultCase(String value1, String value2) { + return "def" + value1 + value2; + } + }; + + assertEquals("boolv1v2", s.doSwitch(boolean.class, "v1", "v2")); + assertEquals("boolwv1v2", s.doSwitch(Boolean.class, "v1", "v2")); + assertEquals("bytev1v2", s.doSwitch(byte.class, "v1", "v2")); + assertEquals("bytewv1v2", s.doSwitch(Byte.class, "v1", "v2")); + assertEquals("cv1v2", s.doSwitch(char.class, "v1", "v2")); + assertEquals("cwv1v2", s.doSwitch(Character.class, "v1", "v2")); + assertEquals("sv1v2", s.doSwitch(short.class, "v1", "v2")); + assertEquals("swv1v2", s.doSwitch(Short.class, "v1", "v2")); + assertEquals("iv1v2", s.doSwitch(int.class, "v1", "v2")); + assertEquals("iwv1v2", s.doSwitch(Integer.class, "v1", "v2")); + assertEquals("lv1v2", s.doSwitch(long.class, "v1", "v2")); + assertEquals("lwv1v2", s.doSwitch(Long.class, "v1", "v2")); + assertEquals("fv1v2", s.doSwitch(float.class, "v1", "v2")); + assertEquals("fwv1v2", s.doSwitch(Float.class, "v1", "v2")); + assertEquals("dv1v2", s.doSwitch(double.class, "v1", "v2")); + assertEquals("dwv1v2", s.doSwitch(Double.class, "v1", "v2")); + assertEquals("ldtv1v2", s.doSwitch(LocalDateTime.class, "v1", "v2")); + assertEquals("bav1v2", s.doSwitch(byte[].class, "v1", "v2")); + assertEquals("defv1v2", s.doSwitch(String.class, "v1", "v2")); + } +} diff --git a/core/src/test/java/org/chodavarapu/datamill/values/StringValueTest.java b/core/src/test/java/org/chodavarapu/datamill/values/StringValueTest.java index b18d0db..21643e5 100644 --- a/core/src/test/java/org/chodavarapu/datamill/values/StringValueTest.java +++ b/core/src/test/java/org/chodavarapu/datamill/values/StringValueTest.java @@ -14,21 +14,37 @@ public class StringValueTest { public void booleanConversions() { StringValue value = new StringValue(""); assertFalse(value.asBoolean()); + assertFalse((Boolean) value.asObject(boolean.class)); + assertFalse((Boolean) value.asObject(Boolean.class)); value = new StringValue("false"); assertFalse(value.asBoolean()); + assertFalse((Boolean) value.asObject(boolean.class)); + assertFalse((Boolean) value.asObject(Boolean.class)); value = new StringValue("null"); assertFalse(value.asBoolean()); + assertFalse((Boolean) value.asObject(boolean.class)); + assertFalse((Boolean) value.asObject(Boolean.class)); value = new StringValue("0"); assertFalse(value.asBoolean()); + assertFalse((Boolean) value.asObject(boolean.class)); + assertFalse((Boolean) value.asObject(Boolean.class)); value = new StringValue("undefined"); assertFalse(value.asBoolean()); + assertFalse((Boolean) value.asObject(boolean.class)); + assertFalse((Boolean) value.asObject(Boolean.class)); value = new StringValue("NaN"); assertFalse(value.asBoolean()); + assertFalse((Boolean) value.asObject(boolean.class)); + assertFalse((Boolean) value.asObject(Boolean.class)); value = new StringValue("true"); assertTrue(value.asBoolean()); + assertTrue((Boolean) value.asObject(boolean.class)); + assertTrue((Boolean) value.asObject(Boolean.class)); value = new StringValue("some string"); assertTrue(value.asBoolean()); + assertTrue((Boolean) value.asObject(boolean.class)); + assertTrue((Boolean) value.asObject(Boolean.class)); value = new StringValue("false"); assertTrue(value.isBoolean()); @@ -45,6 +61,7 @@ public void binaryConversion() { StringValue value = new StringValue("test"); assertTrue(value.isString()); assertArrayEquals("test".getBytes(), value.asByteArray()); + assertArrayEquals("test".getBytes(), (byte[]) value.asObject(byte[].class)); } @Test @@ -52,6 +69,8 @@ public void characterConversion() { StringValue value = new StringValue("c"); assertTrue(value.isCharacter()); assertEquals('c', value.asCharacter()); + assertEquals('c', value.asObject(char.class)); + assertEquals('c', value.asObject(Character.class)); } @Test @@ -60,12 +79,20 @@ public void integerConversions() { assertTrue(value.isNumeric()); assertTrue(value.isByte()); assertEquals(12, value.asByte()); + assertEquals((byte) 12, value.asObject(byte.class)); + assertEquals((byte) 12, value.asObject(Byte.class)); assertTrue(value.isShort()); assertEquals(12, value.asShort()); + assertEquals((short) 12, value.asObject(short.class)); + assertEquals((short) 12, value.asObject(Short.class)); assertTrue(value.isInteger()); assertEquals(12, value.asInteger()); + assertEquals(12, value.asObject(int.class)); + assertEquals(12, value.asObject(Integer.class)); assertTrue(value.isLong()); assertEquals(12, value.asLong()); + assertEquals((long) 12, value.asObject(long.class)); + assertEquals((long) 12, value.asObject(Long.class)); } @Test @@ -74,8 +101,12 @@ public void floatConversions() { assertTrue(value.isNumeric()); assertTrue(value.isFloat()); assertEquals(12.1f, value.asFloat(), 0.001f); + assertEquals(12.1f, value.asObject(float.class)); + assertEquals(12.1f, value.asObject(Float.class)); assertTrue(value.isDouble()); assertEquals(12.1d, value.asDouble(), 0.001d); + assertEquals(12.1d, value.asObject(double.class)); + assertEquals(12.1d, value.asObject(Double.class)); } @Test @@ -83,6 +114,7 @@ public void stringConversion() { StringValue value = new StringValue("test"); assertTrue(value.isString()); assertEquals("test", value.asString()); + assertEquals("test", value.asObject(String.class)); } @Test @@ -91,5 +123,6 @@ public void timeConversions() { String time = now.toString(); StringValue value = new StringValue(time); assertEquals(now, value.asLocalDateTime()); + assertEquals(now, value.asObject(LocalDateTime.class)); } }