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