From 2bd1afdb9e2982d355528a0a2fa99003e1178739 Mon Sep 17 00:00:00 2001 From: John Blum Date: Wed, 29 Aug 2018 10:06:33 -0700 Subject: [PATCH] Add utiliy method to invoke a method on an object. --- .../geode/core/util/ObjectUtils.java | 33 +++++++++++++++++++ .../geode/core/util/ObjectUtilsUnitTests.java | 29 ++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/spring-geode/src/main/java/org/springframework/geode/core/util/ObjectUtils.java b/spring-geode/src/main/java/org/springframework/geode/core/util/ObjectUtils.java index ced604b4..5241af8e 100644 --- a/spring-geode/src/main/java/org/springframework/geode/core/util/ObjectUtils.java +++ b/spring-geode/src/main/java/org/springframework/geode/core/util/ObjectUtils.java @@ -19,15 +19,20 @@ package org.springframework.geode.core.util; import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException; import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException; +import java.lang.reflect.Method; +import java.util.Optional; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.Nullable; +import org.springframework.util.ReflectionUtils; /** * The {@link ObjectUtils} class is an abstract utility class with operations for {@link Object objects}. * * @author John Blum * @see java.lang.Object + * @see java.lang.reflect.Method * @since 1.0.0 */ @SuppressWarnings("all") @@ -85,6 +90,34 @@ public abstract class ObjectUtils extends org.springframework.util.ObjectUtils { } } + /** + * Invokes a {@link Method} on an {@link Object} with the given {@link String name}. + * + * @param {@link Class type} of the {@link Method} return value. + * @param obj {@link Object} on which to invoke the {@link Method}. + * @param methodName {@link String} containing the name of the {@link Method} to invoke on {@link Object}. + * @return the return value of the invoked {@link Method} on {@link Object}. + * @throws IllegalArgumentException if no {@link Method} with {@link String name} could be found on {@link Object}. + * @see java.lang.reflect.Method + * @see java.lang.Object + */ + @SuppressWarnings("unchecked") + public static T invoke(Object obj, String methodName) { + + return (T) Optional.ofNullable(obj) + .map(Object::getClass) + .map(type -> ReflectionUtils.findMethod(type, methodName)) + .map(ObjectUtils::makeAccessible) + .map(method -> ReflectionUtils.invokeMethod(method, obj)) + .orElseThrow(() -> newIllegalArgumentException("Method [%1$s] on Object of type [%2$s] not found", + methodName, org.springframework.util.ObjectUtils.nullSafeClassName(obj))); + } + + private static Method makeAccessible(Method method) { + ReflectionUtils.makeAccessible(method); + return method; + } + /** * Returns the given {@link Object value} or throws an {@link IllegalArgumentException} * if {@link Object value} is {@literal null}. diff --git a/spring-geode/src/test/java/org/springframework/geode/core/util/ObjectUtilsUnitTests.java b/spring-geode/src/test/java/org/springframework/geode/core/util/ObjectUtilsUnitTests.java index c4ca24d6..3ccfc25e 100644 --- a/spring-geode/src/test/java/org/springframework/geode/core/util/ObjectUtilsUnitTests.java +++ b/spring-geode/src/test/java/org/springframework/geode/core/util/ObjectUtilsUnitTests.java @@ -59,6 +59,28 @@ public class ObjectUtilsUnitTests { } } + @Test + public void invokeMethodOnObjectReturnsValue() { + assertThat(ObjectUtils.invoke(new TestObject(), "testMethod")).isEqualTo("TEST"); + } + + @Test(expected = IllegalArgumentException.class) + public void invokeNonExistingMethodOnObjectThrowsIllegalArgumentException() { + + try { + ObjectUtils.invoke(new TestObject(), "nonExistingMethod"); + } + catch (IllegalArgumentException expected) { + + assertThat(expected).hasMessage("Method [nonExistingMethod] on Object of type [%s] not found", + TestObject.class.getName()); + + assertThat(expected).hasNoCause(); + + throw expected; + } + } + @Test public void returnValueThrowOnNullWithNonNullValueReturnsValue() { assertThat(ObjectUtils.returnValueThrowOnNull("test")).isEqualTo("test"); @@ -78,4 +100,11 @@ public class ObjectUtilsUnitTests { throw expected; } } + + public static class TestObject { + + public String testMethod() { + return "TEST"; + } + } }