MethodCoercions { public static Maybe<?> tryFindAndInvokeSingleParameterMethod(final Object instance, final String methodName, final Object argument) { Class<?> clazz = instance.getClass(); Iterable<Method> methods = Arrays.asList(clazz.getMethods()); Optional<Method> matchingMethod = Iterables.tryFind(methods, matchSingleParameterMethod(methodName, argument)); if (matchingMethod.isPresent()) { Method method = matchingMethod.get(); Method accessibleMethod = Reflections.findAccessibleMethod(method).get(); try { Type paramType = method.getGenericParameterTypes()[0]; Maybe<?> coercedArgumentM = TypeCoercions.tryCoerce(argument, TypeToken.of(paramType)); RuntimeException exception = Maybe.getException(coercedArgumentM); if (coercedArgumentM.isPresent() && coercedArgumentM.get()!=null) { if (!Boxing.boxedTypeToken(paramType).getRawType().isAssignableFrom(coercedArgumentM.get().getClass())) { exception = new IllegalArgumentException("Type mismatch after coercion; "+coercedArgumentM.get()+" is not a "+TypeToken.of(paramType)); } } if (coercedArgumentM.isAbsent() || exception!=null) { return Maybe.absent("Cannot convert parameter for "+method+": "+ Exceptions.collapseText(Maybe.getException(coercedArgumentM)), exception); } return Maybe.of(accessibleMethod.invoke(instance, coercedArgumentM.get())); } catch (IllegalAccessException | InvocationTargetException e) { throw Exceptions.propagate(e); } } else { return Maybe.absent("No method matching '"+methodName+"("+(argument==null ? argument : argument.getClass().getName())+")'"); } }  static Predicate<Method> matchSingleParameterMethod(final String methodName, final Object argument); static Maybe<?> tryFindAndInvokeSingleParameterMethod(final Object instance, final String methodName, final Object argument); static Predicate<Method> matchMultiParameterMethod(final String methodName, final List<?> arguments); static Predicate<Method> matchMethodByName(final String methodName); static Predicate<Method> matchMultiParameterMethod(final List<?> arguments); static Maybe<?> tryFindAndInvokeMultiParameterMethod(Object instanceOrClazz, Iterable<Method> methods, List<?> arguments); static Maybe<?> tryFindAndInvokeMultiParameterMethod(Object instance, String methodName, List<?> arguments); static Maybe<?> tryFindAndInvokeBestMatchingMethod(Object instance, String methodName, Object argument);  }
@Test public void testTryFindAndInvokeSingleParameterMethod() throws Exception { TestClass instance = new TestClass(); Maybe<?> maybe = MethodCoercions.tryFindAndInvokeSingleParameterMethod(instance, "singleParameterMethod", "42"); assertTrue(maybe.isPresent()); assertTrue(instance.wasSingleParameterMethodCalled()); }
@Test public void testTryFindAndInvokeSingleCollectionParameterMethod() throws Exception { TestClass instance = new TestClass(); Maybe<?> maybe = MethodCoercions.tryFindAndInvokeSingleParameterMethod(instance, "singleCollectionParameterMethod", ImmutableList.of("42")); assertTrue(maybe.isPresent()); assertTrue(instance.wasSingleCollectionParameterMethodCalled()); }