From 9bc992b133f7169288f1fa6b53a04f74c1549947 Mon Sep 17 00:00:00 2001 From: pascalschumacher Date: Sat, 21 May 2016 17:41:15 +0200 Subject: [PATCH] LANG-901: StringUtils#startsWithAny/endsWithAny is case sensitive - documented as case insensitive (closes #149) Improve the documentation and introduce more test cases that verify the documented behaviors. Patch by Matthew Bartenschlag --- src/changes/changes.xml | 1 + .../org/apache/commons/lang3/StringUtils.java | 41 +++++++++++-------- .../lang3/StringUtilsStartsEndsWithTest.java | 9 ++++ 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 7fd5f0ffe..5299260c0 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,7 @@ + StringUtils#startsWithAny/endsWithAny is case sensitive - documented as case insensitive Add StopWatch#getTime(TimeUnit) Add methods to ObjectUtils class to check for null elements in the array Prefer Throwable.getCause() in ExceptionUtils.getCause() diff --git a/src/main/java/org/apache/commons/lang3/StringUtils.java b/src/main/java/org/apache/commons/lang3/StringUtils.java index c169e0a62..c403f54e9 100644 --- a/src/main/java/org/apache/commons/lang3/StringUtils.java +++ b/src/main/java/org/apache/commons/lang3/StringUtils.java @@ -7971,30 +7971,33 @@ public class StringUtils { } /** - *

Check if a CharSequence starts with any of an array of specified strings.

+ *

Check if a CharSequence starts with any of the provided case-sensitive prefixes.

* *
      * StringUtils.startsWithAny(null, null)      = false
      * StringUtils.startsWithAny(null, new String[] {"abc"})  = false
      * StringUtils.startsWithAny("abcxyz", null)     = false
-     * StringUtils.startsWithAny("abcxyz", new String[] {""}) = false
+     * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true
      * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
      * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
+     * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false
+     * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false
      * 
* - * @param string the CharSequence to check, may be null - * @param searchStrings the CharSequences to find, may be null or empty - * @return {@code true} if the CharSequence starts with any of the the prefixes, case sensitive, or - * both {@code null} + * @param sequence the CharSequence to check, may be null + * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null} + * @see StringUtils#startsWith(CharSequence, CharSequence) + * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or + * the input {@code sequence} begins with any of the provided case-sensitive {@code searchStrings}. * @since 2.5 * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...) */ - public static boolean startsWithAny(final CharSequence string, final CharSequence... searchStrings) { - if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) { + public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { + if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) { return false; } for (final CharSequence searchString : searchStrings) { - if (startsWith(string, searchString)) { + if (startsWith(sequence, searchString)) { return true; } } @@ -8017,6 +8020,7 @@ public class StringUtils { * StringUtils.endsWith("abcdef", "def") = true * StringUtils.endsWith("ABCDEF", "def") = false * StringUtils.endsWith("ABCDEF", "cde") = false + * StringUtils.endsWith("ABCDEF", "") = true * * * @see java.lang.String#endsWith(String) @@ -8153,7 +8157,7 @@ public class StringUtils { } /** - *

Check if a CharSequence ends with any of an array of specified strings.

+ *

Check if a CharSequence ends with any of the provided case-sensitive suffixes.

* *
      * StringUtils.endsWithAny(null, null)      = false
@@ -8162,20 +8166,23 @@ public class StringUtils {
      * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
      * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
      * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
+     * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true
+     * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false
      * 
* - * @param string the CharSequence to check, may be null - * @param searchStrings the CharSequences to find, may be null or empty - * @return {@code true} if the CharSequence ends with any of the the prefixes, case insensitive, or - * both {@code null} + * @param sequence the CharSequence to check, may be null + * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null} + * @see StringUtils#endsWith(CharSequence, CharSequence) + * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or + * the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}. * @since 3.0 */ - public static boolean endsWithAny(final CharSequence string, final CharSequence... searchStrings) { - if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) { + public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { + if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) { return false; } for (final CharSequence searchString : searchStrings) { - if (endsWith(string, searchString)) { + if (endsWith(sequence, searchString)) { return true; } } diff --git a/src/test/java/org/apache/commons/lang3/StringUtilsStartsEndsWithTest.java b/src/test/java/org/apache/commons/lang3/StringUtilsStartsEndsWithTest.java index 2f053d56a..a351a2fc5 100644 --- a/src/test/java/org/apache/commons/lang3/StringUtilsStartsEndsWithTest.java +++ b/src/test/java/org/apache/commons/lang3/StringUtilsStartsEndsWithTest.java @@ -90,6 +90,9 @@ public class StringUtilsStartsEndsWithTest { assertTrue(StringUtils.startsWithAny("abcxyz", "abc")); assertTrue(StringUtils.startsWithAny("abcxyz", null, "xyz", "abc")); assertFalse(StringUtils.startsWithAny("abcxyz", null, "xyz", "abcd")); + assertTrue(StringUtils.startsWithAny("abcxyz", new String[]{""})); + assertFalse(StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX")); + assertFalse(StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc")); assertTrue("StringUtils.startsWithAny(abcxyz, StringBuilder(xyz), StringBuffer(abc))", StringUtils.startsWithAny("abcxyz", new StringBuilder("xyz"), new StringBuffer("abc"))); assertTrue("StringUtils.startsWithAny( StrBuilder(abcxyz), StringBuilder(xyz), StringBuffer(abc))", StringUtils.startsWithAny( new StrBuilder("abcxyz"), new StringBuilder("xyz"), new StringBuffer("abc"))); @@ -172,6 +175,12 @@ public class StringUtilsStartsEndsWithTest { assertTrue("StringUtils.endsWithAny(abcxyz, new String[] {xyz})", StringUtils.endsWithAny("abcxyz", new String[] {"xyz"})); assertTrue("StringUtils.endsWithAny(abcxyz, new String[] {null, xyz, abc})", StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"})); assertFalse("StringUtils.endsWithAny(defg, new String[] {null, xyz, abc})", StringUtils.endsWithAny("defg", new String[] {null, "xyz", "abc"})); + assertTrue(StringUtils.endsWithAny("abcXYZ", "def", "XYZ")); + assertFalse(StringUtils.endsWithAny("abcXYZ", "def", "xyz")); + assertTrue(StringUtils.endsWithAny("abcXYZ", "def", "YZ")); + + assertFalse(StringUtils.endsWithAny("abcXYZ", null)); + assertTrue(StringUtils.endsWithAny("abcXYZ", "")); assertTrue("StringUtils.endsWithAny(abcxyz, StringBuilder(abc), StringBuffer(xyz))", StringUtils.endsWithAny("abcxyz", new StringBuilder("abc"), new StringBuffer("xyz"))); assertTrue("StringUtils.endsWithAny( StrBuilder(abcxyz), StringBuilder(abc), StringBuffer(xyz))", StringUtils.endsWithAny( new StrBuilder("abcxyz"), new StringBuilder("abc"), new StringBuffer("xyz")));