/* * Copyright 2014 mango.jfaster.org * * The Mango Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package org.jfaster.mango.invoker; import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.google.common.primitives.Ints; import org.jfaster.mango.annotation.Setter; import org.jfaster.mango.util.reflect.TypeToken; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import javax.annotation.Nullable; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Arrays; import java.util.List; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; /** * @author ash */ public class FunctionalSetterInvokerTest { public static class StringToIntegerFunction implements SetterFunction<String, Integer> { @Nullable @Override public Integer apply(@Nullable String input) { return Integer.valueOf(input); } } static class A { private int x; private int y; int getX() { return x; } void setX(int x) { this.x = x; } int getY() { return y; } @Setter(StringToIntegerFunction.class) void setY(int y) { this.y = y; } } @Test public void testStringToInt() throws Exception { Method method = A.class.getDeclaredMethod("setX", int.class); A a = new A(); SetterInvoker invoker = FunctionalSetterInvoker.create("x", method); assertThat(invoker.getName(), is("x")); assertThat(int.class.equals(invoker.getParameterType()), is(true)); assertThat(int.class.equals(invoker.getParameterRawType()), is(true)); invoker.invoke(a, 100); assertThat(a.getX(), is(100)); method = A.class.getDeclaredMethod("setY", int.class); a = new A(); invoker = FunctionalSetterInvoker.create("y", method); assertThat(invoker.getName(), is("y")); assertThat(String.class.equals(invoker.getParameterType()), is(true)); assertThat(String.class.equals(invoker.getParameterRawType()), is(true)); invoker.invoke(a, "100"); assertThat(a.getY(), is(100)); } static class B { private Integer x; private Integer y; Integer getX() { return x; } void setX(Integer x) { this.x = x; } Integer getY() { return y; } @Setter(StringToIntegerFunction.class) void setY(Integer y) { this.y = y; } } @Test public void testStringToInteger() throws Exception { Method method = B.class.getDeclaredMethod("setX", Integer.class); B b = new B(); SetterInvoker invoker = FunctionalSetterInvoker.create("x", method); assertThat(invoker.getName(), is("x")); assertThat(Integer.class.equals(invoker.getParameterType()), is(true)); assertThat(Integer.class.equals(invoker.getParameterRawType()), is(true)); invoker.invoke(b, 100); assertThat(b.getX(), is(100)); method = B.class.getDeclaredMethod("setY", Integer.class); b = new B(); invoker = FunctionalSetterInvoker.create("y", method); assertThat(invoker.getName(), is("y")); assertThat(String.class.equals(invoker.getParameterType()), is(true)); assertThat(String.class.equals(invoker.getParameterRawType()), is(true)); invoker.invoke(b, "100"); assertThat(b.getY(), is(100)); } public static class IntegerToStringFunction implements SetterFunction<Integer, String> { @Nullable @Override public String apply(@Nullable Integer input) { return "xx" + input; } } static class C { private String x; private String y; String getX() { return x; } void setX(String x) { this.x = x; } String getY() { return y; } @Setter(IntegerToStringFunction.class) void setY(String y) { this.y = y; } } @Test public void testIntegerToString() throws Exception { Method method = C.class.getDeclaredMethod("setX", String.class); C c = new C(); SetterInvoker invoker = FunctionalSetterInvoker.create("x", method); assertThat(invoker.getName(), is("x")); assertThat(String.class.equals(invoker.getParameterType()), is(true)); assertThat(String.class.equals(invoker.getParameterRawType()), is(true)); invoker.invoke(c, "xx100"); assertThat(c.getX(), is("xx100")); method = C.class.getDeclaredMethod("setY", String.class); c = new C(); invoker = FunctionalSetterInvoker.create("y", method); assertThat(invoker.getName(), is("y")); assertThat(Integer.class.equals(invoker.getParameterType()), is(true)); assertThat(Integer.class.equals(invoker.getParameterRawType()), is(true)); invoker.invoke(c, 100); assertThat(c.getY(), is("xx100")); } public static class StringToIntegerListFunction implements SetterFunction<String, List<Integer>> { @Nullable @Override public List<Integer> apply(@Nullable String input) { List<Integer> r = Lists.newArrayList(); for (String s : Splitter.on(",").split(input)) { r.add(Integer.valueOf(s)); } return r; } } static class D { private List<Integer> x; private List<Integer> y; List<Integer> getX() { return x; } void setX(List<Integer> x) { this.x = x; } List<Integer> getY() { return y; } @Setter(StringToIntegerListFunction.class) void setY(List<Integer> y) { this.y = y; } } @SuppressWarnings("unchecked") @Test public void testStringToList() throws Exception { Method method = D.class.getDeclaredMethod("setX", List.class); D d = new D(); SetterInvoker invoker = FunctionalSetterInvoker.create("x", method); assertThat(invoker.getName(), is("x")); Type type = new TypeToken<List<Integer>>() { }.getType(); assertThat(type.equals(invoker.getParameterType()), is(true)); assertThat(List.class.equals(invoker.getParameterRawType()), is(true)); List<Integer> x = Lists.newArrayList(1, 2); invoker.invoke(d, x); assertThat(d.getX().equals(x), is(true)); method = D.class.getDeclaredMethod("setY", List.class); d = new D(); invoker = FunctionalSetterInvoker.create("y", method); assertThat(invoker.getName(), is("y")); assertThat(String.class.equals(invoker.getParameterType()), is(true)); assertThat(String.class.equals(invoker.getParameterRawType()), is(true)); invoker.invoke(d, "1,2"); assertThat(d.getY().equals(x), is(true)); } static class E { private String x; String getX() { return x; } @Setter(StringToIntegerFunction.class) void setX(String x) { this.x = x; } } @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testException() throws Exception { thrown.expect(ClassCastException.class); thrown.expectMessage("function[class org.jfaster.mango.invoker.FunctionalSetterInvokerTest$StringToIntegerFunction] on method[void org.jfaster.mango.invoker.FunctionalSetterInvokerTest$E.setX(java.lang.String)] error, method's parameterType[class java.lang.String] must be assignable from function's outputType[class java.lang.Integer]"); Method method = E.class.getDeclaredMethod("setX", String.class); FunctionalSetterInvoker.create("x", method); } static class F { private List<String> x; List<String> getX() { return x; } @Setter(StringToIntegerListFunction.class) void setX(List<String> x) { this.x = x; } } @Test public void testException2() throws Exception { thrown.expect(ClassCastException.class); thrown.expectMessage("function[class org.jfaster.mango.invoker.FunctionalSetterInvokerTest$StringToIntegerListFunction] on method[void org.jfaster.mango.invoker.FunctionalSetterInvokerTest$F.setX(java.util.List)] error, method's parameterType[java.util.List<java.lang.String>] must be assignable from function's outputType[java.util.List<java.lang.Integer>]"); Method method = F.class.getDeclaredMethod("setX", List.class); FunctionalSetterInvoker.create("x", method); } public static class StringIntArrayFunction implements SetterFunction<String, int[]> { @Nullable @Override public int[] apply(@Nullable String input) { List<Integer> r = Lists.newArrayList(); for (String s : Splitter.on(",").split(input)) { r.add(Integer.valueOf(s)); } return Ints.toArray(r); } } static class G { private int[] x; private int[] y; int[] getX() { return x; } void setX(int[] x) { this.x = x; } int[] getY() { return y; } @Setter(StringIntArrayFunction.class) void setY(int[] y) { this.y = y; } } @Test public void testIntArrayToString() throws Exception { Method method = G.class.getDeclaredMethod("setX", int[].class); G g = new G(); SetterInvoker invoker = FunctionalSetterInvoker.create("x", method); assertThat(invoker.getName(), is("x")); assertThat(int[].class.equals(invoker.getParameterType()), is(true)); assertThat(int[].class.equals(invoker.getParameterRawType()), is(true)); int[] x = new int[]{1, 2}; invoker.invoke(g, x); assertThat(Arrays.toString(g.getX()).equals(Arrays.toString(x)), is(true)); method = G.class.getDeclaredMethod("setY", int[].class); g = new G(); invoker = FunctionalSetterInvoker.create("y", method); assertThat(invoker.getName(), is("y")); assertThat(String.class.equals(invoker.getParameterType()), is(true)); assertThat(String.class.equals(invoker.getParameterRawType()), is(true)); invoker.invoke(g, "1,2"); assertThat(Arrays.toString(g.getY()).equals(Arrays.toString(x)), is(true)); } static class H { private String x; @Setter(StringToIntegerFunction.class) String getX() { return x; } void setX(String x) { this.x = x; } } }