Skip to content

Commit

Permalink
Refactor to type switches so we have something re-usable that improve…
Browse files Browse the repository at this point in the history
…s maintainability

Add some tests
  • Loading branch information
rchodava committed May 10, 2016
1 parent aeb4195 commit 7bd78e8
Show file tree
Hide file tree
Showing 8 changed files with 876 additions and 118 deletions.
99 changes: 60 additions & 39 deletions core/src/main/java/org/chodavarapu/datamill/json/JsonObject.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -16,6 +17,64 @@
* @author Ravi Chodavarapu (rchodava@gmail.com)
*/
public class JsonObject implements Json, ReflectableValue {
private static final TripleArgumentTypeSwitch<JSONObject, String, JsonProperty, Object> propertyAsObjectSwitch =
new TripleArgumentTypeSwitch<JSONObject, String, JsonProperty, Object>() {
@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) {
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -32,6 +31,123 @@
* @author Ravi Chodavarapu (rchodava@gmail.com)
*/
public class OutlineImpl<T> implements Outline<T> {
private final TripleArgumentTypeSwitch<Property, T, Value, Void> propertySetterSwitch =
new TripleArgumentTypeSwitch<Property, T, Value, Void>() {
@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) {
Expand Down Expand Up @@ -294,45 +410,7 @@ public Outline<T> outline() {
public Bean<T> set(Consumer<T> 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;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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<T1, T2, T3, R> {
private final Map<Class<?>, Func3<T1, T2, T3, R>> 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<T1, T2, T3, R> typeCase = cases.get(type);
if (typeCase != null) {
return typeCase.call(value1, value2, value3);
} else {
return defaultCase(value1, value2, value3);
}
}
}
Loading

0 comments on commit 7bd78e8

Please sign in to comment.