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 da17bd29..0b3ebfdd 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 @@ -27,6 +27,7 @@ import java.util.Arrays; import java.util.Optional; import java.util.function.Function; import java.util.function.Predicate; +import java.util.function.Supplier; import org.apache.geode.pdx.PdxInstance; @@ -258,6 +259,33 @@ public abstract class ObjectUtils extends org.springframework.util.ObjectUtils { return doOperationSafely(() -> (T) field.get(obj), (T) null); } + /** + * An initialization operator used to evalutate a given {@link Object target} and conditionally + * {@link Supplier supply} a new value if the {@link Object target} is {@literal null}. + * + * The {@code initialize} operator simplifies a common initialization safety pattern that appears in code as: + * + * + * target = target != null ? target : new Target(); + * + * + * While the expression uses Java's ternary operator, users could very well use a if-then-else statement instead. + * Either way, since Java is {@literal call-by-value} then the above statement and expression can be replaced with: + * + * + * target = initialize(target, Target::new); + * + * + * @param {@link Class type} of the {@link Object target}. + * @param target {@link Object} to evaluate and initialize; must not be {@literal null}. + * @param supplier {@link Supplier} used to initialize the {@link Object target} on return. + * @return the existing {@link Object target} if not {@literal null}, otherwise invoke the {@link Supplier} + * to supply a new instance of {@link T}. + */ + public static T initialize(@Nullable T target, @NonNull Supplier supplier) { + return target != null ? target : supplier.get(); + } + /** * Invokes a {@link Method} on an {@link Object} with the given {@link String name}. * @@ -281,13 +309,27 @@ public abstract class ObjectUtils extends org.springframework.util.ObjectUtils { methodName, org.springframework.util.ObjectUtils.nullSafeClassName(obj))); } - public static Constructor makeAccessible(Constructor constructor) { + /** + * Makes the {@link Constructor} accessible. + * + * @param constructor {@link Constructor} to make accessible; must not be {@literal null}. + * @return the given {@link Constructor}. + * @see java.lang.reflect.Constructor + */ + public static Constructor makeAccessible(@NonNull Constructor constructor) { ReflectionUtils.makeAccessible(constructor); return constructor; } + /** + * Makes the {@link Field} accessible. + * + * @param field {@link Field} to make accessible; must not be {@literal null}. + * @return the given {@link Field}. + * @see java.lang.reflect.Field + */ public static Field makeAccessible(Field field) { ReflectionUtils.makeAccessible(field); @@ -295,6 +337,13 @@ public abstract class ObjectUtils extends org.springframework.util.ObjectUtils { return field; } + /** + * Makes the {@link Method} accessible. + * + * @param constructor {@link Method} to make accessible; must not be {@literal null}. + * @return the given {@link Method}. + * @see java.lang.reflect.Method + */ public static Method makeAccessible(Method method) { ReflectionUtils.makeAccessible(method); 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 9f8de780..2c3d6a01 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 @@ -95,7 +95,7 @@ public class ObjectUtilsUnitTests { } @Test(expected = IllegalArgumentException.class) - public void asPdxInstanceTypeReturnNonMatchingType() { + public void asPdxInstanceTypeReturningNonMatchingType() { C source = new C(); @@ -300,6 +300,16 @@ public class ObjectUtilsUnitTests { } } + @Test + public void initializeWithNonNullTarget() { + assertThat(ObjectUtils.initialize("test", () -> "mock")).isEqualTo("test"); + } + + @Test + public void initializeWithNullTarget() { + assertThat(ObjectUtils.initialize(null, () -> "mock")).isEqualTo("mock"); + } + @Test public void invokeMethodOnObjectReturnsValue() { assertThat(ObjectUtils.invoke(new TestObject(), "testMethod")).isEqualTo("TEST");