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