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