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