    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017    package org.apache.commons.lang;
    018
    019    import java.util.ArrayList;
    020    import java.util.Collection;
    021    import java.util.Iterator;
    022    import java.util.List;
    023    import java.util.Locale;
    024
    025    import org.apache.commons.lang.text.StrBuilder;
    026
    027    /**
    028     * <p>Operations on {@link java.lang.String} that are
    029     * <code>null</code> safe.</p>
    030     *
    031     * <ul>
    032     *  <li><b>IsEmpty/IsBlank</b>
    033     *      - checks if a String contains text</li>
    034     *  <li><b>Trim/Strip</b>
    035     *      - removes leading and trailing whitespace</li>
    036     *  <li><b>Equals</b>
    037     *      - compares two strings null-safe</li>
    038     *  <li><b>startsWith</b>
    039     *      - check if a String starts with a prefix null-safe</li>
    040     *  <li><b>endsWith</b>
    041     *      - check if a String ends with a suffix null-safe</li>
    042     *  <li><b>IndexOf/LastIndexOf/Contains</b>
    043     *      - null-safe index-of checks
    044     *  <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>
    045     *      - index-of any of a set of Strings</li>
    046     *  <li><b>ContainsOnly/ContainsNone/ContainsAny</b>
    047     *      - does String contains only/none/any of these characters</li>
    048     *  <li><b>Substring/Left/Right/Mid</b>
    049     *      - null-safe substring extractions</li>
    050     *  <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>
    051     *      - substring extraction relative to other strings</li>
    052     *  <li><b>Split/Join</b>
    053     *      - splits a String into an array of substrings and vice versa</li>
    054     *  <li><b>Remove/Delete</b>
    055     *      - removes part of a String</li>
    056     *  <li><b>Replace/Overlay</b>
    057     *      - Searches a String and replaces one String with another</li>
    058     *  <li><b>Chomp/Chop</b>
    059     *      - removes the last part of a String</li>
    060     *  <li><b>LeftPad/RightPad/Center/Repeat</b>
    061     *      - pads a String</li>
    062     *  <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>
    063     *      - changes the case of a String</li>
    064     *  <li><b>CountMatches</b>
    065     *      - counts the number of occurrences of one String in another</li>
    066     *  <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>
    067     *      - checks the characters in a String</li>
    068     *  <li><b>DefaultString</b>
    069     *      - protects against a null input String</li>
    070     *  <li><b>Reverse/ReverseDelimited</b>
    071     *      - reverses a String</li>
    072     *  <li><b>Abbreviate</b>
    073     *      - abbreviates a string using ellipsis</li>
    074     *  <li><b>Difference</b>
    075     *      - compares Strings and reports on their differences</li>
    076     *  <li><b>LevensteinDistance</b>
    077     *      - the number of changes needed to change one String into another</li>
    078     * </ul>
    079     *
    080     * <p>The <code>StringUtils</code> class defines certain words related to
    081     * String handling.</p>
    082     *
    083     * <ul>
    084     *  <li>null - <code>null</code></li>
    085     *  <li>empty - a zero-length string (<code>""</code>)</li>
    086     *  <li>space - the space character (<code>' '</code>, char 32)</li>
    087     *  <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
    088     *  <li>trim - the characters &lt;= 32 as in {@link String#trim()}</li>
    089     * </ul>
    090     *
    091     * <p><code>StringUtils</code> handles <code>null</code> input Strings quietly.
    092     * That is to say that a <code>null</code> input will return <code>null</code>.
    093     * Where a <code>boolean</code> or <code>int</code> is being returned
    094     * details vary by method.</p>
    095     *
    096     * <p>A side effect of the <code>null</code> handling is that a
    097     * <code>NullPointerException</code> should be considered a bug in
    098     * <code>StringUtils</code> (except for deprecated methods).</p>
    099     *
    100     * <p>Methods in this class give sample code to explain their operation.
    101     * The symbol <code>*</code> is used to indicate any input including <code>null</code>.</p>
    102     *
    103     * <p>#ThreadSafe#</p>
    104     * @see java.lang.String
    105     * @author Apache Software Foundation
    106     * @author <a href="http://jakarta.apache.org/turbine/">Apache Jakarta Turbine</a>
    107     * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
    108     * @author Daniel L. Rall
    109     * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
    110     * @author <a href="mailto:ed@apache.org">Ed Korthof</a>
    111     * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
    112     * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
    113     * @author Holger Krauth
    114     * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
    115     * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    116     * @author Arun Mammen Thomas
    117     * @author Gary Gregory
    118     * @author Phil Steitz
    119     * @author Al Chou
    120     * @author Michael Davey
    121     * @author Reuben Sivan
    122     * @author Chris Hyzer
    123     * @author Scott Johnson
    124     * @since 1.0
    125     * @version $Id: StringUtils.java 1058365 2011-01-13 00:04:49Z niallp $
    126     */
    127    //@Immutable
    128    public class StringUtils {
    129        // Performance testing notes (JDK 1.4, Jul03, scolebourne)
    130        // Whitespace:
    131        // Character.isWhitespace() is faster than WHITESPACE.indexOf()
    132        // where WHITESPACE is a string of all whitespace characters
    133        //
    134        // Character access:
    135        // String.charAt(n) versus toCharArray(), then array[n]
    136        // String.charAt(n) is about 15% worse for a 10K string
    137        // They are about equal for a length 50 string
    138        // String.charAt(n) is about 4 times better for a length 3 string
    139        // String.charAt(n) is best bet overall
    140        //
    141        // Append:
    142        // String.concat about twice as fast as StringBuffer.append
    143        // (not sure who tested this)
    144
    145        /**
    146         * The empty String <code>""</code>.
    147         * @since 2.0
    148         */
    149        public static final String EMPTY = "";
    150
    151        /**
    152         * Represents a failed index search.
    153         * @since 2.1
    154         */
    155        public static final int INDEX_NOT_FOUND = -1;
    156
    157        /**
    158         * <p>The maximum size to which the padding constant(s) can expand.</p>
    159         */
    160        private static final int PAD_LIMIT = 8192;
    161
    162        /**
    163         * <p><code>StringUtils</code> instances should NOT be constructed in
    164         * standard programming. Instead, the class should be used as
    165         * <code>StringUtils.trim(" foo ");</code>.</p>
    166         *
    167         * <p>This constructor is public to permit tools that require a JavaBean
    168         * instance to operate.</p>
    169         */
    170        public StringUtils() {
    171            super();
    172        }
    173
    174        // Empty checks
    175        //-----------------------------------------------------------------------
    176        /**
    177         * <p>Checks if a String is empty ("") or null.</p>
    178         *
    179         * <pre>
    180         * StringUtils.isEmpty(null)      = true
    181         * StringUtils.isEmpty("")        = true
    182         * StringUtils.isEmpty(" ")       = false
    183         * StringUtils.isEmpty("bob")     = false
    184         * StringUtils.isEmpty("  bob  ") = false
    185         * </pre>
    186         *
    187         * <p>NOTE: This method changed in Lang version 2.0.
    188         * It no longer trims the String.
    189         * That functionality is available in isBlank().</p>
    190         *
    191         * @param str  the String to check, may be null
    192         * @return <code>true</code> if the String is empty or null
    193         */
    194        public static boolean isEmpty(String str) {
    195            return str == null || str.length() == 0;
    196        }
    197
    198        /**
    199         * <p>Checks if a String is not empty ("") and not null.</p>
    200         *
    201         * <pre>
    202         * StringUtils.isNotEmpty(null)      = false
    203         * StringUtils.isNotEmpty("")        = false
    204         * StringUtils.isNotEmpty(" ")       = true
    205         * StringUtils.isNotEmpty("bob")     = true
    206         * StringUtils.isNotEmpty("  bob  ") = true
    207         * </pre>
    208         *
    209         * @param str  the String to check, may be null
    210         * @return <code>true</code> if the String is not empty and not null
    211         */
    212        public static boolean isNotEmpty(String str) {
    213            return !StringUtils.isEmpty(str);
    214        }
    215
    216        /**
    217         * <p>Checks if a String is whitespace, empty ("") or null.</p>
    218         *
    219         * <pre>
    220         * StringUtils.isBlank(null)      = true
    221         * StringUtils.isBlank("")        = true
    222         * StringUtils.isBlank(" ")       = true
    223         * StringUtils.isBlank("bob")     = false
    224         * StringUtils.isBlank("  bob  ") = false
    225         * </pre>
    226         *
    227         * @param str  the String to check, may be null
    228         * @return <code>true</code> if the String is null, empty or whitespace
    229         * @since 2.0
    230         */
    231        public static boolean isBlank(String str) {
    232            int strLen;
    233            if (str == null || (strLen = str.length()) == 0) {
    234                return true;
    235            }
    236            for (int i = 0; i < strLen; i++) {
    237                if ((Character.isWhitespace(str.charAt(i)) == false)) {
    238                    return false;
    239                }
    240            }
    241            return true;
    242        }
    243
    244        /**
    245         * <p>Checks if a String is not empty (""), not null and not whitespace only.</p>
    246         *
    247         * <pre>
    248         * StringUtils.isNotBlank(null)      = false
    249         * StringUtils.isNotBlank("")        = false
    250         * StringUtils.isNotBlank(" ")       = false
    251         * StringUtils.isNotBlank("bob")     = true
    252         * StringUtils.isNotBlank("  bob  ") = true
    253         * </pre>
    254         *
    255         * @param str  the String to check, may be null
    256         * @return <code>true</code> if the String is
    257         *  not empty and not null and not whitespace
    258         * @since 2.0
    259         */
    260        public static boolean isNotBlank(String str) {
    261            return !StringUtils.isBlank(str);
    262        }
    263
    264        // Trim
    265        //-----------------------------------------------------------------------
    266        /**
    267         * <p>Removes control characters (char &lt;= 32) from both
    268         * ends of this String, handling <code>null</code> by returning
    269         * an empty String ("").</p>
    270         *
    271         * <pre>
    272         * StringUtils.clean(null)          = ""
    273         * StringUtils.clean("")            = ""
    274         * StringUtils.clean("abc")         = "abc"
    275         * StringUtils.clean("    abc    ") = "abc"
    276         * StringUtils.clean("     ")       = ""
    277         * </pre>
    278         *
    279         * @see java.lang.String#trim()
    280         * @param str  the String to clean, may be null
    281         * @return the trimmed text, never <code>null</code>
    282         * @deprecated Use the clearer named {@link #trimToEmpty(String)}.
    283         *             Method will be removed in Commons Lang 3.0.
    284         */
    285        public static String clean(String str) {
    286            return str == null ? EMPTY : str.trim();
    287        }
    288
    289        /**
    290         * <p>Removes control characters (char &lt;= 32) from both
    291         * ends of this String, handling <code>null</code> by returning
    292         * <code>null</code>.</p>
    293         *
    294         * <p>The String is trimmed using {@link String#trim()}.
    295         * Trim removes start and end characters &lt;= 32.
    296         * To strip whitespace use {@link #strip(String)}.</p>
    297         *
    298         * <p>To trim your choice of characters, use the
    299         * {@link #strip(String, String)} methods.</p>
    300         *
    301         * <pre>
    302         * StringUtils.trim(null)          = null
    303         * StringUtils.trim("")            = ""
    304         * StringUtils.trim("     ")       = ""
    305         * StringUtils.trim("abc")         = "abc"
    306         * StringUtils.trim("    abc    ") = "abc"
    307         * </pre>
    308         *
    309         * @param str  the String to be trimmed, may be null
    310         * @return the trimmed string, <code>null</code> if null String input
    311         */
    312        public static String trim(String str) {
    313            return str == null ? null : str.trim();
    314        }
    315
    316        /**
    317         * <p>Removes control characters (char &lt;= 32) from both
    318         * ends of this String returning <code>null</code> if the String is
    319         * empty ("") after the trim or if it is <code>null</code>.
    320         *
    321         * <p>The String is trimmed using {@link String#trim()}.
    322         * Trim removes start and end characters &lt;= 32.
    323         * To strip whitespace use {@link #stripToNull(String)}.</p>
    324         *
    325         * <pre>
    326         * StringUtils.trimToNull(null)          = null
    327         * StringUtils.trimToNull("")            = null
    328         * StringUtils.trimToNull("     ")       = null
    329         * StringUtils.trimToNull("abc")         = "abc"
    330         * StringUtils.trimToNull("    abc    ") = "abc"
    331         * </pre>
    332         *
    333         * @param str  the String to be trimmed, may be null
    334         * @return the trimmed String,
    335         *  <code>null</code> if only chars &lt;= 32, empty or null String input
    336         * @since 2.0
    337         */
    338        public static String trimToNull(String str) {
    339            String ts = trim(str);
    340            return isEmpty(ts) ? null : ts;
    341        }
    342
    343        /**
    344         * <p>Removes control characters (char &lt;= 32) from both
    345         * ends of this String returning an empty String ("") if the String
    346         * is empty ("") after the trim or if it is <code>null</code>.
    347         *
    348         * <p>The String is trimmed using {@link String#trim()}.
    349         * Trim removes start and end characters &lt;= 32.
    350         * To strip whitespace use {@link #stripToEmpty(String)}.</p>
    351         *
    352         * <pre>
    353         * StringUtils.trimToEmpty(null)          = ""
    354         * StringUtils.trimToEmpty("")            = ""
    355         * StringUtils.trimToEmpty("     ")       = ""
    356         * StringUtils.trimToEmpty("abc")         = "abc"
    357         * StringUtils.trimToEmpty("    abc    ") = "abc"
    358         * </pre>
    359         *
    360         * @param str  the String to be trimmed, may be null
    361         * @return the trimmed String, or an empty String if <code>null</code> input
    362         * @since 2.0
    363         */
    364        public static String trimToEmpty(String str) {
    365            return str == null ? EMPTY : str.trim();
    366        }
    367
    368        // Stripping
    369        //-----------------------------------------------------------------------
    370        /**
    371         * <p>Strips whitespace from the start and end of a String.</p>
    372         *
    373         * <p>This is similar to {@link #trim(String)} but removes whitespace.
    374         * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    375         *
    376         * <p>A <code>null</code> input String returns <code>null</code>.</p>
    377         *
    378         * <pre>
    379         * StringUtils.strip(null)     = null
    380         * StringUtils.strip("")       = ""
    381         * StringUtils.strip("   ")    = ""
    382         * StringUtils.strip("abc")    = "abc"
    383         * StringUtils.strip("  abc")  = "abc"
    384         * StringUtils.strip("abc  ")  = "abc"
    385         * StringUtils.strip(" abc ")  = "abc"
    386         * StringUtils.strip(" ab c ") = "ab c"
    387         * </pre>
    388         *
    389         * @param str  the String to remove whitespace from, may be null
    390         * @return the stripped String, <code>null</code> if null String input
    391         */
    392        public static String strip(String str) {
    393            return strip(str, null);
    394        }
    395
    396        /**
    397         * <p>Strips whitespace from the start and end of a String  returning
    398         * <code>null</code> if the String is empty ("") after the strip.</p>
    399         *
    400         * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.
    401         * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    402         *
    403         * <pre>
    404         * StringUtils.stripToNull(null)     = null
    405         * StringUtils.stripToNull("")       = null
    406         * StringUtils.stripToNull("   ")    = null
    407         * StringUtils.stripToNull("abc")    = "abc"
    408         * StringUtils.stripToNull("  abc")  = "abc"
    409         * StringUtils.stripToNull("abc  ")  = "abc"
    410         * StringUtils.stripToNull(" abc ")  = "abc"
    411         * StringUtils.stripToNull(" ab c ") = "ab c"
    412         * </pre>
    413         *
    414         * @param str  the String to be stripped, may be null
    415         * @return the stripped String,
    416         *  <code>null</code> if whitespace, empty or null String input
    417         * @since 2.0
    418         */
    419        public static String stripToNull(String str) {
    420            if (str == null) {
    421                return null;
    422            }
    423            str = strip(str, null);
    424            return str.length() == 0 ? null : str;
    425        }
    426
    427        /**
    428         * <p>Strips whitespace from the start and end of a String  returning
    429         * an empty String if <code>null</code> input.</p>
    430         *
    431         * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.
    432         * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    433         *
    434         * <pre>
    435         * StringUtils.stripToEmpty(null)     = ""
    436         * StringUtils.stripToEmpty("")       = ""
    437         * StringUtils.stripToEmpty("   ")    = ""
    438         * StringUtils.stripToEmpty("abc")    = "abc"
    439         * StringUtils.stripToEmpty("  abc")  = "abc"
    440         * StringUtils.stripToEmpty("abc  ")  = "abc"
    441         * StringUtils.stripToEmpty(" abc ")  = "abc"
    442         * StringUtils.stripToEmpty(" ab c ") = "ab c"
    443         * </pre>
    444         *
    445         * @param str  the String to be stripped, may be null
    446         * @return the trimmed String, or an empty String if <code>null</code> input
    447         * @since 2.0
    448         */
    449        public static String stripToEmpty(String str) {
    450            return str == null ? EMPTY : strip(str, null);
    451        }
    452
    453        /**
    454         * <p>Strips any of a set of characters from the start and end of a String.
    455         * This is similar to {@link String#trim()} but allows the characters
    456         * to be stripped to be controlled.</p>
    457         *
    458         * <p>A <code>null</code> input String returns <code>null</code>.
    459         * An empty string ("") input returns the empty string.</p>
    460         *
    461         * <p>If the stripChars String is <code>null</code>, whitespace is
    462         * stripped as defined by {@link Character#isWhitespace(char)}.
    463         * Alternatively use {@link #strip(String)}.</p>
    464         *
    465         * <pre>
    466         * StringUtils.strip(null, *)          = null
    467         * StringUtils.strip("", *)            = ""
    468         * StringUtils.strip("abc", null)      = "abc"
    469         * StringUtils.strip("  abc", null)    = "abc"
    470         * StringUtils.strip("abc  ", null)    = "abc"
    471         * StringUtils.strip(" abc ", null)    = "abc"
    472         * StringUtils.strip("  abcyx", "xyz") = "  abc"
    473         * </pre>
    474         *
    475         * @param str  the String to remove characters from, may be null
    476         * @param stripChars  the characters to remove, null treated as whitespace
    477         * @return the stripped String, <code>null</code> if null String input
    478         */
    479        public static String strip(String str, String stripChars) {
    480            if (isEmpty(str)) {
    481                return str;
    482            }
    483            str = stripStart(str, stripChars);
    484            return stripEnd(str, stripChars);
    485        }
    486
    487        /**
    488         * <p>Strips any of a set of characters from the start of a String.</p>
    489         *
    490         * <p>A <code>null</code> input String returns <code>null</code>.
    491         * An empty string ("") input returns the empty string.</p>
    492         *
    493         * <p>If the stripChars String is <code>null</code>, whitespace is
    494         * stripped as defined by {@link Character#isWhitespace(char)}.</p>
    495         *
    496         * <pre>
    497         * StringUtils.stripStart(null, *)          = null
    498         * StringUtils.stripStart("", *)            = ""
    499         * StringUtils.stripStart("abc", "")        = "abc"
    500         * StringUtils.stripStart("abc", null)      = "abc"
    501         * StringUtils.stripStart("  abc", null)    = "abc"
    502         * StringUtils.stripStart("abc  ", null)    = "abc  "
    503         * StringUtils.stripStart(" abc ", null)    = "abc "
    504         * StringUtils.stripStart("yxabc  ", "xyz") = "abc  "
    505         * </pre>
    506         *
    507         * @param str  the String to remove characters from, may be null
    508         * @param stripChars  the characters to remove, null treated as whitespace
    509         * @return the stripped String, <code>null</code> if null String input
    510         */
    511        public static String stripStart(String str, String stripChars) {
    512            int strLen;
    513            if (str == null || (strLen = str.length()) == 0) {
    514                return str;
    515            }
    516            int start = 0;
    517            if (stripChars == null) {
    518                while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {
    519                    start++;
    520                }
    521            } else if (stripChars.length() == 0) {
    522                return str;
    523            } else {
    524                while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND)) {
    525                    start++;
    526                }
    527            }
    528            return str.substring(start);
    529        }
    530
    531        /**
    532         * <p>Strips any of a set of characters from the end of a String.</p>
    533         *
    534         * <p>A <code>null</code> input String returns <code>null</code>.
    535         * An empty string ("") input returns the empty string.</p>
    536         *
    537         * <p>If the stripChars String is <code>null</code>, whitespace is
    538         * stripped as defined by {@link Character#isWhitespace(char)}.</p>
    539         *
    540         * <pre>
    541         * StringUtils.stripEnd(null, *)          = null
    542         * StringUtils.stripEnd("", *)            = ""
    543         * StringUtils.stripEnd("abc", "")        = "abc"
    544         * StringUtils.stripEnd("abc", null)      = "abc"
    545         * StringUtils.stripEnd("  abc", null)    = "  abc"
    546         * StringUtils.stripEnd("abc  ", null)    = "abc"
    547         * StringUtils.stripEnd(" abc ", null)    = " abc"
    548         * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
    549         * StringUtils.stripEnd("120.00", ".0")   = "12"
    550         * </pre>
    551         *
    552         * @param str  the String to remove characters from, may be null
    553         * @param stripChars  the set of characters to remove, null treated as whitespace
    554         * @return the stripped String, <code>null</code> if null String input
    555         */
    556        public static String stripEnd(String str, String stripChars) {
    557            int end;
    558            if (str == null || (end = str.length()) == 0) {
    559                return str;
    560            }
    561
    562            if (stripChars == null) {
    563                while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
    564                    end--;
    565                }
    566            } else if (stripChars.length() == 0) {
    567                return str;
    568            } else {
    569                while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND)) {
    570                    end--;
    571                }
    572            }
    573            return str.substring(0, end);
    574        }
    575
    576        // StripAll
    577        //-----------------------------------------------------------------------
    578        /**
    579         * <p>Strips whitespace from the start and end of every String in an array.
    580         * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    581         *
    582         * <p>A new array is returned each time, except for length zero.
    583         * A <code>null</code> array will return <code>null</code>.
    584         * An empty array will return itself.
    585         * A <code>null</code> array entry will be ignored.</p>
    586         *
    587         * <pre>
    588         * StringUtils.stripAll(null)             = null
    589         * StringUtils.stripAll([])               = []
    590         * StringUtils.stripAll(["abc", "  abc"]) = ["abc", "abc"]
    591         * StringUtils.stripAll(["abc  ", null])  = ["abc", null]
    592         * </pre>
    593         *
    594         * @param strs  the array to remove whitespace from, may be null
    595         * @return the stripped Strings, <code>null</code> if null array input
    596         */
    597        public static String[] stripAll(String[] strs) {
    598            return stripAll(strs, null);
    599        }
    600
    601        /**
    602         * <p>Strips any of a set of characters from the start and end of every
    603         * String in an array.</p>
    604         * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    605         *
    606         * <p>A new array is returned each time, except for length zero.
    607         * A <code>null</code> array will return <code>null</code>.
    608         * An empty array will return itself.
    609         * A <code>null</code> array entry will be ignored.
    610         * A <code>null</code> stripChars will strip whitespace as defined by
    611         * {@link Character#isWhitespace(char)}.</p>
    612         *
    613         * <pre>
    614         * StringUtils.stripAll(null, *)                = null
    615         * StringUtils.stripAll([], *)                  = []
    616         * StringUtils.stripAll(["abc", "  abc"], null) = ["abc", "abc"]
    617         * StringUtils.stripAll(["abc  ", null], null)  = ["abc", null]
    618         * StringUtils.stripAll(["abc  ", null], "yz")  = ["abc  ", null]
    619         * StringUtils.stripAll(["yabcz", null], "yz")  = ["abc", null]
    620         * </pre>
    621         *
    622         * @param strs  the array to remove characters from, may be null
    623         * @param stripChars  the characters to remove, null treated as whitespace
    624         * @return the stripped Strings, <code>null</code> if null array input
    625         */
    626        public static String[] stripAll(String[] strs, String stripChars) {
    627            int strsLen;
    628            if (strs == null || (strsLen = strs.length) == 0) {
    629                return strs;
    630            }
    631            String[] newArr = new String[strsLen];
    632            for (int i = 0; i < strsLen; i++) {
    633                newArr[i] = strip(strs[i], stripChars);
    634            }
    635            return newArr;
    636        }
    637
    638        // Equals
    639        //-----------------------------------------------------------------------
    640        /**
    641         * <p>Compares two Strings, returning <code>true</code> if they are equal.</p>
    642         *
    643         * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
    644         * references are considered to be equal. The comparison is case sensitive.</p>
    645         *
    646         * <pre>
    647         * StringUtils.equals(null, null)   = true
    648         * StringUtils.equals(null, "abc")  = false
    649         * StringUtils.equals("abc", null)  = false
    650         * StringUtils.equals("abc", "abc") = true
    651         * StringUtils.equals("abc", "ABC") = false
    652         * </pre>
    653         *
    654         * @see java.lang.String#equals(Object)
    655         * @param str1  the first String, may be null
    656         * @param str2  the second String, may be null
    657         * @return <code>true</code> if the Strings are equal, case sensitive, or
    658         *  both <code>null</code>
    659         */
    660        public static boolean equals(String str1, String str2) {
    661            return str1 == null ? str2 == null : str1.equals(str2);
    662        }
    663
    664        /**
    665         * <p>Compares two Strings, returning <code>true</code> if they are equal ignoring
    666         * the case.</p>
    667         *
    668         * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
    669         * references are considered equal. Comparison is case insensitive.</p>
    670         *
    671         * <pre>
    672         * StringUtils.equalsIgnoreCase(null, null)   = true
    673         * StringUtils.equalsIgnoreCase(null, "abc")  = false
    674         * StringUtils.equalsIgnoreCase("abc", null)  = false
    675         * StringUtils.equalsIgnoreCase("abc", "abc") = true
    676         * StringUtils.equalsIgnoreCase("abc", "ABC") = true
    677         * </pre>
    678         *
    679         * @see java.lang.String#equalsIgnoreCase(String)
    680         * @param str1  the first String, may be null
    681         * @param str2  the second String, may be null
    682         * @return <code>true</code> if the Strings are equal, case insensitive, or
    683         *  both <code>null</code>
    684         */
    685        public static boolean equalsIgnoreCase(String str1, String str2) {
    686            return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
    687        }
    688
    689        // IndexOf
    690        //-----------------------------------------------------------------------
    691        /**
    692         * <p>Finds the first index within a String, handling <code>null</code>.
    693         * This method uses {@link String#indexOf(int)}.</p>
    694         *
    695         * <p>A <code>null</code> or empty ("") String will return <code>INDEX_NOT_FOUND (-1)</code>.</p>
    696         *
    697         * <pre>
    698         * StringUtils.indexOf(null, *)         = -1
    699         * StringUtils.indexOf("", *)           = -1
    700         * StringUtils.indexOf("aabaabaa", 'a') = 0
    701         * StringUtils.indexOf("aabaabaa", 'b') = 2
    702         * </pre>
    703         *
    704         * @param str  the String to check, may be null
    705         * @param searchChar  the character to find
    706         * @return the first index of the search character,
    707         *  -1 if no match or <code>null</code> string input
    708         * @since 2.0
    709         */
    710        public static int indexOf(String str, char searchChar) {
    711            if (isEmpty(str)) {
    712                return INDEX_NOT_FOUND;
    713            }
    714            return str.indexOf(searchChar);
    715        }
    716
    717        /**
    718         * <p>Finds the first index within a String from a start position,
    719         * handling <code>null</code>.
    720         * This method uses {@link String#indexOf(int, int)}.</p>
    721         *
    722         * <p>A <code>null</code> or empty ("") String will return <code>(INDEX_NOT_FOUND) -1</code>.
    723         * A negative start position is treated as zero.
    724         * A start position greater than the string length returns <code>-1</code>.</p>
    725         *
    726         * <pre>
    727         * StringUtils.indexOf(null, *, *)          = -1
    728         * StringUtils.indexOf("", *, *)            = -1
    729         * StringUtils.indexOf("aabaabaa", 'b', 0)  = 2
    730         * StringUtils.indexOf("aabaabaa", 'b', 3)  = 5
    731         * StringUtils.indexOf("aabaabaa", 'b', 9)  = -1
    732         * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
    733         * </pre>
    734         *
    735         * @param str  the String to check, may be null
    736         * @param searchChar  the character to find
    737         * @param startPos  the start position, negative treated as zero
    738         * @return the first index of the search character,
    739         *  -1 if no match or <code>null</code> string input
    740         * @since 2.0
    741         */
    742        public static int indexOf(String str, char searchChar, int startPos) {
    743            if (isEmpty(str)) {
    744                return INDEX_NOT_FOUND;
    745            }
    746            return str.indexOf(searchChar, startPos);
    747        }
    748
    749        /**
    750         * <p>Finds the first index within a String, handling <code>null</code>.
    751         * This method uses {@link String#indexOf(String)}.</p>
    752         *
    753         * <p>A <code>null</code> String will return <code>-1</code>.</p>
    754         *
    755         * <pre>
    756         * StringUtils.indexOf(null, *)          = -1
    757         * StringUtils.indexOf(*, null)          = -1
    758         * StringUtils.indexOf("", "")           = 0
    759         * StringUtils.indexOf("", *)            = -1 (except when * = "")
    760         * StringUtils.indexOf("aabaabaa", "a")  = 0
    761         * StringUtils.indexOf("aabaabaa", "b")  = 2
    762         * StringUtils.indexOf("aabaabaa", "ab") = 1
    763         * StringUtils.indexOf("aabaabaa", "")   = 0
    764         * </pre>
    765         *
    766         * @param str  the String to check, may be null
    767         * @param searchStr  the String to find, may be null
    768         * @return the first index of the search String,
    769         *  -1 if no match or <code>null</code> string input
    770         * @since 2.0
    771         */
    772        public static int indexOf(String str, String searchStr) {
    773            if (str == null || searchStr == null) {
    774                return INDEX_NOT_FOUND;
    775            }
    776            return str.indexOf(searchStr);
    777        }
    778
    779        /**
    780         * <p>Finds the n-th index within a String, handling <code>null</code>.
    781         * This method uses {@link String#indexOf(String)}.</p>
    782         *
    783         * <p>A <code>null</code> String will return <code>-1</code>.</p>
    784         *
    785         * <pre>
    786         * StringUtils.ordinalIndexOf(null, *, *)          = -1
    787         * StringUtils.ordinalIndexOf(*, null, *)          = -1
    788         * StringUtils.ordinalIndexOf("", "", *)           = 0
    789         * StringUtils.ordinalIndexOf("aabaabaa", "a", 1)  = 0
    790         * StringUtils.ordinalIndexOf("aabaabaa", "a", 2)  = 1
    791         * StringUtils.ordinalIndexOf("aabaabaa", "b", 1)  = 2
    792         * StringUtils.ordinalIndexOf("aabaabaa", "b", 2)  = 5
    793         * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
    794         * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
    795         * StringUtils.ordinalIndexOf("aabaabaa", "", 1)   = 0
    796         * StringUtils.ordinalIndexOf("aabaabaa", "", 2)   = 0
    797         * </pre>
    798         *
    799         * <p>Note that 'head(String str, int n)' may be implemented as: </p>
    800         *
    801         * <pre>
    802         *   str.substring(0, lastOrdinalIndexOf(str, "\n", n))
    803         * </pre>
    804         *
    805         * @param str  the String to check, may be null
    806         * @param searchStr  the String to find, may be null
    807         * @param ordinal  the n-th <code>searchStr</code> to find
    808         * @return the n-th index of the search String,
    809         *  <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
    810         * @since 2.1
    811         */
    812        public static int ordinalIndexOf(String str, String searchStr, int ordinal) {
    813            return ordinalIndexOf(str, searchStr, ordinal, false);
    814        }
    815
    816        /**
    817         * <p>Finds the n-th index within a String, handling <code>null</code>.
    818         * This method uses {@link String#indexOf(String)}.</p>
    819         *
    820         * <p>A <code>null</code> String will return <code>-1</code>.</p>
    821         *
    822         * @param str  the String to check, may be null
    823         * @param searchStr  the String to find, may be null
    824         * @param ordinal  the n-th <code>searchStr</code> to find
    825         * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
    826         * @return the n-th index of the search String,
    827         *  <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
    828         */
    829        // Shared code between ordinalIndexOf(String,String,int) and lastOrdinalIndexOf(String,String,int)
    830        private static int ordinalIndexOf(String str, String searchStr, int ordinal, boolean lastIndex) {
    831            if (str == null || searchStr == null || ordinal <= 0) {
    832                return INDEX_NOT_FOUND;
    833            }
    834            if (searchStr.length() == 0) {
    835                return lastIndex ? str.length() : 0;
    836            }
    837            int found = 0;
    838            int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
    839            do {
    840                if(lastIndex) {
    841                    index = str.lastIndexOf(searchStr, index - 1);
    842                } else {
    843                    index = str.indexOf(searchStr, index + 1);
    844                }
    845                if (index < 0) {
    846                    return index;
    847                }
    848                found++;
    849            } while (found < ordinal);
    850            return index;
    851        }
    852
    853        /**
    854         * <p>Finds the first index within a String, handling <code>null</code>.
    855         * This method uses {@link String#indexOf(String, int)}.</p>
    856         *
    857         * <p>A <code>null</code> String will return <code>-1</code>.
    858         * A negative start position is treated as zero.
    859         * An empty ("") search String always matches.
    860         * A start position greater than the string length only matches
    861         * an empty search String.</p>
    862         *
    863         * <pre>
    864         * StringUtils.indexOf(null, *, *)          = -1
    865         * StringUtils.indexOf(*, null, *)          = -1
    866         * StringUtils.indexOf("", "", 0)           = 0
    867         * StringUtils.indexOf("", *, 0)            = -1 (except when * = "")
    868         * StringUtils.indexOf("aabaabaa", "a", 0)  = 0
    869         * StringUtils.indexOf("aabaabaa", "b", 0)  = 2
    870         * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
    871         * StringUtils.indexOf("aabaabaa", "b", 3)  = 5
    872         * StringUtils.indexOf("aabaabaa", "b", 9)  = -1
    873         * StringUtils.indexOf("aabaabaa", "b", -1) = 2
    874         * StringUtils.indexOf("aabaabaa", "", 2)   = 2
    875         * StringUtils.indexOf("abc", "", 9)        = 3
    876         * </pre>
    877         *
    878         * @param str  the String to check, may be null
    879         * @param searchStr  the String to find, may be null
    880         * @param startPos  the start position, negative treated as zero
    881         * @return the first index of the search String,
    882         *  -1 if no match or <code>null</code> string input
    883         * @since 2.0
    884         */
    885        public static int indexOf(String str, String searchStr, int startPos) {
    886            if (str == null || searchStr == null) {
    887                return INDEX_NOT_FOUND;
    888            }
    889            // JDK1.2/JDK1.3 have a bug, when startPos > str.length for "", hence
    890            if (searchStr.length() == 0 && startPos >= str.length()) {
    891                return str.length();
    892            }
    893            return str.indexOf(searchStr, startPos);
    894        }
    895
    896        /**
    897         * <p>Case in-sensitive find of the first index within a String.</p>
    898         *
    899         * <p>A <code>null</code> String will return <code>-1</code>.
    900         * A negative start position is treated as zero.
    901         * An empty ("") search String always matches.
    902         * A start position greater than the string length only matches
    903         * an empty search String.</p>
    904         *
    905         * <pre>
    906         * StringUtils.indexOfIgnoreCase(null, *)          = -1
    907         * StringUtils.indexOfIgnoreCase(*, null)          = -1
    908         * StringUtils.indexOfIgnoreCase("", "")           = 0
    909         * StringUtils.indexOfIgnoreCase("aabaabaa", "a")  = 0
    910         * StringUtils.indexOfIgnoreCase("aabaabaa", "b")  = 2
    911         * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
    912         * </pre>
    913         *
    914         * @param str  the String to check, may be null
    915         * @param searchStr  the String to find, may be null
    916         * @return the first index of the search String,
    917         *  -1 if no match or <code>null</code> string input
    918         * @since 2.5
    919         */
    920        public static int indexOfIgnoreCase(String str, String searchStr) {
    921            return indexOfIgnoreCase(str, searchStr, 0);
    922        }
    923
    924        /**
    925         * <p>Case in-sensitive find of the first index within a String
    926         * from the specified position.</p>
    927         *
    928         * <p>A <code>null</code> String will return <code>-1</code>.
    929         * A negative start position is treated as zero.
    930         * An empty ("") search String always matches.
    931         * A start position greater than the string length only matches
    932         * an empty search String.</p>
    933         *
    934         * <pre>
    935         * StringUtils.indexOfIgnoreCase(null, *, *)          = -1
    936         * StringUtils.indexOfIgnoreCase(*, null, *)          = -1
    937         * StringUtils.indexOfIgnoreCase("", "", 0)           = 0
    938         * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
    939         * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
    940         * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
    941         * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
    942         * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
    943         * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
    944         * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
    945         * StringUtils.indexOfIgnoreCase("abc", "", 9)        = 3
    946         * </pre>
    947         *
    948         * @param str  the String to check, may be null
    949         * @param searchStr  the String to find, may be null
    950         * @param startPos  the start position, negative treated as zero
    951         * @return the first index of the search String,
    952         *  -1 if no match or <code>null</code> string input
    953         * @since 2.5
    954         */
    955        public static int indexOfIgnoreCase(String str, String searchStr, int startPos) {
    956            if (str == null || searchStr == null) {
    957                return INDEX_NOT_FOUND;
    958            }
    959            if (startPos < 0) {
    960                startPos = 0;
    961            }
    962            int endLimit = (str.length() - searchStr.length()) + 1;
    963            if (startPos > endLimit) {
    964                return INDEX_NOT_FOUND;
    965            }
    966            if (searchStr.length() == 0) {
    967                return startPos;
    968            }
    969            for (int i = startPos; i < endLimit; i++) {
    970                if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {
    971                    return i;
    972                }
    973            }
    974            return INDEX_NOT_FOUND;
    975        }
    976
    977        // LastIndexOf
    978        //-----------------------------------------------------------------------
    979        /**
    980         * <p>Finds the last index within a String, handling <code>null</code>.
    981         * This method uses {@link String#lastIndexOf(int)}.</p>
    982         *
    983         * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.</p>
    984         *
    985         * <pre>
    986         * StringUtils.lastIndexOf(null, *)         = -1
    987         * StringUtils.lastIndexOf("", *)           = -1
    988         * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
    989         * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
    990         * </pre>
    991         *
    992         * @param str  the String to check, may be null
    993         * @param searchChar  the character to find
    994         * @return the last index of the search character,
    995         *  -1 if no match or <code>null</code> string input
    996         * @since 2.0
    997         */
    998        public static int lastIndexOf(String str, char searchChar) {
    999            if (isEmpty(str)) {
    1000                return INDEX_NOT_FOUND;
    1001            }
    1002            return str.lastIndexOf(searchChar);
    1003        }
    1004
    1005        /**
    1006         * <p>Finds the last index within a String from a start position,
    1007         * handling <code>null</code>.
    1008         * This method uses {@link String#lastIndexOf(int, int)}.</p>
    1009         *
    1010         * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.
    1011         * A negative start position returns <code>-1</code>.
    1012         * A start position greater than the string length searches the whole string.</p>
    1013         *
    1014         * <pre>
    1015         * StringUtils.lastIndexOf(null, *, *)          = -1
    1016         * StringUtils.lastIndexOf("", *,  *)           = -1
    1017         * StringUtils.lastIndexOf("aabaabaa", 'b', 8)  = 5
    1018         * StringUtils.lastIndexOf("aabaabaa", 'b', 4)  = 2
    1019         * StringUtils.lastIndexOf("aabaabaa", 'b', 0)  = -1
    1020         * StringUtils.lastIndexOf("aabaabaa", 'b', 9)  = 5
    1021         * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
    1022         * StringUtils.lastIndexOf("aabaabaa", 'a', 0)  = 0
    1023         * </pre>
    1024         *
    1025         * @param str  the String to check, may be null
    1026         * @param searchChar  the character to find
    1027         * @param startPos  the start position
    1028         * @return the last index of the search character,
    1029         *  -1 if no match or <code>null</code> string input
    1030         * @since 2.0
    1031         */
    1032        public static int lastIndexOf(String str, char searchChar, int startPos) {
    1033            if (isEmpty(str)) {
    1034                return INDEX_NOT_FOUND;
    1035            }
    1036            return str.lastIndexOf(searchChar, startPos);
    1037        }
    1038
    1039        /**
    1040         * <p>Finds the last index within a String, handling <code>null</code>.
    1041         * This method uses {@link String#lastIndexOf(String)}.</p>
    1042         *
    1043         * <p>A <code>null</code> String will return <code>-1</code>.</p>
    1044         *
    1045         * <pre>
    1046         * StringUtils.lastIndexOf(null, *)          = -1
    1047         * StringUtils.lastIndexOf(*, null)          = -1
    1048         * StringUtils.lastIndexOf("", "")           = 0
    1049         * StringUtils.lastIndexOf("aabaabaa", "a")  = 7
    1050         * StringUtils.lastIndexOf("aabaabaa", "b")  = 5
    1051         * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
    1052         * StringUtils.lastIndexOf("aabaabaa", "")   = 8
    1053         * </pre>
    1054         *
    1055         * @param str  the String to check, may be null
    1056         * @param searchStr  the String to find, may be null
    1057         * @return the last index of the search String,
    1058         *  -1 if no match or <code>null</code> string input
    1059         * @since 2.0
    1060         */
    1061        public static int lastIndexOf(String str, String searchStr) {
    1062            if (str == null || searchStr == null) {
    1063                return INDEX_NOT_FOUND;
    1064            }
    1065            return str.lastIndexOf(searchStr);
    1066        }
    1067
    1068        /**
    1069         * <p>Finds the n-th last index within a String, handling <code>null</code>.
    1070         * This method uses {@link String#lastIndexOf(String)}.</p>
    1071         *
    1072         * <p>A <code>null</code> String will return <code>-1</code>.</p>
    1073         *
    1074         * <pre>
    1075         * StringUtils.lastOrdinalIndexOf(null, *, *)          = -1
    1076         * StringUtils.lastOrdinalIndexOf(*, null, *)          = -1
    1077         * StringUtils.lastOrdinalIndexOf("", "", *)           = 0
    1078         * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1)  = 7
    1079         * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2)  = 6
    1080         * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1)  = 5
    1081         * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2)  = 2
    1082         * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
    1083         * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
    1084         * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1)   = 8
    1085         * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2)   = 8
    1086         * </pre>
    1087         *
    1088         * <p>Note that 'tail(String str, int n)' may be implemented as: </p>
    1089         *
    1090         * <pre>
    1091         *   str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
    1092         * </pre>
    1093         *
    1094         * @param str  the String to check, may be null
    1095         * @param searchStr  the String to find, may be null
    1096         * @param ordinal  the n-th last <code>searchStr</code> to find
    1097         * @return the n-th last index of the search String,
    1098         *  <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
    1099         * @since 2.5
    1100         */
    1101        public static int lastOrdinalIndexOf(String str, String searchStr, int ordinal) {
    1102            return ordinalIndexOf(str, searchStr, ordinal, true);
    1103        }
    1104
    1105        /**
    1106         * <p>Finds the first index within a String, handling <code>null</code>.
    1107         * This method uses {@link String#lastIndexOf(String, int)}.</p>
    1108         *
    1109         * <p>A <code>null</code> String will return <code>-1</code>.
    1110         * A negative start position returns <code>-1</code>.
    1111         * An empty ("") search String always matches unless the start position is negative.
    1112         * A start position greater than the string length searches the whole string.</p>
    1113         *
    1114         * <pre>
    1115         * StringUtils.lastIndexOf(null, *, *)          = -1
    1116         * StringUtils.lastIndexOf(*, null, *)          = -1
    1117         * StringUtils.lastIndexOf("aabaabaa", "a", 8)  = 7
    1118         * StringUtils.lastIndexOf("aabaabaa", "b", 8)  = 5
    1119         * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
    1120         * StringUtils.lastIndexOf("aabaabaa", "b", 9)  = 5
    1121         * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
    1122         * StringUtils.lastIndexOf("aabaabaa", "a", 0)  = 0
    1123         * StringUtils.lastIndexOf("aabaabaa", "b", 0)  = -1
    1124         * </pre>
    1125         *
    1126         * @param str  the String to check, may be null
    1127         * @param searchStr  the String to find, may be null
    1128         * @param startPos  the start position, negative treated as zero
    1129         * @return the first index of the search String,
    1130         *  -1 if no match or <code>null</code> string input
    1131         * @since 2.0
    1132         */
    1133        public static int lastIndexOf(String str, String searchStr, int startPos) {
    1134            if (str == null || searchStr == null) {
    1135                return INDEX_NOT_FOUND;
    1136            }
    1137            return str.lastIndexOf(searchStr, startPos);
    1138        }
    1139
    1140        /**
    1141         * <p>Case in-sensitive find of the last index within a String.</p>
    1142         *
    1143         * <p>A <code>null</code> String will return <code>-1</code>.
    1144         * A negative start position returns <code>-1</code>.
    1145         * An empty ("") search String always matches unless the start position is negative.
    1146         * A start position greater than the string length searches the whole string.</p>
    1147         *
    1148         * <pre>
    1149         * StringUtils.lastIndexOfIgnoreCase(null, *)          = -1
    1150         * StringUtils.lastIndexOfIgnoreCase(*, null)          = -1
    1151         * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A")  = 7
    1152         * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B")  = 5
    1153         * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
    1154         * </pre>
    1155         *
    1156         * @param str  the String to check, may be null
    1157         * @param searchStr  the String to find, may be null
    1158         * @return the first index of the search String,
    1159         *  -1 if no match or <code>null</code> string input
    1160         * @since 2.5
    1161         */
    1162        public static int lastIndexOfIgnoreCase(String str, String searchStr) {
    1163            if (str == null || searchStr == null) {
    1164                return INDEX_NOT_FOUND;
    1165            }
    1166            return lastIndexOfIgnoreCase(str, searchStr, str.length());
    1167        }
    1168
    1169        /**
    1170         * <p>Case in-sensitive find of the last index within a String
    1171         * from the specified position.</p>
    1172         *
    1173         * <p>A <code>null</code> String will return <code>-1</code>.
    1174         * A negative start position returns <code>-1</code>.
    1175         * An empty ("") search String always matches unless the start position is negative.
    1176         * A start position greater than the string length searches the whole string.</p>
    1177         *
    1178         * <pre>
    1179         * StringUtils.lastIndexOfIgnoreCase(null, *, *)          = -1
    1180         * StringUtils.lastIndexOfIgnoreCase(*, null, *)          = -1
    1181         * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8)  = 7
    1182         * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8)  = 5
    1183         * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
    1184         * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9)  = 5
    1185         * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
    1186         * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0)  = 0
    1187         * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0)  = -1
    1188         * </pre>
    1189         *
    1190         * @param str  the String to check, may be null
    1191         * @param searchStr  the String to find, may be null
    1192         * @param startPos  the start position
    1193         * @return the first index of the search String,
    1194         *  -1 if no match or <code>null</code> string input
    1195         * @since 2.5
    1196         */
    1197        public static int lastIndexOfIgnoreCase(String str, String searchStr, int startPos) {
    1198            if (str == null || searchStr == null) {
    1199                return INDEX_NOT_FOUND;
    1200            }
    1201            if (startPos > (str.length() - searchStr.length())) {
    1202                startPos = str.length() - searchStr.length();
    1203            }
    1204            if (startPos < 0) {
    1205                return INDEX_NOT_FOUND;
    1206            }
    1207            if (searchStr.length() == 0) {
    1208                return startPos;
    1209            }
    1210
    1211            for (int i = startPos; i >= 0; i--) {
    1212                if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {
    1213                    return i;
    1214                }
    1215            }
    1216            return INDEX_NOT_FOUND;
    1217        }
    1218
    1219        // Contains
    1220        //-----------------------------------------------------------------------
    1221        /**
    1222         * <p>Checks if String contains a search character, handling <code>null</code>.
    1223         * This method uses {@link String#indexOf(int)}.</p>
    1224         *
    1225         * <p>A <code>null</code> or empty ("") String will return <code>false</code>.</p>
    1226         *
    1227         * <pre>
    1228         * StringUtils.contains(null, *)    = false
    1229         * StringUtils.contains("", *)      = false
    1230         * StringUtils.contains("abc", 'a') = true
    1231         * StringUtils.contains("abc", 'z') = false
    1232         * </pre>
    1233         *
    1234         * @param str  the String to check, may be null
    1235         * @param searchChar  the character to find
    1236         * @return true if the String contains the search character,
    1237         *  false if not or <code>null</code> string input
    1238         * @since 2.0
    1239         */
    1240        public static boolean contains(String str, char searchChar) {
    1241            if (isEmpty(str)) {
    1242                return false;
    1243            }
    1244            return str.indexOf(searchChar) >= 0;
    1245        }
    1246
    1247        /**
    1248         * <p>Checks if String contains a search String, handling <code>null</code>.
    1249         * This method uses {@link String#indexOf(String)}.</p>
    1250         *
    1251         * <p>A <code>null</code> String will return <code>false</code>.</p>
    1252         *
    1253         * <pre>
    1254         * StringUtils.contains(null, *)     = false
    1255         * StringUtils.contains(*, null)     = false
    1256         * StringUtils.contains("", "")      = true
    1257         * StringUtils.contains("abc", "")   = true
    1258         * StringUtils.contains("abc", "a")  = true
    1259         * StringUtils.contains("abc", "z")  = false
    1260         * </pre>
    1261         *
    1262         * @param str  the String to check, may be null
    1263         * @param searchStr  the String to find, may be null
    1264         * @return true if the String contains the search String,
    1265         *  false if not or <code>null</code> string input
    1266         * @since 2.0
    1267         */
    1268        public static boolean contains(String str, String searchStr) {
    1269            if (str == null || searchStr == null) {
    1270                return false;
    1271            }
    1272            return str.indexOf(searchStr) >= 0;
    1273        }
    1274
    1275        /**
    1276         * <p>Checks if String contains a search String irrespective of case,
    1277         * handling <code>null</code>. Case-insensitivity is defined as by
    1278         * {@link String#equalsIgnoreCase(String)}.
    1279         *
    1280         * <p>A <code>null</code> String will return <code>false</code>.</p>
    1281         *
    1282         * <pre>
    1283         * StringUtils.contains(null, *) = false
    1284         * StringUtils.contains(*, null) = false
    1285         * StringUtils.contains("", "") = true
    1286         * StringUtils.contains("abc", "") = true
    1287         * StringUtils.contains("abc", "a") = true
    1288         * StringUtils.contains("abc", "z") = false
    1289         * StringUtils.contains("abc", "A") = true
    1290         * StringUtils.contains("abc", "Z") = false
    1291         * </pre>
    1292         *
    1293         * @param str  the String to check, may be null
    1294         * @param searchStr  the String to find, may be null
    1295         * @return true if the String contains the search String irrespective of
    1296         * case or false if not or <code>null</code> string input
    1297         */
    1298        public static boolean containsIgnoreCase(String str, String searchStr) {
    1299            if (str == null || searchStr == null) {
    1300                return false;
    1301            }
    1302            int len = searchStr.length();
    1303            int max = str.length() - len;
    1304            for (int i = 0; i <= max; i++) {
    1305                if (str.regionMatches(true, i, searchStr, 0, len)) {
    1306                    return true;
    1307                }
    1308            }
    1309            return false;
    1310        }
    1311
    1312        // IndexOfAny chars
    1313        //-----------------------------------------------------------------------
    1314        /**
    1315         * <p>Search a String to find the first index of any
    1316         * character in the given set of characters.</p>
    1317         *
    1318         * <p>A <code>null</code> String will return <code>-1</code>.
    1319         * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
    1320         *
    1321         * <pre>
    1322         * StringUtils.indexOfAny(null, *)                = -1
    1323         * StringUtils.indexOfAny("", *)                  = -1
    1324         * StringUtils.indexOfAny(*, null)                = -1
    1325         * StringUtils.indexOfAny(*, [])                  = -1
    1326         * StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0
    1327         * StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3
    1328         * StringUtils.indexOfAny("aba", ['z'])           = -1
    1329         * </pre>
    1330         *
    1331         * @param str  the String to check, may be null
    1332         * @param searchChars  the chars to search for, may be null
    1333         * @return the index of any of the chars, -1 if no match or null input
    1334         * @since 2.0
    1335         */
    1336        public static int indexOfAny(String str, char[] searchChars) {
    1337            if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
    1338                return INDEX_NOT_FOUND;
    1339            }
    1340            int csLen = str.length();
    1341            int csLast = csLen - 1;
    1342            int searchLen = searchChars.length;
    1343            int searchLast = searchLen - 1;
    1344            for (int i = 0; i < csLen; i++) {
    1345                char ch = str.charAt(i);
    1346                for (int j = 0; j < searchLen; j++) {
    1347                    if (searchChars[j] == ch) {
    1348                        if (i < csLast && j < searchLast && CharUtils.isHighSurrogate(ch)) {
    1349                            // ch is a supplementary character
    1350                            if (searchChars[j + 1] == str.charAt(i + 1)) {
    1351                                return i;
    1352                            }
    1353                        } else {
    1354                            return i;
    1355                        }
    1356                    }
    1357                }
    1358            }
    1359            return INDEX_NOT_FOUND;
    1360        }
    1361
    1362        /**
    1363         * <p>Search a String to find the first index of any
    1364         * character in the given set of characters.</p>
    1365         *
    1366         * <p>A <code>null</code> String will return <code>-1</code>.
    1367         * A <code>null</code> search string will return <code>-1</code>.</p>
    1368         *
    1369         * <pre>
    1370         * StringUtils.indexOfAny(null, *)            = -1
    1371         * StringUtils.indexOfAny("", *)              = -1
    1372         * StringUtils.indexOfAny(*, null)            = -1
    1373         * StringUtils.indexOfAny(*, "")              = -1
    1374         * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
    1375         * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
    1376         * StringUtils.indexOfAny("aba","z")          = -1
    1377         * </pre>
    1378         *
    1379         * @param str  the String to check, may be null
    1380         * @param searchChars  the chars to search for, may be null
    1381         * @return the index of any of the chars, -1 if no match or null input
    1382         * @since 2.0
    1383         */
    1384        public static int indexOfAny(String str, String searchChars) {
    1385            if (isEmpty(str) || isEmpty(searchChars)) {
    1386                return INDEX_NOT_FOUND;
    1387            }
    1388            return indexOfAny(str, searchChars.toCharArray());
    1389        }
    1390
    1391        // ContainsAny
    1392        //-----------------------------------------------------------------------
    1393        /**
    1394         * <p>Checks if the String contains any character in the given
    1395         * set of characters.</p>
    1396         *
    1397         * <p>A <code>null</code> String will return <code>false</code>.
    1398         * A <code>null</code> or zero length search array will return <code>false</code>.</p>
    1399         *
    1400         * <pre>
    1401         * StringUtils.containsAny(null, *)                = false
    1402         * StringUtils.containsAny("", *)                  = false
    1403         * StringUtils.containsAny(*, null)                = false
    1404         * StringUtils.containsAny(*, [])                  = false
    1405         * StringUtils.containsAny("zzabyycdxx",['z','a']) = true
    1406         * StringUtils.containsAny("zzabyycdxx",['b','y']) = true
    1407         * StringUtils.containsAny("aba", ['z'])           = false
    1408         * </pre>
    1409         *
    1410         * @param str  the String to check, may be null
    1411         * @param searchChars  the chars to search for, may be null
    1412         * @return the <code>true</code> if any of the chars are found,
    1413         * <code>false</code> if no match or null input
    1414         * @since 2.4
    1415         */
    1416        public static boolean containsAny(String str, char[] searchChars) {
    1417            if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
    1418                return false;
    1419            }
    1420            int csLength = str.length();
    1421            int searchLength = searchChars.length;
    1422            int csLast = csLength - 1;
    1423            int searchLast = searchLength - 1;
    1424            for (int i = 0; i < csLength; i++) {
    1425                char ch = str.charAt(i);
    1426                for (int j = 0; j < searchLength; j++) {
    1427                    if (searchChars[j] == ch) {
    1428                        if (CharUtils.isHighSurrogate(ch)) {
    1429                            if (j == searchLast) {
    1430                                // missing low surrogate, fine, like String.indexOf(String)
    1431                                return true;
    1432                            }
    1433                            if (i < csLast && searchChars[j + 1] == str.charAt(i + 1)) {
    1434                                return true;
    1435                            }
    1436                        } else {
    1437                            // ch is in the Basic Multilingual Plane
    1438                            return true;
    1439                        }
    1440                    }
    1441                }
    1442            }
    1443            return false;
    1444        }
    1445
    1446        /**
    1447         * <p>
    1448         * Checks if the String contains any character in the given set of characters.
    1449         * </p>
    1450         *
    1451         * <p>
    1452         * A <code>null</code> String will return <code>false</code>. A <code>null</code> search string will return
    1453         * <code>false</code>.
    1454         * </p>
    1455         *
    1456         * <pre>
    1457         * StringUtils.containsAny(null, *)            = false
    1458         * StringUtils.containsAny("", *)              = false
    1459         * StringUtils.containsAny(*, null)            = false
    1460         * StringUtils.containsAny(*, "")              = false
    1461         * StringUtils.containsAny("zzabyycdxx", "za") = true
    1462         * StringUtils.containsAny("zzabyycdxx", "by") = true
    1463         * StringUtils.containsAny("aba","z")          = false
    1464         * </pre>
    1465         *
    1466         * @param str
    1467         *            the String to check, may be null
    1468         * @param searchChars
    1469         *            the chars to search for, may be null
    1470         * @return the <code>true</code> if any of the chars are found, <code>false</code> if no match or null input
    1471         * @since 2.4
    1472         */
    1473        public static boolean containsAny(String str, String searchChars) {
    1474            if (searchChars == null) {
    1475                return false;
    1476            }
    1477            return containsAny(str, searchChars.toCharArray());
    1478        }
    1479
    1480        // IndexOfAnyBut chars
    1481        //-----------------------------------------------------------------------
    1482        /**
    1483         * <p>Search a String to find the first index of any
    1484         * character not in the given set of characters.</p>
    1485         *
    1486         * <p>A <code>null</code> String will return <code>-1</code>.
    1487         * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
    1488         *
    1489         * <pre>
    1490         * StringUtils.indexOfAnyBut(null, *)                              = -1
    1491         * StringUtils.indexOfAnyBut("", *)                                = -1
    1492         * StringUtils.indexOfAnyBut(*, null)                              = -1
    1493         * StringUtils.indexOfAnyBut(*, [])                                = -1
    1494         * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
    1495         * StringUtils.indexOfAnyBut("aba", new char[] {'z'} )             = 0
    1496         * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} )        = -1
    1497         * </pre>
    1498         *
    1499         * @param str  the String to check, may be null
    1500         * @param searchChars  the chars to search for, may be null
    1501         * @return the index of any of the chars, -1 if no match or null input
    1502         * @since 2.0
    1503         */
    1504        public static int indexOfAnyBut(String str, char[] searchChars) {
    1505            if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
    1506                return INDEX_NOT_FOUND;
    1507            }
    1508            int csLen = str.length();
    1509            int csLast = csLen - 1;
    1510            int searchLen = searchChars.length;
    1511            int searchLast = searchLen - 1;
    1512            outer:
    1513            for (int i = 0; i < csLen; i++) {
    1514                char ch = str.charAt(i);
    1515                for (int j = 0; j < searchLen; j++) {
    1516                    if (searchChars[j] == ch) {
    1517                        if (i < csLast && j < searchLast && CharUtils.isHighSurrogate(ch)) {
    1518                            if (searchChars[j + 1] == str.charAt(i + 1)) {
    1519                                continue outer;
    1520                            }
    1521                        } else {
    1522                            continue outer;
    1523                        }
    1524                    }
    1525                }
    1526                return i;
    1527            }
    1528            return INDEX_NOT_FOUND;
    1529        }
    1530
    1531        /**
    1532         * <p>Search a String to find the first index of any
    1533         * character not in the given set of characters.</p>
    1534         *
    1535         * <p>A <code>null</code> String will return <code>-1</code>.
    1536         * A <code>null</code> or empty search string will return <code>-1</code>.</p>
    1537         *
    1538         * <pre>
    1539         * StringUtils.indexOfAnyBut(null, *)            = -1
    1540         * StringUtils.indexOfAnyBut("", *)              = -1
    1541         * StringUtils.indexOfAnyBut(*, null)            = -1
    1542         * StringUtils.indexOfAnyBut(*, "")              = -1
    1543         * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
    1544         * StringUtils.indexOfAnyBut("zzabyycdxx", "")   = -1
    1545         * StringUtils.indexOfAnyBut("aba","ab")         = -1
    1546         * </pre>
    1547         *
    1548         * @param str  the String to check, may be null
    1549         * @param searchChars  the chars to search for, may be null
    1550         * @return the index of any of the chars, -1 if no match or null input
    1551         * @since 2.0
    1552         */
    1553        public static int indexOfAnyBut(String str, String searchChars) {
    1554            if (isEmpty(str) || isEmpty(searchChars)) {
    1555                return INDEX_NOT_FOUND;
    1556            }
    1557            int strLen = str.length();
    1558            for (int i = 0; i < strLen; i++) {
    1559                char ch = str.charAt(i);
    1560                boolean chFound = searchChars.indexOf(ch) >= 0;
    1561                if (i + 1 < strLen && CharUtils.isHighSurrogate(ch)) {
    1562                    char ch2 = str.charAt(i + 1);
    1563                    if (chFound && searchChars.indexOf(ch2) < 0) {
    1564                        return i;
    1565                    }
    1566                } else {
    1567                    if (!chFound) {
    1568                        return i;
    1569                    }
    1570                }
    1571            }
    1572            return INDEX_NOT_FOUND;
    1573        }
    1574
    1575        // ContainsOnly
    1576        //-----------------------------------------------------------------------
    1577        /**
    1578         * <p>Checks if the String contains only certain characters.</p>
    1579         *
    1580         * <p>A <code>null</code> String will return <code>false</code>.
    1581         * A <code>null</code> valid character array will return <code>false</code>.
    1582         * An empty String (length()=0) always returns <code>true</code>.</p>
    1583         *
    1584         * <pre>
    1585         * StringUtils.containsOnly(null, *)       = false
    1586         * StringUtils.containsOnly(*, null)       = false
    1587         * StringUtils.containsOnly("", *)         = true
    1588         * StringUtils.containsOnly("ab", '')      = false
    1589         * StringUtils.containsOnly("abab", 'abc') = true
    1590         * StringUtils.containsOnly("ab1", 'abc')  = false
    1591         * StringUtils.containsOnly("abz", 'abc')  = false
    1592         * </pre>
    1593         *
    1594         * @param str  the String to check, may be null
    1595         * @param valid  an array of valid chars, may be null
    1596         * @return true if it only contains valid chars and is non-null
    1597         */
    1598        public static boolean containsOnly(String str, char[] valid) {
    1599            // All these pre-checks are to maintain API with an older version
    1600            if ((valid == null) || (str == null)) {
    1601                return false;
    1602            }
    1603            if (str.length() == 0) {
    1604                return true;
    1605            }
    1606            if (valid.length == 0) {
    1607                return false;
    1608            }
    1609            return indexOfAnyBut(str, valid) == INDEX_NOT_FOUND;
    1610        }
    1611
    1612        /**
    1613         * <p>Checks if the String contains only certain characters.</p>
    1614         *
    1615         * <p>A <code>null</code> String will return <code>false</code>.
    1616         * A <code>null</code> valid character String will return <code>false</code>.
    1617         * An empty String (length()=0) always returns <code>true</code>.</p>
    1618         *
    1619         * <pre>
    1620         * StringUtils.containsOnly(null, *)       = false
    1621         * StringUtils.containsOnly(*, null)       = false
    1622         * StringUtils.containsOnly("", *)         = true
    1623         * StringUtils.containsOnly("ab", "")      = false
    1624         * StringUtils.containsOnly("abab", "abc") = true
    1625         * StringUtils.containsOnly("ab1", "abc")  = false
    1626         * StringUtils.containsOnly("abz", "abc")  = false
    1627         * </pre>
    1628         *
    1629         * @param str  the String to check, may be null
    1630         * @param validChars  a String of valid chars, may be null
    1631         * @return true if it only contains valid chars and is non-null
    1632         * @since 2.0
    1633         */
    1634        public static boolean containsOnly(String str, String validChars) {
    1635            if (str == null || validChars == null) {
    1636                return false;
    1637            }
    1638            return containsOnly(str, validChars.toCharArray());
    1639        }
    1640
    1641        // ContainsNone
    1642        //-----------------------------------------------------------------------
    1643        /**
    1644         * <p>Checks that the String does not contain certain characters.</p>
    1645         *
    1646         * <p>A <code>null</code> String will return <code>true</code>.
    1647         * A <code>null</code> invalid character array will return <code>true</code>.
    1648         * An empty String (length()=0) always returns true.</p>
    1649         *
    1650         * <pre>
    1651         * StringUtils.containsNone(null, *)       = true
    1652         * StringUtils.containsNone(*, null)       = true
    1653         * StringUtils.containsNone("", *)         = true
    1654         * StringUtils.containsNone("ab", '')      = true
    1655         * StringUtils.containsNone("abab", 'xyz') = true
    1656         * StringUtils.containsNone("ab1", 'xyz')  = true
    1657         * StringUtils.containsNone("abz", 'xyz')  = false
    1658         * </pre>
    1659         *
    1660         * @param str  the String to check, may be null
    1661         * @param searchChars  an array of invalid chars, may be null
    1662         * @return true if it contains none of the invalid chars, or is null
    1663         * @since 2.0
    1664         */
    1665        public static boolean containsNone(String str, char[] searchChars) {
    1666            if (str == null || searchChars == null) {
    1667                return true;
    1668            }
    1669            int csLen = str.length();
    1670            int csLast = csLen - 1;
    1671            int searchLen = searchChars.length;
    1672            int searchLast = searchLen - 1;
    1673            for (int i = 0; i < csLen; i++) {
    1674                char ch = str.charAt(i);
    1675                for (int j = 0; j < searchLen; j++) {
    1676                    if (searchChars[j] == ch) {
    1677                        if (CharUtils.isHighSurrogate(ch)) {
    1678                            if (j == searchLast) {
    1679                                // missing low surrogate, fine, like String.indexOf(String)
    1680                                return false;
    1681                            }
    1682                            if (i < csLast && searchChars[j + 1] == str.charAt(i + 1)) {
    1683                                return false;
    1684                            }
    1685                        } else {
    1686                            // ch is in the Basic Multilingual Plane
    1687                            return false;
    1688                        }
    1689                    }
    1690                }
    1691            }
    1692            return true;
    1693        }
    1694
    1695        /**
    1696         * <p>Checks that the String does not contain certain characters.</p>
    1697         *
    1698         * <p>A <code>null</code> String will return <code>true</code>.
    1699         * A <code>null</code> invalid character array will return <code>true</code>.
    1700         * An empty String ("") always returns true.</p>
    1701         *
    1702         * <pre>
    1703         * StringUtils.containsNone(null, *)       = true
    1704         * StringUtils.containsNone(*, null)       = true
    1705         * StringUtils.containsNone("", *)         = true
    1706         * StringUtils.containsNone("ab", "")      = true
    1707         * StringUtils.containsNone("abab", "xyz") = true
    1708         * StringUtils.containsNone("ab1", "xyz")  = true
    1709         * StringUtils.containsNone("abz", "xyz")  = false
    1710         * </pre>
    1711         *
    1712         * @param str  the String to check, may be null
    1713         * @param invalidChars  a String of invalid chars, may be null
    1714         * @return true if it contains none of the invalid chars, or is null
    1715         * @since 2.0
    1716         */
    1717        public static boolean containsNone(String str, String invalidChars) {
    1718            if (str == null || invalidChars == null) {
    1719                return true;
    1720            }
    1721            return containsNone(str, invalidChars.toCharArray());
    1722        }
    1723
    1724        // IndexOfAny strings
    1725        //-----------------------------------------------------------------------
    1726        /**
    1727         * <p>Find the first index of any of a set of potential substrings.</p>
    1728         *
    1729         * <p>A <code>null</code> String will return <code>-1</code>.
    1730         * A <code>null</code> or zero length search array will return <code>-1</code>.
    1731         * A <code>null</code> search array entry will be ignored, but a search
    1732         * array containing "" will return <code>0</code> if <code>str</code> is not
    1733         * null. This method uses {@link String#indexOf(String)}.</p>
    1734         *
    1735         * <pre>
    1736         * StringUtils.indexOfAny(null, *)                     = -1
    1737         * StringUtils.indexOfAny(*, null)                     = -1
    1738         * StringUtils.indexOfAny(*, [])                       = -1
    1739         * StringUtils.indexOfAny("zzabyycdxx", ["ab","cd"])   = 2
    1740         * StringUtils.indexOfAny("zzabyycdxx", ["cd","ab"])   = 2
    1741         * StringUtils.indexOfAny("zzabyycdxx", ["mn","op"])   = -1
    1742         * StringUtils.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1
    1743         * StringUtils.indexOfAny("zzabyycdxx", [""])          = 0
    1744         * StringUtils.indexOfAny("", [""])                    = 0
    1745         * StringUtils.indexOfAny("", ["a"])                   = -1
    1746         * </pre>
    1747         *
    1748         * @param str  the String to check, may be null
    1749         * @param searchStrs  the Strings to search for, may be null
    1750         * @return the first index of any of the searchStrs in str, -1 if no match
    1751         */
    1752        public static int indexOfAny(String str, String[] searchStrs) {
    1753            if ((str == null) || (searchStrs == null)) {
    1754                return INDEX_NOT_FOUND;
    1755            }
    1756            int sz = searchStrs.length;
    1757
    1758            // String's can't have a MAX_VALUEth index.
    1759            int ret = Integer.MAX_VALUE;
    1760
    1761            int tmp = 0;
    1762            for (int i = 0; i < sz; i++) {
    1763                String search = searchStrs[i];
    1764                if (search == null) {
    1765                    continue;
    1766                }
    1767                tmp = str.indexOf(search);
    1768                if (tmp == INDEX_NOT_FOUND) {
    1769                    continue;
    1770                }
    1771
    1772                if (tmp < ret) {
    1773                    ret = tmp;
    1774                }
    1775            }
    1776
    1777            return (ret == Integer.MAX_VALUE) ? INDEX_NOT_FOUND : ret;
    1778        }
    1779
    1780        /**
    1781         * <p>Find the latest index of any of a set of potential substrings.</p>
    1782         *
    1783         * <p>A <code>null</code> String will return <code>-1</code>.
    1784         * A <code>null</code> search array will return <code>-1</code>.
    1785         * A <code>null</code> or zero length search array entry will be ignored,
    1786         * but a search array containing "" will return the length of <code>str</code>
    1787         * if <code>str</code> is not null. This method uses {@link String#indexOf(String)}</p>
    1788         *
    1789         * <pre>
    1790         * StringUtils.lastIndexOfAny(null, *)                   = -1
    1791         * StringUtils.lastIndexOfAny(*, null)                   = -1
    1792         * StringUtils.lastIndexOfAny(*, [])                     = -1
    1793         * StringUtils.lastIndexOfAny(*, [null])                 = -1
    1794         * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6
    1795         * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6
    1796         * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
    1797         * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
    1798         * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn",""])   = 10
    1799         * </pre>
    1800         *
    1801         * @param str  the String to check, may be null
    1802         * @param searchStrs  the Strings to search for, may be null
    1803         * @return the last index of any of the Strings, -1 if no match
    1804         */
    1805        public static int lastIndexOfAny(String str, String[] searchStrs) {
    1806            if ((str == null) || (searchStrs == null)) {
    1807                return INDEX_NOT_FOUND;
    1808            }
    1809            int sz = searchStrs.length;
    1810            int ret = INDEX_NOT_FOUND;
    1811            int tmp = 0;
    1812            for (int i = 0; i < sz; i++) {
    1813                String search = searchStrs[i];
    1814                if (search == null) {
    1815                    continue;
    1816                }
    1817                tmp = str.lastIndexOf(search);
    1818                if (tmp > ret) {
    1819                    ret = tmp;
    1820                }
    1821            }
    1822            return ret;
    1823        }
    1824
    1825        // Substring
    1826        //-----------------------------------------------------------------------
    1827        /**
    1828         * <p>Gets a substring from the specified String avoiding exceptions.</p>
    1829         *
    1830         * <p>A negative start position can be used to start <code>n</code>
    1831         * characters from the end of the String.</p>
    1832         *
    1833         * <p>A <code>null</code> String will return <code>null</code>.
    1834         * An empty ("") String will return "".</p>
    1835         *
    1836         * <pre>
    1837         * StringUtils.substring(null, *)   = null
    1838         * StringUtils.substring("", *)     = ""
    1839         * StringUtils.substring("abc", 0)  = "abc"
    1840         * StringUtils.substring("abc", 2)  = "c"
    1841         * StringUtils.substring("abc", 4)  = ""
    1842         * StringUtils.substring("abc", -2) = "bc"
    1843         * StringUtils.substring("abc", -4) = "abc"
    1844         * </pre>
    1845         *
    1846         * @param str  the String to get the substring from, may be null
    1847         * @param start  the position to start from, negative means
    1848         *  count back from the end of the String by this many characters
    1849         * @return substring from start position, <code>null</code> if null String input
    1850         */
    1851        public static String substring(String str, int start) {
    1852            if (str == null) {
    1853                return null;
    1854            }
    1855
    1856            // handle negatives, which means last n characters
    1857            if (start < 0) {
    1858                start = str.length() + start; // remember start is negative
    1859            }
    1860
    1861            if (start < 0) {
    1862                start = 0;
    1863            }
    1864            if (start > str.length()) {
    1865                return EMPTY;
    1866            }
    1867
    1868            return str.substring(start);
    1869        }
    1870
    1871        /**
    1872         * <p>Gets a substring from the specified String avoiding exceptions.</p>
    1873         *
    1874         * <p>A negative start position can be used to start/end <code>n</code>
    1875         * characters from the end of the String.</p>
    1876         *
    1877         * <p>The returned substring starts with the character in the <code>start</code>
    1878         * position and ends before the <code>end</code> position. All position counting is
    1879         * zero-based -- i.e., to start at the beginning of the string use
    1880         * <code>start = 0</code>. Negative start and end positions can be used to
    1881         * specify offsets relative to the end of the String.</p>
    1882         *
    1883         * <p>If <code>start</code> is not strictly to the left of <code>end</code>, ""
    1884         * is returned.</p>
    1885         *
    1886         * <pre>
    1887         * StringUtils.substring(null, *, *)    = null
    1888         * StringUtils.substring("", * ,  *)    = "";
    1889         * StringUtils.substring("abc", 0, 2)   = "ab"
    1890         * StringUtils.substring("abc", 2, 0)   = ""
    1891         * StringUtils.substring("abc", 2, 4)   = "c"
    1892         * StringUtils.substring("abc", 4, 6)   = ""
    1893         * StringUtils.substring("abc", 2, 2)   = ""
    1894         * StringUtils.substring("abc", -2, -1) = "b"
    1895         * StringUtils.substring("abc", -4, 2)  = "ab"
    1896         * </pre>
    1897         *
    1898         * @param str  the String to get the substring from, may be null
    1899         * @param start  the position to start from, negative means
    1900         *  count back from the end of the String by this many characters
    1901         * @param end  the position to end at (exclusive), negative means
    1902         *  count back from the end of the String by this many characters
    1903         * @return substring from start position to end positon,
    1904         *  <code>null</code> if null String input
    1905         */
    1906        public static String substring(String str, int start, int end) {
    1907            if (str == null) {
    1908                return null;
    1909            }
    1910
    1911            // handle negatives
    1912            if (end < 0) {
    1913                end = str.length() + end; // remember end is negative
    1914            }
    1915            if (start < 0) {
    1916                start = str.length() + start; // remember start is negative
    1917            }
    1918
    1919            // check length next
    1920            if (end > str.length()) {
    1921                end = str.length();
    1922            }
    1923
    1924            // if start is greater than end, return ""
    1925            if (start > end) {
    1926                return EMPTY;
    1927            }
    1928
    1929            if (start < 0) {
    1930                start = 0;
    1931            }
    1932            if (end < 0) {
    1933                end = 0;
    1934            }
    1935
    1936            return str.substring(start, end);
    1937        }
    1938
    1939        // Left/Right/Mid
    1940        //-----------------------------------------------------------------------
    1941        /**
    1942         * <p>Gets the leftmost <code>len</code> characters of a String.</p>
    1943         *
    1944         * <p>If <code>len</code> characters are not available, or the
    1945         * String is <code>null</code>, the String will be returned without
    1946         * an exception. An empty String is returned if len is negative.</p>
    1947         *
    1948         * <pre>
    1949         * StringUtils.left(null, *)    = null
    1950         * StringUtils.left(*, -ve)     = ""
    1951         * StringUtils.left("", *)      = ""
    1952         * StringUtils.left("abc", 0)   = ""
    1953         * StringUtils.left("abc", 2)   = "ab"
    1954         * StringUtils.left("abc", 4)   = "abc"
    1955         * </pre>
    1956         *
    1957         * @param str  the String to get the leftmost characters from, may be null
    1958         * @param len  the length of the required String
    1959         * @return the leftmost characters, <code>null</code> if null String input
    1960         */
    1961        public static String left(String str, int len) {
    1962            if (str == null) {
    1963                return null;
    1964            }
    1965            if (len < 0) {
    1966                return EMPTY;
    1967            }
    1968            if (str.length() <= len) {
    1969                return str;
    1970            }
    1971            return str.substring(0, len);
    1972        }
    1973
    1974        /**
    1975         * <p>Gets the rightmost <code>len</code> characters of a String.</p>
    1976         *
    1977         * <p>If <code>len</code> characters are not available, or the String
    1978         * is <code>null</code>, the String will be returned without an
    1979         * an exception. An empty String is returned if len is negative.</p>
    1980         *
    1981         * <pre>
    1982         * StringUtils.right(null, *)    = null
    1983         * StringUtils.right(*, -ve)     = ""
    1984         * StringUtils.right("", *)      = ""
    1985         * StringUtils.right("abc", 0)   = ""
    1986         * StringUtils.right("abc", 2)   = "bc"
    1987         * StringUtils.right("abc", 4)   = "abc"
    1988         * </pre>
    1989         *
    1990         * @param str  the String to get the rightmost characters from, may be null
    1991         * @param len  the length of the required String
    1992         * @return the rightmost characters, <code>null</code> if null String input
    1993         */
    1994        public static String right(String str, int len) {
    1995            if (str == null) {
    1996                return null;
    1997            }
    1998            if (len < 0) {
    1999                return EMPTY;
    2000            }
    2001            if (str.length() <= len) {
    2002                return str;
    2003            }
    2004            return str.substring(str.length() - len);
    2005        }
    2006
    2007        /**
    2008         * <p>Gets <code>len</code> characters from the middle of a String.</p>
    2009         *
    2010         * <p>If <code>len</code> characters are not available, the remainder
    2011         * of the String will be returned without an exception. If the
    2012         * String is <code>null</code>, <code>null</code> will be returned.
    2013         * An empty String is returned if len is negative or exceeds the
    2014         * length of <code>str</code>.</p>
    2015         *
    2016         * <pre>
    2017         * StringUtils.mid(null, *, *)    = null
    2018         * StringUtils.mid(*, *, -ve)     = ""
    2019         * StringUtils.mid("", 0, *)      = ""
    2020         * StringUtils.mid("abc", 0, 2)   = "ab"
    2021         * StringUtils.mid("abc", 0, 4)   = "abc"
    2022         * StringUtils.mid("abc", 2, 4)   = "c"
    2023         * StringUtils.mid("abc", 4, 2)   = ""
    2024         * StringUtils.mid("abc", -2, 2)  = "ab"
    2025         * </pre>
    2026         *
    2027         * @param str  the String to get the characters from, may be null
    2028         * @param pos  the position to start from, negative treated as zero
    2029         * @param len  the length of the required String
    2030         * @return the middle characters, <code>null</code> if null String input
    2031         */
    2032        public static String mid(String str, int pos, int len) {
    2033            if (str == null) {
    2034                return null;
    2035            }
    2036            if (len < 0 || pos > str.length()) {
    2037                return EMPTY;
    2038            }
    2039            if (pos < 0) {
    2040                pos = 0;
    2041            }
    2042            if (str.length() <= (pos + len)) {
    2043                return str.substring(pos);
    2044            }
    2045            return str.substring(pos, pos + len);
    2046        }
    2047
    2048        // SubStringAfter/SubStringBefore
    2049        //-----------------------------------------------------------------------
    2050        /**
    2051         * <p>Gets the substring before the first occurrence of a separator.
    2052         * The separator is not returned.</p>
    2053         *
    2054         * <p>A <code>null</code> string input will return <code>null</code>.
    2055         * An empty ("") string input will return the empty string.
    2056         * A <code>null</code> separator will return the input string.</p>
    2057         *
    2058         * <p>If nothing is found, the string input is returned.</p>
    2059         *
    2060         * <pre>
    2061         * StringUtils.substringBefore(null, *)      = null
    2062         * StringUtils.substringBefore("", *)        = ""
    2063         * StringUtils.substringBefore("abc", "a")   = ""
    2064         * StringUtils.substringBefore("abcba", "b") = "a"
    2065         * StringUtils.substringBefore("abc", "c")   = "ab"
    2066         * StringUtils.substringBefore("abc", "d")   = "abc"
    2067         * StringUtils.substringBefore("abc", "")    = ""
    2068         * StringUtils.substringBefore("abc", null)  = "abc"
    2069         * </pre>
    2070         *
    2071         * @param str  the String to get a substring from, may be null
    2072         * @param separator  the String to search for, may be null
    2073         * @return the substring before the first occurrence of the separator,
    2074         *  <code>null</code> if null String input
    2075         * @since 2.0
    2076         */
    2077        public static String substringBefore(String str, String separator) {
    2078            if (isEmpty(str) || separator == null) {
    2079                return str;
    2080            }
    2081            if (separator.length() == 0) {
    2082                return EMPTY;
    2083            }
    2084            int pos = str.indexOf(separator);
    2085            if (pos == INDEX_NOT_FOUND) {
    2086                return str;
    2087            }
    2088            return str.substring(0, pos);
    2089        }
    2090
    2091        /**
    2092         * <p>Gets the substring after the first occurrence of a separator.
    2093         * The separator is not returned.</p>
    2094         *
    2095         * <p>A <code>null</code> string input will return <code>null</code>.
    2096         * An empty ("") string input will return the empty string.
    2097         * A <code>null</code> separator will return the empty string if the
    2098         * input string is not <code>null</code>.</p>
    2099         *
    2100         * <p>If nothing is found, the empty string is returned.</p>
    2101         *
    2102         * <pre>
    2103         * StringUtils.substringAfter(null, *)      = null
    2104         * StringUtils.substringAfter("", *)        = ""
    2105         * StringUtils.substringAfter(*, null)      = ""
    2106         * StringUtils.substringAfter("abc", "a")   = "bc"
    2107         * StringUtils.substringAfter("abcba", "b") = "cba"
    2108         * StringUtils.substringAfter("abc", "c")   = ""
    2109         * StringUtils.substringAfter("abc", "d")   = ""
    2110         * StringUtils.substringAfter("abc", "")    = "abc"
    2111         * </pre>
    2112         *
    2113         * @param str  the String to get a substring from, may be null
    2114         * @param separator  the String to search for, may be null
    2115         * @return the substring after the first occurrence of the separator,
    2116         *  <code>null</code> if null String input
    2117         * @since 2.0
    2118         */
    2119        public static String substringAfter(String str, String separator) {
    2120            if (isEmpty(str)) {
    2121                return str;
    2122            }
    2123            if (separator == null) {
    2124                return EMPTY;
    2125            }
    2126            int pos = str.indexOf(separator);
    2127            if (pos == INDEX_NOT_FOUND) {
    2128                return EMPTY;
    2129            }
    2130            return str.substring(pos + separator.length());
    2131        }
    2132
    2133        /**
    2134         * <p>Gets the substring before the last occurrence of a separator.
    2135         * The separator is not returned.</p>
    2136         *
    2137         * <p>A <code>null</code> string input will return <code>null</code>.
    2138         * An empty ("") string input will return the empty string.
    2139         * An empty or <code>null</code> separator will return the input string.</p>
    2140         *
    2141         * <p>If nothing is found, the string input is returned.</p>
    2142         *
    2143         * <pre>
    2144         * StringUtils.substringBeforeLast(null, *)      = null
    2145         * StringUtils.substringBeforeLast("", *)        = ""
    2146         * StringUtils.substringBeforeLast("abcba", "b") = "abc"
    2147         * StringUtils.substringBeforeLast("abc", "c")   = "ab"
    2148         * StringUtils.substringBeforeLast("a", "a")     = ""
    2149         * StringUtils.substringBeforeLast("a", "z")     = "a"
    2150         * StringUtils.substringBeforeLast("a", null)    = "a"
    2151         * StringUtils.substringBeforeLast("a", "")      = "a"
    2152         * </pre>
    2153         *
    2154         * @param str  the String to get a substring from, may be null
    2155         * @param separator  the String to search for, may be null
    2156         * @return the substring before the last occurrence of the separator,
    2157         *  <code>null</code> if null String input
    2158         * @since 2.0
    2159         */
    2160        public static String substringBeforeLast(String str, String separator) {
    2161            if (isEmpty(str) || isEmpty(separator)) {
    2162                return str;
    2163            }
    2164            int pos = str.lastIndexOf(separator);
    2165            if (pos == INDEX_NOT_FOUND) {
    2166                return str;
    2167            }
    2168            return str.substring(0, pos);
    2169        }
    2170
    2171        /**
    2172         * <p>Gets the substring after the last occurrence of a separator.
    2173         * The separator is not returned.</p>
    2174         *
    2175         * <p>A <code>null</code> string input will return <code>null</code>.
    2176         * An empty ("") string input will return the empty string.
    2177         * An empty or <code>null</code> separator will return the empty string if
    2178         * the input string is not <code>null</code>.</p>
    2179         *
    2180         * <p>If nothing is found, the empty string is returned.</p>
    2181         *
    2182         * <pre>
    2183         * StringUtils.substringAfterLast(null, *)      = null
    2184         * StringUtils.substringAfterLast("", *)        = ""
    2185         * StringUtils.substringAfterLast(*, "")        = ""
    2186         * StringUtils.substringAfterLast(*, null)      = ""
    2187         * StringUtils.substringAfterLast("abc", "a")   = "bc"
    2188         * StringUtils.substringAfterLast("abcba", "b") = "a"
    2189         * StringUtils.substringAfterLast("abc", "c")   = ""
    2190         * StringUtils.substringAfterLast("a", "a")     = ""
    2191         * StringUtils.substringAfterLast("a", "z")     = ""
    2192         * </pre>
    2193         *
    2194         * @param str  the String to get a substring from, may be null
    2195         * @param separator  the String to search for, may be null
    2196         * @return the substring after the last occurrence of the separator,
    2197         *  <code>null</code> if null String input
    2198         * @since 2.0
    2199         */
    2200        public static String substringAfterLast(String str, String separator) {
    2201            if (isEmpty(str)) {
    2202                return str;
    2203            }
    2204            if (isEmpty(separator)) {
    2205                return EMPTY;
    2206            }
    2207            int pos = str.lastIndexOf(separator);
    2208            if (pos == INDEX_NOT_FOUND || pos == (str.length() - separator.length())) {
    2209                return EMPTY;
    2210            }
    2211            return str.substring(pos + separator.length());
    2212        }
    2213
    2214        // Substring between
    2215        //-----------------------------------------------------------------------
    2216        /**
    2217         * <p>Gets the String that is nested in between two instances of the
    2218         * same String.</p>
    2219         *
    2220         * <p>A <code>null</code> input String returns <code>null</code>.
    2221         * A <code>null</code> tag returns <code>null</code>.</p>
    2222         *
    2223         * <pre>
    2224         * StringUtils.substringBetween(null, *)            = null
    2225         * StringUtils.substringBetween("", "")             = ""
    2226         * StringUtils.substringBetween("", "tag")          = null
    2227         * StringUtils.substringBetween("tagabctag", null)  = null
    2228         * StringUtils.substringBetween("tagabctag", "")    = ""
    2229         * StringUtils.substringBetween("tagabctag", "tag") = "abc"
    2230         * </pre>
    2231         *
    2232         * @param str  the String containing the substring, may be null
    2233         * @param tag  the String before and after the substring, may be null
    2234         * @return the substring, <code>null</code> if no match
    2235         * @since 2.0
    2236         */
    2237        public static String substringBetween(String str, String tag) {
    2238            return substringBetween(str, tag, tag);
    2239        }
    2240
    2241        /**
    2242         * <p>Gets the String that is nested in between two Strings.
    2243         * Only the first match is returned.</p>
    2244         *
    2245         * <p>A <code>null</code> input String returns <code>null</code>.
    2246         * A <code>null</code> open/close returns <code>null</code> (no match).
    2247         * An empty ("") open and close returns an empty string.</p>
    2248         *
    2249         * <pre>
    2250         * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
    2251         * StringUtils.substringBetween(null, *, *)          = null
    2252         * StringUtils.substringBetween(*, null, *)          = null
    2253         * StringUtils.substringBetween(*, *, null)          = null
    2254         * StringUtils.substringBetween("", "", "")          = ""
    2255         * StringUtils.substringBetween("", "", "]")         = null
    2256         * StringUtils.substringBetween("", "[", "]")        = null
    2257         * StringUtils.substringBetween("yabcz", "", "")     = ""
    2258         * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
    2259         * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
    2260         * </pre>
    2261         *
    2262         * @param str  the String containing the substring, may be null
    2263         * @param open  the String before the substring, may be null
    2264         * @param close  the String after the substring, may be null
    2265         * @return the substring, <code>null</code> if no match
    2266         * @since 2.0
    2267         */
    2268        public static String substringBetween(String str, String open, String close) {
    2269            if (str == null || open == null || close == null) {
    2270                return null;
    2271            }
    2272            int start = str.indexOf(open);
    2273            if (start != INDEX_NOT_FOUND) {
    2274                int end = str.indexOf(close, start + open.length());
    2275                if (end != INDEX_NOT_FOUND) {
    2276                    return str.substring(start + open.length(), end);
    2277                }
    2278            }
    2279            return null;
    2280        }
    2281
    2282        /**
    2283         * <p>Searches a String for substrings delimited by a start and end tag,
    2284         * returning all matching substrings in an array.</p>
    2285         *
    2286         * <p>A <code>null</code> input String returns <code>null</code>.
    2287         * A <code>null</code> open/close returns <code>null</code> (no match).
    2288         * An empty ("") open/close returns <code>null</code> (no match).</p>
    2289         *
    2290         * <pre>
    2291         * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
    2292         * StringUtils.substringsBetween(null, *, *)            = null
    2293         * StringUtils.substringsBetween(*, null, *)            = null
    2294         * StringUtils.substringsBetween(*, *, null)            = null
    2295         * StringUtils.substringsBetween("", "[", "]")          = []
    2296         * </pre>
    2297         *
    2298         * @param str  the String containing the substrings, null returns null, empty returns empty
    2299         * @param open  the String identifying the start of the substring, empty returns null
    2300         * @param close  the String identifying the end of the substring, empty returns null
    2301         * @return a String Array of substrings, or <code>null</code> if no match
    2302         * @since 2.3
    2303         */
    2304        public static String[] substringsBetween(String str, String open, String close) {
    2305            if (str == null || isEmpty(open) || isEmpty(close)) {
    2306                return null;
    2307            }
    2308            int strLen = str.length();
    2309            if (strLen == 0) {
    2310                return ArrayUtils.EMPTY_STRING_ARRAY;
    2311            }
    2312            int closeLen = close.length();
    2313            int openLen = open.length();
    2314            List list = new ArrayList();
    2315            int pos = 0;
    2316            while (pos < (strLen - closeLen)) {
    2317                int start = str.indexOf(open, pos);
    2318                if (start < 0) {
    2319                    break;
    2320                }
    2321                start += openLen;
    2322                int end = str.indexOf(close, start);
    2323                if (end < 0) {
    2324                    break;
    2325                }
    2326                list.add(str.substring(start, end));
    2327                pos = end + closeLen;
    2328            }
    2329            if (list.isEmpty()) {
    2330                return null;
    2331            }
    2332            return (String[]) list.toArray(new String [list.size()]);
    2333        }
    2334
    2335        // Nested extraction
    2336        //-----------------------------------------------------------------------
    2337        /**
    2338         * <p>Gets the String that is nested in between two instances of the
    2339         * same String.</p>
    2340         *
    2341         * <p>A <code>null</code> input String returns <code>null</code>.
    2342         * A <code>null</code> tag returns <code>null</code>.</p>
    2343         *
    2344         * <pre>
    2345         * StringUtils.getNestedString(null, *)            = null
    2346         * StringUtils.getNestedString("", "")             = ""
    2347         * StringUtils.getNestedString("", "tag")          = null
    2348         * StringUtils.getNestedString("tagabctag", null)  = null
    2349         * StringUtils.getNestedString("tagabctag", "")    = ""
    2350         * StringUtils.getNestedString("tagabctag", "tag") = "abc"
    2351         * </pre>
    2352         *
    2353         * @param str  the String containing nested-string, may be null
    2354         * @param tag  the String before and after nested-string, may be null
    2355         * @return the nested String, <code>null</code> if no match
    2356         * @deprecated Use the better named {@link #substringBetween(String, String)}.
    2357         *             Method will be removed in Commons Lang 3.0.
    2358         */
    2359        public static String getNestedString(String str, String tag) {
    2360            return substringBetween(str, tag, tag);
    2361        }
    2362
    2363        /**
    2364         * <p>Gets the String that is nested in between two Strings.
    2365         * Only the first match is returned.</p>
    2366         *
    2367         * <p>A <code>null</code> input String returns <code>null</code>.
    2368         * A <code>null</code> open/close returns <code>null</code> (no match).
    2369         * An empty ("") open/close returns an empty string.</p>
    2370         *
    2371         * <pre>
    2372         * StringUtils.getNestedString(null, *, *)          = null
    2373         * StringUtils.getNestedString("", "", "")          = ""
    2374         * StringUtils.getNestedString("", "", "tag")       = null
    2375         * StringUtils.getNestedString("", "tag", "tag")    = null
    2376         * StringUtils.getNestedString("yabcz", null, null) = null
    2377         * StringUtils.getNestedString("yabcz", "", "")     = ""
    2378         * StringUtils.getNestedString("yabcz", "y", "z")   = "abc"
    2379         * StringUtils.getNestedString("yabczyabcz", "y", "z")   = "abc"
    2380         * </pre>
    2381         *
    2382         * @param str  the String containing nested-string, may be null
    2383         * @param open  the String before nested-string, may be null
    2384         * @param close  the String after nested-string, may be null
    2385         * @return the nested String, <code>null</code> if no match
    2386         * @deprecated Use the better named {@link #substringBetween(String, String, String)}.
    2387         *             Method will be removed in Commons Lang 3.0.
    2388         */
    2389        public static String getNestedString(String str, String open, String close) {
    2390            return substringBetween(str, open, close);
    2391        }
    2392
    2393        // Splitting
    2394        //-----------------------------------------------------------------------
    2395        /**
    2396         * <p>Splits the provided text into an array, using whitespace as the
    2397         * separator.
    2398         * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    2399         *
    2400         * <p>The separator is not included in the returned String array.
    2401         * Adjacent separators are treated as one separator.
    2402         * For more control over the split use the StrTokenizer class.</p>
    2403         *
    2404         * <p>A <code>null</code> input String returns <code>null</code>.</p>
    2405         *
    2406         * <pre>
    2407         * StringUtils.split(null)       = null
    2408         * StringUtils.split("")         = []
    2409         * StringUtils.split("abc def")  = ["abc", "def"]
    2410         * StringUtils.split("abc  def") = ["abc", "def"]
    2411         * StringUtils.split(" abc ")    = ["abc"]
    2412         * </pre>
    2413         *
    2414         * @param str  the String to parse, may be null
    2415         * @return an array of parsed Strings, <code>null</code> if null String input
    2416         */
    2417        public static String[] split(String str) {
    2418            return split(str, null, -1);
    2419        }
    2420
    2421        /**
    2422         * <p>Splits the provided text into an array, separator specified.
    2423         * This is an alternative to using StringTokenizer.</p>
    2424         *
    2425         * <p>The separator is not included in the returned String array.
    2426         * Adjacent separators are treated as one separator.
    2427         * For more control over the split use the StrTokenizer class.</p>
    2428         *
    2429         * <p>A <code>null</code> input String returns <code>null</code>.</p>
    2430         *
    2431         * <pre>
    2432         * StringUtils.split(null, *)         = null
    2433         * StringUtils.split("", *)           = []
    2434         * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
    2435         * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
    2436         * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
    2437         * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
    2438         * </pre>
    2439         *
    2440         * @param str  the String to parse, may be null
    2441         * @param separatorChar  the character used as the delimiter
    2442         * @return an array of parsed Strings, <code>null</code> if null String input
    2443         * @since 2.0
    2444         */
    2445        public static String[] split(String str, char separatorChar) {
    2446            return splitWorker(str, separatorChar, false);
    2447        }
    2448
    2449        /**
    2450         * <p>Splits the provided text into an array, separators specified.
    2451         * This is an alternative to using StringTokenizer.</p>
    2452         *
    2453         * <p>The separator is not included in the returned String array.
    2454         * Adjacent separators are treated as one separator.
    2455         * For more control over the split use the StrTokenizer class.</p>
    2456         *
    2457         * <p>A <code>null</code> input String returns <code>null</code>.
    2458         * A <code>null</code> separatorChars splits on whitespace.</p>
    2459         *
    2460         * <pre>
    2461         * StringUtils.split(null, *)         = null
    2462         * StringUtils.split("", *)           = []
    2463         * StringUtils.split("abc def", null) = ["abc", "def"]
    2464         * StringUtils.split("abc def", " ")  = ["abc", "def"]
    2465         * StringUtils.split("abc  def", " ") = ["abc", "def"]
    2466         * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
    2467         * </pre>
    2468         *
    2469         * @param str  the String to parse, may be null
    2470         * @param separatorChars  the characters used as the delimiters,
    2471         *  <code>null</code> splits on whitespace
    2472         * @return an array of parsed Strings, <code>null</code> if null String input
    2473         */
    2474        public static String[] split(String str, String separatorChars) {
    2475            return splitWorker(str, separatorChars, -1, false);
    2476        }
    2477
    2478        /**
    2479         * <p>Splits the provided text into an array with a maximum length,
    2480         * separators specified.</p>
    2481         *
    2482         * <p>The separator is not included in the returned String array.
    2483         * Adjacent separators are treated as one separator.</p>
    2484         *
    2485         * <p>A <code>null</code> input String returns <code>null</code>.
    2486         * A <code>null</code> separatorChars splits on whitespace.</p>
    2487         *
    2488         * <p>If more than <code>max</code> delimited substrings are found, the last
    2489         * returned string includes all characters after the first <code>max - 1</code>
    2490         * returned strings (including separator characters).</p>
    2491         *
    2492         * <pre>
    2493         * StringUtils.split(null, *, *)            = null
    2494         * StringUtils.split("", *, *)              = []
    2495         * StringUtils.split("ab de fg", null, 0)   = ["ab", "cd", "ef"]
    2496         * StringUtils.split("ab   de fg", null, 0) = ["ab", "cd", "ef"]
    2497         * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
    2498         * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
    2499         * </pre>
    2500         *
    2501         * @param str  the String to parse, may be null
    2502         * @param separatorChars  the characters used as the delimiters,
    2503         *  <code>null</code> splits on whitespace
    2504         * @param max  the maximum number of elements to include in the
    2505         *  array. A zero or negative value implies no limit
    2506         * @return an array of parsed Strings, <code>null</code> if null String input
    2507         */
    2508        public static String[] split(String str, String separatorChars, int max) {
    2509            return splitWorker(str, separatorChars, max, false);
    2510        }
    2511
    2512        /**
    2513         * <p>Splits the provided text into an array, separator string specified.</p>
    2514         *
    2515         * <p>The separator(s) will not be included in the returned String array.
    2516         * Adjacent separators are treated as one separator.</p>
    2517         *
    2518         * <p>A <code>null</code> input String returns <code>null</code>.
    2519         * A <code>null</code> separator splits on whitespace.</p>
    2520         *
    2521         * <pre>
    2522         * StringUtils.splitByWholeSeparator(null, *)               = null
    2523         * StringUtils.splitByWholeSeparator("", *)                 = []
    2524         * StringUtils.splitByWholeSeparator("ab de fg", null)      = ["ab", "de", "fg"]
    2525         * StringUtils.splitByWholeSeparator("ab   de fg", null)    = ["ab", "de", "fg"]
    2526         * StringUtils.splitByWholeSeparator("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
    2527         * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
    2528         * </pre>
    2529         *
    2530         * @param str  the String to parse, may be null
    2531         * @param separator  String containing the String to be used as a delimiter,
    2532         *  <code>null</code> splits on whitespace
    2533         * @return an array of parsed Strings, <code>null</code> if null String was input
    2534         */
    2535        public static String[] splitByWholeSeparator(String str, String separator) {
    2536            return splitByWholeSeparatorWorker( str, separator, -1, false ) ;
    2537        }
    2538
    2539        /**
    2540         * <p>Splits the provided text into an array, separator string specified.
    2541         * Returns a maximum of <code>max</code> substrings.</p>
    2542         *
    2543         * <p>The separator(s) will not be included in the returned String array.
    2544         * Adjacent separators are treated as one separator.</p>
    2545         *
    2546         * <p>A <code>null</code> input String returns <code>null</code>.
    2547         * A <code>null</code> separator splits on whitespace.</p>
    2548         *
    2549         * <pre>
    2550         * StringUtils.splitByWholeSeparator(null, *, *)               = null
    2551         * StringUtils.splitByWholeSeparator("", *, *)                 = []
    2552         * StringUtils.splitByWholeSeparator("ab de fg", null, 0)      = ["ab", "de", "fg"]
    2553         * StringUtils.splitByWholeSeparator("ab   de fg", null, 0)    = ["ab", "de", "fg"]
    2554         * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
    2555         * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
    2556         * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
    2557         * </pre>
    2558         *
    2559         * @param str  the String to parse, may be null
    2560         * @param separator  String containing the String to be used as a delimiter,
    2561         *  <code>null</code> splits on whitespace
    2562         * @param max  the maximum number of elements to include in the returned
    2563         *  array. A zero or negative value implies no limit.
    2564         * @return an array of parsed Strings, <code>null</code> if null String was input
    2565         */
    2566        public static String[] splitByWholeSeparator( String str, String separator, int max ) {
    2567            return splitByWholeSeparatorWorker(str, separator, max, false);
    2568        }
    2569
    2570        /**
    2571         * <p>Splits the provided text into an array, separator string specified. </p>
    2572         *
    2573         * <p>The separator is not included in the returned String array.
    2574         * Adjacent separators are treated as separators for empty tokens.
    2575         * For more control over the split use the StrTokenizer class.</p>
    2576         *
    2577         * <p>A <code>null</code> input String returns <code>null</code>.
    2578         * A <code>null</code> separator splits on whitespace.</p>
    2579         *
    2580         * <pre>
    2581         * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *)               = null
    2582         * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *)                 = []
    2583         * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null)      = ["ab", "de", "fg"]
    2584         * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null)    = ["ab", "", "", "de", "fg"]
    2585         * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
    2586         * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
    2587         * </pre>
    2588         *
    2589         * @param str  the String to parse, may be null
    2590         * @param separator  String containing the String to be used as a delimiter,
    2591         *  <code>null</code> splits on whitespace
    2592         * @return an array of parsed Strings, <code>null</code> if null String was input
    2593         * @since 2.4
    2594         */
    2595        public static String[] splitByWholeSeparatorPreserveAllTokens(String str, String separator) {
    2596            return splitByWholeSeparatorWorker(str, separator, -1, true);
    2597        }
    2598
    2599        /**
    2600         * <p>Splits the provided text into an array, separator string specified.
    2601         * Returns a maximum of <code>max</code> substrings.</p>
    2602         *
    2603         * <p>The separator is not included in the returned String array.
    2604         * Adjacent separators are treated as separators for empty tokens.
    2605         * For more control over the split use the StrTokenizer class.</p>
    2606         *
    2607         * <p>A <code>null</code> input String returns <code>null</code>.
    2608         * A <code>null</code> separator splits on whitespace.</p>
    2609         *
    2610         * <pre>
    2611         * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *)               = null
    2612         * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *)                 = []
    2613         * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0)      = ["ab", "de", "fg"]
    2614         * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null, 0)    = ["ab", "", "", "de", "fg"]
    2615         * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
    2616         * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
    2617         * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
    2618         * </pre>
    2619         *
    2620         * @param str  the String to parse, may be null
    2621         * @param separator  String containing the String to be used as a delimiter,
    2622         *  <code>null</code> splits on whitespace
    2623         * @param max  the maximum number of elements to include in the returned
    2624         *  array. A zero or negative value implies no limit.
    2625         * @return an array of parsed Strings, <code>null</code> if null String was input
    2626         * @since 2.4
    2627         */
    2628        public static String[] splitByWholeSeparatorPreserveAllTokens(String str, String separator, int max) {
    2629            return splitByWholeSeparatorWorker(str, separator, max, true);
    2630        }
    2631
    2632        /**
    2633         * Performs the logic for the <code>splitByWholeSeparatorPreserveAllTokens</code> methods.
    2634         *
    2635         * @param str  the String to parse, may be <code>null</code>
    2636         * @param separator  String containing the String to be used as a delimiter,
    2637         *  <code>null</code> splits on whitespace
    2638         * @param max  the maximum number of elements to include in the returned
    2639         *  array. A zero or negative value implies no limit.
    2640         * @param preserveAllTokens if <code>true</code>, adjacent separators are
    2641         * treated as empty token separators; if <code>false</code>, adjacent
    2642         * separators are treated as one separator.
    2643         * @return an array of parsed Strings, <code>null</code> if null String input
    2644         * @since 2.4
    2645         */
    2646        private static String[] splitByWholeSeparatorWorker(String str, String separator, int max,
    2647                                                            boolean preserveAllTokens)
    2648        {
    2649            if (str == null) {
    2650                return null;
    2651            }
    2652
    2653            int len = str.length();
    2654
    2655            if (len == 0) {
    2656                return ArrayUtils.EMPTY_STRING_ARRAY;
    2657            }
    2658
    2659            if ((separator == null) || (EMPTY.equals(separator))) {
    2660                // Split on whitespace.
    2661                return splitWorker(str, null, max, preserveAllTokens);
    2662            }
    2663
    2664            int separatorLength = separator.length();
    2665
    2666            ArrayList substrings = new ArrayList();
    2667            int numberOfSubstrings = 0;
    2668            int beg = 0;
    2669            int end = 0;
    2670            while (end < len) {
    2671                end = str.indexOf(separator, beg);
    2672
    2673                if (end > -1) {
    2674                    if (end > beg) {
    2675                        numberOfSubstrings += 1;
    2676
    2677                        if (numberOfSubstrings == max) {
    2678                            end = len;
    2679                            substrings.add(str.substring(beg));
    2680                        } else {
    2681                            // The following is OK, because String.substring( beg, end ) excludes
    2682                            // the character at the position 'end'.
    2683                            substrings.add(str.substring(beg, end));
    2684
    2685                            // Set the starting point for the next search.
    2686                            // The following is equivalent to beg = end + (separatorLength - 1) + 1,
    2687                            // which is the right calculation:
    2688                            beg = end + separatorLength;
    2689                        }
    2690                    } else {
    2691                        // We found a consecutive occurrence of the separator, so skip it.
    2692                        if (preserveAllTokens) {
    2693                            numberOfSubstrings += 1;
    2694                            if (numberOfSubstrings == max) {
    2695                                end = len;
    2696                                substrings.add(str.substring(beg));
    2697                            } else {
    2698                                substrings.add(EMPTY);
    2699                            }
    2700                        }
    2701                        beg = end + separatorLength;
    2702                    }
    2703                } else {
    2704                    // String.substring( beg ) goes from 'beg' to the end of the String.
    2705                    substrings.add(str.substring(beg));
    2706                    end = len;
    2707                }
    2708            }
    2709
    2710            return (String[]) substrings.toArray(new String[substrings.size()]);
    2711        }
    2712
    2713        // -----------------------------------------------------------------------
    2714        /**
    2715         * <p>Splits the provided text into an array, using whitespace as the
    2716         * separator, preserving all tokens, including empty tokens created by
    2717         * adjacent separators. This is an alternative to using StringTokenizer.
    2718         * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    2719         *
    2720         * <p>The separator is not included in the returned String array.
    2721         * Adjacent separators are treated as separators for empty tokens.
    2722         * For more control over the split use the StrTokenizer class.</p>
    2723         *
    2724         * <p>A <code>null</code> input String returns <code>null</code>.</p>
    2725         *
    2726         * <pre>
    2727         * StringUtils.splitPreserveAllTokens(null)       = null
    2728         * StringUtils.splitPreserveAllTokens("")         = []
    2729         * StringUtils.splitPreserveAllTokens("abc def")  = ["abc", "def"]
    2730         * StringUtils.splitPreserveAllTokens("abc  def") = ["abc", "", "def"]
    2731         * StringUtils.splitPreserveAllTokens(" abc ")    = ["", "abc", ""]
    2732         * </pre>
    2733         *
    2734         * @param str  the String to parse, may be <code>null</code>
    2735         * @return an array of parsed Strings, <code>null</code> if null String input
    2736         * @since 2.1
    2737         */
    2738        public static String[] splitPreserveAllTokens(String str) {
    2739            return splitWorker(str, null, -1, true);
    2740        }
    2741
    2742        /**
    2743         * <p>Splits the provided text into an array, separator specified,
    2744         * preserving all tokens, including empty tokens created by adjacent
    2745         * separators. This is an alternative to using StringTokenizer.</p>
    2746         *
    2747         * <p>The separator is not included in the returned String array.
    2748         * Adjacent separators are treated as separators for empty tokens.
    2749         * For more control over the split use the StrTokenizer class.</p>
    2750         *
    2751         * <p>A <code>null</code> input String returns <code>null</code>.</p>
    2752         *
    2753         * <pre>
    2754         * StringUtils.splitPreserveAllTokens(null, *)         = null
    2755         * StringUtils.splitPreserveAllTokens("", *)           = []
    2756         * StringUtils.splitPreserveAllTokens("a.b.c", '.')    = ["a", "b", "c"]
    2757         * StringUtils.splitPreserveAllTokens("a..b.c", '.')   = ["a", "", "b", "c"]
    2758         * StringUtils.splitPreserveAllTokens("a:b:c", '.')    = ["a:b:c"]
    2759         * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
    2760         * StringUtils.splitPreserveAllTokens("a b c", ' ')    = ["a", "b", "c"]
    2761         * StringUtils.splitPreserveAllTokens("a b c ", ' ')   = ["a", "b", "c", ""]
    2762         * StringUtils.splitPreserveAllTokens("a b c  ", ' ')   = ["a", "b", "c", "", ""]
    2763         * StringUtils.splitPreserveAllTokens(" a b c", ' ')   = ["", a", "b", "c"]
    2764         * StringUtils.splitPreserveAllTokens("  a b c", ' ')  = ["", "", a", "b", "c"]
    2765         * StringUtils.splitPreserveAllTokens(" a b c ", ' ')  = ["", a", "b", "c", ""]
    2766         * </pre>
    2767         *
    2768         * @param str  the String to parse, may be <code>null</code>
    2769         * @param separatorChar  the character used as the delimiter,
    2770         *  <code>null</code> splits on whitespace
    2771         * @return an array of parsed Strings, <code>null</code> if null String input
    2772         * @since 2.1
    2773         */
    2774        public static String[] splitPreserveAllTokens(String str, char separatorChar) {
    2775            return splitWorker(str, separatorChar, true);
    2776        }
    2777
    2778        /**
    2779         * Performs the logic for the <code>split</code> and
    2780         * <code>splitPreserveAllTokens</code> methods that do not return a
    2781         * maximum array length.
    2782         *
    2783         * @param str  the String to parse, may be <code>null</code>
    2784         * @param separatorChar the separate character
    2785         * @param preserveAllTokens if <code>true</code>, adjacent separators are
    2786         * treated as empty token separators; if <code>false</code>, adjacent
    2787         * separators are treated as one separator.
    2788         * @return an array of parsed Strings, <code>null</code> if null String input
    2789         */
    2790        private static String[] splitWorker(String str, char separatorChar, boolean preserveAllTokens) {
    2791            // Performance tuned for 2.0 (JDK1.4)
    2792
    2793            if (str == null) {
    2794                return null;
    2795            }
    2796            int len = str.length();
    2797            if (len == 0) {
    2798                return ArrayUtils.EMPTY_STRING_ARRAY;
    2799            }
    2800            List list = new ArrayList();
    2801            int i = 0, start = 0;
    2802            boolean match = false;
    2803            boolean lastMatch = false;
    2804            while (i < len) {
    2805                if (str.charAt(i) == separatorChar) {
    2806                    if (match || preserveAllTokens) {
    2807                        list.add(str.substring(start, i));
    2808                        match = false;
    2809                        lastMatch = true;
    2810                    }
    2811                    start = ++i;
    2812                    continue;
    2813                }
    2814                lastMatch = false;
    2815                match = true;
    2816                i++;
    2817            }
    2818            if (match || (preserveAllTokens && lastMatch)) {
    2819                list.add(str.substring(start, i));
    2820            }
    2821            return (String[]) list.toArray(new String[list.size()]);
    2822        }
    2823
    2824        /**
    2825         * <p>Splits the provided text into an array, separators specified,
    2826         * preserving all tokens, including empty tokens created by adjacent
    2827         * separators. This is an alternative to using StringTokenizer.</p>
    2828         *
    2829         * <p>The separator is not included in the returned String array.
    2830         * Adjacent separators are treated as separators for empty tokens.
    2831         * For more control over the split use the StrTokenizer class.</p>
    2832         *
    2833         * <p>A <code>null</code> input String returns <code>null</code>.
    2834         * A <code>null</code> separatorChars splits on whitespace.</p>
    2835         *
    2836         * <pre>
    2837         * StringUtils.splitPreserveAllTokens(null, *)           = null
    2838         * StringUtils.splitPreserveAllTokens("", *)             = []
    2839         * StringUtils.splitPreserveAllTokens("abc def", null)   = ["abc", "def"]
    2840         * StringUtils.splitPreserveAllTokens("abc def", " ")    = ["abc", "def"]
    2841         * StringUtils.splitPreserveAllTokens("abc  def", " ")   = ["abc", "", def"]
    2842         * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":")   = ["ab", "cd", "ef"]
    2843         * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":")  = ["ab", "cd", "ef", ""]
    2844         * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
    2845         * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":")  = ["ab", "", cd", "ef"]
    2846         * StringUtils.splitPreserveAllTokens(":cd:ef", ":")     = ["", cd", "ef"]
    2847         * StringUtils.splitPreserveAllTokens("::cd:ef", ":")    = ["", "", cd", "ef"]
    2848         * StringUtils.splitPreserveAllTokens(":cd:ef:", ":")    = ["", cd", "ef", ""]
    2849         * </pre>
    2850         *
    2851         * @param str  the String to parse, may be <code>null</code>
    2852         * @param separatorChars  the characters used as the delimiters,
    2853         *  <code>null</code> splits on whitespace
    2854         * @return an array of parsed Strings, <code>null</code> if null String input
    2855         * @since 2.1
    2856         */
    2857        public static String[] splitPreserveAllTokens(String str, String separatorChars) {
    2858            return splitWorker(str, separatorChars, -1, true);
    2859        }
    2860
    2861        /**
    2862         * <p>Splits the provided text into an array with a maximum length,
    2863         * separators specified, preserving all tokens, including empty tokens
    2864         * created by adjacent separators.</p>
    2865         *
    2866         * <p>The separator is not included in the returned String array.
    2867         * Adjacent separators are treated as separators for empty tokens.
    2868         * Adjacent separators are treated as one separator.</p>
    2869         *
    2870         * <p>A <code>null</code> input String returns <code>null</code>.
    2871         * A <code>null</code> separatorChars splits on whitespace.</p>
    2872         *
    2873         * <p>If more than <code>max</code> delimited substrings are found, the last
    2874         * returned string includes all characters after the first <code>max - 1</code>
    2875         * returned strings (including separator characters).</p>
    2876         *
    2877         * <pre>
    2878         * StringUtils.splitPreserveAllTokens(null, *, *)            = null
    2879         * StringUtils.splitPreserveAllTokens("", *, *)              = []
    2880         * StringUtils.splitPreserveAllTokens("ab de fg", null, 0)   = ["ab", "cd", "ef"]
    2881         * StringUtils.splitPreserveAllTokens("ab   de fg", null, 0) = ["ab", "cd", "ef"]
    2882         * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
    2883         * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
    2884         * StringUtils.splitPreserveAllTokens("ab   de fg", null, 2) = ["ab", "  de fg"]
    2885         * StringUtils.splitPreserveAllTokens("ab   de fg", null, 3) = ["ab", "", " de fg"]
    2886         * StringUtils.splitPreserveAllTokens("ab   de fg", null, 4) = ["ab", "", "", "de fg"]
    2887         * </pre>
    2888         *
    2889         * @param str  the String to parse, may be <code>null</code>
    2890         * @param separatorChars  the characters used as the delimiters,
    2891         *  <code>null</code> splits on whitespace
    2892         * @param max  the maximum number of elements to include in the
    2893         *  array. A zero or negative value implies no limit
    2894         * @return an array of parsed Strings, <code>null</code> if null String input
    2895         * @since 2.1
    2896         */
    2897        public static String[] splitPreserveAllTokens(String str, String separatorChars, int max) {
    2898            return splitWorker(str, separatorChars, max, true);
    2899        }
    2900
    2901        /**
    2902         * Performs the logic for the <code>split</code> and
    2903         * <code>splitPreserveAllTokens</code> methods that return a maximum array
    2904         * length.
    2905         *
    2906         * @param str  the String to parse, may be <code>null</code>
    2907         * @param separatorChars the separate character
    2908         * @param max  the maximum number of elements to include in the
    2909         *  array. A zero or negative value implies no limit.
    2910         * @param preserveAllTokens if <code>true</code>, adjacent separators are
    2911         * treated as empty token separators; if <code>false</code>, adjacent
    2912         * separators are treated as one separator.
    2913         * @return an array of parsed Strings, <code>null</code> if null String input
    2914         */
    2915        private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens) {
    2916            // Performance tuned for 2.0 (JDK1.4)
    2917            // Direct code is quicker than StringTokenizer.
    2918            // Also, StringTokenizer uses isSpace() not isWhitespace()
    2919
    2920            if (str == null) {
    2921                return null;
    2922            }
    2923            int len = str.length();
    2924            if (len == 0) {
    2925                return ArrayUtils.EMPTY_STRING_ARRAY;
    2926            }
    2927            List list = new ArrayList();
    2928            int sizePlus1 = 1;
    2929            int i = 0, start = 0;
    2930            boolean match = false;
    2931            boolean lastMatch = false;
    2932            if (separatorChars == null) {
    2933                // Null separator means use whitespace
    2934                while (i < len) {
    2935                    if (Character.isWhitespace(str.charAt(i))) {
    2936                        if (match || preserveAllTokens) {
    2937                            lastMatch = true;
    2938                            if (sizePlus1++ == max) {
    2939                                i = len;
    2940                                lastMatch = false;
    2941                            }
    2942                            list.add(str.substring(start, i));
    2943                            match = false;
    2944                        }
    2945                        start = ++i;
    2946                        continue;
    2947                    }
    2948                    lastMatch = false;
    2949                    match = true;
    2950                    i++;
    2951                }
    2952            } else if (separatorChars.length() == 1) {
    2953                // Optimise 1 character case
    2954                char sep = separatorChars.charAt(0);
    2955                while (i < len) {
    2956                    if (str.charAt(i) == sep) {
    2957                        if (match || preserveAllTokens) {
    2958                            lastMatch = true;
    2959                            if (sizePlus1++ == max) {
    2960                                i = len;
    2961                                lastMatch = false;
    2962                            }
    2963                            list.add(str.substring(start, i));
    2964                            match = false;
    2965                        }
    2966                        start = ++i;
    2967                        continue;
    2968                    }
    2969                    lastMatch = false;
    2970                    match = true;
    2971                    i++;
    2972                }
    2973            } else {
    2974                // standard case
    2975                while (i < len) {
    2976                    if (separatorChars.indexOf(str.charAt(i)) >= 0) {
    2977                        if (match || preserveAllTokens) {
    2978                            lastMatch = true;
    2979                            if (sizePlus1++ == max) {
    2980                                i = len;
    2981                                lastMatch = false;
    2982                            }
    2983                            list.add(str.substring(start, i));
    2984                            match = false;
    2985                        }
    2986                        start = ++i;
    2987                        continue;
    2988                    }
    2989                    lastMatch = false;
    2990                    match = true;
    2991                    i++;
    2992                }
    2993            }
    2994            if (match || (preserveAllTokens && lastMatch)) {
    2995                list.add(str.substring(start, i));
    2996            }
    2997            return (String[]) list.toArray(new String[list.size()]);
    2998        }
    2999
    3000        /**
    3001         * <p>Splits a String by Character type as returned by
    3002         * <code>java.lang.Character.getType(char)</code>. Groups of contiguous
    3003         * characters of the same type are returned as complete tokens.
    3004         * <pre>
    3005         * StringUtils.splitByCharacterType(null)         = null
    3006         * StringUtils.splitByCharacterType("")           = []
    3007         * StringUtils.splitByCharacterType("ab de fg")   = ["ab", " ", "de", " ", "fg"]
    3008         * StringUtils.splitByCharacterType("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
    3009         * StringUtils.splitByCharacterType("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
    3010         * StringUtils.splitByCharacterType("number5")    = ["number", "5"]
    3011         * StringUtils.splitByCharacterType("fooBar")     = ["foo", "B", "ar"]
    3012         * StringUtils.splitByCharacterType("foo200Bar")  = ["foo", "200", "B", "ar"]
    3013         * StringUtils.splitByCharacterType("ASFRules")   = ["ASFR", "ules"]
    3014         * </pre>
    3015         * @param str the String to split, may be <code>null</code>
    3016         * @return an array of parsed Strings, <code>null</code> if null String input
    3017         * @since 2.4
    3018         */
    3019        public static String[] splitByCharacterType(String str) {
    3020            return splitByCharacterType(str, false);
    3021        }
    3022
    3023        /**
    3024         * <p>Splits a String by Character type as returned by
    3025         * <code>java.lang.Character.getType(char)</code>. Groups of contiguous
    3026         * characters of the same type are returned as complete tokens, with the
    3027         * following exception: the character of type
    3028         * <code>Character.UPPERCASE_LETTER</code>, if any, immediately
    3029         * preceding a token of type <code>Character.LOWERCASE_LETTER</code>
    3030         * will belong to the following token rather than to the preceding, if any,
    3031         * <code>Character.UPPERCASE_LETTER</code> token.
    3032         * <pre>
    3033         * StringUtils.splitByCharacterTypeCamelCase(null)         = null
    3034         * StringUtils.splitByCharacterTypeCamelCase("")           = []
    3035         * StringUtils.splitByCharacterTypeCamelCase("ab de fg")   = ["ab", " ", "de", " ", "fg"]
    3036         * StringUtils.splitByCharacterTypeCamelCase("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
    3037         * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
    3038         * StringUtils.splitByCharacterTypeCamelCase("number5")    = ["number", "5"]
    3039         * StringUtils.splitByCharacterTypeCamelCase("fooBar")     = ["foo", "Bar"]
    3040         * StringUtils.splitByCharacterTypeCamelCase("foo200Bar")  = ["foo", "200", "Bar"]
    3041         * StringUtils.splitByCharacterTypeCamelCase("ASFRules")   = ["ASF", "Rules"]
    3042         * </pre>
    3043         * @param str the String to split, may be <code>null</code>
    3044         * @return an array of parsed Strings, <code>null</code> if null String input
    3045         * @since 2.4
    3046         */
    3047        public static String[] splitByCharacterTypeCamelCase(String str) {
    3048            return splitByCharacterType(str, true);
    3049        }
    3050
    3051        /**
    3052         * <p>Splits a String by Character type as returned by
    3053         * <code>java.lang.Character.getType(char)</code>. Groups of contiguous
    3054         * characters of the same type are returned as complete tokens, with the
    3055         * following exception: if <code>camelCase</code> is <code>true</code>,
    3056         * the character of type <code>Character.UPPERCASE_LETTER</code>, if any,
    3057         * immediately preceding a token of type <code>Character.LOWERCASE_LETTER</code>
    3058         * will belong to the following token rather than to the preceding, if any,
    3059         * <code>Character.UPPERCASE_LETTER</code> token.
    3060         * @param str the String to split, may be <code>null</code>
    3061         * @param camelCase whether to use so-called "camel-case" for letter types
    3062         * @return an array of parsed Strings, <code>null</code> if null String input
    3063         * @since 2.4
    3064         */
    3065        private static String[] splitByCharacterType(String str, boolean camelCase) {
    3066            if (str == null) {
    3067                return null;
    3068            }
    3069            if (str.length() == 0) {
    3070                return ArrayUtils.EMPTY_STRING_ARRAY;
    3071            }
    3072            char[] c = str.toCharArray();
    3073            List list = new ArrayList();
    3074            int tokenStart = 0;
    3075            int currentType = Character.getType(c[tokenStart]);
    3076            for (int pos = tokenStart + 1; pos < c.length; pos++) {
    3077                int type = Character.getType(c[pos]);
    3078                if (type == currentType) {
    3079                    continue;
    3080                }
    3081                if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
    3082                    int newTokenStart = pos - 1;
    3083                    if (newTokenStart != tokenStart) {
    3084                        list.add(new String(c, tokenStart, newTokenStart - tokenStart));
    3085                        tokenStart = newTokenStart;
    3086                    }
    3087                } else {
    3088                    list.add(new String(c, tokenStart, pos - tokenStart));
    3089                    tokenStart = pos;
    3090                }
    3091                currentType = type;
    3092            }
    3093            list.add(new String(c, tokenStart, c.length - tokenStart));
    3094            return (String[]) list.toArray(new String[list.size()]);
    3095        }
    3096
    3097        // Joining
    3098        //-----------------------------------------------------------------------
    3099        /**
    3100         * <p>Joins the provided elements into a single String. </p>
    3101         *
    3102         * <p>No separator is added to the joined String.
    3103         * Null objects or empty string elements are represented by
    3104         * empty strings.</p>
    3105         *
    3106         * <pre>
    3107         * StringUtils.concatenate(null)            = null
    3108         * StringUtils.concatenate([])              = ""
    3109         * StringUtils.concatenate([null])          = ""
    3110         * StringUtils.concatenate(["a", "b", "c"]) = "abc"
    3111         * StringUtils.concatenate([null, "", "a"]) = "a"
    3112         * </pre>
    3113         *
    3114         * @param array  the array of values to concatenate, may be null
    3115         * @return the concatenated String, <code>null</code> if null array input
    3116         * @deprecated Use the better named {@link #join(Object[])} instead.
    3117         *             Method will be removed in Commons Lang 3.0.
    3118         */
    3119        public static String concatenate(Object[] array) {
    3120            return join(array, null);
    3121        }
    3122
    3123        /**
    3124         * <p>Joins the elements of the provided array into a single String
    3125         * containing the provided list of elements.</p>
    3126         *
    3127         * <p>No separator is added to the joined String.
    3128         * Null objects or empty strings within the array are represented by
    3129         * empty strings.</p>
    3130         *
    3131         * <pre>
    3132         * StringUtils.join(null)            = null
    3133         * StringUtils.join([])              = ""
    3134         * StringUtils.join([null])          = ""
    3135         * StringUtils.join(["a", "b", "c"]) = "abc"
    3136         * StringUtils.join([null, "", "a"]) = "a"
    3137         * </pre>
    3138         *
    3139         * @param array  the array of values to join together, may be null
    3140         * @return the joined String, <code>null</code> if null array input
    3141         * @since 2.0
    3142         */
    3143        public static String join(Object[] array) {
    3144            return join(array, null);
    3145        }
    3146
    3147        /**
    3148         * <p>Joins the elements of the provided array into a single String
    3149         * containing the provided list of elements.</p>
    3150         *
    3151         * <p>No delimiter is added before or after the list.
    3152         * Null objects or empty strings within the array are represented by
    3153         * empty strings.</p>
    3154         *
    3155         * <pre>
    3156         * StringUtils.join(null, *)               = null
    3157         * StringUtils.join([], *)                 = ""
    3158         * StringUtils.join([null], *)             = ""
    3159         * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    3160         * StringUtils.join(["a", "b", "c"], null) = "abc"
    3161         * StringUtils.join([null, "", "a"], ';')  = ";;a"
    3162         * </pre>
    3163         *
    3164         * @param array  the array of values to join together, may be null
    3165         * @param separator  the separator character to use
    3166         * @return the joined String, <code>null</code> if null array input
    3167         * @since 2.0
    3168         */
    3169        public static String join(Object[] array, char separator) {
    3170            if (array == null) {
    3171                return null;
    3172            }
    3173
    3174            return join(array, separator, 0, array.length);
    3175        }
    3176
    3177        /**
    3178         * <p>Joins the elements of the provided array into a single String
    3179         * containing the provided list of elements.</p>
    3180         *
    3181         * <p>No delimiter is added before or after the list.
    3182         * Null objects or empty strings within the array are represented by
    3183         * empty strings.</p>
    3184         *
    3185         * <pre>
    3186         * StringUtils.join(null, *)               = null
    3187         * StringUtils.join([], *)                 = ""
    3188         * StringUtils.join([null], *)             = ""
    3189         * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    3190         * StringUtils.join(["a", "b", "c"], null) = "abc"
    3191         * StringUtils.join([null, "", "a"], ';')  = ";;a"
    3192         * </pre>
    3193         *
    3194         * @param array  the array of values to join together, may be null
    3195         * @param separator  the separator character to use
    3196         * @param startIndex the first index to start joining from.  It is
    3197         * an error to pass in an end index past the end of the array
    3198         * @param endIndex the index to stop joining from (exclusive). It is
    3199         * an error to pass in an end index past the end of the array
    3200         * @return the joined String, <code>null</code> if null array input
    3201         * @since 2.0
    3202         */
    3203        public static String join(Object[] array, char separator, int startIndex, int endIndex) {
    3204            if (array == null) {
    3205                return null;
    3206            }
    3207            int bufSize = (endIndex - startIndex);
    3208            if (bufSize <= 0) {
    3209                return EMPTY;
    3210            }
    3211
    3212            bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length()) + 1);
    3213            StrBuilder buf = new StrBuilder(bufSize);
    3214
    3215            for (int i = startIndex; i < endIndex; i++) {
    3216                if (i > startIndex) {
    3217                    buf.append(separator);
    3218                }
    3219                if (array[i] != null) {
    3220                    buf.append(array[i]);
    3221                }
    3222            }
    3223            return buf.toString();
    3224        }
    3225
    3226
    3227        /**
    3228         * <p>Joins the elements of the provided array into a single String
    3229         * containing the provided list of elements.</p>
    3230         *
    3231         * <p>No delimiter is added before or after the list.
    3232         * A <code>null</code> separator is the same as an empty String ("").
    3233         * Null objects or empty strings within the array are represented by
    3234         * empty strings.</p>
    3235         *
    3236         * <pre>
    3237         * StringUtils.join(null, *)                = null
    3238         * StringUtils.join([], *)                  = ""
    3239         * StringUtils.join([null], *)              = ""
    3240         * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
    3241         * StringUtils.join(["a", "b", "c"], null)  = "abc"
    3242         * StringUtils.join(["a", "b", "c"], "")    = "abc"
    3243         * StringUtils.join([null, "", "a"], ',')   = ",,a"
    3244         * </pre>
    3245         *
    3246         * @param array  the array of values to join together, may be null
    3247         * @param separator  the separator character to use, null treated as ""
    3248         * @return the joined String, <code>null</code> if null array input
    3249         */
    3250        public static String join(Object[] array, String separator) {
    3251            if (array == null) {
    3252                return null;
    3253            }
    3254            return join(array, separator, 0, array.length);
    3255        }
    3256
    3257        /**
    3258         * <p>Joins the elements of the provided array into a single String
    3259         * containing the provided list of elements.</p>
    3260         *
    3261         * <p>No delimiter is added before or after the list.
    3262         * A <code>null</code> separator is the same as an empty String ("").
    3263         * Null objects or empty strings within the array are represented by
    3264         * empty strings.</p>
    3265         *
    3266         * <pre>
    3267         * StringUtils.join(null, *)                = null
    3268         * StringUtils.join([], *)                  = ""
    3269         * StringUtils.join([null], *)              = ""
    3270         * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
    3271         * StringUtils.join(["a", "b", "c"], null)  = "abc"
    3272         * StringUtils.join(["a", "b", "c"], "")    = "abc"
    3273         * StringUtils.join([null, "", "a"], ',')   = ",,a"
    3274         * </pre>
    3275         *
    3276         * @param array  the array of values to join together, may be null
    3277         * @param separator  the separator character to use, null treated as ""
    3278         * @param startIndex the first index to start joining from.  It is
    3279         * an error to pass in an end index past the end of the array
    3280         * @param endIndex the index to stop joining from (exclusive). It is
    3281         * an error to pass in an end index past the end of the array
    3282         * @return the joined String, <code>null</code> if null array input
    3283         */
    3284        public static String join(Object[] array, String separator, int startIndex, int endIndex) {
    3285            if (array == null) {
    3286                return null;
    3287            }
    3288            if (separator == null) {
    3289                separator = EMPTY;
    3290            }
    3291
    3292            // endIndex - startIndex > 0:   Len = NofStrings *(len(firstString) + len(separator))
    3293            //           (Assuming that all Strings are roughly equally long)
    3294            int bufSize = (endIndex - startIndex);
    3295            if (bufSize <= 0) {
    3296                return EMPTY;
    3297            }
    3298
    3299            bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length())
    3300                            + separator.length());
    3301
    3302            StrBuilder buf = new StrBuilder(bufSize);
    3303
    3304            for (int i = startIndex; i < endIndex; i++) {
    3305                if (i > startIndex) {
    3306                    buf.append(separator);
    3307                }
    3308                if (array[i] != null) {
    3309                    buf.append(array[i]);
    3310                }
    3311            }
    3312            return buf.toString();
    3313        }
    3314
    3315        /**
    3316         * <p>Joins the elements of the provided <code>Iterator</code> into
    3317         * a single String containing the provided elements.</p>
    3318         *
    3319         * <p>No delimiter is added before or after the list. Null objects or empty
    3320         * strings within the iteration are represented by empty strings.</p>
    3321         *
    3322         * <p>See the examples here: {@link #join(Object[],char)}. </p>
    3323         *
    3324         * @param iterator  the <code>Iterator</code> of values to join together, may be null
    3325         * @param separator  the separator character to use
    3326         * @return the joined String, <code>null</code> if null iterator input
    3327         * @since 2.0
    3328         */
    3329        public static String join(Iterator iterator, char separator) {
    3330
    3331            // handle null, zero and one elements before building a buffer
    3332            if (iterator == null) {
    3333                return null;
    3334            }
    3335            if (!iterator.hasNext()) {
    3336                return EMPTY;
    3337            }
    3338            Object first = iterator.next();
    3339            if (!iterator.hasNext()) {
    3340                return ObjectUtils.toString(first);
    3341            }
    3342
    3343            // two or more elements
    3344            StrBuilder buf = new StrBuilder(256); // Java default is 16, probably too small
    3345            if (first != null) {
    3346                buf.append(first);
    3347            }
    3348
    3349            while (iterator.hasNext()) {
    3350                buf.append(separator);
    3351                Object obj = iterator.next();
    3352                if (obj != null) {
    3353                    buf.append(obj);
    3354                }
    3355            }
    3356
    3357            return buf.toString();
    3358        }
    3359
    3360        /**
    3361         * <p>Joins the elements of the provided <code>Iterator</code> into
    3362         * a single String containing the provided elements.</p>
    3363         *
    3364         * <p>No delimiter is added before or after the list.
    3365         * A <code>null</code> separator is the same as an empty String ("").</p>
    3366         *
    3367         * <p>See the examples here: {@link #join(Object[],String)}. </p>
    3368         *
    3369         * @param iterator  the <code>Iterator</code> of values to join together, may be null
    3370         * @param separator  the separator character to use, null treated as ""
    3371         * @return the joined String, <code>null</code> if null iterator input
    3372         */
    3373        public static String join(Iterator iterator, String separator) {
    3374
    3375            // handle null, zero and one elements before building a buffer
    3376            if (iterator == null) {
    3377                return null;
    3378            }
    3379            if (!iterator.hasNext()) {
    3380                return EMPTY;
    3381            }
    3382            Object first = iterator.next();
    3383            if (!iterator.hasNext()) {
    3384                return ObjectUtils.toString(first);
    3385            }
    3386
    3387            // two or more elements
    3388            StrBuilder buf = new StrBuilder(256); // Java default is 16, probably too small
    3389            if (first != null) {
    3390                buf.append(first);
    3391            }
    3392
    3393            while (iterator.hasNext()) {
    3394                if (separator != null) {
    3395                    buf.append(separator);
    3396                }
    3397                Object obj = iterator.next();
    3398                if (obj != null) {
    3399                    buf.append(obj);
    3400                }
    3401            }
    3402            return buf.toString();
    3403        }
    3404
    3405        /**
    3406         * <p>Joins the elements of the provided <code>Collection</code> into
    3407         * a single String containing the provided elements.</p>
    3408         *
    3409         * <p>No delimiter is added before or after the list. Null objects or empty
    3410         * strings within the iteration are represented by empty strings.</p>
    3411         *
    3412         * <p>See the examples here: {@link #join(Object[],char)}. </p>
    3413         *
    3414         * @param collection  the <code>Collection</code> of values to join together, may be null
    3415         * @param separator  the separator character to use
    3416         * @return the joined String, <code>null</code> if null iterator input
    3417         * @since 2.3
    3418         */
    3419        public static String join(Collection collection, char separator) {
    3420            if (collection == null) {
    3421                return null;
    3422            }
    3423            return join(collection.iterator(), separator);
    3424        }
    3425
    3426        /**
    3427         * <p>Joins the elements of the provided <code>Collection</code> into
    3428         * a single String containing the provided elements.</p>
    3429         *
    3430         * <p>No delimiter is added before or after the list.
    3431         * A <code>null</code> separator is the same as an empty String ("").</p>
    3432         *
    3433         * <p>See the examples here: {@link #join(Object[],String)}. </p>
    3434         *
    3435         * @param collection  the <code>Collection</code> of values to join together, may be null
    3436         * @param separator  the separator character to use, null treated as ""
    3437         * @return the joined String, <code>null</code> if null iterator input
    3438         * @since 2.3
    3439         */
    3440        public static String join(Collection collection, String separator) {
    3441            if (collection == null) {
    3442                return null;
    3443            }
    3444            return join(collection.iterator(), separator);
    3445        }
    3446
    3447        // Delete
    3448        //-----------------------------------------------------------------------
    3449        /**
    3450         * <p>Deletes all 'space' characters from a String as defined by
    3451         * {@link Character#isSpace(char)}.</p>
    3452         *
    3453         * <p>This is the only StringUtils method that uses the
    3454         * <code>isSpace</code> definition. You are advised to use
    3455         * {@link #deleteWhitespace(String)} instead as whitespace is much
    3456         * better localized.</p>
    3457         *
    3458         * <pre>
    3459         * StringUtils.deleteSpaces(null)           = null
    3460         * StringUtils.deleteSpaces("")             = ""
    3461         * StringUtils.deleteSpaces("abc")          = "abc"
    3462         * StringUtils.deleteSpaces(" \t  abc \n ") = "abc"
    3463         * StringUtils.deleteSpaces("ab  c")        = "abc"
    3464         * StringUtils.deleteSpaces("a\nb\tc     ") = "abc"
    3465         * </pre>
    3466         *
    3467         * <p>Spaces are defined as <code>{' ', '\t', '\r', '\n', '\b'}</code>
    3468         * in line with the deprecated <code>isSpace</code> method.</p>
    3469         *
    3470         * @param str  the String to delete spaces from, may be null
    3471         * @return the String without 'spaces', <code>null</code> if null String input
    3472         * @deprecated Use the better localized {@link #deleteWhitespace(String)}.
    3473         *             Method will be removed in Commons Lang 3.0.
    3474         */
    3475        public static String deleteSpaces(String str) {
    3476            if (str == null) {
    3477                return null;
    3478            }
    3479            return CharSetUtils.delete(str, " \t\r\n\b");
    3480        }
    3481
    3482        /**
    3483         * <p>Deletes all whitespaces from a String as defined by
    3484         * {@link Character#isWhitespace(char)}.</p>
    3485         *
    3486         * <pre>
    3487         * StringUtils.deleteWhitespace(null)         = null
    3488         * StringUtils.deleteWhitespace("")           = ""
    3489         * StringUtils.deleteWhitespace("abc")        = "abc"
    3490         * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
    3491         * </pre>
    3492         *
    3493         * @param str  the String to delete whitespace from, may be null
    3494         * @return the String without whitespaces, <code>null</code> if null String input
    3495         */
    3496        public static String deleteWhitespace(String str) {
    3497            if (isEmpty(str)) {
    3498                return str;
    3499            }
    3500            int sz = str.length();
    3501            char[] chs = new char[sz];
    3502            int count = 0;
    3503            for (int i = 0; i < sz; i++) {
    3504                if (!Character.isWhitespace(str.charAt(i))) {
    3505                    chs[count++] = str.charAt(i);
    3506                }
    3507            }
    3508            if (count == sz) {
    3509                return str;
    3510            }
    3511            return new String(chs, 0, count);
    3512        }
    3513
    3514        // Remove
    3515        //-----------------------------------------------------------------------
    3516        /**
    3517         * <p>Removes a substring only if it is at the begining of a source string,
    3518         * otherwise returns the source string.</p>
    3519         *
    3520         * <p>A <code>null</code> source string will return <code>null</code>.
    3521         * An empty ("") source string will return the empty string.
    3522         * A <code>null</code> search string will return the source string.</p>
    3523         *
    3524         * <pre>
    3525         * StringUtils.removeStart(null, *)      = null
    3526         * StringUtils.removeStart("", *)        = ""
    3527         * StringUtils.removeStart(*, null)      = *
    3528         * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
    3529         * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
    3530         * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
    3531         * StringUtils.removeStart("abc", "")    = "abc"
    3532         * </pre>
    3533         *
    3534         * @param str  the source String to search, may be null
    3535         * @param remove  the String to search for and remove, may be null
    3536         * @return the substring with the string removed if found,
    3537         *  <code>null</code> if null String input
    3538         * @since 2.1
    3539         */
    3540        public static String removeStart(String str, String remove) {
    3541            if (isEmpty(str) || isEmpty(remove)) {
    3542                return str;
    3543            }
    3544            if (str.startsWith(remove)){
    3545                return str.substring(remove.length());
    3546            }
    3547            return str;
    3548        }
    3549
    3550        /**
    3551         * <p>Case insensitive removal of a substring if it is at the begining of a source string,
    3552         * otherwise returns the source string.</p>
    3553         *
    3554         * <p>A <code>null</code> source string will return <code>null</code>.
    3555         * An empty ("") source string will return the empty string.
    3556         * A <code>null</code> search string will return the source string.</p>
    3557         *
    3558         * <pre>
    3559         * StringUtils.removeStartIgnoreCase(null, *)      = null
    3560         * StringUtils.removeStartIgnoreCase("", *)        = ""
    3561         * StringUtils.removeStartIgnoreCase(*, null)      = *
    3562         * StringUtils.removeStartIgnoreCase("www.domain.com", "www.")   = "domain.com"
    3563         * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.")   = "domain.com"
    3564         * StringUtils.removeStartIgnoreCase("domain.com", "www.")       = "domain.com"
    3565         * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
    3566         * StringUtils.removeStartIgnoreCase("abc", "")    = "abc"
    3567         * </pre>
    3568         *
    3569         * @param str  the source String to search, may be null
    3570         * @param remove  the String to search for (case insensitive) and remove, may be null
    3571         * @return the substring with the string removed if found,
    3572         *  <code>null</code> if null String input
    3573         * @since 2.4
    3574         */
    3575        public static String removeStartIgnoreCase(String str, String remove) {
    3576            if (isEmpty(str) || isEmpty(remove)) {
    3577                return str;
    3578            }
    3579            if (startsWithIgnoreCase(str, remove)) {
    3580                return str.substring(remove.length());
    3581            }
    3582            return str;
    3583        }
    3584
    3585        /**
    3586         * <p>Removes a substring only if it is at the end of a source string,
    3587         * otherwise returns the source string.</p>
    3588         *
    3589         * <p>A <code>null</code> source string will return <code>null</code>.
    3590         * An empty ("") source string will return the empty string.
    3591         * A <code>null</code> search string will return the source string.</p>
    3592         *
    3593         * <pre>
    3594         * StringUtils.removeEnd(null, *)      = null
    3595         * StringUtils.removeEnd("", *)        = ""
    3596         * StringUtils.removeEnd(*, null)      = *
    3597         * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
    3598         * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
    3599         * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
    3600         * StringUtils.removeEnd("abc", "")    = "abc"
    3601         * </pre>
    3602         *
    3603         * @param str  the source String to search, may be null
    3604         * @param remove  the String to search for and remove, may be null
    3605         * @return the substring with the string removed if found,
    3606         *  <code>null</code> if null String input
    3607         * @since 2.1
    3608         */
    3609        public static String removeEnd(String str, String remove) {
    3610            if (isEmpty(str) || isEmpty(remove)) {
    3611                return str;
    3612            }
    3613            if (str.endsWith(remove)) {
    3614                return str.substring(0, str.length() - remove.length());
    3615            }
    3616            return str;
    3617        }
    3618
    3619        /**
    3620         * <p>Case insensitive removal of a substring if it is at the end of a source string,
    3621         * otherwise returns the source string.</p>
    3622         *
    3623         * <p>A <code>null</code> source string will return <code>null</code>.
    3624         * An empty ("") source string will return the empty string.
    3625         * A <code>null</code> search string will return the source string.</p>
    3626         *
    3627         * <pre>
    3628         * StringUtils.removeEndIgnoreCase(null, *)      = null
    3629         * StringUtils.removeEndIgnoreCase("", *)        = ""
    3630         * StringUtils.removeEndIgnoreCase(*, null)      = *
    3631         * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.")  = "www.domain.com"
    3632         * StringUtils.removeEndIgnoreCase("www.domain.com", ".com")   = "www.domain"
    3633         * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
    3634         * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"
    3635         * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
    3636         * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
    3637         * </pre>
    3638         *
    3639         * @param str  the source String to search, may be null
    3640         * @param remove  the String to search for (case insensitive) and remove, may be null
    3641         * @return the substring with the string removed if found,
    3642         *  <code>null</code> if null String input
    3643         * @since 2.4
    3644         */
    3645        public static String removeEndIgnoreCase(String str, String remove) {
    3646            if (isEmpty(str) || isEmpty(remove)) {
    3647                return str;
    3648            }
    3649            if (endsWithIgnoreCase(str, remove)) {
    3650                return str.substring(0, str.length() - remove.length());
    3651            }
    3652            return str;
    3653        }
    3654
    3655        /**
    3656         * <p>Removes all occurrences of a substring from within the source string.</p>
    3657         *
    3658         * <p>A <code>null</code> source string will return <code>null</code>.
    3659         * An empty ("") source string will return the empty string.
    3660         * A <code>null</code> remove string will return the source string.
    3661         * An empty ("") remove string will return the source string.</p>
    3662         *
    3663         * <pre>
    3664         * StringUtils.remove(null, *)        = null
    3665         * StringUtils.remove("", *)          = ""
    3666         * StringUtils.remove(*, null)        = *
    3667         * StringUtils.remove(*, "")          = *
    3668         * StringUtils.remove("queued", "ue") = "qd"
    3669         * StringUtils.remove("queued", "zz") = "queued"
    3670         * </pre>
    3671         *
    3672         * @param str  the source String to search, may be null
    3673         * @param remove  the String to search for and remove, may be null
    3674         * @return the substring with the string removed if found,
    3675         *  <code>null</code> if null String input
    3676         * @since 2.1
    3677         */
    3678        public static String remove(String str, String remove) {
    3679            if (isEmpty(str) || isEmpty(remove)) {
    3680                return str;
    3681            }
    3682            return replace(str, remove, EMPTY, -1);
    3683        }
    3684
    3685        /**
    3686         * <p>Removes all occurrences of a character from within the source string.</p>
    3687         *
    3688         * <p>A <code>null</code> source string will return <code>null</code>.
    3689         * An empty ("") source string will return the empty string.</p>
    3690         *
    3691         * <pre>
    3692         * StringUtils.remove(null, *)       = null
    3693         * StringUtils.remove("", *)         = ""
    3694         * StringUtils.remove("queued", 'u') = "qeed"
    3695         * StringUtils.remove("queued", 'z') = "queued"
    3696         * </pre>
    3697         *
    3698         * @param str  the source String to search, may be null
    3699         * @param remove  the char to search for and remove, may be null
    3700         * @return the substring with the char removed if found,
    3701         *  <code>null</code> if null String input
    3702         * @since 2.1
    3703         */
    3704        public static String remove(String str, char remove) {
    3705            if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
    3706                return str;
    3707            }
    3708            char[] chars = str.toCharArray();
    3709            int pos = 0;
    3710            for (int i = 0; i < chars.length; i++) {
    3711                if (chars[i] != remove) {
    3712                    chars[pos++] = chars[i];
    3713                }
    3714            }
    3715            return new String(chars, 0, pos);
    3716        }
    3717
    3718        // Replacing
    3719        //-----------------------------------------------------------------------
    3720        /**
    3721         * <p>Replaces a String with another String inside a larger String, once.</p>
    3722         *
    3723         * <p>A <code>null</code> reference passed to this method is a no-op.</p>
    3724         *
    3725         * <pre>
    3726         * StringUtils.replaceOnce(null, *, *)        = null
    3727         * StringUtils.replaceOnce("", *, *)          = ""
    3728         * StringUtils.replaceOnce("any", null, *)    = "any"
    3729         * StringUtils.replaceOnce("any", *, null)    = "any"
    3730         * StringUtils.replaceOnce("any", "", *)      = "any"
    3731         * StringUtils.replaceOnce("aba", "a", null)  = "aba"
    3732         * StringUtils.replaceOnce("aba", "a", "")    = "ba"
    3733         * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
    3734         * </pre>
    3735         *
    3736         * @see #replace(String text, String searchString, String replacement, int max)
    3737         * @param text  text to search and replace in, may be null
    3738         * @param searchString  the String to search for, may be null
    3739         * @param replacement  the String to replace with, may be null
    3740         * @return the text with any replacements processed,
    3741         *  <code>null</code> if null String input
    3742         */
    3743        public static String replaceOnce(String text, String searchString, String replacement) {
    3744            return replace(text, searchString, replacement, 1);
    3745        }
    3746
    3747        /**
    3748         * <p>Replaces all occurrences of a String within another String.</p>
    3749         *
    3750         * <p>A <code>null</code> reference passed to this method is a no-op.</p>
    3751         *
    3752         * <pre>
    3753         * StringUtils.replace(null, *, *)        = null
    3754         * StringUtils.replace("", *, *)          = ""
    3755         * StringUtils.replace("any", null, *)    = "any"
    3756         * StringUtils.replace("any", *, null)    = "any"
    3757         * StringUtils.replace("any", "", *)      = "any"
    3758         * StringUtils.replace("aba", "a", null)  = "aba"
    3759         * StringUtils.replace("aba", "a", "")    = "b"
    3760         * StringUtils.replace("aba", "a", "z")   = "zbz"
    3761         * </pre>
    3762         *
    3763         * @see #replace(String text, String searchString, String replacement, int max)
    3764         * @param text  text to search and replace in, may be null
    3765         * @param searchString  the String to search for, may be null
    3766         * @param replacement  the String to replace it with, may be null
    3767         * @return the text with any replacements processed,
    3768         *  <code>null</code> if null String input
    3769         */
    3770        public static String replace(String text, String searchString, String replacement) {
    3771            return replace(text, searchString, replacement, -1);
    3772        }
    3773
    3774        /**
    3775         * <p>Replaces a String with another String inside a larger String,
    3776         * for the first <code>max</code> values of the search String.</p>
    3777         *
    3778         * <p>A <code>null</code> reference passed to this method is a no-op.</p>
    3779         *
    3780         * <pre>
    3781         * StringUtils.replace(null, *, *, *)         = null
    3782         * StringUtils.replace("", *, *, *)           = ""
    3783         * StringUtils.replace("any", null, *, *)     = "any"
    3784         * StringUtils.replace("any", *, null, *)     = "any"
    3785         * StringUtils.replace("any", "", *, *)       = "any"
    3786         * StringUtils.replace("any", *, *, 0)        = "any"
    3787         * StringUtils.replace("abaa", "a", null, -1) = "abaa"
    3788         * StringUtils.replace("abaa", "a", "", -1)   = "b"
    3789         * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
    3790         * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
    3791         * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
    3792         * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
    3793         * </pre>
    3794         *
    3795         * @param text  text to search and replace in, may be null
    3796         * @param searchString  the String to search for, may be null
    3797         * @param replacement  the String to replace it with, may be null
    3798         * @param max  maximum number of values to replace, or <code>-1</code> if no maximum
    3799         * @return the text with any replacements processed,
    3800         *  <code>null</code> if null String input
    3801         */
    3802        public static String replace(String text, String searchString, String replacement, int max) {
    3803            if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) {
    3804                return text;
    3805            }
    3806            int start = 0;
    3807            int end = text.indexOf(searchString, start);
    3808            if (end == INDEX_NOT_FOUND) {
    3809                return text;
    3810            }
    3811            int replLength = searchString.length();
    3812            int increase = replacement.length() - replLength;
    3813            increase = (increase < 0 ? 0 : increase);
    3814            increase *= (max < 0 ? 16 : (max > 64 ? 64 : max));
    3815            StrBuilder buf = new StrBuilder(text.length() + increase);
    3816            while (end != INDEX_NOT_FOUND) {
    3817                buf.append(text.substring(start, end)).append(replacement);
    3818                start = end + replLength;
    3819                if (--max == 0) {
    3820                    break;
    3821                }
    3822                end = text.indexOf(searchString, start);
    3823            }
    3824            buf.append(text.substring(start));
    3825            return buf.toString();
    3826        }
    3827
    3828        /**
    3829         * <p>
    3830         * Replaces all occurrences of Strings within another String.
    3831         * </p>
    3832         *
    3833         * <p>
    3834         * A <code>null</code> reference passed to this method is a no-op, or if
    3835         * any "search string" or "string to replace" is null, that replace will be
    3836         * ignored. This will not repeat. For repeating replaces, call the
    3837         * overloaded method.
    3838         * </p>
    3839         *
    3840         * <pre>
    3841         *  StringUtils.replaceEach(null, *, *)        = null
    3842         *  StringUtils.replaceEach("", *, *)          = ""
    3843         *  StringUtils.replaceEach("aba", null, null) = "aba"
    3844         *  StringUtils.replaceEach("aba", new String[0], null) = "aba"
    3845         *  StringUtils.replaceEach("aba", null, new String[0]) = "aba"
    3846         *  StringUtils.replaceEach("aba", new String[]{"a"}, null)  = "aba"
    3847         *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""})  = "b"
    3848         *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"})  = "aba"
    3849         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"})  = "wcte"
    3850         *  (example of how it does not repeat)
    3851         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"})  = "dcte"
    3852         * </pre>
    3853         *
    3854         * @param text
    3855         *            text to search and replace in, no-op if null
    3856         * @param searchList
    3857         *            the Strings to search for, no-op if null
    3858         * @param replacementList
    3859         *            the Strings to replace them with, no-op if null
    3860         * @return the text with any replacements processed, <code>null</code> if
    3861         *         null String input
    3862         * @throws IndexOutOfBoundsException
    3863         *             if the lengths of the arrays are not the same (null is ok,
    3864         *             and/or size 0)
    3865         * @since 2.4
    3866         */
    3867        public static String replaceEach(String text, String[] searchList, String[] replacementList) {
    3868            return replaceEach(text, searchList, replacementList, false, 0);
    3869        }
    3870
    3871        /**
    3872         * <p>
    3873         * Replaces all occurrences of Strings within another String.
    3874         * </p>
    3875         *
    3876         * <p>
    3877         * A <code>null</code> reference passed to this method is a no-op, or if
    3878         * any "search string" or "string to replace" is null, that replace will be
    3879         * ignored. This will not repeat. For repeating replaces, call the
    3880         * overloaded method.
    3881         * </p>
    3882         *
    3883         * <pre>
    3884         *  StringUtils.replaceEach(null, *, *, *) = null
    3885         *  StringUtils.replaceEach("", *, *, *) = ""
    3886         *  StringUtils.replaceEach("aba", null, null, *) = "aba"
    3887         *  StringUtils.replaceEach("aba", new String[0], null, *) = "aba"
    3888         *  StringUtils.replaceEach("aba", null, new String[0], *) = "aba"
    3889         *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba"
    3890         *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b"
    3891         *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba"
    3892         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte"
    3893         *  (example of how it repeats)
    3894         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte"
    3895         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte"
    3896         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, true) = IllegalArgumentException
    3897         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, false) = "dcabe"
    3898         * </pre>
    3899         *
    3900         * @param text
    3901         *            text to search and replace in, no-op if null
    3902         * @param searchList
    3903         *            the Strings to search for, no-op if null
    3904         * @param replacementList
    3905         *            the Strings to replace them with, no-op if null
    3906         * @return the text with any replacements processed, <code>null</code> if
    3907         *         null String input
    3908         * @throws IllegalArgumentException
    3909         *             if the search is repeating and there is an endless loop due
    3910         *             to outputs of one being inputs to another
    3911         * @throws IndexOutOfBoundsException
    3912         *             if the lengths of the arrays are not the same (null is ok,
    3913         *             and/or size 0)
    3914         * @since 2.4
    3915         */
    3916        public static String replaceEachRepeatedly(String text, String[] searchList, String[] replacementList) {
    3917            // timeToLive should be 0 if not used or nothing to replace, else it's
    3918            // the length of the replace array
    3919            int timeToLive = searchList == null ? 0 : searchList.length;
    3920            return replaceEach(text, searchList, replacementList, true, timeToLive);
    3921        }
    3922
    3923        /**
    3924         * <p>
    3925         * Replaces all occurrences of Strings within another String.
    3926         * </p>
    3927         *
    3928         * <p>
    3929         * A <code>null</code> reference passed to this method is a no-op, or if
    3930         * any "search string" or "string to replace" is null, that replace will be
    3931         * ignored.
    3932         * </p>
    3933         *
    3934         * <pre>
    3935         *  StringUtils.replaceEach(null, *, *, *) = null
    3936         *  StringUtils.replaceEach("", *, *, *) = ""
    3937         *  StringUtils.replaceEach("aba", null, null, *) = "aba"
    3938         *  StringUtils.replaceEach("aba", new String[0], null, *) = "aba"
    3939         *  StringUtils.replaceEach("aba", null, new String[0], *) = "aba"
    3940         *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba"
    3941         *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b"
    3942         *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba"
    3943         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte"
    3944         *  (example of how it repeats)
    3945         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte"
    3946         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte"
    3947         *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *) = IllegalArgumentException
    3948         * </pre>
    3949         *
    3950         * @param text
    3951         *            text to search and replace in, no-op if null
    3952         * @param searchList
    3953         *            the Strings to search for, no-op if null
    3954         * @param replacementList
    3955         *            the Strings to replace them with, no-op if null
    3956         * @param repeat if true, then replace repeatedly
    3957         *       until there are no more possible replacements or timeToLive < 0
    3958         * @param timeToLive
    3959         *            if less than 0 then there is a circular reference and endless
    3960         *            loop
    3961         * @return the text with any replacements processed, <code>null</code> if
    3962         *         null String input
    3963         * @throws IllegalArgumentException
    3964         *             if the search is repeating and there is an endless loop due
    3965         *             to outputs of one being inputs to another
    3966         * @throws IndexOutOfBoundsException
    3967         *             if the lengths of the arrays are not the same (null is ok,
    3968         *             and/or size 0)
    3969         * @since 2.4
    3970         */
    3971        private static String replaceEach(String text, String[] searchList, String[] replacementList,
    3972                                          boolean repeat, int timeToLive)
    3973        {
    3974
    3975            // mchyzer Performance note: This creates very few new objects (one major goal)
    3976            // let me know if there are performance requests, we can create a harness to measure
    3977
    3978            if (text == null || text.length() == 0 || searchList == null ||
    3979                searchList.length == 0 || replacementList == null || replacementList.length == 0)
    3980            {
    3981                return text;
    3982            }
    3983
    3984            // if recursing, this shouldnt be less than 0
    3985            if (timeToLive < 0) {
    3986                throw new IllegalStateException("TimeToLive of " + timeToLive + " is less than 0: " + text);
    3987            }
    3988
    3989            int searchLength = searchList.length;
    3990            int replacementLength = replacementList.length;
    3991
    3992            // make sure lengths are ok, these need to be equal
    3993            if (searchLength != replacementLength) {
    3994                throw new IllegalArgumentException("Search and Replace array lengths don't match: "
    3995                    + searchLength
    3996                    + " vs "
    3997                    + replacementLength);
    3998            }
    3999
    4000            // keep track of which still have matches
    4001            boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
    4002
    4003            // index on index that the match was found
    4004            int textIndex = -1;
    4005            int replaceIndex = -1;
    4006            int tempIndex = -1;
    4007
    4008            // index of replace array that will replace the search string found
    4009            // NOTE: logic duplicated below START
    4010            for (int i = 0; i < searchLength; i++) {
    4011                if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
    4012                    searchList[i].length() == 0 || replacementList[i] == null)
    4013                {
    4014                    continue;
    4015                }
    4016                tempIndex = text.indexOf(searchList[i]);
    4017
    4018                // see if we need to keep searching for this
    4019                if (tempIndex == -1) {
    4020                    noMoreMatchesForReplIndex[i] = true;
    4021                } else {
    4022                    if (textIndex == -1 || tempIndex < textIndex) {
    4023                        textIndex = tempIndex;
    4024                        replaceIndex = i;
    4025                    }
    4026                }
    4027            }
    4028            // NOTE: logic mostly below END
    4029
    4030            // no search strings found, we are done
    4031            if (textIndex == -1) {
    4032                return text;
    4033            }
    4034
    4035            int start = 0;
    4036
    4037            // get a good guess on the size of the result buffer so it doesnt have to double if it goes over a bit
    4038            int increase = 0;
    4039
    4040            // count the replacement text elements that are larger than their corresponding text being replaced
    4041            for (int i = 0; i < searchList.length; i++) {
    4042                if (searchList[i] == null || replacementList[i] == null) {
    4043                    continue;
    4044                }
    4045                int greater = replacementList[i].length() - searchList[i].length();
    4046                if (greater > 0) {
    4047                    increase += 3 * greater; // assume 3 matches
    4048                }
    4049            }
    4050            // have upper-bound at 20% increase, then let Java take over
    4051            increase = Math.min(increase, text.length() / 5);
    4052
    4053            StrBuilder buf = new StrBuilder(text.length() + increase);
    4054
    4055            while (textIndex != -1) {
    4056
    4057                for (int i = start; i < textIndex; i++) {
    4058                    buf.append(text.charAt(i));
    4059                }
    4060                buf.append(replacementList[replaceIndex]);
    4061
    4062                start = textIndex + searchList[replaceIndex].length();
    4063
    4064                textIndex = -1;
    4065                replaceIndex = -1;
    4066                tempIndex = -1;
    4067                // find the next earliest match
    4068                // NOTE: logic mostly duplicated above START
    4069                for (int i = 0; i < searchLength; i++) {
    4070                    if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
    4071                        searchList[i].length() == 0 || replacementList[i] == null)
    4072                    {
    4073                        continue;
    4074                    }
    4075                    tempIndex = text.indexOf(searchList[i], start);
    4076
    4077                    // see if we need to keep searching for this
    4078                    if (tempIndex == -1) {
    4079                        noMoreMatchesForReplIndex[i] = true;
    4080                    } else {
    4081                        if (textIndex == -1 || tempIndex < textIndex) {
    4082                            textIndex = tempIndex;
    4083                            replaceIndex = i;
    4084                        }
    4085                    }
    4086                }
    4087                // NOTE: logic duplicated above END
    4088
    4089            }
    4090            int textLength = text.length();
    4091            for (int i = start; i < textLength; i++) {
    4092                buf.append(text.charAt(i));
    4093            }
    4094            String result = buf.toString();
    4095            if (!repeat) {
    4096                return result;
    4097            }
    4098
    4099            return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
    4100        }
    4101
    4102        // Replace, character based
    4103        //-----------------------------------------------------------------------
    4104        /**
    4105         * <p>Replaces all occurrences of a character in a String with another.
    4106         * This is a null-safe version of {@link String#replace(char, char)}.</p>
    4107         *
    4108         * <p>A <code>null</code> string input returns <code>null</code>.
    4109         * An empty ("") string input returns an empty string.</p>
    4110         *
    4111         * <pre>
    4112         * StringUtils.replaceChars(null, *, *)        = null
    4113         * StringUtils.replaceChars("", *, *)          = ""
    4114         * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
    4115         * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
    4116         * </pre>
    4117         *
    4118         * @param str  String to replace characters in, may be null
    4119         * @param searchChar  the character to search for, may be null
    4120         * @param replaceChar  the character to replace, may be null
    4121         * @return modified String, <code>null</code> if null string input
    4122         * @since 2.0
    4123         */
    4124        public static String replaceChars(String str, char searchChar, char replaceChar) {
    4125            if (str == null) {
    4126                return null;
    4127            }
    4128            return str.replace(searchChar, replaceChar);
    4129        }
    4130
    4131        /**
    4132         * <p>Replaces multiple characters in a String in one go.
    4133         * This method can also be used to delete characters.</p>
    4134         *
    4135         * <p>For example:<br />
    4136         * <code>replaceChars(&quot;hello&quot;, &quot;ho&quot;, &quot;jy&quot;) = jelly</code>.</p>
    4137         *
    4138         * <p>A <code>null</code> string input returns <code>null</code>.
    4139         * An empty ("") string input returns an empty string.
    4140         * A null or empty set of search characters returns the input string.</p>
    4141         *
    4142         * <p>The length of the search characters should normally equal the length
    4143         * of the replace characters.
    4144         * If the search characters is longer, then the extra search characters
    4145         * are deleted.
    4146         * If the search characters is shorter, then the extra replace characters
    4147         * are ignored.</p>
    4148         *
    4149         * <pre>
    4150         * StringUtils.replaceChars(null, *, *)           = null
    4151         * StringUtils.replaceChars("", *, *)             = ""
    4152         * StringUtils.replaceChars("abc", null, *)       = "abc"
    4153         * StringUtils.replaceChars("abc", "", *)         = "abc"
    4154         * StringUtils.replaceChars("abc", "b", null)     = "ac"
    4155         * StringUtils.replaceChars("abc", "b", "")       = "ac"
    4156         * StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
    4157         * StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
    4158         * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
    4159         * </pre>
    4160         *
    4161         * @param str  String to replace characters in, may be null
    4162         * @param searchChars  a set of characters to search for, may be null
    4163         * @param replaceChars  a set of characters to replace, may be null
    4164         * @return modified String, <code>null</code> if null string input
    4165         * @since 2.0
    4166         */
    4167        public static String replaceChars(String str, String searchChars, String replaceChars) {
    4168            if (isEmpty(str) || isEmpty(searchChars)) {
    4169                return str;
    4170            }
    4171            if (replaceChars == null) {
    4172                replaceChars = EMPTY;
    4173            }
    4174            boolean modified = false;
    4175            int replaceCharsLength = replaceChars.length();
    4176            int strLength = str.length();
    4177            StrBuilder buf = new StrBuilder(strLength);
    4178            for (int i = 0; i < strLength; i++) {
    4179                char ch = str.charAt(i);
    4180                int index = searchChars.indexOf(ch);
    4181                if (index >= 0) {
    4182                    modified = true;
    4183                    if (index < replaceCharsLength) {
    4184                        buf.append(replaceChars.charAt(index));
    4185                    }
    4186                } else {
    4187                    buf.append(ch);
    4188                }
    4189            }
    4190            if (modified) {
    4191                return buf.toString();
    4192            }
    4193            return str;
    4194        }
    4195
    4196        // Overlay
    4197        //-----------------------------------------------------------------------
    4198        /**
    4199         * <p>Overlays part of a String with another String.</p>
    4200         *
    4201         * <pre>
    4202         * StringUtils.overlayString(null, *, *, *)           = NullPointerException
    4203         * StringUtils.overlayString(*, null, *, *)           = NullPointerException
    4204         * StringUtils.overlayString("", "abc", 0, 0)         = "abc"
    4205         * StringUtils.overlayString("abcdef", null, 2, 4)    = "abef"
    4206         * StringUtils.overlayString("abcdef", "", 2, 4)      = "abef"
    4207         * StringUtils.overlayString("abcdef", "zzzz", 2, 4)  = "abzzzzef"
    4208         * StringUtils.overlayString("abcdef", "zzzz", 4, 2)  = "abcdzzzzcdef"
    4209         * StringUtils.overlayString("abcdef", "zzzz", -1, 4) = IndexOutOfBoundsException
    4210         * StringUtils.overlayString("abcdef", "zzzz", 2, 8)  = IndexOutOfBoundsException
    4211         * </pre>
    4212         *
    4213         * @param text  the String to do overlaying in, may be null
    4214         * @param overlay  the String to overlay, may be null
    4215         * @param start  the position to start overlaying at, must be valid
    4216         * @param end  the position to stop overlaying before, must be valid
    4217         * @return overlayed String, <code>null</code> if null String input
    4218         * @throws NullPointerException if text or overlay is null
    4219         * @throws IndexOutOfBoundsException if either position is invalid
    4220         * @deprecated Use better named {@link #overlay(String, String, int, int)} instead.
    4221         *             Method will be removed in Commons Lang 3.0.
    4222         */
    4223        public static String overlayString(String text, String overlay, int start, int end) {
    4224            return new StrBuilder(start + overlay.length() + text.length() - end + 1)
    4225                .append(text.substring(0, start))
    4226                .append(overlay)
    4227                .append(text.substring(end))
    4228                .toString();
    4229        }
    4230
    4231        /**
    4232         * <p>Overlays part of a String with another String.</p>
    4233         *
    4234         * <p>A <code>null</code> string input returns <code>null</code>.
    4235         * A negative index is treated as zero.
    4236         * An index greater than the string length is treated as the string length.
    4237         * The start index is always the smaller of the two indices.</p>
    4238         *
    4239         * <pre>
    4240         * StringUtils.overlay(null, *, *, *)            = null
    4241         * StringUtils.overlay("", "abc", 0, 0)          = "abc"
    4242         * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
    4243         * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
    4244         * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
    4245         * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
    4246         * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
    4247         * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
    4248         * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
    4249         * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
    4250         * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
    4251         * </pre>
    4252         *
    4253         * @param str  the String to do overlaying in, may be null
    4254         * @param overlay  the String to overlay, may be null
    4255         * @param start  the position to start overlaying at
    4256         * @param end  the position to stop overlaying before
    4257         * @return overlayed String, <code>null</code> if null String input
    4258         * @since 2.0
    4259         */
    4260        public static String overlay(String str, String overlay, int start, int end) {
    4261            if (str == null) {
    4262                return null;
    4263            }
    4264            if (overlay == null) {
    4265                overlay = EMPTY;
    4266            }
    4267            int len = str.length();
    4268            if (start < 0) {
    4269                start = 0;
    4270            }
    4271            if (start > len) {
    4272                start = len;
    4273            }
    4274            if (end < 0) {
    4275                end = 0;
    4276            }
    4277            if (end > len) {
    4278                end = len;
    4279            }
    4280            if (start > end) {
    4281                int temp = start;
    4282                start = end;
    4283                end = temp;
    4284            }
    4285            return new StrBuilder(len + start - end + overlay.length() + 1)
    4286                .append(str.substring(0, start))
    4287                .append(overlay)
    4288                .append(str.substring(end))
    4289                .toString();
    4290        }
    4291
    4292        // Chomping
    4293        //-----------------------------------------------------------------------
    4294        /**
    4295         * <p>Removes one newline from end of a String if it's there,
    4296         * otherwise leave it alone.  A newline is &quot;<code>\n</code>&quot;,
    4297         * &quot;<code>\r</code>&quot;, or &quot;<code>\r\n</code>&quot;.</p>
    4298         *
    4299         * <p>NOTE: This method changed in 2.0.
    4300         * It now more closely matches Perl chomp.</p>
    4301         *
    4302         * <pre>
    4303         * StringUtils.chomp(null)          = null
    4304         * StringUtils.chomp("")            = ""
    4305         * StringUtils.chomp("abc \r")      = "abc "
    4306         * StringUtils.chomp("abc\n")       = "abc"
    4307         * StringUtils.chomp("abc\r\n")     = "abc"
    4308         * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
    4309         * StringUtils.chomp("abc\n\r")     = "abc\n"
    4310         * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
    4311         * StringUtils.chomp("\r")          = ""
    4312         * StringUtils.chomp("\n")          = ""
    4313         * StringUtils.chomp("\r\n")        = ""
    4314         * </pre>
    4315         *
    4316         * @param str  the String to chomp a newline from, may be null
    4317         * @return String without newline, <code>null</code> if null String input
    4318         */
    4319        public static String chomp(String str) {
    4320            if (isEmpty(str)) {
    4321                return str;
    4322            }
    4323
    4324            if (str.length() == 1) {
    4325                char ch = str.charAt(0);
    4326                if (ch == CharUtils.CR || ch == CharUtils.LF) {
    4327                    return EMPTY;
    4328                }
    4329                return str;
    4330            }
    4331
    4332            int lastIdx = str.length() - 1;
    4333            char last = str.charAt(lastIdx);
    4334
    4335            if (last == CharUtils.LF) {
    4336                if (str.charAt(lastIdx - 1) == CharUtils.CR) {
    4337                    lastIdx--;
    4338                }
    4339            } else if (last != CharUtils.CR) {
    4340                lastIdx++;
    4341            }
    4342            return str.substring(0, lastIdx);
    4343        }
    4344
    4345        /**
    4346         * <p>Removes <code>separator</code> from the end of
    4347         * <code>str</code> if it's there, otherwise leave it alone.</p>
    4348         *
    4349         * <p>NOTE: This method changed in version 2.0.
    4350         * It now more closely matches Perl chomp.
    4351         * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
    4352         * This method uses {@link String#endsWith(String)}.</p>
    4353         *
    4354         * <pre>
    4355         * StringUtils.chomp(null, *)         = null
    4356         * StringUtils.chomp("", *)           = ""
    4357         * StringUtils.chomp("foobar", "bar") = "foo"
    4358         * StringUtils.chomp("foobar", "baz") = "foobar"
    4359         * StringUtils.chomp("foo", "foo")    = ""
    4360         * StringUtils.chomp("foo ", "foo")   = "foo "
    4361         * StringUtils.chomp(" foo", "foo")   = " "
    4362         * StringUtils.chomp("foo", "foooo")  = "foo"
    4363         * StringUtils.chomp("foo", "")       = "foo"
    4364         * StringUtils.chomp("foo", null)     = "foo"
    4365         * </pre>
    4366         *
    4367         * @param str  the String to chomp from, may be null
    4368         * @param separator  separator String, may be null
    4369         * @return String without trailing separator, <code>null</code> if null String input
    4370         */
    4371        public static String chomp(String str, String separator) {
    4372            if (isEmpty(str) || separator == null) {
    4373                return str;
    4374            }
    4375            if (str.endsWith(separator)) {
    4376                return str.substring(0, str.length() - separator.length());
    4377            }
    4378            return str;
    4379        }
    4380
    4381        /**
    4382         * <p>Remove any &quot;\n&quot; if and only if it is at the end
    4383         * of the supplied String.</p>
    4384         *
    4385         * @param str  the String to chomp from, must not be null
    4386         * @return String without chomped ending
    4387         * @throws NullPointerException if str is <code>null</code>
    4388         * @deprecated Use {@link #chomp(String)} instead.
    4389         *             Method will be removed in Commons Lang 3.0.
    4390         */
    4391        public static String chompLast(String str) {
    4392            return chompLast(str, "\n");
    4393        }
    4394
    4395        /**
    4396         * <p>Remove a value if and only if the String ends with that value.</p>
    4397         *
    4398         * @param str  the String to chomp from, must not be null
    4399         * @param sep  the String to chomp, must not be null
    4400         * @return String without chomped ending
    4401         * @throws NullPointerException if str or sep is <code>null</code>
    4402         * @deprecated Use {@link #chomp(String,String)} instead.
    4403         *             Method will be removed in Commons Lang 3.0.
    4404         */
    4405        public static String chompLast(String str, String sep) {
    4406            if (str.length() == 0) {
    4407                return str;
    4408            }
    4409            String sub = str.substring(str.length() - sep.length());
    4410            if (sep.equals(sub)) {
    4411                return str.substring(0, str.length() - sep.length());
    4412            }
    4413            return str;
    4414        }
    4415
    4416        /**
    4417         * <p>Remove everything and return the last value of a supplied String, and
    4418         * everything after it from a String.</p>
    4419         *
    4420         * @param str  the String to chomp from, must not be null
    4421         * @param sep  the String to chomp, must not be null
    4422         * @return String chomped
    4423         * @throws NullPointerException if str or sep is <code>null</code>
    4424         * @deprecated Use {@link #substringAfterLast(String, String)} instead
    4425         *             (although this doesn't include the separator)
    4426         *             Method will be removed in Commons Lang 3.0.
    4427         */
    4428        public static String getChomp(String str, String sep) {
    4429            int idx = str.lastIndexOf(sep);
    4430            if (idx == str.length() - sep.length()) {
    4431                return sep;
    4432            } else if (idx != -1) {
    4433                return str.substring(idx);
    4434            } else {
    4435                return EMPTY;
    4436            }
    4437        }
    4438
    4439        /**
    4440         * <p>Remove the first value of a supplied String, and everything before it
    4441         * from a String.</p>
    4442         *
    4443         * @param str  the String to chomp from, must not be null
    4444         * @param sep  the String to chomp, must not be null
    4445         * @return String without chomped beginning
    4446         * @throws NullPointerException if str or sep is <code>null</code>
    4447         * @deprecated Use {@link #substringAfter(String,String)} instead.
    4448         *             Method will be removed in Commons Lang 3.0.
    4449         */
    4450        public static String prechomp(String str, String sep) {
    4451            int idx = str.indexOf(sep);
    4452            if (idx == -1) {
    4453                return str;
    4454            }
    4455            return str.substring(idx + sep.length());
    4456        }
    4457
    4458        /**
    4459         * <p>Remove and return everything before the first value of a
    4460         * supplied String from another String.</p>
    4461         *
    4462         * @param str  the String to chomp from, must not be null
    4463         * @param sep  the String to chomp, must not be null
    4464         * @return String prechomped
    4465         * @throws NullPointerException if str or sep is <code>null</code>
    4466         * @deprecated Use {@link #substringBefore(String,String)} instead
    4467         *             (although this doesn't include the separator).
    4468         *             Method will be removed in Commons Lang 3.0.
    4469         */
    4470        public static String getPrechomp(String str, String sep) {
    4471            int idx = str.indexOf(sep);
    4472            if (idx == -1) {
    4473                return EMPTY;
    4474            }
    4475            return str.substring(0, idx + sep.length());
    4476        }
    4477
    4478        // Chopping
    4479        //-----------------------------------------------------------------------
    4480        /**
    4481         * <p>Remove the last character from a String.</p>
    4482         *
    4483         * <p>If the String ends in <code>\r\n</code>, then remove both
    4484         * of them.</p>
    4485         *
    4486         * <pre>
    4487         * StringUtils.chop(null)          = null
    4488         * StringUtils.chop("")            = ""
    4489         * StringUtils.chop("abc \r")      = "abc "
    4490         * StringUtils.chop("abc\n")       = "abc"
    4491         * StringUtils.chop("abc\r\n")     = "abc"
    4492         * StringUtils.chop("abc")         = "ab"
    4493         * StringUtils.chop("abc\nabc")    = "abc\nab"
    4494         * StringUtils.chop("a")           = ""
    4495         * StringUtils.chop("\r")          = ""
    4496         * StringUtils.chop("\n")          = ""
    4497         * StringUtils.chop("\r\n")        = ""
    4498         * </pre>
    4499         *
    4500         * @param str  the String to chop last character from, may be null
    4501         * @return String without last character, <code>null</code> if null String input
    4502         */
    4503        public static String chop(String str) {
    4504            if (str == null) {
    4505                return null;
    4506            }
    4507            int strLen = str.length();
    4508            if (strLen < 2) {
    4509                return EMPTY;
    4510            }
    4511            int lastIdx = strLen - 1;
    4512            String ret = str.substring(0, lastIdx);
    4513            char last = str.charAt(lastIdx);
    4514            if (last == CharUtils.LF) {
    4515                if (ret.charAt(lastIdx - 1) == CharUtils.CR) {
    4516                    return ret.substring(0, lastIdx - 1);
    4517                }
    4518            }
    4519            return ret;
    4520        }
    4521
    4522        /**
    4523         * <p>Removes <code>\n</code> from end of a String if it's there.
    4524         * If a <code>\r</code> precedes it, then remove that too.</p>
    4525         *
    4526         * @param str  the String to chop a newline from, must not be null
    4527         * @return String without newline
    4528         * @throws NullPointerException if str is <code>null</code>
    4529         * @deprecated Use {@link #chomp(String)} instead.
    4530         *             Method will be removed in Commons Lang 3.0.
    4531         */
    4532        public static String chopNewline(String str) {
    4533            int lastIdx = str.length() - 1;
    4534            if (lastIdx <= 0) {
    4535                return EMPTY;
    4536            }
    4537            char last = str.charAt(lastIdx);
    4538            if (last == CharUtils.LF) {
    4539                if (str.charAt(lastIdx - 1) == CharUtils.CR) {
    4540                    lastIdx--;
    4541                }
    4542            } else {
    4543                lastIdx++;
    4544            }
    4545            return str.substring(0, lastIdx);
    4546        }
    4547
    4548        // Conversion
    4549        //-----------------------------------------------------------------------
    4550        /**
    4551         * <p>Escapes any values it finds into their String form.</p>
    4552         *
    4553         * <p>So a tab becomes the characters <code>'\\'</code> and
    4554         * <code>'t'</code>.</p>
    4555         *
    4556         * <p>As of Lang 2.0, this calls {@link StringEscapeUtils#escapeJava(String)}
    4557         * behind the scenes.
    4558         * </p>
    4559         * @see StringEscapeUtils#escapeJava(java.lang.String)
    4560         * @param str String to escape values in
    4561         * @return String with escaped values
    4562         * @throws NullPointerException if str is <code>null</code>
    4563         * @deprecated Use {@link StringEscapeUtils#escapeJava(String)}
    4564         *             This method will be removed in Commons Lang 3.0
    4565         */
    4566        public static String escape(String str) {
    4567            return StringEscapeUtils.escapeJava(str);
    4568        }
    4569
    4570        // Padding
    4571        //-----------------------------------------------------------------------
    4572        /**
    4573         * <p>Repeat a String <code>repeat</code> times to form a
    4574         * new String.</p>
    4575         *
    4576         * <pre>
    4577         * StringUtils.repeat(null, 2) = null
    4578         * StringUtils.repeat("", 0)   = ""
    4579         * StringUtils.repeat("", 2)   = ""
    4580         * StringUtils.repeat("a", 3)  = "aaa"
    4581         * StringUtils.repeat("ab", 2) = "abab"
    4582         * StringUtils.repeat("a", -2) = ""
    4583         * </pre>
    4584         *
    4585         * @param str  the String to repeat, may be null
    4586         * @param repeat  number of times to repeat str, negative treated as zero
    4587         * @return a new String consisting of the original String repeated,
    4588         *  <code>null</code> if null String input
    4589         */
    4590        public static String repeat(String str, int repeat) {
    4591            // Performance tuned for 2.0 (JDK1.4)
    4592
    4593            if (str == null) {
    4594                return null;
    4595            }
    4596            if (repeat <= 0) {
    4597                return EMPTY;
    4598            }
    4599            int inputLength = str.length();
    4600            if (repeat == 1 || inputLength == 0) {
    4601                return str;
    4602            }
    4603            if (inputLength == 1 && repeat <= PAD_LIMIT) {
    4604                return padding(repeat, str.charAt(0));
    4605            }
    4606
    4607            int outputLength = inputLength * repeat;
    4608            switch (inputLength) {
    4609                case 1 :
    4610                    char ch = str.charAt(0);
    4611                    char[] output1 = new char[outputLength];
    4612                    for (int i = repeat - 1; i >= 0; i--) {
    4613                        output1[i] = ch;
    4614                    }
    4615                    return new String(output1);
    4616                case 2 :
    4617                    char ch0 = str.charAt(0);
    4618                    char ch1 = str.charAt(1);
    4619                    char[] output2 = new char[outputLength];
    4620                    for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
    4621                        output2[i] = ch0;
    4622                        output2[i + 1] = ch1;
    4623                    }
    4624                    return new String(output2);
    4625                default :
    4626                    StrBuilder buf = new StrBuilder(outputLength);
    4627                    for (int i = 0; i < repeat; i++) {
    4628                        buf.append(str);
    4629                    }
    4630                    return buf.toString();
    4631            }
    4632        }
    4633
    4634        /**
    4635         * <p>Repeat a String <code>repeat</code> times to form a
    4636         * new String, with a String separator injected each time. </p>
    4637         *
    4638         * <pre>
    4639         * StringUtils.repeat(null, null, 2) = null
    4640         * StringUtils.repeat(null, "x", 2)  = null
    4641         * StringUtils.repeat("", null, 0)   = ""
    4642         * StringUtils.repeat("", "", 2)     = ""
    4643         * StringUtils.repeat("", "x", 3)    = "xxx"
    4644         * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
    4645         * </pre>
    4646         *
    4647         * @param str        the String to repeat, may be null
    4648         * @param separator  the String to inject, may be null
    4649         * @param repeat     number of times to repeat str, negative treated as zero
    4650         * @return a new String consisting of the original String repeated,
    4651         *  <code>null</code> if null String input
    4652         * @since 2.5
    4653         */
    4654        public static String repeat(String str, String separator, int repeat) {
    4655            if(str == null || separator == null) {
    4656                return repeat(str, repeat);
    4657            } else {
    4658                // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
    4659                String result = repeat(str + separator, repeat);
    4660                return removeEnd(result, separator);
    4661            }
    4662        }
    4663
    4664        /**
    4665         * <p>Returns padding using the specified delimiter repeated
    4666         * to a given length.</p>
    4667         *
    4668         * <pre>
    4669         * StringUtils.padding(0, 'e')  = ""
    4670         * StringUtils.padding(3, 'e')  = "eee"
    4671         * StringUtils.padding(-2, 'e') = IndexOutOfBoundsException
    4672         * </pre>
    4673         *
    4674         * <p>Note: this method doesn't not support padding with
    4675         * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
    4676         * as they require a pair of <code>char</code>s to be represented.
    4677         * If you are needing to support full I18N of your applications
    4678         * consider using {@link #repeat(String, int)} instead.
    4679         * </p>
    4680         *
    4681         * @param repeat  number of times to repeat delim
    4682         * @param padChar  character to repeat
    4683         * @return String with repeated character
    4684         * @throws IndexOutOfBoundsException if <code>repeat &lt; 0</code>
    4685         * @see #repeat(String, int)
    4686         */
    4687        private static String padding(int repeat, char padChar) throws IndexOutOfBoundsException {
    4688            if (repeat < 0) {
    4689                throw new IndexOutOfBoundsException("Cannot pad a negative amount: " + repeat);
    4690            }
    4691            final char[] buf = new char[repeat];
    4692            for (int i = 0; i < buf.length; i++) {
    4693                buf[i] = padChar;
    4694            }
    4695            return new String(buf);
    4696        }
    4697
    4698        /**
    4699         * <p>Right pad a String with spaces (' ').</p>
    4700         *
    4701         * <p>The String is padded to the size of <code>size</code>.</p>
    4702         *
    4703         * <pre>
    4704         * StringUtils.rightPad(null, *)   = null
    4705         * StringUtils.rightPad("", 3)     = "   "
    4706         * StringUtils.rightPad("bat", 3)  = "bat"
    4707         * StringUtils.rightPad("bat", 5)  = "bat  "
    4708         * StringUtils.rightPad("bat", 1)  = "bat"
    4709         * StringUtils.rightPad("bat", -1) = "bat"
    4710         * </pre>
    4711         *
    4712         * @param str  the String to pad out, may be null
    4713         * @param size  the size to pad to
    4714         * @return right padded String or original String if no padding is necessary,
    4715         *  <code>null</code> if null String input
    4716         */
    4717        public static String rightPad(String str, int size) {
    4718            return rightPad(str, size, ' ');
    4719        }
    4720
    4721        /**
    4722         * <p>Right pad a String with a specified character.</p>
    4723         *
    4724         * <p>The String is padded to the size of <code>size</code>.</p>
    4725         *
    4726         * <pre>
    4727         * StringUtils.rightPad(null, *, *)     = null
    4728         * StringUtils.rightPad("", 3, 'z')     = "zzz"
    4729         * StringUtils.rightPad("bat", 3, 'z')  = "bat"
    4730         * StringUtils.rightPad("bat", 5, 'z')  = "batzz"
    4731         * StringUtils.rightPad("bat", 1, 'z')  = "bat"
    4732         * StringUtils.rightPad("bat", -1, 'z') = "bat"
    4733         * </pre>
    4734         *
    4735         * @param str  the String to pad out, may be null
    4736         * @param size  the size to pad to
    4737         * @param padChar  the character to pad with
    4738         * @return right padded String or original String if no padding is necessary,
    4739         *  <code>null</code> if null String input
    4740         * @since 2.0
    4741         */
    4742        public static String rightPad(String str, int size, char padChar) {
    4743            if (str == null) {
    4744                return null;
    4745            }
    4746            int pads = size - str.length();
    4747            if (pads <= 0) {
    4748                return str; // returns original String when possible
    4749            }
    4750            if (pads > PAD_LIMIT) {
    4751                return rightPad(str, size, String.valueOf(padChar));
    4752            }
    4753            return str.concat(padding(pads, padChar));
    4754        }
    4755
    4756        /**
    4757         * <p>Right pad a String with a specified String.</p>
    4758         *
    4759         * <p>The String is padded to the size of <code>size</code>.</p>
    4760         *
    4761         * <pre>
    4762         * StringUtils.rightPad(null, *, *)      = null
    4763         * StringUtils.rightPad("", 3, "z")      = "zzz"
    4764         * StringUtils.rightPad("bat", 3, "yz")  = "bat"
    4765         * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
    4766         * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
    4767         * StringUtils.rightPad("bat", 1, "yz")  = "bat"
    4768         * StringUtils.rightPad("bat", -1, "yz") = "bat"
    4769         * StringUtils.rightPad("bat", 5, null)  = "bat  "
    4770         * StringUtils.rightPad("bat", 5, "")    = "bat  "
    4771         * </pre>
    4772         *
    4773         * @param str  the String to pad out, may be null
    4774         * @param size  the size to pad to
    4775         * @param padStr  the String to pad with, null or empty treated as single space
    4776         * @return right padded String or original String if no padding is necessary,
    4777         *  <code>null</code> if null String input
    4778         */
    4779        public static String rightPad(String str, int size, String padStr) {
    4780            if (str == null) {
    4781                return null;
    4782            }
    4783            if (isEmpty(padStr)) {
    4784                padStr = " ";
    4785            }
    4786            int padLen = padStr.length();
    4787            int strLen = str.length();
    4788            int pads = size - strLen;
    4789            if (pads <= 0) {
    4790                return str; // returns original String when possible
    4791            }
    4792            if (padLen == 1 && pads <= PAD_LIMIT) {
    4793                return rightPad(str, size, padStr.charAt(0));
    4794            }
    4795
    4796            if (pads == padLen) {
    4797                return str.concat(padStr);
    4798            } else if (pads < padLen) {
    4799                return str.concat(padStr.substring(0, pads));
    4800            } else {
    4801                char[] padding = new char[pads];
    4802                char[] padChars = padStr.toCharArray();
    4803                for (int i = 0; i < pads; i++) {
    4804                    padding[i] = padChars[i % padLen];
    4805                }
    4806                return str.concat(new String(padding));
    4807            }
    4808        }
    4809
    4810        /**
    4811         * <p>Left pad a String with spaces (' ').</p>
    4812         *
    4813         * <p>The String is padded to the size of <code>size</code>.</p>
    4814         *
    4815         * <pre>
    4816         * StringUtils.leftPad(null, *)   = null
    4817         * StringUtils.leftPad("", 3)     = "   "
    4818         * StringUtils.leftPad("bat", 3)  = "bat"
    4819         * StringUtils.leftPad("bat", 5)  = "  bat"
    4820         * StringUtils.leftPad("bat", 1)  = "bat"
    4821         * StringUtils.leftPad("bat", -1) = "bat"
    4822         * </pre>
    4823         *
    4824         * @param str  the String to pad out, may be null
    4825         * @param size  the size to pad to
    4826         * @return left padded String or original String if no padding is necessary,
    4827         *  <code>null</code> if null String input
    4828         */
    4829        public static String leftPad(String str, int size) {
    4830            return leftPad(str, size, ' ');
    4831        }
    4832
    4833        /**
    4834         * <p>Left pad a String with a specified character.</p>
    4835         *
    4836         * <p>Pad to a size of <code>size</code>.</p>
    4837         *
    4838         * <pre>
    4839         * StringUtils.leftPad(null, *, *)     = null
    4840         * StringUtils.leftPad("", 3, 'z')     = "zzz"
    4841         * StringUtils.leftPad("bat", 3, 'z')  = "bat"
    4842         * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"
    4843         * StringUtils.leftPad("bat", 1, 'z')  = "bat"
    4844         * StringUtils.leftPad("bat", -1, 'z') = "bat"
    4845         * </pre>
    4846         *
    4847         * @param str  the String to pad out, may be null
    4848         * @param size  the size to pad to
    4849         * @param padChar  the character to pad with
    4850         * @return left padded String or original String if no padding is necessary,
    4851         *  <code>null</code> if null String input
    4852         * @since 2.0
    4853         */
    4854        public static String leftPad(String str, int size, char padChar) {
    4855            if (str == null) {
    4856                return null;
    4857            }
    4858            int pads = size - str.length();
    4859            if (pads <= 0) {
    4860                return str; // returns original String when possible
    4861            }
    4862            if (pads > PAD_LIMIT) {
    4863                return leftPad(str, size, String.valueOf(padChar));
    4864            }
    4865            return padding(pads, padChar).concat(str);
    4866        }
    4867
    4868        /**
    4869         * <p>Left pad a String with a specified String.</p>
    4870         *
    4871         * <p>Pad to a size of <code>size</code>.</p>
    4872         *
    4873         * <pre>
    4874         * StringUtils.leftPad(null, *, *)      = null
    4875         * StringUtils.leftPad("", 3, "z")      = "zzz"
    4876         * StringUtils.leftPad("bat", 3, "yz")  = "bat"
    4877         * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
    4878         * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
    4879         * StringUtils.leftPad("bat", 1, "yz")  = "bat"
    4880         * StringUtils.leftPad("bat", -1, "yz") = "bat"
    4881         * StringUtils.leftPad("bat", 5, null)  = "  bat"
    4882         * StringUtils.leftPad("bat", 5, "")    = "  bat"
    4883         * </pre>
    4884         *
    4885         * @param str  the String to pad out, may be null
    4886         * @param size  the size to pad to
    4887         * @param padStr  the String to pad with, null or empty treated as single space
    4888         * @return left padded String or original String if no padding is necessary,
    4889         *  <code>null</code> if null String input
    4890         */
    4891        public static String leftPad(String str, int size, String padStr) {
    4892            if (str == null) {
    4893                return null;
    4894            }
    4895            if (isEmpty(padStr)) {
    4896                padStr = " ";
    4897            }
    4898            int padLen = padStr.length();
    4899            int strLen = str.length();
    4900            int pads = size - strLen;
    4901            if (pads <= 0) {
    4902                return str; // returns original String when possible
    4903            }
    4904            if (padLen == 1 && pads <= PAD_LIMIT) {
    4905                return leftPad(str, size, padStr.charAt(0));
    4906            }
    4907
    4908            if (pads == padLen) {
    4909                return padStr.concat(str);
    4910            } else if (pads < padLen) {
    4911                return padStr.substring(0, pads).concat(str);
    4912            } else {
    4913                char[] padding = new char[pads];
    4914                char[] padChars = padStr.toCharArray();
    4915                for (int i = 0; i < pads; i++) {
    4916                    padding[i] = padChars[i % padLen];
    4917                }
    4918                return new String(padding).concat(str);
    4919            }
    4920        }
    4921
    4922        /**
    4923         * Gets a String's length or <code>0</code> if the String is <code>null</code>.
    4924         *
    4925         * @param str
    4926         *            a String or <code>null</code>
    4927         * @return String length or <code>0</code> if the String is <code>null</code>.
    4928         * @since 2.4
    4929         */
    4930        public static int length(String str) {
    4931            return str == null ? 0 : str.length();
    4932        }
    4933
    4934        // Centering
    4935        //-----------------------------------------------------------------------
    4936        /**
    4937         * <p>Centers a String in a larger String of size <code>size</code>
    4938         * using the space character (' ').<p>
    4939         *
    4940         * <p>If the size is less than the String length, the String is returned.
    4941         * A <code>null</code> String returns <code>null</code>.
    4942         * A negative size is treated as zero.</p>
    4943         *
    4944         * <p>Equivalent to <code>center(str, size, " ")</code>.</p>
    4945         *
    4946         * <pre>
    4947         * StringUtils.center(null, *)   = null
    4948         * StringUtils.center("", 4)     = "    "
    4949         * StringUtils.center("ab", -1)  = "ab"
    4950         * StringUtils.center("ab", 4)   = " ab "
    4951         * StringUtils.center("abcd", 2) = "abcd"
    4952         * StringUtils.center("a", 4)    = " a  "
    4953         * </pre>
    4954         *
    4955         * @param str  the String to center, may be null
    4956         * @param size  the int size of new String, negative treated as zero
    4957         * @return centered String, <code>null</code> if null String input
    4958         */
    4959        public static String center(String str, int size) {
    4960            return center(str, size, ' ');
    4961        }
    4962
    4963        /**
    4964         * <p>Centers a String in a larger String of size <code>size</code>.
    4965         * Uses a supplied character as the value to pad the String with.</p>
    4966         *
    4967         * <p>If the size is less than the String length, the String is returned.
    4968         * A <code>null</code> String returns <code>null</code>.
    4969         * A negative size is treated as zero.</p>
    4970         *
    4971         * <pre>
    4972         * StringUtils.center(null, *, *)     = null
    4973         * StringUtils.center("", 4, ' ')     = "    "
    4974         * StringUtils.center("ab", -1, ' ')  = "ab"
    4975         * StringUtils.center("ab", 4, ' ')   = " ab"
    4976         * StringUtils.center("abcd", 2, ' ') = "abcd"
    4977         * StringUtils.center("a", 4, ' ')    = " a  "
    4978         * StringUtils.center("a", 4, 'y')    = "yayy"
    4979         * </pre>
    4980         *
    4981         * @param str  the String to center, may be null
    4982         * @param size  the int size of new String, negative treated as zero
    4983         * @param padChar  the character to pad the new String with
    4984         * @return centered String, <code>null</code> if null String input
    4985         * @since 2.0
    4986         */
    4987        public static String center(String str, int size, char padChar) {
    4988            if (str == null || size <= 0) {
    4989                return str;
    4990            }
    4991            int strLen = str.length();
    4992            int pads = size - strLen;
    4993            if (pads <= 0) {
    4994                return str;
    4995            }
    4996            str = leftPad(str, strLen + pads / 2, padChar);
    4997            str = rightPad(str, size, padChar);
    4998            return str;
    4999        }
    5000
    5001        /**
    5002         * <p>Centers a String in a larger String of size <code>size</code>.
    5003         * Uses a supplied String as the value to pad the String with.</p>
    5004         *
    5005         * <p>If the size is less than the String length, the String is returned.
    5006         * A <code>null</code> String returns <code>null</code>.
    5007         * A negative size is treated as zero.</p>
    5008         *
    5009         * <pre>
    5010         * StringUtils.center(null, *, *)     = null
    5011         * StringUtils.center("", 4, " ")     = "    "
    5012         * StringUtils.center("ab", -1, " ")  = "ab"
    5013         * StringUtils.center("ab", 4, " ")   = " ab"
    5014         * StringUtils.center("abcd", 2, " ") = "abcd"
    5015         * StringUtils.center("a", 4, " ")    = " a  "
    5016         * StringUtils.center("a", 4, "yz")   = "yayz"
    5017         * StringUtils.center("abc", 7, null) = "  abc  "
    5018         * StringUtils.center("abc", 7, "")   = "  abc  "
    5019         * </pre>
    5020         *
    5021         * @param str  the String to center, may be null
    5022         * @param size  the int size of new String, negative treated as zero
    5023         * @param padStr  the String to pad the new String with, must not be null or empty
    5024         * @return centered String, <code>null</code> if null String input
    5025         * @throws IllegalArgumentException if padStr is <code>null</code> or empty
    5026         */
    5027        public static String center(String str, int size, String padStr) {
    5028            if (str == null || size <= 0) {
    5029                return str;
    5030            }
    5031            if (isEmpty(padStr)) {
    5032                padStr = " ";
    5033            }
    5034            int strLen = str.length();
    5035            int pads = size - strLen;
    5036            if (pads <= 0) {
    5037                return str;
    5038            }
    5039            str = leftPad(str, strLen + pads / 2, padStr);
    5040            str = rightPad(str, size, padStr);
    5041            return str;
    5042        }
    5043
    5044        // Case conversion
    5045        //-----------------------------------------------------------------------
    5046        /**
    5047         * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p>
    5048         *
    5049         * <p>A <code>null</code> input String returns <code>null</code>.</p>
    5050         *
    5051         * <pre>
    5052         * StringUtils.upperCase(null)  = null
    5053         * StringUtils.upperCase("")    = ""
    5054         * StringUtils.upperCase("aBc") = "ABC"
    5055         * </pre>
    5056         *
    5057         * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()},
    5058         * the result of this method is affected by the current locale.
    5059         * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
    5060         * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
    5061         *
    5062         * @param str  the String to upper case, may be null
    5063         * @return the upper cased String, <code>null</code> if null String input
    5064         */
    5065        public static String upperCase(String str) {
    5066            if (str == null) {
    5067                return null;
    5068            }
    5069            return str.toUpperCase();
    5070        }
    5071
    5072        /**
    5073         * <p>Converts a String to upper case as per {@link String#toUpperCase(Locale)}.</p>
    5074         *
    5075         * <p>A <code>null</code> input String returns <code>null</code>.</p>
    5076         *
    5077         * <pre>
    5078         * StringUtils.upperCase(null, Locale.ENGLISH)  = null
    5079         * StringUtils.upperCase("", Locale.ENGLISH)    = ""
    5080         * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
    5081         * </pre>
    5082         *
    5083         * @param str  the String to upper case, may be null
    5084         * @param locale  the locale that defines the case transformation rules, must not be null
    5085         * @return the upper cased String, <code>null</code> if null String input
    5086         * @since 2.5
    5087         */
    5088        public static String upperCase(String str, Locale locale) {
    5089            if (str == null) {
    5090                return null;
    5091            }
    5092            return str.toUpperCase(locale);
    5093        }
    5094
    5095        /**
    5096         * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p>
    5097         *
    5098         * <p>A <code>null</code> input String returns <code>null</code>.</p>
    5099         *
    5100         * <pre>
    5101         * StringUtils.lowerCase(null)  = null
    5102         * StringUtils.lowerCase("")    = ""
    5103         * StringUtils.lowerCase("aBc") = "abc"
    5104         * </pre>
    5105         *
    5106         * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()},
    5107         * the result of this method is affected by the current locale.
    5108         * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
    5109         * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
    5110         *
    5111         * @param str  the String to lower case, may be null
    5112         * @return the lower cased String, <code>null</code> if null String input
    5113         */
    5114        public static String lowerCase(String str) {
    5115            if (str == null) {
    5116                return null;
    5117            }
    5118            return str.toLowerCase();
    5119        }
    5120
    5121        /**
    5122         * <p>Converts a String to lower case as per {@link String#toLowerCase(Locale)}.</p>
    5123         *
    5124         * <p>A <code>null</code> input String returns <code>null</code>.</p>
    5125         *
    5126         * <pre>
    5127         * StringUtils.lowerCase(null, Locale.ENGLISH)  = null
    5128         * StringUtils.lowerCase("", Locale.ENGLISH)    = ""
    5129         * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
    5130         * </pre>
    5131         *
    5132         * @param str  the String to lower case, may be null
    5133         * @param locale  the locale that defines the case transformation rules, must not be null
    5134         * @return the lower cased String, <code>null</code> if null String input
    5135         * @since 2.5
    5136         */
    5137        public static String lowerCase(String str, Locale locale) {
    5138            if (str == null) {
    5139                return null;
    5140            }
    5141            return str.toLowerCase(locale);
    5142        }
    5143
    5144        /**
    5145         * <p>Capitalizes a String changing the first letter to title case as
    5146         * per {@link Character#toTitleCase(char)}. No other letters are changed.</p>
    5147         *
    5148         * <p>For a word based algorithm, see {@link WordUtils#capitalize(String)}.
    5149         * A <code>null</code> input String returns <code>null</code>.</p>
    5150         *
    5151         * <pre>
    5152         * StringUtils.capitalize(null)  = null
    5153         * StringUtils.capitalize("")    = ""
    5154         * StringUtils.capitalize("cat") = "Cat"
    5155         * StringUtils.capitalize("cAt") = "CAt"
    5156         * </pre>
    5157         *
    5158         * @param str  the String to capitalize, may be null
    5159         * @return the capitalized String, <code>null</code> if null String input
    5160         * @see WordUtils#capitalize(String)
    5161         * @see #uncapitalize(String)
    5162         * @since 2.0
    5163         */
    5164        public static String capitalize(String str) {
    5165            int strLen;
    5166            if (str == null || (strLen = str.length()) == 0) {
    5167                return str;
    5168            }
    5169            return new StrBuilder(strLen)
    5170                .append(Character.toTitleCase(str.charAt(0)))
    5171                .append(str.substring(1))
    5172                .toString();
    5173        }
    5174
    5175        /**
    5176         * <p>Capitalizes a String changing the first letter to title case as
    5177         * per {@link Character#toTitleCase(char)}. No other letters are changed.</p>
    5178         *
    5179         * @param str  the String to capitalize, may be null
    5180         * @return the capitalized String, <code>null</code> if null String input
    5181         * @deprecated Use the standardly named {@link #capitalize(String)}.
    5182         *             Method will be removed in Commons Lang 3.0.
    5183         */
    5184        public static String capitalise(String str) {
    5185            return capitalize(str);
    5186        }
    5187
    5188        /**
    5189         * <p>Uncapitalizes a String changing the first letter to title case as
    5190         * per {@link Character#toLowerCase(char)}. No other letters are changed.</p>
    5191         *
    5192         * <p>For a word based algorithm, see {@link WordUtils#uncapitalize(String)}.
    5193         * A <code>null</code> input String returns <code>null</code>.</p>
    5194         *
    5195         * <pre>
    5196         * StringUtils.uncapitalize(null)  = null
    5197         * StringUtils.uncapitalize("")    = ""
    5198         * StringUtils.uncapitalize("Cat") = "cat"
    5199         * StringUtils.uncapitalize("CAT") = "cAT"
    5200         * </pre>
    5201         *
    5202         * @param str  the String to uncapitalize, may be null
    5203         * @return the uncapitalized String, <code>null</code> if null String input
    5204         * @see WordUtils#uncapitalize(String)
    5205         * @see #capitalize(String)
    5206         * @since 2.0
    5207         */
    5208        public static String uncapitalize(String str) {
    5209            int strLen;
    5210            if (str == null || (strLen = str.length()) == 0) {
    5211                return str;
    5212            }
    5213            return new StrBuilder(strLen)
    5214                .append(Character.toLowerCase(str.charAt(0)))
    5215                .append(str.substring(1))
    5216                .toString();
    5217        }
    5218
    5219        /**
    5220         * <p>Uncapitalizes a String changing the first letter to title case as
    5221         * per {@link Character#toLowerCase(char)}. No other letters are changed.</p>
    5222         *
    5223         * @param str  the String to uncapitalize, may be null
    5224         * @return the uncapitalized String, <code>null</code> if null String input
    5225         * @deprecated Use the standardly named {@link #uncapitalize(String)}.
    5226         *             Method will be removed in Commons Lang 3.0.
    5227         */
    5228        public static String uncapitalise(String str) {
    5229            return uncapitalize(str);
    5230        }
    5231
    5232        /**
    5233         * <p>Swaps the case of a String changing upper and title case to
    5234         * lower case, and lower case to upper case.</p>
    5235         *
    5236         * <ul>
    5237         *  <li>Upper case character converts to Lower case</li>
    5238         *  <li>Title case character converts to Lower case</li>
    5239         *  <li>Lower case character converts to Upper case</li>
    5240         * </ul>
    5241         *
    5242         * <p>For a word based algorithm, see {@link WordUtils#swapCase(String)}.
    5243         * A <code>null</code> input String returns <code>null</code>.</p>
    5244         *
    5245         * <pre>
    5246         * StringUtils.swapCase(null)                 = null
    5247         * StringUtils.swapCase("")                   = ""
    5248         * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
    5249         * </pre>
    5250         *
    5251         * <p>NOTE: This method changed in Lang version 2.0.
    5252         * It no longer performs a word based algorithm.
    5253         * If you only use ASCII, you will notice no change.
    5254         * That functionality is available in WordUtils.</p>
    5255         *
    5256         * @param str  the String to swap case, may be null
    5257         * @return the changed String, <code>null</code> if null String input
    5258         */
    5259        public static String swapCase(String str) {
    5260            int strLen;
    5261            if (str == null || (strLen = str.length()) == 0) {
    5262                return str;
    5263            }
    5264            StrBuilder buffer = new StrBuilder(strLen);
    5265
    5266            char ch = 0;
    5267            for (int i = 0; i < strLen; i++) {
    5268                ch = str.charAt(i);
    5269                if (Character.isUpperCase(ch)) {
    5270                    ch = Character.toLowerCase(ch);
    5271                } else if (Character.isTitleCase(ch)) {
    5272                    ch = Character.toLowerCase(ch);
    5273                } else if (Character.isLowerCase(ch)) {
    5274                    ch = Character.toUpperCase(ch);
    5275                }
    5276                buffer.append(ch);
    5277            }
    5278            return buffer.toString();
    5279        }
    5280
    5281        /**
    5282         * <p>Capitalizes all the whitespace separated words in a String.
    5283         * Only the first letter of each word is changed.</p>
    5284         *
    5285         * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
    5286         * A <code>null</code> input String returns <code>null</code>.</p>
    5287         *
    5288         * @param str  the String to capitalize, may be null
    5289         * @return capitalized String, <code>null</code> if null String input
    5290         * @deprecated Use the relocated {@link WordUtils#capitalize(String)}.
    5291         *             Method will be removed in Commons Lang 3.0.
    5292         */
    5293        public static String capitaliseAllWords(String str) {
    5294            return WordUtils.capitalize(str);
    5295        }
    5296
    5297        // Count matches
    5298        //-----------------------------------------------------------------------
    5299        /**
    5300         * <p>Counts how many times the substring appears in the larger String.</p>
    5301         *
    5302         * <p>A <code>null</code> or empty ("") String input returns <code>0</code>.</p>
    5303         *
    5304         * <pre>
    5305         * StringUtils.countMatches(null, *)       = 0
    5306         * StringUtils.countMatches("", *)         = 0
    5307         * StringUtils.countMatches("abba", null)  = 0
    5308         * StringUtils.countMatches("abba", "")    = 0
    5309         * StringUtils.countMatches("abba", "a")   = 2
    5310         * StringUtils.countMatches("abba", "ab")  = 1
    5311         * StringUtils.countMatches("abba", "xxx") = 0
    5312         * </pre>
    5313         *
    5314         * @param str  the String to check, may be null
    5315         * @param sub  the substring to count, may be null
    5316         * @return the number of occurrences, 0 if either String is <code>null</code>
    5317         */
    5318        public static int countMatches(String str, String sub) {
    5319            if (isEmpty(str) || isEmpty(sub)) {
    5320                return 0;
    5321            }
    5322            int count = 0;
    5323            int idx = 0;
    5324            while ((idx = str.indexOf(sub, idx)) != INDEX_NOT_FOUND) {
    5325                count++;
    5326                idx += sub.length();
    5327            }
    5328            return count;
    5329        }
    5330
    5331        // Character Tests
    5332        //-----------------------------------------------------------------------
    5333        /**
    5334         * <p>Checks if the String contains only unicode letters.</p>
    5335         *
    5336         * <p><code>null</code> will return <code>false</code>.
    5337         * An empty String (length()=0) will return <code>true</code>.</p>
    5338         *
    5339         * <pre>
    5340         * StringUtils.isAlpha(null)   = false
    5341         * StringUtils.isAlpha("")     = true
    5342         * StringUtils.isAlpha("  ")   = false
    5343         * StringUtils.isAlpha("abc")  = true
    5344         * StringUtils.isAlpha("ab2c") = false
    5345         * StringUtils.isAlpha("ab-c") = false
    5346         * </pre>
    5347         *
    5348         * @param str  the String to check, may be null
    5349         * @return <code>true</code> if only contains letters, and is non-null
    5350         */
    5351        public static boolean isAlpha(String str) {
    5352            if (str == null) {
    5353                return false;
    5354            }
    5355            int sz = str.length();
    5356            for (int i = 0; i < sz; i++) {
    5357                if (Character.isLetter(str.charAt(i)) == false) {
    5358                    return false;
    5359                }
    5360            }
    5361            return true;
    5362        }
    5363
    5364        /**
    5365         * <p>Checks if the String contains only unicode letters and
    5366         * space (' ').</p>
    5367         *
    5368         * <p><code>null</code> will return <code>false</code>
    5369         * An empty String (length()=0) will return <code>true</code>.</p>
    5370         *
    5371         * <pre>
    5372         * StringUtils.isAlphaSpace(null)   = false
    5373         * StringUtils.isAlphaSpace("")     = true
    5374         * StringUtils.isAlphaSpace("  ")   = true
    5375         * StringUtils.isAlphaSpace("abc")  = true
    5376         * StringUtils.isAlphaSpace("ab c") = true
    5377         * StringUtils.isAlphaSpace("ab2c") = false
    5378         * StringUtils.isAlphaSpace("ab-c") = false
    5379         * </pre>
    5380         *
    5381         * @param str  the String to check, may be null
    5382         * @return <code>true</code> if only contains letters and space,
    5383         *  and is non-null
    5384         */
    5385        public static boolean isAlphaSpace(String str) {
    5386            if (str == null) {
    5387                return false;
    5388            }
    5389            int sz = str.length();
    5390            for (int i = 0; i < sz; i++) {
    5391                if ((Character.isLetter(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
    5392                    return false;
    5393                }
    5394            }
    5395            return true;
    5396        }
    5397
    5398        /**
    5399         * <p>Checks if the String contains only unicode letters or digits.</p>
    5400         *
    5401         * <p><code>null</code> will return <code>false</code>.
    5402         * An empty String (length()=0) will return <code>true</code>.</p>
    5403         *
    5404         * <pre>
    5405         * StringUtils.isAlphanumeric(null)   = false
    5406         * StringUtils.isAlphanumeric("")     = true
    5407         * StringUtils.isAlphanumeric("  ")   = false
    5408         * StringUtils.isAlphanumeric("abc")  = true
    5409         * StringUtils.isAlphanumeric("ab c") = false
    5410         * StringUtils.isAlphanumeric("ab2c") = true
    5411         * StringUtils.isAlphanumeric("ab-c") = false
    5412         * </pre>
    5413         *
    5414         * @param str  the String to check, may be null
    5415         * @return <code>true</code> if only contains letters or digits,
    5416         *  and is non-null
    5417         */
    5418        public static boolean isAlphanumeric(String str) {
    5419            if (str == null) {
    5420                return false;
    5421            }
    5422            int sz = str.length();
    5423            for (int i = 0; i < sz; i++) {
    5424                if (Character.isLetterOrDigit(str.charAt(i)) == false) {
    5425                    return false;
    5426                }
    5427            }
    5428            return true;
    5429        }
    5430
    5431        /**
    5432         * <p>Checks if the String contains only unicode letters, digits
    5433         * or space (<code>' '</code>).</p>
    5434         *
    5435         * <p><code>null</code> will return <code>false</code>.
    5436         * An empty String (length()=0) will return <code>true</code>.</p>
    5437         *
    5438         * <pre>
    5439         * StringUtils.isAlphanumeric(null)   = false
    5440         * StringUtils.isAlphanumeric("")     = true
    5441         * StringUtils.isAlphanumeric("  ")   = true
    5442         * StringUtils.isAlphanumeric("abc")  = true
    5443         * StringUtils.isAlphanumeric("ab c") = true
    5444         * StringUtils.isAlphanumeric("ab2c") = true
    5445         * StringUtils.isAlphanumeric("ab-c") = false
    5446         * </pre>
    5447         *
    5448         * @param str  the String to check, may be null
    5449         * @return <code>true</code> if only contains letters, digits or space,
    5450         *  and is non-null
    5451         */
    5452        public static boolean isAlphanumericSpace(String str) {
    5453            if (str == null) {
    5454                return false;
    5455            }
    5456            int sz = str.length();
    5457            for (int i = 0; i < sz; i++) {
    5458                if ((Character.isLetterOrDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
    5459                    return false;
    5460                }
    5461            }
    5462            return true;
    5463        }
    5464
    5465        /**
    5466         * <p>Checks if the string contains only ASCII printable characters.</p>
    5467         *
    5468         * <p><code>null</code> will return <code>false</code>.
    5469         * An empty String (length()=0) will return <code>true</code>.</p>
    5470         *
    5471         * <pre>
    5472         * StringUtils.isAsciiPrintable(null)     = false
    5473         * StringUtils.isAsciiPrintable("")       = true
    5474         * StringUtils.isAsciiPrintable(" ")      = true
    5475         * StringUtils.isAsciiPrintable("Ceki")   = true
    5476         * StringUtils.isAsciiPrintable("ab2c")   = true
    5477         * StringUtils.isAsciiPrintable("!ab-c~") = true
    5478         * StringUtils.isAsciiPrintable("\u0020") = true
    5479         * StringUtils.isAsciiPrintable("\u0021") = true
    5480         * StringUtils.isAsciiPrintable("\u007e") = true
    5481         * StringUtils.isAsciiPrintable("\u007f") = false
    5482         * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
    5483         * </pre>
    5484         *
    5485         * @param str the string to check, may be null
    5486         * @return <code>true</code> if every character is in the range
    5487         *  32 thru 126
    5488         * @since 2.1
    5489         */
    5490        public static boolean isAsciiPrintable(String str) {
    5491            if (str == null) {
    5492                return false;
    5493            }
    5494            int sz = str.length();
    5495            for (int i = 0; i < sz; i++) {
    5496                if (CharUtils.isAsciiPrintable(str.charAt(i)) == false) {
    5497                    return false;
    5498                }
    5499            }
    5500            return true;
    5501        }
    5502
    5503        /**
    5504         * <p>Checks if the String contains only unicode digits.
    5505         * A decimal point is not a unicode digit and returns false.</p>
    5506         *
    5507         * <p><code>null</code> will return <code>false</code>.
    5508         * An empty String (length()=0) will return <code>true</code>.</p>
    5509         *
    5510         * <pre>
    5511         * StringUtils.isNumeric(null)   = false
    5512         * StringUtils.isNumeric("")     = true
    5513         * StringUtils.isNumeric("  ")   = false
    5514         * StringUtils.isNumeric("123")  = true
    5515         * StringUtils.isNumeric("12 3") = false
    5516         * StringUtils.isNumeric("ab2c") = false
    5517         * StringUtils.isNumeric("12-3") = false
    5518         * StringUtils.isNumeric("12.3") = false
    5519         * </pre>
    5520         *
    5521         * @param str  the String to check, may be null
    5522         * @return <code>true</code> if only contains digits, and is non-null
    5523         */
    5524        public static boolean isNumeric(String str) {
    5525            if (str == null) {
    5526                return false;
    5527            }
    5528            int sz = str.length();
    5529            for (int i = 0; i < sz; i++) {
    5530                if (Character.isDigit(str.charAt(i)) == false) {
    5531                    return false;
    5532                }
    5533            }
    5534            return true;
    5535        }
    5536
    5537        /**
    5538         * <p>Checks if the String contains only unicode digits or space
    5539         * (<code>' '</code>).
    5540         * A decimal point is not a unicode digit and returns false.</p>
    5541         *
    5542         * <p><code>null</code> will return <code>false</code>.
    5543         * An empty String (length()=0) will return <code>true</code>.</p>
    5544         *
    5545         * <pre>
    5546         * StringUtils.isNumeric(null)   = false
    5547         * StringUtils.isNumeric("")     = true
    5548         * StringUtils.isNumeric("  ")   = true
    5549         * StringUtils.isNumeric("123")  = true
    5550         * StringUtils.isNumeric("12 3") = true
    5551         * StringUtils.isNumeric("ab2c") = false
    5552         * StringUtils.isNumeric("12-3") = false
    5553         * StringUtils.isNumeric("12.3") = false
    5554         * </pre>
    5555         *
    5556         * @param str  the String to check, may be null
    5557         * @return <code>true</code> if only contains digits or space,
    5558         *  and is non-null
    5559         */
    5560        public static boolean isNumericSpace(String str) {
    5561            if (str == null) {
    5562                return false;
    5563            }
    5564            int sz = str.length();
    5565            for (int i = 0; i < sz; i++) {
    5566                if ((Character.isDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
    5567                    return false;
    5568                }
    5569            }
    5570            return true;
    5571        }
    5572
    5573        /**
    5574         * <p>Checks if the String contains only whitespace.</p>
    5575         *
    5576         * <p><code>null</code> will return <code>false</code>.
    5577         * An empty String (length()=0) will return <code>true</code>.</p>
    5578         *
    5579         * <pre>
    5580         * StringUtils.isWhitespace(null)   = false
    5581         * StringUtils.isWhitespace("")     = true
    5582         * StringUtils.isWhitespace("  ")   = true
    5583         * StringUtils.isWhitespace("abc")  = false
    5584         * StringUtils.isWhitespace("ab2c") = false
    5585         * StringUtils.isWhitespace("ab-c") = false
    5586         * </pre>
    5587         *
    5588         * @param str  the String to check, may be null
    5589         * @return <code>true</code> if only contains whitespace, and is non-null
    5590         * @since 2.0
    5591         */
    5592        public static boolean isWhitespace(String str) {
    5593            if (str == null) {
    5594                return false;
    5595            }
    5596            int sz = str.length();
    5597            for (int i = 0; i < sz; i++) {
    5598                if ((Character.isWhitespace(str.charAt(i)) == false)) {
    5599                    return false;
    5600                }
    5601            }
    5602            return true;
    5603        }
    5604
    5605        /**
    5606         * <p>Checks if the String contains only lowercase characters.</p>
    5607         *
    5608         * <p><code>null</code> will return <code>false</code>.
    5609         * An empty String (length()=0) will return <code>false</code>.</p>
    5610         *
    5611         * <pre>
    5612         * StringUtils.isAllLowerCase(null)   = false
    5613         * StringUtils.isAllLowerCase("")     = false
    5614         * StringUtils.isAllLowerCase("  ")   = false
    5615         * StringUtils.isAllLowerCase("abc")  = true
    5616         * StringUtils.isAllLowerCase("abC") = false
    5617         * </pre>
    5618         *
    5619         * @param str  the String to check, may be null
    5620         * @return <code>true</code> if only contains lowercase characters, and is non-null
    5621         * @since 2.5
    5622         */
    5623        public static boolean isAllLowerCase(String str) {
    5624            if (str == null || isEmpty(str)) {
    5625                return false;
    5626            }
    5627            int sz = str.length();
    5628            for (int i = 0; i < sz; i++) {
    5629                if (Character.isLowerCase(str.charAt(i)) == false) {
    5630                    return false;
    5631                }
    5632            }
    5633            return true;
    5634        }
    5635
    5636        /**
    5637         * <p>Checks if the String contains only uppercase characters.</p>
    5638         *
    5639         * <p><code>null</code> will return <code>false</code>.
    5640         * An empty String (length()=0) will return <code>false</code>.</p>
    5641         *
    5642         * <pre>
    5643         * StringUtils.isAllUpperCase(null)   = false
    5644         * StringUtils.isAllUpperCase("")     = false
    5645         * StringUtils.isAllUpperCase("  ")   = false
    5646         * StringUtils.isAllUpperCase("ABC")  = true
    5647         * StringUtils.isAllUpperCase("aBC") = false
    5648         * </pre>
    5649         *
    5650         * @param str  the String to check, may be null
    5651         * @return <code>true</code> if only contains uppercase characters, and is non-null
    5652         * @since 2.5
    5653         */
    5654        public static boolean isAllUpperCase(String str) {
    5655            if (str == null || isEmpty(str)) {
    5656                return false;
    5657            }
    5658            int sz = str.length();
    5659            for (int i = 0; i < sz; i++) {
    5660                if (Character.isUpperCase(str.charAt(i)) == false) {
    5661                    return false;
    5662                }
    5663            }
    5664            return true;
    5665        }
    5666
    5667        // Defaults
    5668        //-----------------------------------------------------------------------
    5669        /**
    5670         * <p>Returns either the passed in String,
    5671         * or if the String is <code>null</code>, an empty String ("").</p>
    5672         *
    5673         * <pre>
    5674         * StringUtils.defaultString(null)  = ""
    5675         * StringUtils.defaultString("")    = ""
    5676         * StringUtils.defaultString("bat") = "bat"
    5677         * </pre>
    5678         *
    5679         * @see ObjectUtils#toString(Object)
    5680         * @see String#valueOf(Object)
    5681         * @param str  the String to check, may be null
    5682         * @return the passed in String, or the empty String if it
    5683         *  was <code>null</code>
    5684         */
    5685        public static String defaultString(String str) {
    5686            return str == null ? EMPTY : str;
    5687        }
    5688
    5689        /**
    5690         * <p>Returns either the passed in String, or if the String is
    5691         * <code>null</code>, the value of <code>defaultStr</code>.</p>
    5692         *
    5693         * <pre>
    5694         * StringUtils.defaultString(null, "NULL")  = "NULL"
    5695         * StringUtils.defaultString("", "NULL")    = ""
    5696         * StringUtils.defaultString("bat", "NULL") = "bat"
    5697         * </pre>
    5698         *
    5699         * @see ObjectUtils#toString(Object,String)
    5700         * @see String#valueOf(Object)
    5701         * @param str  the String to check, may be null
    5702         * @param defaultStr  the default String to return
    5703         *  if the input is <code>null</code>, may be null
    5704         * @return the passed in String, or the default if it was <code>null</code>
    5705         */
    5706        public static String defaultString(String str, String defaultStr) {
    5707            return str == null ? defaultStr : str;
    5708        }
    5709
    5710        /**
    5711         * <p>Returns either the passed in String, or if the String is
    5712         * whitespace, empty ("") or <code>null</code>, the value of <code>defaultStr</code>.</p>
    5713         *
    5714         * <pre>
    5715         * StringUtils.defaultIfBlank(null, "NULL")  = "NULL"
    5716         * StringUtils.defaultIfBlank("", "NULL")    = "NULL"
    5717         * StringUtils.defaultIfBlank(" ", "NULL")   = "NULL"
    5718         * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
    5719         * StringUtils.defaultIfBlank("", null)      = null
    5720         * </pre>
    5721         * @param str the String to check, may be null
    5722         * @param defaultStr  the default String to return
    5723         *  if the input is whitespace, empty ("") or <code>null</code>, may be null
    5724         * @return the passed in String, or the default
    5725         * @see StringUtils#defaultString(String, String)
    5726         * @since 2.6
    5727         */
    5728        public static String defaultIfBlank(String str, String defaultStr) {
    5729            return StringUtils.isBlank(str) ? defaultStr : str;
    5730        }
    5731
    5732        /**
    5733         * <p>Returns either the passed in String, or if the String is
    5734         * empty or <code>null</code>, the value of <code>defaultStr</code>.</p>
    5735         *
    5736         * <pre>
    5737         * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
    5738         * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
    5739         * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
    5740         * StringUtils.defaultIfEmpty("", null)      = null
    5741         * </pre>
    5742         *
    5743         * @param str  the String to check, may be null
    5744         * @param defaultStr  the default String to return
    5745         *  if the input is empty ("") or <code>null</code>, may be null
    5746         * @return the passed in String, or the default
    5747         * @see StringUtils#defaultString(String, String)
    5748         */
    5749        public static String defaultIfEmpty(String str, String defaultStr) {
    5750            return StringUtils.isEmpty(str) ? defaultStr : str;
    5751        }
    5752
    5753        // Reversing
    5754        //-----------------------------------------------------------------------
    5755        /**
    5756         * <p>Reverses a String as per {@link StrBuilder#reverse()}.</p>
    5757         *
    5758         * <p>A <code>null</code> String returns <code>null</code>.</p>
    5759         *
    5760         * <pre>
    5761         * StringUtils.reverse(null)  = null
    5762         * StringUtils.reverse("")    = ""
    5763         * StringUtils.reverse("bat") = "tab"
    5764         * </pre>
    5765         *
    5766         * @param str  the String to reverse, may be null
    5767         * @return the reversed String, <code>null</code> if null String input
    5768         */
    5769        public static String reverse(String str) {
    5770            if (str == null) {
    5771                return null;
    5772            }
    5773            return new StrBuilder(str).reverse().toString();
    5774        }
    5775
    5776        /**
    5777         * <p>Reverses a String that is delimited by a specific character.</p>
    5778         *
    5779         * <p>The Strings between the delimiters are not reversed.
    5780         * Thus java.lang.String becomes String.lang.java (if the delimiter
    5781         * is <code>'.'</code>).</p>
    5782         *
    5783         * <pre>
    5784         * StringUtils.reverseDelimited(null, *)      = null
    5785         * StringUtils.reverseDelimited("", *)        = ""
    5786         * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
    5787         * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
    5788         * </pre>
    5789         *
    5790         * @param str  the String to reverse, may be null
    5791         * @param separatorChar  the separator character to use
    5792         * @return the reversed String, <code>null</code> if null String input
    5793         * @since 2.0
    5794         */
    5795        public static String reverseDelimited(String str, char separatorChar) {
    5796            if (str == null) {
    5797                return null;
    5798            }
    5799            // could implement manually, but simple way is to reuse other,
    5800            // probably slower, methods.
    5801            String[] strs = split(str, separatorChar);
    5802            ArrayUtils.reverse(strs);
    5803            return join(strs, separatorChar);
    5804        }
    5805
    5806        /**
    5807         * <p>Reverses a String that is delimited by a specific character.</p>
    5808         *
    5809         * <p>The Strings between the delimiters are not reversed.
    5810         * Thus java.lang.String becomes String.lang.java (if the delimiter
    5811         * is <code>"."</code>).</p>
    5812         *
    5813         * <pre>
    5814         * StringUtils.reverseDelimitedString(null, *)       = null
    5815         * StringUtils.reverseDelimitedString("",*)          = ""
    5816         * StringUtils.reverseDelimitedString("a.b.c", null) = "a.b.c"
    5817         * StringUtils.reverseDelimitedString("a.b.c", ".")  = "c.b.a"
    5818         * </pre>
    5819         *
    5820         * @param str  the String to reverse, may be null
    5821         * @param separatorChars  the separator characters to use, null treated as whitespace
    5822         * @return the reversed String, <code>null</code> if null String input
    5823         * @deprecated Use {@link #reverseDelimited(String, char)} instead.
    5824         *      This method is broken as the join doesn't know which char to use.
    5825         *      Method will be removed in Commons Lang 3.0.
    5826         *
    5827         */
    5828        public static String reverseDelimitedString(String str, String separatorChars) {
    5829            if (str == null) {
    5830                return null;
    5831            }
    5832            // could implement manually, but simple way is to reuse other,
    5833            // probably slower, methods.
    5834            String[] strs = split(str, separatorChars);
    5835            ArrayUtils.reverse(strs);
    5836            if (separatorChars == null) {
    5837                return join(strs, ' ');
    5838            }
    5839            return join(strs, separatorChars);
    5840        }
    5841
    5842        // Abbreviating
    5843        //-----------------------------------------------------------------------
    5844        /**
    5845         * <p>Abbreviates a String using ellipses. This will turn
    5846         * "Now is the time for all good men" into "Now is the time for..."</p>
    5847         *
    5848         * <p>Specifically:
    5849         * <ul>
    5850         *   <li>If <code>str</code> is less than <code>maxWidth</code> characters
    5851         *       long, return it.</li>
    5852         *   <li>Else abbreviate it to <code>(substring(str, 0, max-3) + "...")</code>.</li>
    5853         *   <li>If <code>maxWidth</code> is less than <code>4</code>, throw an
    5854         *       <code>IllegalArgumentException</code>.</li>
    5855         *   <li>In no case will it return a String of length greater than
    5856         *       <code>maxWidth</code>.</li>
    5857         * </ul>
    5858         * </p>
    5859         *
    5860         * <pre>
    5861         * StringUtils.abbreviate(null, *)      = null
    5862         * StringUtils.abbreviate("", 4)        = ""
    5863         * StringUtils.abbreviate("abcdefg", 6) = "abc..."
    5864         * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
    5865         * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
    5866         * StringUtils.abbreviate("abcdefg", 4) = "a..."
    5867         * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
    5868         * </pre>
    5869         *
    5870         * @param str  the String to check, may be null
    5871         * @param maxWidth  maximum length of result String, must be at least 4
    5872         * @return abbreviated String, <code>null</code> if null String input
    5873         * @throws IllegalArgumentException if the width is too small
    5874         * @since 2.0
    5875         */
    5876        public static String abbreviate(String str, int maxWidth) {
    5877            return abbreviate(str, 0, maxWidth);
    5878        }
    5879
    5880        /**
    5881         * <p>Abbreviates a String using ellipses. This will turn
    5882         * "Now is the time for all good men" into "...is the time for..."</p>
    5883         *
    5884         * <p>Works like <code>abbreviate(String, int)</code>, but allows you to specify
    5885         * a "left edge" offset.  Note that this left edge is not necessarily going to
    5886         * be the leftmost character in the result, or the first character following the
    5887         * ellipses, but it will appear somewhere in the result.
    5888         *
    5889         * <p>In no case will it return a String of length greater than
    5890         * <code>maxWidth</code>.</p>
    5891         *
    5892         * <pre>
    5893         * StringUtils.abbreviate(null, *, *)                = null
    5894         * StringUtils.abbreviate("", 0, 4)                  = ""
    5895         * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
    5896         * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
    5897         * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
    5898         * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
    5899         * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
    5900         * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
    5901         * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
    5902         * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
    5903         * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
    5904         * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
    5905         * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
    5906         * </pre>
    5907         *
    5908         * @param str  the String to check, may be null
    5909         * @param offset  left edge of source String
    5910         * @param maxWidth  maximum length of result String, must be at least 4
    5911         * @return abbreviated String, <code>null</code> if null String input
    5912         * @throws IllegalArgumentException if the width is too small
    5913         * @since 2.0
    5914         */
    5915        public static String abbreviate(String str, int offset, int maxWidth) {
    5916            if (str == null) {
    5917                return null;
    5918            }
    5919            if (maxWidth < 4) {
    5920                throw new IllegalArgumentException("Minimum abbreviation width is 4");
    5921            }
    5922            if (str.length() <= maxWidth) {
    5923                return str;
    5924            }
    5925            if (offset > str.length()) {
    5926                offset = str.length();
    5927            }
    5928            if ((str.length() - offset) < (maxWidth - 3)) {
    5929                offset = str.length() - (maxWidth - 3);
    5930            }
    5931            if (offset <= 4) {
    5932                return str.substring(0, maxWidth - 3) + "...";
    5933            }
    5934            if (maxWidth < 7) {
    5935                throw new IllegalArgumentException("Minimum abbreviation width with offset is 7");
    5936            }
    5937            if ((offset + (maxWidth - 3)) < str.length()) {
    5938                return "..." + abbreviate(str.substring(offset), maxWidth - 3);
    5939            }
    5940            return "..." + str.substring(str.length() - (maxWidth - 3));
    5941        }
    5942
    5943        /**
    5944         * <p>Abbreviates a String to the length passed, replacing the middle characters with the supplied
    5945         * replacement String.</p>
    5946         *
    5947         * <p>This abbreviation only occurs if the following criteria is met:
    5948         * <ul>
    5949         * <li>Neither the String for abbreviation nor the replacement String are null or empty </li>
    5950         * <li>The length to truncate to is less than the length of the supplied String</li>
    5951         * <li>The length to truncate to is greater than 0</li>
    5952         * <li>The abbreviated String will have enough room for the length supplied replacement String
    5953         * and the first and last characters of the supplied String for abbreviation</li>
    5954         * </ul>
    5955         * Otherwise, the returned String will be the same as the supplied String for abbreviation.
    5956         * </p>
    5957         *
    5958         * <pre>
    5959         * StringUtils.abbreviateMiddle(null, null, 0)      = null
    5960         * StringUtils.abbreviateMiddle("abc", null, 0)      = "abc"
    5961         * StringUtils.abbreviateMiddle("abc", ".", 0)      = "abc"
    5962         * StringUtils.abbreviateMiddle("abc", ".", 3)      = "abc"
    5963         * StringUtils.abbreviateMiddle("abcdef", ".", 4)     = "ab.f"
    5964         * </pre>
    5965         *
    5966         * @param str  the String to abbreviate, may be null
    5967         * @param middle the String to replace the middle characters with, may be null
    5968         * @param length the length to abbreviate <code>str</code> to.
    5969         * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
    5970         * @since 2.5
    5971         */
    5972        public static String abbreviateMiddle(String str, String middle, int length) {
    5973            if (isEmpty(str) || isEmpty(middle)) {
    5974                return str;
    5975            }
    5976
    5977            if (length >= str.length() || length < (middle.length()+2)) {
    5978                return str;
    5979            }
    5980
    5981            int targetSting = length-middle.length();
    5982            int startOffset = targetSting/2+targetSting%2;
    5983            int endOffset = str.length()-targetSting/2;
    5984
    5985            StrBuilder builder = new StrBuilder(length);
    5986            builder.append(str.substring(0,startOffset));
    5987            builder.append(middle);
    5988            builder.append(str.substring(endOffset));
    5989
    5990            return builder.toString();
    5991        }
    5992
    5993        // Difference
    5994        //-----------------------------------------------------------------------
    5995        /**
    5996         * <p>Compares two Strings, and returns the portion where they differ.
    5997         * (More precisely, return the remainder of the second String,
    5998         * starting from where it's different from the first.)</p>
    5999         *
    6000         * <p>For example,
    6001         * <code>difference("i am a machine", "i am a robot") -> "robot"</code>.</p>
    6002         *
    6003         * <pre>
    6004         * StringUtils.difference(null, null) = null
    6005         * StringUtils.difference("", "") = ""
    6006         * StringUtils.difference("", "abc") = "abc"
    6007         * StringUtils.difference("abc", "") = ""
    6008         * StringUtils.difference("abc", "abc") = ""
    6009         * StringUtils.difference("ab", "abxyz") = "xyz"
    6010         * StringUtils.difference("abcde", "abxyz") = "xyz"
    6011         * StringUtils.difference("abcde", "xyz") = "xyz"
    6012         * </pre>
    6013         *
    6014         * @param str1  the first String, may be null
    6015         * @param str2  the second String, may be null
    6016         * @return the portion of str2 where it differs from str1; returns the
    6017         * empty String if they are equal
    6018         * @since 2.0
    6019         */
    6020        public static String difference(String str1, String str2) {
    6021            if (str1 == null) {
    6022                return str2;
    6023            }
    6024            if (str2 == null) {
    6025                return str1;
    6026            }
    6027            int at = indexOfDifference(str1, str2);
    6028            if (at == INDEX_NOT_FOUND) {
    6029                return EMPTY;
    6030            }
    6031            return str2.substring(at);
    6032        }
    6033
    6034        /**
    6035         * <p>Compares two Strings, and returns the index at which the
    6036         * Strings begin to differ.</p>
    6037         *
    6038         * <p>For example,
    6039         * <code>indexOfDifference("i am a machine", "i am a robot") -> 7</code></p>
    6040         *
    6041         * <pre>
    6042         * StringUtils.indexOfDifference(null, null) = -1
    6043         * StringUtils.indexOfDifference("", "") = -1
    6044         * StringUtils.indexOfDifference("", "abc") = 0
    6045         * StringUtils.indexOfDifference("abc", "") = 0
    6046         * StringUtils.indexOfDifference("abc", "abc") = -1
    6047         * StringUtils.indexOfDifference("ab", "abxyz") = 2
    6048         * StringUtils.indexOfDifference("abcde", "abxyz") = 2
    6049         * StringUtils.indexOfDifference("abcde", "xyz") = 0
    6050         * </pre>
    6051         *
    6052         * @param str1  the first String, may be null
    6053         * @param str2  the second String, may be null
    6054         * @return the index where str2 and str1 begin to differ; -1 if they are equal
    6055         * @since 2.0
    6056         */
    6057        public static int indexOfDifference(String str1, String str2) {
    6058            if (str1 == str2) {
    6059                return INDEX_NOT_FOUND;
    6060            }
    6061            if (str1 == null || str2 == null) {
    6062                return 0;
    6063            }
    6064            int i;
    6065            for (i = 0; i < str1.length() && i < str2.length(); ++i) {
    6066                if (str1.charAt(i) != str2.charAt(i)) {
    6067                    break;
    6068                }
    6069            }
    6070            if (i < str2.length() || i < str1.length()) {
    6071                return i;
    6072            }
    6073            return INDEX_NOT_FOUND;
    6074        }
    6075
    6076        /**
    6077         * <p>Compares all Strings in an array and returns the index at which the
    6078         * Strings begin to differ.</p>
    6079         *
    6080         * <p>For example,
    6081         * <code>indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7</code></p>
    6082         *
    6083         * <pre>
    6084         * StringUtils.indexOfDifference(null) = -1
    6085         * StringUtils.indexOfDifference(new String[] {}) = -1
    6086         * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
    6087         * StringUtils.indexOfDifference(new String[] {null, null}) = -1
    6088         * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
    6089         * StringUtils.indexOfDifference(new String[] {"", null}) = 0
    6090         * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
    6091         * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
    6092         * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
    6093         * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
    6094         * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
    6095         * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
    6096         * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
    6097         * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
    6098         * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
    6099         * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
    6100         * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
    6101         * </pre>
    6102         *
    6103         * @param strs  array of strings, entries may be null
    6104         * @return the index where the strings begin to differ; -1 if they are all equal
    6105         * @since 2.4
    6106         */
    6107        public static int indexOfDifference(String[] strs) {
    6108            if (strs == null || strs.length <= 1) {
    6109                return INDEX_NOT_FOUND;
    6110            }
    6111            boolean anyStringNull = false;
    6112            boolean allStringsNull = true;
    6113            int arrayLen = strs.length;
    6114            int shortestStrLen = Integer.MAX_VALUE;
    6115            int longestStrLen = 0;
    6116
    6117            // find the min and max string lengths; this avoids checking to make
    6118            // sure we are not exceeding the length of the string each time through
    6119            // the bottom loop.
    6120            for (int i = 0; i < arrayLen; i++) {
    6121                if (strs[i] == null) {
    6122                    anyStringNull = true;
    6123                    shortestStrLen = 0;
    6124                } else {
    6125                    allStringsNull = false;
    6126                    shortestStrLen = Math.min(strs[i].length(), shortestStrLen);
    6127                    longestStrLen = Math.max(strs[i].length(), longestStrLen);
    6128                }
    6129            }
    6130
    6131            // handle lists containing all nulls or all empty strings
    6132            if (allStringsNull || (longestStrLen == 0 && !anyStringNull)) {
    6133                return INDEX_NOT_FOUND;
    6134            }
    6135
    6136            // handle lists containing some nulls or some empty strings
    6137            if (shortestStrLen == 0) {
    6138                return 0;
    6139            }
    6140
    6141            // find the position with the first difference across all strings
    6142            int firstDiff = -1;
    6143            for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
    6144                char comparisonChar = strs[0].charAt(stringPos);
    6145                for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
    6146                    if (strs[arrayPos].charAt(stringPos) != comparisonChar) {
    6147                        firstDiff = stringPos;
    6148                        break;
    6149                    }
    6150                }
    6151                if (firstDiff != -1) {
    6152                    break;
    6153                }
    6154            }
    6155
    6156            if (firstDiff == -1 && shortestStrLen != longestStrLen) {
    6157                // we compared all of the characters up to the length of the
    6158                // shortest string and didn't find a match, but the string lengths
    6159                // vary, so return the length of the shortest string.
    6160                return shortestStrLen;
    6161            }
    6162            return firstDiff;
    6163        }
    6164
    6165        /**
    6166         * <p>Compares all Strings in an array and returns the initial sequence of
    6167         * characters that is common to all of them.</p>
    6168         *
    6169         * <p>For example,
    6170         * <code>getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "</code></p>
    6171         *
    6172         * <pre>
    6173         * StringUtils.getCommonPrefix(null) = ""
    6174         * StringUtils.getCommonPrefix(new String[] {}) = ""
    6175         * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc"
    6176         * StringUtils.getCommonPrefix(new String[] {null, null}) = ""
    6177         * StringUtils.getCommonPrefix(new String[] {"", ""}) = ""
    6178         * StringUtils.getCommonPrefix(new String[] {"", null}) = ""
    6179         * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
    6180         * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
    6181         * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = ""
    6182         * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = ""
    6183         * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc"
    6184         * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a"
    6185         * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab"
    6186         * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"
    6187         * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = ""
    6188         * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = ""
    6189         * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
    6190         * </pre>
    6191         *
    6192         * @param strs  array of String objects, entries may be null
    6193         * @return the initial sequence of characters that are common to all Strings
    6194         * in the array; empty String if the array is null, the elements are all null
    6195         * or if there is no common prefix.
    6196         * @since 2.4
    6197         */
    6198        public static String getCommonPrefix(String[] strs) {
    6199            if (strs == null || strs.length == 0) {
    6200                return EMPTY;
    6201            }
    6202            int smallestIndexOfDiff = indexOfDifference(strs);
    6203            if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
    6204                // all strings were identical
    6205                if (strs[0] == null) {
    6206                    return EMPTY;
    6207                }
    6208                return strs[0];
    6209            } else if (smallestIndexOfDiff == 0) {
    6210                // there were no common initial characters
    6211                return EMPTY;
    6212            } else {
    6213                // we found a common initial character sequence
    6214                return strs[0].substring(0, smallestIndexOfDiff);
    6215            }
    6216        }
    6217
    6218        // Misc
    6219        //-----------------------------------------------------------------------
    6220        /**
    6221         * <p>Find the Levenshtein distance between two Strings.</p>
    6222         *
    6223         * <p>This is the number of changes needed to change one String into
    6224         * another, where each change is a single character modification (deletion,
    6225         * insertion or substitution).</p>
    6226         *
    6227         * <p>The previous implementation of the Levenshtein distance algorithm
    6228         * was from <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
    6229         *
    6230         * <p>Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError
    6231         * which can occur when my Java implementation is used with very large strings.<br>
    6232         * This implementation of the Levenshtein distance algorithm
    6233         * is from <a href="http://www.merriampark.com/ldjava.htm">http://www.merriampark.com/ldjava.htm</a></p>
    6234         *
    6235         * <pre>
    6236         * StringUtils.getLevenshteinDistance(null, *)             = IllegalArgumentException
    6237         * StringUtils.getLevenshteinDistance(*, null)             = IllegalArgumentException
    6238         * StringUtils.getLevenshteinDistance("","")               = 0
    6239         * StringUtils.getLevenshteinDistance("","a")              = 1
    6240         * StringUtils.getLevenshteinDistance("aaapppp", "")       = 7
    6241         * StringUtils.getLevenshteinDistance("frog", "fog")       = 1
    6242         * StringUtils.getLevenshteinDistance("fly", "ant")        = 3
    6243         * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
    6244         * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
    6245         * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
    6246         * StringUtils.getLevenshteinDistance("hello", "hallo")    = 1
    6247         * </pre>
    6248         *
    6249         * @param s  the first String, must not be null
    6250         * @param t  the second String, must not be null
    6251         * @return result distance
    6252         * @throws IllegalArgumentException if either String input <code>null</code>
    6253         */
    6254        public static int getLevenshteinDistance(String s, String t) {
    6255            if (s == null || t == null) {
    6256                throw new IllegalArgumentException("Strings must not be null");
    6257            }
    6258
    6259            /*
    6260               The difference between this impl. and the previous is that, rather
    6261               than creating and retaining a matrix of size s.length()+1 by t.length()+1,
    6262               we maintain two single-dimensional arrays of length s.length()+1.  The first, d,
    6263               is the 'current working' distance array that maintains the newest distance cost
    6264               counts as we iterate through the characters of String s.  Each time we increment
    6265               the index of String t we are comparing, d is copied to p, the second int[].  Doing so
    6266               allows us to retain the previous cost counts as required by the algorithm (taking
    6267               the minimum of the cost count to the left, up one, and diagonally up and to the left
    6268               of the current cost count being calculated).  (Note that the arrays aren't really
    6269               copied anymore, just switched...this is clearly much better than cloning an array
    6270               or doing a System.arraycopy() each time  through the outer loop.)
    6271
    6272               Effectively, the difference between the two implementations is this one does not
    6273               cause an out of memory condition when calculating the LD over two very large strings.
    6274             */
    6275
    6276            int n = s.length(); // length of s
    6277            int m = t.length(); // length of t
    6278
    6279            if (n == 0) {
    6280                return m;
    6281            } else if (m == 0) {
    6282                return n;
    6283            }
    6284
    6285            if (n > m) {
    6286                // swap the input strings to consume less memory
    6287                String tmp = s;
    6288                s = t;
    6289                t = tmp;
    6290                n = m;
    6291                m = t.length();
    6292            }
    6293
    6294            int p[] = new int[n+1]; //'previous' cost array, horizontally
    6295            int d[] = new int[n+1]; // cost array, horizontally
    6296            int _d[]; //placeholder to assist in swapping p and d
    6297
    6298            // indexes into strings s and t
    6299            int i; // iterates through s
    6300            int j; // iterates through t
    6301
    6302            char t_j; // jth character of t
    6303
    6304            int cost; // cost
    6305
    6306            for (i = 0; i<=n; i++) {
    6307                p[i] = i;
    6308            }
    6309
    6310            for (j = 1; j<=m; j++) {
    6311                t_j = t.charAt(j-1);
    6312                d[0] = j;
    6313
    6314                for (i=1; i<=n; i++) {
    6315                    cost = s.charAt(i-1)==t_j ? 0 : 1;
    6316                    // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
    6317                    d[i] = Math.min(Math.min(d[i-1]+1, p[i]+1),  p[i-1]+cost);
    6318                }
    6319
    6320                // copy current distance counts to 'previous row' distance counts
    6321                _d = p;
    6322                p = d;
    6323                d = _d;
    6324            }
    6325
    6326            // our last action in the above loop was to switch d and p, so p now
    6327            // actually has the most recent cost counts
    6328            return p[n];
    6329        }
    6330
    6331        // startsWith
    6332        //-----------------------------------------------------------------------
    6333
    6334        /**
    6335         * <p>Check if a String starts with a specified prefix.</p>
    6336         *
    6337         * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
    6338         * references are considered to be equal. The comparison is case sensitive.</p>
    6339         *
    6340         * <pre>
    6341         * StringUtils.startsWith(null, null)      = true
    6342         * StringUtils.startsWith(null, "abc")     = false
    6343         * StringUtils.startsWith("abcdef", null)  = false
    6344         * StringUtils.startsWith("abcdef", "abc") = true
    6345         * StringUtils.startsWith("ABCDEF", "abc") = false
    6346         * </pre>
    6347         *
    6348         * @see java.lang.String#startsWith(String)
    6349         * @param str  the String to check, may be null
    6350         * @param prefix the prefix to find, may be null
    6351         * @return <code>true</code> if the String starts with the prefix, case sensitive, or
    6352         *  both <code>null</code>
    6353         * @since 2.4
    6354         */
    6355        public static boolean startsWith(String str, String prefix) {
    6356            return startsWith(str, prefix, false);
    6357        }
    6358
    6359        /**
    6360         * <p>Case insensitive check if a String starts with a specified prefix.</p>
    6361         *
    6362         * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
    6363         * references are considered to be equal. The comparison is case insensitive.</p>
    6364         *
    6365         * <pre>
    6366         * StringUtils.startsWithIgnoreCase(null, null)      = true
    6367         * StringUtils.startsWithIgnoreCase(null, "abc")     = false
    6368         * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
    6369         * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
    6370         * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
    6371         * </pre>
    6372         *
    6373         * @see java.lang.String#startsWith(String)
    6374         * @param str  the String to check, may be null
    6375         * @param prefix the prefix to find, may be null
    6376         * @return <code>true</code> if the String starts with the prefix, case insensitive, or
    6377         *  both <code>null</code>
    6378         * @since 2.4
    6379         */
    6380        public static boolean startsWithIgnoreCase(String str, String prefix) {
    6381            return startsWith(str, prefix, true);
    6382        }
    6383
    6384        /**
    6385         * <p>Check if a String starts with a specified prefix (optionally case insensitive).</p>
    6386         *
    6387         * @see java.lang.String#startsWith(String)
    6388         * @param str  the String to check, may be null
    6389         * @param prefix the prefix to find, may be null
    6390         * @param ignoreCase inidicates whether the compare should ignore case
    6391         *  (case insensitive) or not.
    6392         * @return <code>true</code> if the String starts with the prefix or
    6393         *  both <code>null</code>
    6394         */
    6395        private static boolean startsWith(String str, String prefix, boolean ignoreCase) {
    6396            if (str == null || prefix == null) {
    6397                return (str == null && prefix == null);
    6398            }
    6399            if (prefix.length() > str.length()) {
    6400                return false;
    6401            }
    6402            return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
    6403        }
    6404
    6405        /**
    6406         * <p>Check if a String starts with any of an array of specified strings.</p>
    6407         *
    6408         * <pre>
    6409         * StringUtils.startsWithAny(null, null)      = false
    6410         * StringUtils.startsWithAny(null, new String[] {"abc"})  = false
    6411         * StringUtils.startsWithAny("abcxyz", null)     = false
    6412         * StringUtils.startsWithAny("abcxyz", new String[] {""}) = false
    6413         * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
    6414         * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
    6415         * </pre>
    6416         *
    6417         * @see #startsWith(String, String)
    6418         * @param string  the String to check, may be null
    6419         * @param searchStrings the Strings to find, may be null or empty
    6420         * @return <code>true</code> if the String starts with any of the the prefixes, case insensitive, or
    6421         *  both <code>null</code>
    6422         * @since 2.5
    6423         */
    6424        public static boolean startsWithAny(String string, String[] searchStrings) {
    6425            if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) {
    6426                return false;
    6427            }
    6428            for (int i = 0; i < searchStrings.length; i++) {
    6429                String searchString = searchStrings[i];
    6430                if (StringUtils.startsWith(string, searchString)) {
    6431                    return true;
    6432                }
    6433            }
    6434            return false;
    6435        }
    6436
    6437        // endsWith
    6438        //-----------------------------------------------------------------------
    6439
    6440        /**
    6441         * <p>Check if a String ends with a specified suffix.</p>
    6442         *
    6443         * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
    6444         * references are considered to be equal. The comparison is case sensitive.</p>
    6445         *
    6446         * <pre>
    6447         * StringUtils.endsWith(null, null)      = true
    6448         * StringUtils.endsWith(null, "def")     = false
    6449         * StringUtils.endsWith("abcdef", null)  = false
    6450         * StringUtils.endsWith("abcdef", "def") = true
    6451         * StringUtils.endsWith("ABCDEF", "def") = false
    6452         * StringUtils.endsWith("ABCDEF", "cde") = false
    6453         * </pre>
    6454         *
    6455         * @see java.lang.String#endsWith(String)
    6456         * @param str  the String to check, may be null
    6457         * @param suffix the suffix to find, may be null
    6458         * @return <code>true</code> if the String ends with the suffix, case sensitive, or
    6459         *  both <code>null</code>
    6460         * @since 2.4
    6461         */
    6462        public static boolean endsWith(String str, String suffix) {
    6463            return endsWith(str, suffix, false);
    6464        }
    6465
    6466        /**
    6467         * <p>Case insensitive check if a String ends with a specified suffix.</p>
    6468         *
    6469         * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
    6470         * references are considered to be equal. The comparison is case insensitive.</p>
    6471         *
    6472         * <pre>
    6473         * StringUtils.endsWithIgnoreCase(null, null)      = true
    6474         * StringUtils.endsWithIgnoreCase(null, "def")     = false
    6475         * StringUtils.endsWithIgnoreCase("abcdef", null)  = false
    6476         * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
    6477         * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
    6478         * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
    6479         * </pre>
    6480         *
    6481         * @see java.lang.String#endsWith(String)
    6482         * @param str  the String to check, may be null
    6483         * @param suffix the suffix to find, may be null
    6484         * @return <code>true</code> if the String ends with the suffix, case insensitive, or
    6485         *  both <code>null</code>
    6486         * @since 2.4
    6487         */
    6488        public static boolean endsWithIgnoreCase(String str, String suffix) {
    6489            return endsWith(str, suffix, true);
    6490        }
    6491
    6492        /**
    6493         * <p>Check if a String ends with a specified suffix (optionally case insensitive).</p>
    6494         *
    6495         * @see java.lang.String#endsWith(String)
    6496         * @param str  the String to check, may be null
    6497         * @param suffix the suffix to find, may be null
    6498         * @param ignoreCase inidicates whether the compare should ignore case
    6499         *  (case insensitive) or not.
    6500         * @return <code>true</code> if the String starts with the prefix or
    6501         *  both <code>null</code>
    6502         */
    6503        private static boolean endsWith(String str, String suffix, boolean ignoreCase) {
    6504            if (str == null || suffix == null) {
    6505                return (str == null && suffix == null);
    6506            }
    6507            if (suffix.length() > str.length()) {
    6508                return false;
    6509            }
    6510            int strOffset = str.length() - suffix.length();
    6511            return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length());
    6512        }
    6513
    6514        /**
    6515         * <p>
    6516         * Similar to <a
    6517         * href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize
    6518         * -space</a>
    6519         * </p>
    6520         * <p>
    6521         * The function returns the argument string with whitespace normalized by using
    6522         * <code>{@link #trim(String)}</code> to remove leading and trailing whitespace
    6523         * and then replacing sequences of whitespace characters by a single space.
    6524         * </p>
    6525         * In XML Whitespace characters are the same as those allowed by the <a
    6526         * href="http://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+
    6527         * <p>
    6528         * See Java's {@link Character#isWhitespace(char)} for which characters are considered whitespace.
    6529         * <p>
    6530         * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also
    6531         * normalize. Additonally <code>{@link #trim(String)}</code> removes control characters (char &lt;= 32) from both
    6532         * ends of this String.
    6533         * </p>
    6534         *
    6535         * @see Character#isWhitespace(char)
    6536         * @see #trim(String)
    6537         * @see <ahref="http://www.w3.org/TR/xpath/#function-normalize-space">
    6538         *              http://www.w3.org/TR/xpath/#function-normalize-space</a>
    6539         * @param str the source String to normalize whitespaces from, may be null
    6540         * @return the modified string with whitespace normalized, <code>null</code> if null String input
    6541         *
    6542         * @since 2.6
    6543         */
    6544        public static String normalizeSpace(String str) {
    6545            str = strip(str);
    6546            if(str == null || str.length() <= 2) {
    6547                return str;
    6548            }
    6549            StrBuilder b = new StrBuilder(str.length());
    6550            for (int i = 0; i < str.length(); i++) {
    6551                char c = str.charAt(i);
    6552                if (Character.isWhitespace(c)) {
    6553                    if (i > 0 && !Character.isWhitespace(str.charAt(i - 1))) {
    6554                        b.append(' ');
    6555                    }
    6556                } else {
    6557                    b.append(c);
    6558                }
    6559            }
    6560            return b.toString();
    6561        }
    6562
    6563        /**
    6564         * <p>Check if a String ends with any of an array of specified strings.</p>
    6565         *
    6566         * <pre>
    6567         * StringUtils.endsWithAny(null, null)      = false
    6568         * StringUtils.endsWithAny(null, new String[] {"abc"})  = false
    6569         * StringUtils.endsWithAny("abcxyz", null)     = false
    6570         * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
    6571         * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
    6572         * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
    6573         * </pre>
    6574         *
    6575         * @param string  the String to check, may be null
    6576         * @param searchStrings the Strings to find, may be null or empty
    6577         * @return <code>true</code> if the String ends with any of the the prefixes, case insensitive, or
    6578         *  both <code>null</code>
    6579         * @since 2.6
    6580         */
    6581        public static boolean endsWithAny(String string, String[] searchStrings) {
    6582            if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) {
    6583                return false;
    6584            }
    6585            for (int i = 0; i < searchStrings.length; i++) {
    6586                String searchString = searchStrings[i];
    6587                if (StringUtils.endsWith(string, searchString)) {
    6588                    return true;
    6589                }
    6590            }
    6591            return false;
    6592        }
    6593
    6594    }