This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-lang.git
The following commit(s) were added to refs/heads/master by this push: new 24e6468 [LANG-1498] Add support of lambda value evaluation for defaulting methods #416. 24e6468 is described below commit 24e64686834ecd4a0dda80c91b53b15e227fc898 Author: Gary Gregory <gardgreg...@gmail.com> AuthorDate: Mon Nov 4 17:53:58 2019 -0500 [LANG-1498] Add support of lambda value evaluation for defaulting methods #416. --- .../java/org/apache/commons/lang3/ObjectUtils.java | 54 ++++++++-------- .../java/org/apache/commons/lang3/StringUtils.java | 61 ++++++++++++++++++- .../org/apache/commons/lang3/ObjectUtilsTest.java | 12 ++-- .../org/apache/commons/lang3/StringUtilsTest.java | 71 +++++++++++++++++++--- 4 files changed, 157 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/apache/commons/lang3/ObjectUtils.java b/src/main/java/org/apache/commons/lang3/ObjectUtils.java index 175f3c0..3b83ce1 100644 --- a/src/main/java/org/apache/commons/lang3/ObjectUtils.java +++ b/src/main/java/org/apache/commons/lang3/ObjectUtils.java @@ -155,30 +155,6 @@ public class ObjectUtils { } /** - * <p>Returns the given {@code object} is it is non-null, otherwise returns the Supplier's get value.</p> - * - * <p>The caller responsible for thread-safety and exception handling of default value supplier.</p> - * - * <pre> - * ObjectUtils.getIfNull(null, () -> null) = null - * ObjectUtils.getIfNull(null, null) = null - * ObjectUtils.getIfNull(null, () -> "") = "" - * ObjectUtils.getIfNull(null, () -> "zz") = "zz" - * ObjectUtils.getIfNull("abc", *) = "abc" - * ObjectUtils.getIfNull(Boolean.TRUE, *) = Boolean.TRUE - * </pre> - * - * @param <T> the type of the object - * @param object the {@code Object} to test, may be {@code null} - * @param defaultSupplier the default value to return, may be {@code null} - * @return {@code object} if it is not {@code null}, {@code defaultValueSupplier.get()} otherwise - * @since 3.10 - */ - public static <T> T defaultIfNull(final T object, final Supplier<T> defaultSupplier) { - return object != null ? object : defaultSupplier == null ? null : defaultSupplier.get(); - } - - /** * <p>Returns a default value if the object passed is {@code null}.</p> * * <pre> @@ -193,6 +169,7 @@ public class ObjectUtils { * @param object the {@code Object} to test, may be {@code null} * @param defaultValue the default value to return, may be {@code null} * @return {@code object} if it is not {@code null}, defaultValue otherwise + * TODO Rename to getIfNull in 4.0 */ public static <T> T defaultIfNull(final T object, final T defaultValue) { return object != null ? object : defaultValue; @@ -233,6 +210,35 @@ public class ObjectUtils { } /** + * <p> + * Returns the given {@code object} is it is non-null, otherwise returns the Supplier's {@link Supplier#get()} + * value. + * </p> + * + * <p> + * The caller responsible for thread-safety and exception handling of default value supplier. + * </p> + * + * <pre> + * ObjectUtils.getIfNull(null, () -> null) = null + * ObjectUtils.getIfNull(null, null) = null + * ObjectUtils.getIfNull(null, () -> "") = "" + * ObjectUtils.getIfNull(null, () -> "zz") = "zz" + * ObjectUtils.getIfNull("abc", *) = "abc" + * ObjectUtils.getIfNull(Boolean.TRUE, *) = Boolean.TRUE + * </pre> + * + * @param <T> the type of the object + * @param object the {@code Object} to test, may be {@code null} + * @param defaultSupplier the default value to return, may be {@code null} + * @return {@code object} if it is not {@code null}, {@code defaultValueSupplier.get()} otherwise + * @since 3.10 + */ + public static <T> T getIfNull(final T object, final Supplier<T> defaultSupplier) { + return object != null ? object : defaultSupplier == null ? null : defaultSupplier.get(); + } + + /** * Checks if any value in the given array is not {@code null}. * * <p> diff --git a/src/main/java/org/apache/commons/lang3/StringUtils.java b/src/main/java/org/apache/commons/lang3/StringUtils.java index fe2d78f..ea99127 100644 --- a/src/main/java/org/apache/commons/lang3/StringUtils.java +++ b/src/main/java/org/apache/commons/lang3/StringUtils.java @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Objects; +import java.util.function.Supplier; import java.util.regex.Pattern; /** @@ -1481,7 +1482,6 @@ public class StringUtils { return isBlank(str) ? defaultStr : str; } - /** * <p>Returns either the passed in CharSequence, or if the CharSequence is * empty or {@code null}, the value of {@code defaultStr}.</p> @@ -1504,8 +1504,6 @@ public class StringUtils { return isEmpty(str) ? defaultStr : str; } - // Defaults - //----------------------------------------------------------------------- /** * <p>Returns either the passed in String, * or if the String is {@code null}, an empty String ("").</p> @@ -2149,6 +2147,63 @@ public class StringUtils { } /** + * <p>Returns either the passed in CharSequence, or if the CharSequence is + * whitespace, empty ("") or {@code null}, the value supplied by {@code defaultStrSupplier}.</p> + * + * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> + * + * <p>Caller responsible for thread-safety and exception handling of default value supplier</p> + * + * <pre> + * {@code + * StringUtils.getIfBlank(null, () -> "NULL") = "NULL" + * StringUtils.getIfBlank("", () -> "NULL") = "NULL" + * StringUtils.getIfBlank(" ", () -> "NULL") = "NULL" + * StringUtils.getIfBlank("bat", () -> "NULL") = "bat" + * StringUtils.getIfBlank("", () -> null) = null + * StringUtils.getIfBlank("", null) = null + * }</pre> + * @param <T> the specific kind of CharSequence + * @param str the CharSequence to check, may be null + * @param defaultSupplier the supplier of default CharSequence to return + * if the input is whitespace, empty ("") or {@code null}, may be null + * @return the passed in CharSequence, or the default + * @see StringUtils#defaultString(String, String) + * @since 3.10 + */ + public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) { + return isBlank(str) ? defaultSupplier == null ? null : defaultSupplier.get() : str; + } + + /** + * <p>Returns either the passed in CharSequence, or if the CharSequence is + * empty or {@code null}, the value supplied by {@code defaultStrSupplier}.</p> + * + * <p>Caller responsible for thread-safety and exception handling of default value supplier</p> + * + * <pre> + * {@code + * StringUtils.getIfEmpty(null, () -> "NULL") = "NULL" + * StringUtils.getIfEmpty("", () -> "NULL") = "NULL" + * StringUtils.getIfEmpty(" ", () -> "NULL") = " " + * StringUtils.getIfEmpty("bat", () -> "NULL") = "bat" + * StringUtils.getIfEmpty("", () -> null) = null + * StringUtils.getIfEmpty("", null) = null + * } + * </pre> + * @param <T> the specific kind of CharSequence + * @param str the CharSequence to check, may be null + * @param defaultSupplier the supplier of default CharSequence to return + * if the input is empty ("") or {@code null}, may be null + * @return the passed in CharSequence, or the default + * @see StringUtils#defaultString(String, String) + * @since 3.10 + */ + public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) { + return isEmpty(str) ? defaultSupplier == null ? null : defaultSupplier.get() : str; + } + + /** * <p>Find the Jaro Winkler Distance which indicates the similarity score between two Strings.</p> * * <p>The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. diff --git a/src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java b/src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java index 84059f4..b181524 100644 --- a/src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java @@ -116,18 +116,18 @@ public class ObjectUtilsTest { final Object dflt = BAR; assertSame(dflt, ObjectUtils.defaultIfNull(null, dflt), "dflt was not returned when o was null"); assertSame(o, ObjectUtils.defaultIfNull(o, dflt), "dflt was returned when o was not null"); - assertSame(dflt, ObjectUtils.defaultIfNull(null, () -> dflt), "dflt was not returned when o was null"); - assertSame(o, ObjectUtils.defaultIfNull(o, () -> dflt), "dflt was returned when o was not null"); - assertSame(o, ObjectUtils.defaultIfNull(FOO, () -> dflt), "dflt was returned when o was not null"); - assertSame(o, ObjectUtils.defaultIfNull("foo", () -> dflt), "dflt was returned when o was not null"); + assertSame(dflt, ObjectUtils.getIfNull(null, () -> dflt), "dflt was not returned when o was null"); + assertSame(o, ObjectUtils.getIfNull(o, () -> dflt), "dflt was returned when o was not null"); + assertSame(o, ObjectUtils.getIfNull(FOO, () -> dflt), "dflt was returned when o was not null"); + assertSame(o, ObjectUtils.getIfNull("foo", () -> dflt), "dflt was returned when o was not null"); MutableInt callsCounter = new MutableInt(0); Supplier<Object> countingDefaultSupplier = () -> { callsCounter.increment(); return dflt; }; - ObjectUtils.defaultIfNull(o, countingDefaultSupplier); + ObjectUtils.getIfNull(o, countingDefaultSupplier); assertEquals(0, callsCounter.getValue()); - ObjectUtils.defaultIfNull(null, countingDefaultSupplier); + ObjectUtils.getIfNull(null, countingDefaultSupplier); assertEquals(1, callsCounter.getValue()); } diff --git a/src/test/java/org/apache/commons/lang3/StringUtilsTest.java b/src/test/java/org/apache/commons/lang3/StringUtilsTest.java index 9f36c6d..95e98af 100644 --- a/src/test/java/org/apache/commons/lang3/StringUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/StringUtilsTest.java @@ -39,8 +39,10 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Objects; +import java.util.function.Supplier; import java.util.regex.PatternSyntaxException; +import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.text.WordUtils; import org.junit.jupiter.api.Test; @@ -622,7 +624,7 @@ public class StringUtilsTest { assertEquals("NULL", StringUtils.defaultIfBlank(CharBuffer.wrap(""), CharBuffer.wrap("NULL")).toString()); assertEquals("NULL", StringUtils.defaultIfBlank(CharBuffer.wrap(" "), CharBuffer.wrap("NULL")).toString()); assertEquals("abc", StringUtils.defaultIfBlank(CharBuffer.wrap("abc"), CharBuffer.wrap("NULL")).toString()); - assertNull(StringUtils.defaultIfBlank(CharBuffer.wrap(""), null)); + assertNull(StringUtils.defaultIfBlank(CharBuffer.wrap(""), (CharBuffer) null)); // Tests compatibility for the API return type final CharBuffer s = StringUtils.defaultIfBlank(CharBuffer.wrap("abc"), CharBuffer.wrap("NULL")); assertEquals("abc", s.toString()); @@ -633,7 +635,7 @@ public class StringUtilsTest { assertEquals("NULL", StringUtils.defaultIfBlank(new StringBuffer(""), new StringBuffer("NULL")).toString()); assertEquals("NULL", StringUtils.defaultIfBlank(new StringBuffer(" "), new StringBuffer("NULL")).toString()); assertEquals("abc", StringUtils.defaultIfBlank(new StringBuffer("abc"), new StringBuffer("NULL")).toString()); - assertNull(StringUtils.defaultIfBlank(new StringBuffer(""), null)); + assertNull(StringUtils.defaultIfBlank(new StringBuffer(""), (StringBuffer) null)); // Tests compatibility for the API return type final StringBuffer s = StringUtils.defaultIfBlank(new StringBuffer("abc"), new StringBuffer("NULL")); assertEquals("abc", s.toString()); @@ -644,7 +646,7 @@ public class StringUtilsTest { assertEquals("NULL", StringUtils.defaultIfBlank(new StringBuilder(""), new StringBuilder("NULL")).toString()); assertEquals("NULL", StringUtils.defaultIfBlank(new StringBuilder(" "), new StringBuilder("NULL")).toString()); assertEquals("abc", StringUtils.defaultIfBlank(new StringBuilder("abc"), new StringBuilder("NULL")).toString()); - assertNull(StringUtils.defaultIfBlank(new StringBuilder(""), null)); + assertNull(StringUtils.defaultIfBlank(new StringBuilder(""), (StringBuilder) null)); // Tests compatibility for the API return type final StringBuilder s = StringUtils.defaultIfBlank(new StringBuilder("abc"), new StringBuilder("NULL")); assertEquals("abc", s.toString()); @@ -656,17 +658,45 @@ public class StringUtilsTest { assertEquals("NULL", StringUtils.defaultIfBlank("", "NULL")); assertEquals("NULL", StringUtils.defaultIfBlank(" ", "NULL")); assertEquals("abc", StringUtils.defaultIfBlank("abc", "NULL")); - assertNull(StringUtils.defaultIfBlank("", null)); + assertNull(StringUtils.defaultIfBlank("", (String) null)); // Tests compatibility for the API return type final String s = StringUtils.defaultIfBlank("abc", "NULL"); assertEquals("abc", s); } + + @Test + public void testGetIfBlank_StringStringSupplier() { + assertEquals("NULL", StringUtils.getIfBlank(null, () -> "NULL")); + assertEquals("NULL", StringUtils.getIfBlank("", () -> "NULL")); + assertEquals("NULL", StringUtils.getIfBlank(" ", () -> "NULL")); + assertEquals("abc", StringUtils.getIfBlank("abc", () -> "NULL")); + assertNull(StringUtils.getIfBlank("", () -> null)); + assertNull(StringUtils.defaultIfBlank("", (String) null)); + // Tests compatibility for the API return type + final String s = StringUtils.getIfBlank("abc", () -> "NULL"); + assertEquals("abc", s); + //Checking that default value supplied only on demand + MutableInt numberOfCalls = new MutableInt(0); + Supplier<String> countingDefaultSupplier = () -> { + numberOfCalls.increment(); + return "NULL"; + }; + StringUtils.getIfBlank("abc", countingDefaultSupplier); + assertEquals(0, numberOfCalls.getValue()); + StringUtils.getIfBlank("", countingDefaultSupplier); + assertEquals(1, numberOfCalls.getValue()); + StringUtils.getIfBlank(" ", countingDefaultSupplier); + assertEquals(2, numberOfCalls.getValue()); + StringUtils.getIfBlank(null, countingDefaultSupplier); + assertEquals(3, numberOfCalls.getValue()); + } + @Test public void testDefaultIfEmpty_CharBuffers() { assertEquals("NULL", StringUtils.defaultIfEmpty(CharBuffer.wrap(""), CharBuffer.wrap("NULL")).toString()); assertEquals("abc", StringUtils.defaultIfEmpty(CharBuffer.wrap("abc"), CharBuffer.wrap("NULL")).toString()); - assertNull(StringUtils.defaultIfEmpty(CharBuffer.wrap(""), null)); + assertNull(StringUtils.defaultIfEmpty(CharBuffer.wrap(""), (CharBuffer) null)); // Tests compatibility for the API return type final CharBuffer s = StringUtils.defaultIfEmpty(CharBuffer.wrap("abc"), CharBuffer.wrap("NULL")); assertEquals("abc", s.toString()); @@ -677,7 +707,7 @@ public class StringUtilsTest { public void testDefaultIfEmpty_StringBuffers() { assertEquals("NULL", StringUtils.defaultIfEmpty(new StringBuffer(""), new StringBuffer("NULL")).toString()); assertEquals("abc", StringUtils.defaultIfEmpty(new StringBuffer("abc"), new StringBuffer("NULL")).toString()); - assertNull(StringUtils.defaultIfEmpty(new StringBuffer(""), null)); + assertNull(StringUtils.defaultIfEmpty(new StringBuffer(""), (StringBuffer) null)); // Tests compatibility for the API return type final StringBuffer s = StringUtils.defaultIfEmpty(new StringBuffer("abc"), new StringBuffer("NULL")); assertEquals("abc", s.toString()); @@ -687,7 +717,7 @@ public class StringUtilsTest { public void testDefaultIfEmpty_StringBuilders() { assertEquals("NULL", StringUtils.defaultIfEmpty(new StringBuilder(""), new StringBuilder("NULL")).toString()); assertEquals("abc", StringUtils.defaultIfEmpty(new StringBuilder("abc"), new StringBuilder("NULL")).toString()); - assertNull(StringUtils.defaultIfEmpty(new StringBuilder(""), null)); + assertNull(StringUtils.defaultIfEmpty(new StringBuilder(""), (StringBuilder) null)); // Tests compatibility for the API return type final StringBuilder s = StringUtils.defaultIfEmpty(new StringBuilder("abc"), new StringBuilder("NULL")); assertEquals("abc", s.toString()); @@ -698,13 +728,38 @@ public class StringUtilsTest { assertEquals("NULL", StringUtils.defaultIfEmpty(null, "NULL")); assertEquals("NULL", StringUtils.defaultIfEmpty("", "NULL")); assertEquals("abc", StringUtils.defaultIfEmpty("abc", "NULL")); - assertNull(StringUtils.defaultIfEmpty("", null)); + assertNull(StringUtils.getIfEmpty("", null)); // Tests compatibility for the API return type final String s = StringUtils.defaultIfEmpty("abc", "NULL"); assertEquals("abc", s); } @Test + public void testGetIfEmpty_StringStringSupplier() { + assertEquals("NULL", StringUtils.getIfEmpty((String) null, () -> "NULL")); + assertEquals("NULL", StringUtils.getIfEmpty("", () -> "NULL")); + assertEquals("abc", StringUtils.getIfEmpty("abc", () -> "NULL")); + assertNull(StringUtils.getIfEmpty("", () -> null)); + assertNull(StringUtils.defaultIfEmpty("", (String) null)); + // Tests compatibility for the API return type + final String s = StringUtils.getIfEmpty("abc", () -> "NULL"); + assertEquals("abc", s); + //Checking that default value supplied only on demand + MutableInt numberOfCalls = new MutableInt(0); + Supplier<String> countingDefaultSupplier = () -> { + numberOfCalls.increment(); + return "NULL"; + }; + StringUtils.getIfEmpty("abc", countingDefaultSupplier); + assertEquals(0, numberOfCalls.getValue()); + StringUtils.getIfEmpty("", countingDefaultSupplier); + assertEquals(1, numberOfCalls.getValue()); + StringUtils.getIfEmpty(null, countingDefaultSupplier); + assertEquals(2, numberOfCalls.getValue()); + } + + + @Test public void testDeleteWhitespace_String() { assertNull(StringUtils.deleteWhitespace(null)); assertEquals("", StringUtils.deleteWhitespace(""));