Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods to enhance joins: joinNotEmptyWith, joinNotBlankWith #806

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions src/main/java/org/apache/commons/lang3/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ public class StringUtils {
*/
private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$

/**
* The filter mode for join operations.
*/
private enum JoinFilterMode { NOT_EMPTY, NOT_BLANK }

/**
* <p>Abbreviates a String using ellipses. This will turn
* "Now is the time for all good men" into "Now is the time for..."</p>
Expand Down Expand Up @@ -4887,6 +4892,97 @@ public static String joinWith(final String delimiter, final Object... array) {
return join(array, delimiter);
}

/**
* <p>Joins the elements of the provided varargs into a
* single String containing the filtered provided elements.</p>
*
* <p>Element that do not match the filter criteria is not added.
* No delimiter is added between elements when at least one of them is filtered.
* No delimiter is added before or after the list.
* {@code null} elements and separator are treated as empty Strings ("").</p>
*
* @param filterMode the filter mode, must not be null
* @param delimiter the separator character to use, null treated as ""
* @param array the varargs providing the values to join together. {@code null} elements are treated as ""
* @return the joined String.
* @throws java.lang.IllegalArgumentException if filterMode is null
* @throws java.lang.IllegalArgumentException if a null varargs is provided
* @since ???
*/
private static String joinWith(final JoinFilterMode filterMode, final String delimiter, final Object... array) {
if (filterMode == null) {
throw new IllegalArgumentException("Filter mode must not be null");
}

if (array == null) {
throw new IllegalArgumentException("Object varargs must not be null");
}

final StringJoiner joiner = new StringJoiner(toStringOrEmpty(delimiter));
for (Object o : array) {
String s = toStringOrEmpty(o);
if (filterMode == JoinFilterMode.NOT_EMPTY && isNotEmpty(s)
|| filterMode == JoinFilterMode.NOT_BLANK && isNotBlank(s)) {
joiner.add(s);
}
}
return joiner.toString();
}

/**
* <p>Joins the elements of the provided varargs into a
* single String containing the filtered provided elements.</p>
*
* <p>Elements for which the result of isNotEmpty() is false are skipped.
* No delimiter is added between elements when at least one of them is filtered.
* No delimiter is added before or after the list.
* {@code null} elements and separator are treated as empty Strings ("").</p>
*
* <pre>
* StringUtils.joinNotEmptyWith(",", {"a", "b"}) = "a,b"
* StringUtils.joinNotEmptyWith(",", {"a", "b", " "}) = "a,b, "
* StringUtils.joinNotEmptyWith(",", {"", "a", null, "b"}) = "a,b"
* StringUtils.joinNotEmptyWith(null, {"a", "b"}) = "ab"
* StringUtils.joinNotEmptyWith(null, {null, "a", " ", "b"}) = "a b"
* </pre>
*
* @param delimiter the separator character to use, null treated as ""
* @param array the varargs providing the values to join together. {@code null} elements are treated as ""
* @return the joined String.
* @throws java.lang.IllegalArgumentException if a null varargs is provided
* @since ???
*/
public static String joinNotEmptyWith(final String delimiter, final Object... array) {
return joinWith(JoinFilterMode.NOT_EMPTY, delimiter, array);
}

/**
* <p>Joins the elements of the provided varargs into a
* single String containing the filtered provided elements.</p>
*
* <p>Elements for which the result of isNotBlank() is false are skipped.
* No delimiter is added between elements when at least one of them is filtered.
* No delimiter is added before or after the list.
* {@code null} elements and separator are treated as empty Strings ("").</p>
*
* <pre>
* StringUtils.joinNotBlankWith(",", {"a", "b"}) = "a,b"
* StringUtils.joinNotBlankWith(",", {"a", "b", " "}) = "a,b"
* StringUtils.joinNotBlankWith(",", {"", "a", null, "b"}) = "a,b"
* StringUtils.joinNotBlankWith(null, {"a", "b"}) = "ab"
* StringUtils.joinNotBlankWith(null, {null, "a", " ", "b"}) = "ab"
* </pre>
*
* @param delimiter the separator character to use, null treated as ""
* @param array the varargs providing the values to join together. {@code null} elements are treated as ""
* @return the joined String.
* @throws java.lang.IllegalArgumentException if a null varargs is provided
* @since ???
*/
public static String joinNotBlankWith(final String delimiter, final Object... array) {
return joinWith(JoinFilterMode.NOT_BLANK, delimiter, array);
}

/**
* <p>Finds the last index within a CharSequence, handling {@code null}.
* This method uses {@link String#lastIndexOf(String)} if possible.</p>
Expand Down
26 changes: 26 additions & 0 deletions src/test/java/org/apache/commons/lang3/StringUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,32 @@ public void testJoinWith() {
assertEquals("ab", StringUtils.joinWith(null, "a", "b"));
}

@Test
public void testJoinNotEmptyWith() {
assertEquals("", StringUtils.joinNotEmptyWith(",")); // empty array
assertEquals("", StringUtils.joinNotEmptyWith(",", (Object[]) NULL_ARRAY_LIST));
assertEquals("", StringUtils.joinNotEmptyWith(",", NULL_TO_STRING_LIST));

assertEquals("a,b", StringUtils.joinNotEmptyWith(",", "a", "b"));
assertEquals("a,b, ", StringUtils.joinNotEmptyWith(",", "a", "b", " "));
assertEquals("a,b", StringUtils.joinNotEmptyWith(",", "", "a", null, "b"));
assertEquals("ab", StringUtils.joinNotEmptyWith(null, "a", "b"));
assertEquals("a b", StringUtils.joinNotEmptyWith(null, "a", " ", "b"));
}

@Test
public void testJoinNotBlankWith() {
assertEquals("", StringUtils.joinNotBlankWith(",")); // empty array
assertEquals("", StringUtils.joinNotBlankWith(",", (Object[]) NULL_ARRAY_LIST));
assertEquals("", StringUtils.joinNotBlankWith(",", NULL_TO_STRING_LIST));

assertEquals("a,b", StringUtils.joinNotBlankWith(",", "a", "b"));
assertEquals("a,b", StringUtils.joinNotBlankWith(",", "a", "b", " "));
assertEquals("a,b", StringUtils.joinNotBlankWith(",", "", "a", null, "b"));
assertEquals("ab", StringUtils.joinNotBlankWith(null, "a", "b"));
assertEquals("ab", StringUtils.joinNotBlankWith(null, "a", " ", "b"));
}

@Test
public void testJoinWithThrowsException() {
assertThrows(IllegalArgumentException.class, () -> StringUtils.joinWith(",", (Object[]) null));
Expand Down