Skip to content

Commit

Permalink
setter函数式编程接口化
Browse files Browse the repository at this point in the history
  • Loading branch information
ash committed Apr 14, 2016
1 parent 8f83812 commit 36b6d3e
Show file tree
Hide file tree
Showing 16 changed files with 111 additions and 58 deletions.
4 changes: 2 additions & 2 deletions src/main/java/org/jfaster/mango/annotation/Setter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package org.jfaster.mango.annotation;

import org.jfaster.mango.invoker.TypedSetterFunction;
import org.jfaster.mango.invoker.DummySetterFunction;

import java.lang.annotation.*;

Expand All @@ -28,6 +28,6 @@
@Documented
public @interface Setter {

Class<? extends TypedSetterFunction<?, ?>> value();
Class<? extends DummySetterFunction<?, ?>> value();

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,5 @@
/**
* @author ash
*/
public abstract class GenericSetterFunction<I, O> extends TypedSetterFunction<I, O> {

@Override
public boolean outputTypeIsGeneric() {
return true;
}

public interface DummySetterFunction<I, O> {
}
101 changes: 87 additions & 14 deletions src/main/java/org/jfaster/mango/invoker/FunctionalSetterInvoker.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
import javax.annotation.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Set;

/**
* @author ash
*/
public class FunctionalSetterInvoker extends MethodNamedObject implements SetterInvoker {

private TypedSetterFunction function;
private FunctionAdapter functionAdapter;
private Type parameterType;
private Class<?> parameterRawType;

Expand All @@ -55,22 +55,43 @@ private FunctionalSetterInvoker(String name, Method method) {
Setter setterAnno = method.getAnnotation(Setter.class);

if (setterAnno != null) { // 启用函数式调用功能
Class<? extends TypedSetterFunction<?, ?>> funcClass = setterAnno.value();
function = Reflection.instantiateClass(funcClass);
Type genType = funcClass.getGenericSuperclass();
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
TypeToken<?> inputToken = TypeToken.of(params[0]);
TypeToken<?> outputToken = TypeToken.of(params[1]);
Class<? extends DummySetterFunction<?, ?>> funcClass = setterAnno.value();
if (SetterFunction.class.isAssignableFrom(funcClass)) {
functionAdapter = new SetterFunctionAdapter((SetterFunction) Reflection.instantiateClass(funcClass));
} else if (RuntimeSetterFunction.class.isAssignableFrom(funcClass)) {
functionAdapter = new RuntimeSetterFunctionAdapter((RuntimeSetterFunction) Reflection.instantiateClass(funcClass));
} else {
throw new IllegalArgumentException(); // TODO
}

TypeToken<?> inputToken = null;
TypeToken<?> outputToken = null;
Set<TypeToken<?>> fathers = TypeToken.of(funcClass).getTypes();
for (TypeToken<?> father : fathers) {
if (DummySetterFunction.class.equals(father.getRawType())) {
inputToken = father.resolveType(DummySetterFunction.class.getTypeParameters()[0]);
if (Object.class.equals(inputToken.getRawType())) { // 处理范型T
inputToken = TypeToken.of(Object.class);
}
outputToken = father.resolveType(DummySetterFunction.class.getTypeParameters()[1]);
if (Object.class.equals(outputToken.getRawType())) { // 处理范型T
outputToken = TypeToken.of(Object.class);
}
}
}
if (inputToken == null || outputToken == null) {
throw new IllegalStateException();
}
TypeToken<?> wrapParameterToken = parameterToken.wrap();
if (function.outputTypeIsGeneric()) { // 针对继承GenericSetterFunction的
if (functionAdapter instanceof RuntimeSetterFunctionAdapter) { // 针对继承RuntimeSetterFunction的
if (!outputToken.isAssignableFrom(wrapParameterToken)) {
throw new ClassCastException("function[" + function.getClass() + "] " +
throw new ClassCastException("function[" + functionAdapter.getFunction().getClass() + "] " +
"on method[" + method + "] error, function's outputType[" + outputToken.getType() + "] " +
"must be assignable from method's parameterType[" + parameterToken.getType() + "]");
}
} else { // 针对继承LiteSetterFunction的
if (!wrapParameterToken.isAssignableFrom(outputToken)) {
throw new ClassCastException("function[" + function.getClass() + "] " +
throw new ClassCastException("function[" + functionAdapter.getFunction().getClass() + "] " +
"on method[" + method + "] error, method's parameterType[" + parameterToken.getType() + "] " +
"must be assignable from function's outputType[" + outputToken.getType() + "]");
}
Expand All @@ -85,12 +106,11 @@ public static FunctionalSetterInvoker create(String name, Method method) {
return new FunctionalSetterInvoker(name, method);
}

@SuppressWarnings("unchecked")
@Override
public void invoke(Object object, @Nullable Object parameter) {
try {
if (function != null) {
parameter = function.apply(parameter, runtimeOutputType);
if (functionAdapter != null) {
parameter = functionAdapter.apply(parameter, runtimeOutputType);
}
if (parameter == null && runtimeOutputRawType.isPrimitive()) {
throw new NullPointerException("property " + getName() + " of " +
Expand Down Expand Up @@ -119,4 +139,57 @@ public Class<?> getParameterRawType() {
return parameterRawType;
}

interface FunctionAdapter {

@Nullable
public Object apply(@Nullable Object input, Type runtimeOutputType);

public DummySetterFunction getFunction();

}

static class SetterFunctionAdapter implements FunctionAdapter {

private final SetterFunction function;

SetterFunctionAdapter(SetterFunction function) {
this.function = function;
}

@SuppressWarnings("unchecked")
@Nullable
@Override
public Object apply(@Nullable Object input, Type runtimeOutputType) {
return function.apply(input);
}

@Override
public DummySetterFunction getFunction() {
return function;
}

}

static class RuntimeSetterFunctionAdapter implements FunctionAdapter {

private final RuntimeSetterFunction function;

RuntimeSetterFunctionAdapter(RuntimeSetterFunction function) {
this.function = function;
}

@SuppressWarnings("unchecked")
@Nullable
@Override
public Object apply(@Nullable Object input, Type runtimeOutputType) {
return function.apply(input, runtimeOutputType);
}

@Override
public DummySetterFunction getFunction() {
return function;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@
/**
* @author ash
*/
public abstract class TypedSetterFunction<I, O> {
public interface RuntimeSetterFunction<I, O> extends DummySetterFunction<I, O> {

@Nullable
public abstract O apply(@Nullable I input, Type runtimeOutputType);

public abstract boolean outputTypeIsGeneric();

}
16 changes: 2 additions & 14 deletions src/main/java/org/jfaster/mango/invoker/SetterFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,13 @@
package org.jfaster.mango.invoker;

import javax.annotation.Nullable;
import java.lang.reflect.Type;

/**
* @author ash
*/
public abstract class SetterFunction<I, O> extends TypedSetterFunction<I, O> {
public interface SetterFunction<I, O> extends DummySetterFunction<I, O> {

@Nullable
@Override
public O apply(@Nullable I input, Type runtimeOutputType) {
return apply(input);
}

@Nullable
public abstract O apply(@Nullable I input);

@Override
public boolean outputTypeIsGeneric() {
return false;
}
public O apply(@Nullable I input);

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
*
* @author ash
*/
public class StringToIntArrayFunction extends SetterFunction<String, int[]> {
public class StringToIntArrayFunction implements SetterFunction<String, int[]> {

private final static String SEPARATOR = ",";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*
* @author ash
*/
public class StringToIntegerListFunction extends SetterFunction<String, List<Integer>> {
public class StringToIntegerListFunction implements SetterFunction<String, List<Integer>> {

private final static String SEPARATOR = ",";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
*
* @author ash
*/
public class StringToLongArrayFunction extends SetterFunction<String, long[]> {
public class StringToLongArrayFunction implements SetterFunction<String, long[]> {

private final static String SEPARATOR = ",";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*
* @author ash
*/
public class StringToLongListFunction extends SetterFunction<String, List<Long>> {
public class StringToLongListFunction implements SetterFunction<String, List<Long>> {

private final static String SEPARATOR = ",";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
*
* @author ash
*/
public class StringToStringArrayFunction extends SetterFunction<String, String[]> {
public class StringToStringArrayFunction implements SetterFunction<String, String[]> {

private final static String SEPARATOR = ",";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*
* @author ash
*/
public class StringToStringListFunction extends SetterFunction<String, List<String>> {
public class StringToStringListFunction implements SetterFunction<String, List<String>> {

private final static String SEPARATOR = ",";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package org.jfaster.mango.invoker.function.enums;

import org.jfaster.mango.invoker.GenericSetterFunction;
import org.jfaster.mango.invoker.RuntimeSetterFunction;
import org.jfaster.mango.reflect.TypeToken;
import org.jfaster.mango.util.concurrent.cache.CacheLoader;
import org.jfaster.mango.util.concurrent.cache.DoubleCheckCache;
Expand All @@ -31,7 +31,7 @@
*
* @author ash
*/
public class IntegerToEnumFunction extends GenericSetterFunction<Integer, Enum> {
public class IntegerToEnumFunction implements RuntimeSetterFunction<Integer, Enum> {

private final static LoadingCache<Class, EnumSet> cache = new DoubleCheckCache<Class, EnumSet>(
new CacheLoader<Class, EnumSet>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package org.jfaster.mango.invoker.function.enums;

import org.jfaster.mango.invoker.GenericSetterFunction;
import org.jfaster.mango.invoker.RuntimeSetterFunction;
import org.jfaster.mango.reflect.TypeToken;

import javax.annotation.Nullable;
Expand All @@ -27,7 +27,7 @@
*
* @author ash
*/
public class StringToEnumFunction extends GenericSetterFunction<String, Enum> {
public class StringToEnumFunction implements RuntimeSetterFunction<String, Enum> {

@Nullable
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package org.jfaster.mango.invoker.function.json;

import com.alibaba.fastjson.JSON;
import org.jfaster.mango.invoker.GenericSetterFunction;
import org.jfaster.mango.invoker.RuntimeSetterFunction;

import javax.annotation.Nullable;
import java.lang.reflect.Type;
Expand All @@ -27,7 +27,7 @@
*
* @author ash
*/
public class FastjsonToObjectFunction extends GenericSetterFunction<String, Object> {
public class FastjsonToObjectFunction implements RuntimeSetterFunction<String, Object> {

@Nullable
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package org.jfaster.mango.invoker.function.json;

import com.google.gson.Gson;
import org.jfaster.mango.invoker.GenericSetterFunction;
import org.jfaster.mango.invoker.RuntimeSetterFunction;

import javax.annotation.Nullable;
import java.lang.reflect.Type;
Expand All @@ -27,7 +27,7 @@
*
* @author ash
*/
public class GsonToObjectFunction extends GenericSetterFunction<String, Object> {
public class GsonToObjectFunction implements RuntimeSetterFunction<String, Object> {

@Nullable
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
*/
public class FunctionalSetterInvokerTest {

public static class StringToIntegerFunction extends SetterFunction<String, Integer> {
public static class StringToIntegerFunction implements SetterFunction<String, Integer> {

@Nullable
@Override
Expand Down Expand Up @@ -136,7 +136,7 @@ public void testStringToInteger() throws Exception {
assertThat(b.getY() , is(100));
}

public static class IntegerToStringFunction extends SetterFunction<Integer, String> {
public static class IntegerToStringFunction implements SetterFunction<Integer, String> {

@Nullable
@Override
Expand Down Expand Up @@ -189,7 +189,7 @@ public void testIntegerToString() throws Exception {
assertThat(c.getY() , is("xx100"));
}

public static class StringToIntegerListFunction extends SetterFunction<String, List<Integer>> {
public static class StringToIntegerListFunction implements SetterFunction<String, List<Integer>> {

@Nullable
@Override
Expand Down Expand Up @@ -297,7 +297,7 @@ public void testException2() throws Exception {
FunctionalSetterInvoker.create("x", method);
}

public static class StringIntArrayFunction extends SetterFunction<String, int[]> {
public static class StringIntArrayFunction implements SetterFunction<String, int[]> {

@Nullable
@Override
Expand Down

0 comments on commit 36b6d3e

Please sign in to comment.