[LANG-1498] Add support of lambda value evaluation for defaulting

methods #416.
This commit is contained in:
Gary Gregory 2019-11-04 17:53:58 -05:00
parent 16cc98fbfa
commit 24e6468683
4 changed files with 157 additions and 41 deletions

View File

@ -154,30 +154,6 @@ public static boolean isNotEmpty(final Object object) {
return !isEmpty(object);
}
/**
* <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, () -&gt; null) = null
* ObjectUtils.getIfNull(null, null) = null
* ObjectUtils.getIfNull(null, () -&gt; "") = ""
* ObjectUtils.getIfNull(null, () -&gt; "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>
*
@ -193,6 +169,7 @@ public static <T> T defaultIfNull(final T object, final Supplier<T> defaultSuppl
* @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;
@ -232,6 +209,35 @@ public static <T> T firstNonNull(final T... values) {
return null;
}
/**
* <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, () -&gt; null) = null
* ObjectUtils.getIfNull(null, null) = null
* ObjectUtils.getIfNull(null, () -&gt; "") = ""
* ObjectUtils.getIfNull(null, () -&gt; "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}.
*

View File

@ -25,6 +25,7 @@
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 static <T extends CharSequence> T defaultIfBlank(final T str, final T def
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 static <T extends CharSequence> T defaultIfEmpty(final T str, final T def
return isEmpty(str) ? defaultStr : str;
}
// Defaults
//-----------------------------------------------------------------------
/**
* <p>Returns either the passed in String,
* or if the String is {@code null}, an empty String ("").</p>
@ -2148,6 +2146,63 @@ public static int getFuzzyDistance(final CharSequence term, final CharSequence q
return score;
}
/**
* <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>
*

View File

@ -116,18 +116,18 @@ public void testDefaultIfNull() {
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());
}

View File

@ -39,8 +39,10 @@
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 void testDefaultIfBlank_CharBuffers() {
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 void testDefaultIfBlank_StringBuffers() {
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 void testDefaultIfBlank_StringBuilders() {
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 void testDefaultIfBlank_StringString() {
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 void testDefaultIfEmpty_CharBuffers() {
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 void testDefaultIfEmpty_StringBuffers() {
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,12 +728,37 @@ public void testDefaultIfEmpty_StringString() {
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));