diff --git a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java index 34a2be4e3099..ff72a024e9fb 100644 --- a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java @@ -118,6 +118,82 @@ public static boolean isEmpty(@Nullable Object @Nullable [] array) { return (array == null || array.length == 0); } + /** + * Returns the first non-null element from the provided varargs. + * + * @param objects The objects to check for non-null values. + * @param The type of the objects. + * @return An Optional containing the first non-null object, or an empty Optional if all objects are null. + */ + @SafeVarargs + public static Optional firstNonNull(@Nullable final T... objects) { + return Optional.ofNullable(objects) + .map(arr -> Arrays.stream(arr).filter(Objects::nonNull).findFirst()) + .orElse(Optional.empty()); + } + + /** + * Returns the first non-null element from the provided collection. + * + * @param collection The objects to check for non-null values. + * @param The type of the objects. + * @return An Optional containing the first non-null object, or an empty Optional if all objects are null. + */ + public static Optional firstNonNull(@Nullable final Collection collection) { + if (Objects.isNull(collection) || collection.isEmpty()) { + return Optional.empty(); + } + return collection.stream().filter(Objects::nonNull).findFirst(); + } + + /** + * Returns the object if it is not {@code null}; otherwise, returns the default value. + * + * @param object the object to test, may be {@code null} + * @param defaultValue the default value to return if the object is {@code null}, may be {@code null} + * @param the type of the object + * @return An Optional containing either the object if not null, or the default value wrapped in an Optional. + */ + public static Optional getIfNull(@Nullable final T object, @Nullable final T defaultValue) { + return Optional.ofNullable(object).or(() -> Optional.ofNullable(defaultValue)); + } + + /** + * Returns the collection if it is not {@code null} and not empty; otherwise, returns the default value. + * + * @param object the collection to test, may be {@code null} + * @param defaultValue the default value to return if the collection is {@code null} or empty, may be {@code null} + * @param the type of elements in the collection + * @return An Optional containing the collection if not null and not empty, otherwise an Optional of the default + * value. + */ + public static Optional> getIfEmpty(@Nullable final Collection object, + @Nullable final Collection defaultValue) { + return Optional.ofNullable(object) + .filter(collection -> !collection.isEmpty()) + .or(() -> Optional.ofNullable(defaultValue)); + } + + /** + * Returns the array if it is not {@code null} and not empty; otherwise, returns the default value. + * + * @param object the array to test, may be {@code null} + * @param defaultValue the default value to return if the array is {@code null} or empty, may be {@code null} + * @param the type of elements in the array + * @return An Optional containing the array if not null and not empty, otherwise an Optional of the default + * value. + */ + public static Optional getIfEmpty(@Nullable final T[] object, + @Nullable final T[] defaultValue) { + if (Objects.nonNull(object) && object.length > 0) { + return Optional.of(object); + } + if (Objects.nonNull(defaultValue) && defaultValue.length > 0) { + return Optional.of(defaultValue); + } + return Optional.empty(); + } + /** * Determine whether the given object is empty. *

This method supports the following object types. diff --git a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java index 6f1bb001dfc7..9891a47d669d 100644 --- a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java @@ -31,6 +31,7 @@ import java.time.LocalDate; import java.time.ZoneId; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Currency; import java.util.Date; @@ -52,6 +53,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.springframework.util.ObjectUtils.getIfEmpty; +import static org.springframework.util.ObjectUtils.getIfNull; +import static org.springframework.util.ObjectUtils.firstNonNull; import static org.springframework.util.ObjectUtils.isEmpty; /** @@ -111,6 +115,89 @@ void isCompatibleWithThrowsClause() { assertThat(ObjectUtils.isCompatibleWithThrowsClause(new Throwable(), throwable)).isTrue(); } + @Test + void getIfNullObject() { + String value = UUID.randomUUID().toString(); + String backup = UUID.randomUUID().toString(); + + assertThat(getIfNull(value, backup)).contains(value); + assertThat(getIfNull(value, backup)).contains(value); + assertThat(getIfNull(value, value)).contains(value); + assertThat(getIfNull(backup, backup)).contains(backup); + assertThat(getIfNull(null, value)).contains(value); + assertThat(getIfNull(null, backup)).contains(backup); + assertThat(getIfNull("null", backup)).contains("null"); + assertThat(getIfNull(null, null)).isEmpty(); + } + + @Test + void getIfEmptyObjectCollection() { + Collection empty = Collections.emptyList(); + Collection value = List.of(UUID.randomUUID().toString()); + Collection backup = List.of(UUID.randomUUID().toString()); + + assertThat(getIfEmpty(value, backup)).contains(value); + assertThat(getIfEmpty(value, backup)).contains(value); + assertThat(getIfEmpty(null, backup)).contains(backup); + assertThat(getIfEmpty(empty, backup)).contains(backup); + assertThat(getIfEmpty(value, empty)).contains(value); + assertThat(getIfEmpty(empty, empty)).contains(empty); + assertThat(getIfEmpty(backup, backup)).contains(backup); + assertThat(getIfEmpty(null, empty)).contains(empty); + assertThat(getIfEmpty(null, backup)).contains(backup); + } + + @Test + void getIfEmptyObjectArray() { + String[] empty = new String[0]; + String[] value = {UUID.randomUUID().toString()}; + String[] backup = {UUID.randomUUID().toString()}; + + assertThat(getIfEmpty(value, backup)).contains(value); + assertThat(getIfEmpty(null, backup)).contains(backup); + assertThat(getIfEmpty(empty, backup)).contains(backup); + assertThat(getIfEmpty(value, empty)).contains(value); + assertThat(getIfEmpty(empty, empty)).isEmpty(); + assertThat(getIfEmpty(backup, backup)).contains(backup); + assertThat(getIfEmpty(null, empty)).isEmpty(); + assertThat(getIfEmpty(null, backup)).contains(backup); + } + + @Test + void firstNonNullObjectCollection() { + String value = UUID.randomUUID().toString(); + String backup = UUID.randomUUID().toString(); + + assertThat(ObjectUtils.firstNonNull(Arrays.asList(backup, value, value))).contains(backup); + assertThat(ObjectUtils.firstNonNull(Arrays.asList(value, null, backup))).contains(value); + assertThat(ObjectUtils.firstNonNull(Arrays.asList(backup, value, null))).contains(backup); + assertThat(ObjectUtils.firstNonNull(Arrays.asList(value, backup))).contains(value); + assertThat(ObjectUtils.firstNonNull(Arrays.asList(null, null, value))).contains(value); + + String _null = null; + assertThat(ObjectUtils.firstNonNull(Arrays.asList(null, null, _null))).isEmpty(); + assertThat(ObjectUtils.firstNonNull(Arrays.asList(null, "null", backup))).contains("null"); + assertThat(ObjectUtils.firstNonNull(Arrays.asList(null, null))).isEmpty(); + assertThat(ObjectUtils.firstNonNull(Collections.emptyList())).isEmpty(); + } + + @Test + void firstNonNullObjectArray() { + String value = UUID.randomUUID().toString(); + String backup = UUID.randomUUID().toString(); + + assertThat(firstNonNull(backup, value, value)).contains(backup); + assertThat(firstNonNull(value, null, backup)).contains(value); + assertThat(firstNonNull(backup, value, null)).contains(backup); + assertThat(firstNonNull(value, backup)).contains(value); + assertThat(firstNonNull(null, null, value)).contains(value); + + String _null = null; + assertThat(firstNonNull(null, null, _null)).isEmpty(); + assertThat(firstNonNull(null, "null", backup)).contains("null"); + assertThat(firstNonNull(null, null)).isEmpty(); + } + @Test void isEmptyNull() { assertThat(isEmpty(null)).isTrue();