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