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