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      */
4593     public static String joinWith(final String separator, final Object... objects) {
4594         if (objects == null) {
4595             throw new IllegalArgumentException("Object varargs must not be null");
4596         }
4597 
4598         final String sanitizedSeparator = defaultString(separator, StringUtils.EMPTY);
4599 
4600         final StringBuilder result = new StringBuilder();
4601 
4602         final Iterator<Object> iterator = Arrays.asList(objects).iterator();
4603         while (iterator.hasNext()) {
4604             @SuppressWarnings("deprecation") // o.k. to use as long as we do not require java 7 or greater
4605             final String value = ObjectUtils.toString(iterator.next());
4606             result.append(value);
4607 
4608             if (iterator.hasNext()) {
4609                 result.append(sanitizedSeparator);
4610             }
4611         }
4612 
4613         return result.toString();
4614     }
4615 
4616     // Delete
4617     //-----------------------------------------------------------------------
4618     /**
4619      * <p>Deletes all whitespaces from a String as defined by
4620      * {@link Character#isWhitespace(char)}.</p>
4621      *
4622      * <pre>
4623      * StringUtils.deleteWhitespace(null)         = null
4624      * StringUtils.deleteWhitespace("")           = ""
4625      * StringUtils.deleteWhitespace("abc")        = "abc"
4626      * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
4627      * </pre>
4628      *
4629      * @param str  the String to delete whitespace from, may be null
4630      * @return the String without whitespaces, {@code null} if null String input
4631      */
4632     public static String deleteWhitespace(final String str) {
4633         if (isEmpty(str)) {
4634             return str;
4635         }
4636         final int sz = str.length();
4637         final char[] chs = new char[sz];
4638         int count = 0;
4639         for (int i = 0; i < sz; i++) {
4640             if (!Character.isWhitespace(str.charAt(i))) {
4641                 chs[count++] = str.charAt(i);
4642             }
4643         }
4644         if (count == sz) {
4645             return str;
4646         }
4647         return new String(chs, 0, count);
4648     }
4649 
4650     // Remove
4651     //-----------------------------------------------------------------------
4652     /**
4653      * <p>Removes a substring only if it is at the beginning of a source string,
4654      * otherwise returns the source string.</p>
4655      *
4656      * <p>A {@code null} source string will return {@code null}.
4657      * An empty ("") source string will return the empty string.
4658      * A {@code null} search string will return the source string.</p>
4659      *
4660      * <pre>
4661      * StringUtils.removeStart(null, *)      = null
4662      * StringUtils.removeStart("", *)        = ""
4663      * StringUtils.removeStart(*, null)      = *
4664      * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
4665      * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
4666      * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
4667      * StringUtils.removeStart("abc", "")    = "abc"
4668      * </pre>
4669      *
4670      * @param str  the source String to search, may be null
4671      * @param remove  the String to search for and remove, may be null
4672      * @return the substring with the string removed if found,
4673      *  {@code null} if null String input
4674      * @since 2.1
4675      */
4676     public static String removeStart(final String str, final String remove) {
4677         if (isEmpty(str) || isEmpty(remove)) {
4678             return str;
4679         }
4680         if (str.startsWith(remove)){
4681             return str.substring(remove.length());
4682         }
4683         return str;
4684     }
4685 
4686     /**
4687      * <p>Case insensitive removal of a substring if it is at the beginning of a source string,
4688      * otherwise returns the source string.</p>
4689      *
4690      * <p>A {@code null} source string will return {@code null}.
4691      * An empty ("") source string will return the empty string.
4692      * A {@code null} search string will return the source string.</p>
4693      *
4694      * <pre>
4695      * StringUtils.removeStartIgnoreCase(null, *)      = null
4696      * StringUtils.removeStartIgnoreCase("", *)        = ""
4697      * StringUtils.removeStartIgnoreCase(*, null)      = *
4698      * StringUtils.removeStartIgnoreCase("www.domain.com", "www.")   = "domain.com"
4699      * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.")   = "domain.com"
4700      * StringUtils.removeStartIgnoreCase("domain.com", "www.")       = "domain.com"
4701      * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
4702      * StringUtils.removeStartIgnoreCase("abc", "")    = "abc"
4703      * </pre>
4704      *
4705      * @param str  the source String to search, may be null
4706      * @param remove  the String to search for (case insensitive) and remove, may be null
4707      * @return the substring with the string removed if found,
4708      *  {@code null} if null String input
4709      * @since 2.4
4710      */
4711     public static String removeStartIgnoreCase(final String str, final String remove) {
4712         if (isEmpty(str) || isEmpty(remove)) {
4713             return str;
4714         }
4715         if (startsWithIgnoreCase(str, remove)) {
4716             return str.substring(remove.length());
4717         }
4718         return str;
4719     }
4720 
4721     /**
4722      * <p>Removes a substring only if it is at the end of a source string,
4723      * otherwise returns the source string.</p>
4724      *
4725      * <p>A {@code null} source string will return {@code null}.
4726      * An empty ("") source string will return the empty string.
4727      * A {@code null} search string will return the source string.</p>
4728      *
4729      * <pre>
4730      * StringUtils.removeEnd(null, *)      = null
4731      * StringUtils.removeEnd("", *)        = ""
4732      * StringUtils.removeEnd(*, null)      = *
4733      * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
4734      * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
4735      * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
4736      * StringUtils.removeEnd("abc", "")    = "abc"
4737      * </pre>
4738      *
4739      * @param str  the source String to search, may be null
4740      * @param remove  the String to search for and remove, may be null
4741      * @return the substring with the string removed if found,
4742      *  {@code null} if null String input
4743      * @since 2.1
4744      */
4745     public static String removeEnd(final String str, final String remove) {
4746         if (isEmpty(str) || isEmpty(remove)) {
4747             return str;
4748         }
4749         if (str.endsWith(remove)) {
4750             return str.substring(0, str.length() - remove.length());
4751         }
4752         return str;
4753     }
4754 
4755     /**
4756      * <p>Case insensitive removal of a substring if it is at the end of a source string,
4757      * otherwise returns the source string.</p>
4758      *
4759      * <p>A {@code null} source string will return {@code null}.
4760      * An empty ("") source string will return the empty string.
4761      * A {@code null} search string will return the source string.</p>
4762      *
4763      * <pre>
4764      * StringUtils.removeEndIgnoreCase(null, *)      = null
4765      * StringUtils.removeEndIgnoreCase("", *)        = ""
4766      * StringUtils.removeEndIgnoreCase(*, null)      = *
4767      * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.")  = "www.domain.com"
4768      * StringUtils.removeEndIgnoreCase("www.domain.com", ".com")   = "www.domain"
4769      * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
4770      * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"
4771      * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
4772      * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
4773      * </pre>
4774      *
4775      * @param str  the source String to search, may be null
4776      * @param remove  the String to search for (case insensitive) and remove, may be null
4777      * @return the substring with the string removed if found,
4778      *  {@code null} if null String input
4779      * @since 2.4
4780      */
4781     public static String removeEndIgnoreCase(final String str, final String remove) {
4782         if (isEmpty(str) || isEmpty(remove)) {
4783             return str;
4784         }
4785         if (endsWithIgnoreCase(str, remove)) {
4786             return str.substring(0, str.length() - remove.length());
4787         }
4788         return str;
4789     }
4790 
4791     /**
4792      * <p>Removes all occurrences of a substring from within the source string.</p>
4793      *
4794      * <p>A {@code null} source string will return {@code null}.
4795      * An empty ("") source string will return the empty string.
4796      * A {@code null} remove string will return the source string.
4797      * An empty ("") remove string will return the source string.</p>
4798      *
4799      * <pre>
4800      * StringUtils.remove(null, *)        = null
4801      * StringUtils.remove("", *)          = ""
4802      * StringUtils.remove(*, null)        = *
4803      * StringUtils.remove(*, "")          = *
4804      * StringUtils.remove("queued", "ue") = "qd"
4805      * StringUtils.remove("queued", "zz") = "queued"
4806      * </pre>
4807      *
4808      * @param str  the source String to search, may be null
4809      * @param remove  the String to search for and remove, may be null
4810      * @return the substring with the string removed if found,
4811      *  {@code null} if null String input
4812      * @since 2.1
4813      */
4814     public static String remove(final String str, final String remove) {
4815         if (isEmpty(str) || isEmpty(remove)) {
4816             return str;
4817         }
4818         return replace(str, remove, EMPTY, -1);
4819     }
4820 
4821     /**
4822      * <p>Removes all occurrences of a character from within the source string.</p>
4823      *
4824      * <p>A {@code null} source string will return {@code null}.
4825      * An empty ("") source string will return the empty string.</p>
4826      *
4827      * <pre>
4828      * StringUtils.remove(null, *)       = null
4829      * StringUtils.remove("", *)         = ""
4830      * StringUtils.remove("queued", 'u') = "qeed"
4831      * StringUtils.remove("queued", 'z') = "queued"
4832      * </pre>
4833      *
4834      * @param str  the source String to search, may be null
4835      * @param remove  the char to search for and remove, may be null
4836      * @return the substring with the char removed if found,
4837      *  {@code null} if null String input
4838      * @since 2.1
4839      */
4840     public static String remove(final String str, final char remove) {
4841         if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
4842             return str;
4843         }
4844         final char[] chars = str.toCharArray();
4845         int pos = 0;
4846         for (int i = 0; i < chars.length; i++) {
4847             if (chars[i] != remove) {
4848                 chars[pos++] = chars[i];
4849             }
4850         }
4851         return new String(chars, 0, pos);
4852     }
4853 
4854     /**
4855      * <p>Removes each substring of the text String that matches the given regular expression.</p>
4856      *
4857      * This method is a {@code null} safe equivalent to:
4858      * <ul>
4859      *  <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li>
4860      *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li>
4861      * </ul>
4862      *
4863      * <p>A {@code null} reference passed to this method is a no-op.</p>
4864      *
4865      * <p>Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option
4866      * is NOT automatically added.
4867      * To use the DOTALL option prepend <code>"(?s)"</code> to the regex.
4868      * DOTALL is also know as single-line mode in Perl.</p>
4869      *
4870      * <pre>
4871      * StringUtils.removeAll(null, *)      = null
4872      * StringUtils.removeAll("any", null)  = "any"
4873      * StringUtils.removeAll("any", "")    = "any"
4874      * StringUtils.removeAll("any", ".*")  = ""
4875      * StringUtils.removeAll("any", ".+")  = ""
4876      * StringUtils.removeAll("abc", ".?")  = ""
4877      * StringUtils.removeAll("A&lt;__&gt;\n&lt;__&gt;B", "&lt;.*&gt;")      = "A\nB"
4878      * StringUtils.removeAll("A&lt;__&gt;\n&lt;__&gt;B", "(?s)&lt;.*&gt;")  = "AB"
4879      * StringUtils.removeAll("ABCabc123abc", "[a-z]")     = "ABC123"
4880      * </pre>
4881      *
4882      * @param text  text to remove from, may be null
4883      * @param regex  the regular expression to which this string is to be matched
4884      * @return  the text with any removes processed,
4885      *              {@code null} if null String input
4886      *
4887      * @throws  java.util.regex.PatternSyntaxException
4888      *              if the regular expression's syntax is invalid
4889      *
4890      * @see #replaceAll(String, String, String)
4891      * @see #removePattern(String, String)
4892      * @see String#replaceAll(String, String)
4893      * @see java.util.regex.Pattern
4894      * @see java.util.regex.Pattern#DOTALL
4895      * @since 3.5
4896      */
4897     public static String removeAll(final String text, final String regex) {
4898         return replaceAll(text, regex, StringUtils.EMPTY);
4899     }
4900 
4901     /**
4902      * <p>Removes the first substring of the text string that matches the given regular expression.</p>
4903      *
4904      * This method is a {@code null} safe equivalent to:
4905      * <ul>
4906      *  <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li>
4907      *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li>
4908      * </ul>
4909      *
4910      * <p>A {@code null} reference passed to this method is a no-op.</p>
4911      *
4912      * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
4913      * To use the DOTALL option prepend <code>"(?s)"</code> to the regex.
4914      * DOTALL is also know as single-line mode in Perl.</p>
4915      *
4916      * <pre>
4917      * StringUtils.removeFirst(null, *)      = null
4918      * StringUtils.removeFirst("any", null)  = "any"
4919      * StringUtils.removeFirst("any", "")    = "any"
4920      * StringUtils.removeFirst("any", ".*")  = ""
4921      * StringUtils.removeFirst("any", ".+")  = ""
4922      * StringUtils.removeFirst("abc", ".?")  = "bc"
4923      * StringUtils.removeFirst("A&lt;__&gt;\n&lt;__&gt;B", "&lt;.*&gt;")      = "A\n&lt;__&gt;B"
4924      * StringUtils.removeFirst("A&lt;__&gt;\n&lt;__&gt;B", "(?s)&lt;.*&gt;")  = "AB"
4925      * StringUtils.removeFirst("ABCabc123", "[a-z]")          = "ABCbc123"
4926      * StringUtils.removeFirst("ABCabc123abc", "[a-z]+")      = "ABC123abc"
4927      * </pre>
4928      *
4929      * @param text  text to remove from, may be null
4930      * @param regex  the regular expression to which this string is to be matched
4931      * @return  the text with the first replacement processed,
4932      *              {@code null} if null String input
4933      *
4934      * @throws  java.util.regex.PatternSyntaxException
4935      *              if the regular expression's syntax is invalid
4936      *
4937      * @see #replaceFirst(String, String, String)
4938      * @see String#replaceFirst(String, String)
4939      * @see java.util.regex.Pattern
4940      * @see java.util.regex.Pattern#DOTALL
4941      * @since 3.5
4942      */
4943     public static String removeFirst(final String text, final String regex) {
4944         return replaceFirst(text, regex, StringUtils.EMPTY);
4945     }
4946 
4947     // Replacing
4948     //-----------------------------------------------------------------------
4949     /**
4950      * <p>Replaces a String with another String inside a larger String, once.</p>
4951      *
4952      * <p>A {@code null} reference passed to this method is a no-op.</p>
4953      *
4954      * <pre>
4955      * StringUtils.replaceOnce(null, *, *)        = null
4956      * StringUtils.replaceOnce("", *, *)          = ""
4957      * StringUtils.replaceOnce("any", null, *)    = "any"
4958      * StringUtils.replaceOnce("any", *, null)    = "any"
4959      * StringUtils.replaceOnce("any", "", *)      = "any"
4960      * StringUtils.replaceOnce("aba", "a", null)  = "aba"
4961      * StringUtils.replaceOnce("aba", "a", "")    = "ba"
4962      * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
4963      * </pre>
4964      *
4965      * @see #replace(String text, String searchString, String replacement, int max)
4966      * @param text  text to search and replace in, may be null
4967      * @param searchString  the String to search for, may be null
4968      * @param replacement  the String to replace with, may be null
4969      * @return the text with any replacements processed,
4970      *  {@code null} if null String input
4971      */
4972     public static String replaceOnce(final String text, final String searchString, final String replacement) {
4973         return replace(text, searchString, replacement, 1);
4974     }
4975 
4976     /**
4977      * <p>Replaces each substring of the source String that matches the given regular expression with the given
4978      * replacement using the {@link Pattern#DOTALL} option. DOTALL is also know as single-line mode in Perl.</p>
4979      *
4980      * This call is a {@code null} safe equivalent to:
4981      * <ul>
4982      * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, replacement)}</li>
4983      * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li>
4984      * </ul>
4985      *
4986      * <p>A {@code null} reference passed to this method is a no-op.</p>
4987      *
4988      * <pre>
4989      * StringUtils.replacePattern(null, *, *)       = null
4990      * StringUtils.replacePattern("any", null, *)   = "any"
4991      * StringUtils.replacePattern("any", *, null)   = "any"
4992      * StringUtils.replacePattern("", "", "zzz")    = "zzz"
4993      * StringUtils.replacePattern("", ".*", "zzz")  = "zzz"
4994      * StringUtils.replacePattern("", ".+", "zzz")  = ""
4995      * StringUtils.replacePattern("&lt;__&gt;\n&lt;__&gt;", "&lt;.*&gt;", "z")       = "z"
4996      * StringUtils.replacePattern("ABCabc123", "[a-z]", "_")       = "ABC___123"
4997      * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
4998      * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
4999      * StringUtils.replacePattern("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
5000      * </pre>
5001      *
5002      * @param source
5003      *            the source string
5004      * @param regex
5005      *            the regular expression to which this string is to be matched
5006      * @param replacement
5007      *            the string to be substituted for each match
5008      * @return The resulting {@code String}
5009      * @see #replaceAll(String, String, String)
5010      * @see String#replaceAll(String, String)
5011      * @see Pattern#DOTALL
5012      * @since 3.2
5013      * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
5014      */
5015     public static String replacePattern(final String source, final String regex, final String replacement) {
5016         if (source == null || regex == null|| replacement == null ) {
5017             return source;
5018         }
5019         return Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement);
5020     }
5021 
5022     /**
5023      * <p>Removes each substring of the source String that matches the given regular expression using the DOTALL option.
5024      * </p>
5025      *
5026      * This call is a {@code null} safe equivalent to:
5027      * <ul>
5028      * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, StringUtils.EMPTY)}</li>
5029      * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li>
5030      * </ul>
5031      *
5032      * <p>A {@code null} reference passed to this method is a no-op.</p>
5033      *
5034      * <pre>
5035      * StringUtils.removePattern(null, *)       = null
5036      * StringUtils.removePattern("any", null)   = "any"
5037      * StringUtils.removePattern("A&lt;__&gt;\n&lt;__&gt;B", "&lt;.*&gt;")  = "AB"
5038      * StringUtils.removePattern("ABCabc123", "[a-z]")    = "ABC123"
5039      * </pre>
5040      *
5041      * @param source
5042      *            the source string
5043      * @param regex
5044      *            the regular expression to which this string is to be matched
5045      * @return The resulting {@code String}
5046      * @see #replacePattern(String, String, String)
5047      * @see String#replaceAll(String, String)
5048      * @see Pattern#DOTALL
5049      * @since 3.2
5050      * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
5051      */
5052     public static String removePattern(final String source, final String regex) {
5053         return replacePattern(source, regex, StringUtils.EMPTY);
5054     }
5055 
5056     /**
5057      * <p>Replaces each substring of the text String that matches the given regular expression
5058      * with the given replacement.</p>
5059      *
5060      * This method is a {@code null} safe equivalent to:
5061      * <ul>
5062      *  <li>{@code text.replaceAll(regex, replacement)}</li>
5063      *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li>
5064      * </ul>
5065      *
5066      * <p>A {@code null} reference passed to this method is a no-op.</p>
5067      *
5068      * <p>Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option
5069      * is NOT automatically added.
5070      * To use the DOTALL option prepend <code>"(?s)"</code> to the regex.
5071      * DOTALL is also know as single-line mode in Perl.</p>
5072      *
5073      * <pre>
5074      * StringUtils.replaceAll(null, *, *)       = null
5075      * StringUtils.replaceAll("any", null, *)   = "any"
5076      * StringUtils.replaceAll("any", *, null)   = "any"
5077      * StringUtils.replaceAll("", "", "zzz")    = "zzz"
5078      * StringUtils.replaceAll("", ".*", "zzz")  = "zzz"
5079      * StringUtils.replaceAll("", ".+", "zzz")  = ""
5080      * StringUtils.replaceAll("abc", "", "ZZ")  = "ZZaZZbZZcZZ"
5081      * StringUtils.replaceAll("&lt;__&gt;\n&lt;__&gt;", "&lt;.*&gt;", "z")      = "z\nz"
5082      * StringUtils.replaceAll("&lt;__&gt;\n&lt;__&gt;", "(?s)&lt;.*&gt;", "z")  = "z"
5083      * StringUtils.replaceAll("ABCabc123", "[a-z]", "_")       = "ABC___123"
5084      * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
5085      * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
5086      * StringUtils.replaceAll("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
5087      * </pre>
5088      *
5089      * @param text  text to search and replace in, may be null
5090      * @param regex  the regular expression to which this string is to be matched
5091      * @param replacement  the string to be substituted for each match
5092      * @return  the text with any replacements processed,
5093      *              {@code null} if null String input
5094      *
5095      * @throws  java.util.regex.PatternSyntaxException
5096      *              if the regular expression's syntax is invalid
5097      *
5098      * @see #replacePattern(String, String, String)
5099      * @see String#replaceAll(String, String)
5100      * @see java.util.regex.Pattern
5101      * @see java.util.regex.Pattern#DOTALL
5102      * @since 3.5
5103      */
5104     public static String replaceAll(final String text, final String regex, final String replacement) {
5105         if (text == null || regex == null|| replacement == null ) {
5106             return text;
5107         }
5108         return text.replaceAll(regex, replacement);
5109     }
5110 
5111     /**
5112      * <p>Replaces the first substring of the text string that matches the given regular expression
5113      * with the given replacement.</p>
5114      *
5115      * This method is a {@code null} safe equivalent to:
5116      * <ul>
5117      *  <li>{@code text.replaceFirst(regex, replacement)}</li>
5118      *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li>
5119      * </ul>
5120      *
5121      * <p>A {@code null} reference passed to this method is a no-op.</p>
5122      *
5123      * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
5124      * To use the DOTALL option prepend <code>"(?s)"</code> to the regex.
5125      * DOTALL is also know as single-line mode in Perl.</p>
5126      *
5127      * <pre>
5128      * StringUtils.replaceFirst(null, *, *)       = null
5129      * StringUtils.replaceFirst("any", null, *)   = "any"
5130      * StringUtils.replaceFirst("any", *, null)   = "any"
5131      * StringUtils.replaceFirst("", "", "zzz")    = "zzz"
5132      * StringUtils.replaceFirst("", ".*", "zzz")  = "zzz"
5133      * StringUtils.replaceFirst("", ".+", "zzz")  = ""
5134      * StringUtils.replaceFirst("abc", "", "ZZ")  = "ZZabc"
5135      * StringUtils.replaceFirst("&lt;__&gt;\n&lt;__&gt;", "&lt;.*&gt;", "z")      = "z\n&lt;__&gt;"
5136      * StringUtils.replaceFirst("&lt;__&gt;\n&lt;__&gt;", "(?s)&lt;.*&gt;", "z")  = "z"
5137      * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_")          = "ABC_bc123"
5138      * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_")  = "ABC_123abc"
5139      * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "")   = "ABC123abc"
5140      * StringUtils.replaceFirst("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum  dolor   sit"
5141      * </pre>
5142      *
5143      * @param text  text to search and replace in, may be null
5144      * @param regex  the regular expression to which this string is to be matched
5145      * @param replacement  the string to be substituted for the first match
5146      * @return  the text with the first replacement processed,
5147      *              {@code null} if null String input
5148      *
5149      * @throws  java.util.regex.PatternSyntaxException
5150      *              if the regular expression's syntax is invalid
5151      *
5152      * @see String#replaceFirst(String, String)
5153      * @see java.util.regex.Pattern
5154      * @see java.util.regex.Pattern#DOTALL
5155      * @since 3.5
5156      */
5157     public static String replaceFirst(final String text, final String regex, final String replacement) {
5158         if (text == null || regex == null|| replacement == null ) {
5159             return text;
5160         }
5161         return text.replaceFirst(regex, replacement);
5162     }
5163 
5164     /**
5165      * <p>Replaces all occurrences of a String within another String.</p>
5166      *
5167      * <p>A {@code null} reference passed to this method is a no-op.</p>
5168      *
5169      * <pre>
5170      * StringUtils.replace(null, *, *)        = null
5171      * StringUtils.replace("", *, *)          = ""
5172      * StringUtils.replace("any", null, *)    = "any"
5173      * StringUtils.replace("any", *, null)    = "any"
5174      * StringUtils.replace("any", "", *)      = "any"
5175      * StringUtils.replace("aba", "a", null)  = "aba"
5176      * StringUtils.replace("aba", "a", "")    = "b"
5177      * StringUtils.replace("aba", "a", "z")   = "zbz"
5178      * </pre>
5179      *
5180      * @see #replace(String text, String searchString, String replacement, int max)
5181      * @param text  text to search and replace in, may be null
5182      * @param searchString  the String to search for, may be null
5183      * @param replacement  the String to replace it with, may be null
5184      * @return the text with any replacements processed,
5185      *  {@code null} if null String input
5186      */
5187     public static String replace(final String text, final String searchString, final String replacement) {
5188         return replace(text, searchString, replacement, -1);
5189     }
5190 
5191     /**
5192      * <p>Replaces a String with another String inside a larger String,
5193      * for the first {@code max} values of the search String.</p>
5194      *
5195      * <p>A {@code null} reference passed to this method is a no-op.</p>
5196      *
5197      * <pre>
5198      * StringUtils.replace(null, *, *, *)         = null
5199      * StringUtils.replace("", *, *, *)           = ""
5200      * StringUtils.replace("any", null, *, *)     = "any"
5201      * StringUtils.replace("any", *, null, *)     = "any"
5202      * StringUtils.replace("any", "", *, *)       = "any"
5203      * StringUtils.replace("any", *, *, 0)        = "any"
5204      * StringUtils.replace("abaa", "a", null, -1) = "abaa"
5205      * StringUtils.replace("abaa", "a", "", -1)   = "b"
5206      * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
5207      * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
5208      * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
5209      * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
5210      * </pre>
5211      *
5212      * @param text  text to search and replace in, may be null
5213      * @param searchString  the String to search for, may be null
5214      * @param replacement  the String to replace it with, may be null
5215      * @param max  maximum number of values to replace, or {@code -1} if no maximum
5216      * @return the text with any replacements processed,
5217      *  {@code null} if null String input
5218      */
5219     public static String replace(final String text, final String searchString, final String replacement, int max) {
5220         if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) {
5221             return text;
5222         }
5223         int start = 0;
5224         int end = text.indexOf(searchString, start);
5225         if (end == INDEX_NOT_FOUND) {
5226             return text;
5227         }
5228         final int replLength = searchString.length();
5229         int increase = replacement.length() - replLength;
5230         increase = increase < 0 ? 0 : increase;
5231         increase *= max < 0 ? 16 : max > 64 ? 64 : max;
5232         final StringBuilder buf = new StringBuilder(text.length() + increase);
5233         while (end != INDEX_NOT_FOUND) {
5234             buf.append(text.substring(start, end)).append(replacement);
5235             start = end + replLength;
5236             if (--max == 0) {
5237                 break;
5238             }
5239             end = text.indexOf(searchString, start);
5240         }
5241         buf.append(text.substring(start));
5242         return buf.toString();
5243     }
5244 
5245     /**
5246      * <p>
5247      * Replaces all occurrences of Strings within another String.
5248      * </p>
5249      *
5250      * <p>
5251      * A {@code null} reference passed to this method is a no-op, or if
5252      * any "search string" or "string to replace" is null, that replace will be
5253      * ignored. This will not repeat. For repeating replaces, call the
5254      * overloaded method.
5255      * </p>
5256      *
5257      * <pre>
5258      *  StringUtils.replaceEach(null, *, *)        = null
5259      *  StringUtils.replaceEach("", *, *)          = ""
5260      *  StringUtils.replaceEach("aba", null, null) = "aba"
5261      *  StringUtils.replaceEach("aba", new String[0], null) = "aba"
5262      *  StringUtils.replaceEach("aba", null, new String[0]) = "aba"
5263      *  StringUtils.replaceEach("aba", new String[]{"a"}, null)  = "aba"
5264      *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""})  = "b"
5265      *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"})  = "aba"
5266      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"})  = "wcte"
5267      *  (example of how it does not repeat)
5268      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"})  = "dcte"
5269      * </pre>
5270      *
5271      * @param text
5272      *            text to search and replace in, no-op if null
5273      * @param searchList
5274      *            the Strings to search for, no-op if null
5275      * @param replacementList
5276      *            the Strings to replace them with, no-op if null
5277      * @return the text with any replacements processed, {@code null} if
5278      *         null String input
5279      * @throws IllegalArgumentException
5280      *             if the lengths of the arrays are not the same (null is ok,
5281      *             and/or size 0)
5282      * @since 2.4
5283      */
5284     public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) {
5285         return replaceEach(text, searchList, replacementList, false, 0);
5286     }
5287 
5288     /**
5289      * <p>
5290      * Replaces all occurrences of Strings within another String.
5291      * </p>
5292      *
5293      * <p>
5294      * A {@code null} reference passed to this method is a no-op, or if
5295      * any "search string" or "string to replace" is null, that replace will be
5296      * ignored.
5297      * </p>
5298      *
5299      * <pre>
5300      *  StringUtils.replaceEachRepeatedly(null, *, *) = null
5301      *  StringUtils.replaceEachRepeatedly("", *, *) = ""
5302      *  StringUtils.replaceEachRepeatedly("aba", null, null) = "aba"
5303      *  StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba"
5304      *  StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba"
5305      *  StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba"
5306      *  StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b"
5307      *  StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba"
5308      *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
5309      *  (example of how it repeats)
5310      *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte"
5311      *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException
5312      * </pre>
5313      *
5314      * @param text
5315      *            text to search and replace in, no-op if null
5316      * @param searchList
5317      *            the Strings to search for, no-op if null
5318      * @param replacementList
5319      *            the Strings to replace them with, no-op if null
5320      * @return the text with any replacements processed, {@code null} if
5321      *         null String input
5322      * @throws IllegalStateException
5323      *             if the search is repeating and there is an endless loop due
5324      *             to outputs of one being inputs to another
5325      * @throws IllegalArgumentException
5326      *             if the lengths of the arrays are not the same (null is ok,
5327      *             and/or size 0)
5328      * @since 2.4
5329      */
5330     public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) {
5331         // timeToLive should be 0 if not used or nothing to replace, else it's
5332         // the length of the replace array
5333         final int timeToLive = searchList == null ? 0 : searchList.length;
5334         return replaceEach(text, searchList, replacementList, true, timeToLive);
5335     }
5336 
5337     /**
5338      * <p>
5339      * Replace all occurrences of Strings within another String.
5340      * This is a private recursive helper method for {@link #replaceEachRepeatedly(String, String[], String[])} and
5341      * {@link #replaceEach(String, String[], String[])}
5342      * </p>
5343      *
5344      * <p>
5345      * A {@code null} reference passed to this method is a no-op, or if
5346      * any "search string" or "string to replace" is null, that replace will be
5347      * ignored.
5348      * </p>
5349      *
5350      * <pre>
5351      *  StringUtils.replaceEach(null, *, *, *, *) = null
5352      *  StringUtils.replaceEach("", *, *, *, *) = ""
5353      *  StringUtils.replaceEach("aba", null, null, *, *) = "aba"
5354      *  StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba"
5355      *  StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba"
5356      *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba"
5357      *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b"
5358      *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba"
5359      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte"
5360      *  (example of how it repeats)
5361      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte"
5362      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte"
5363      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = IllegalStateException
5364      * </pre>
5365      *
5366      * @param text
5367      *            text to search and replace in, no-op if null
5368      * @param searchList
5369      *            the Strings to search for, no-op if null
5370      * @param replacementList
5371      *            the Strings to replace them with, no-op if null
5372      * @param repeat if true, then replace repeatedly
5373      *       until there are no more possible replacements or timeToLive < 0
5374      * @param timeToLive
5375      *            if less than 0 then there is a circular reference and endless
5376      *            loop
5377      * @return the text with any replacements processed, {@code null} if
5378      *         null String input
5379      * @throws IllegalStateException
5380      *             if the search is repeating and there is an endless loop due
5381      *             to outputs of one being inputs to another
5382      * @throws IllegalArgumentException
5383      *             if the lengths of the arrays are not the same (null is ok,
5384      *             and/or size 0)
5385      * @since 2.4
5386      */
5387     private static String replaceEach(
5388             final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) {
5389 
5390         // mchyzer Performance note: This creates very few new objects (one major goal)
5391         // let me know if there are performance requests, we can create a harness to measure
5392 
5393         if (text == null || text.isEmpty() || searchList == null ||
5394                 searchList.length == 0 || replacementList == null || replacementList.length == 0) {
5395             return text;
5396         }
5397 
5398         // if recursing, this shouldn't be less than 0
5399         if (timeToLive < 0) {
5400             throw new IllegalStateException("Aborting to protect against StackOverflowError - " +
5401                                             "output of one loop is the input of another");
5402         }
5403 
5404         final int searchLength = searchList.length;
5405         final int replacementLength = replacementList.length;
5406 
5407         // make sure lengths are ok, these need to be equal
5408         if (searchLength != replacementLength) {
5409             throw new IllegalArgumentException("Search and Replace array lengths don't match: "
5410                 + searchLength
5411                 + " vs "
5412                 + replacementLength);
5413         }
5414 
5415         // keep track of which still have matches
5416         final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
5417 
5418         // index on index that the match was found
5419         int textIndex = -1;
5420         int replaceIndex = -1;
5421         int tempIndex = -1;
5422 
5423         // index of replace array that will replace the search string found
5424         // NOTE: logic duplicated below START
5425         for (int i = 0; i < searchLength; i++) {
5426             if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
5427                     searchList[i].isEmpty() || replacementList[i] == null) {
5428                 continue;
5429             }
5430             tempIndex = text.indexOf(searchList[i]);
5431 
5432             // see if we need to keep searching for this
5433             if (tempIndex == -1) {
5434                 noMoreMatchesForReplIndex[i] = true;
5435             } else {
5436                 if (textIndex == -1 || tempIndex < textIndex) {
5437                     textIndex = tempIndex;
5438                     replaceIndex = i;
5439                 }
5440             }
5441         }
5442         // NOTE: logic mostly below END
5443 
5444         // no search strings found, we are done
5445         if (textIndex == -1) {
5446             return text;
5447         }
5448 
5449         int start = 0;
5450 
5451         // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit
5452         int increase = 0;
5453 
5454         // count the replacement text elements that are larger than their corresponding text being replaced
5455         for (int i = 0; i < searchList.length; i++) {
5456             if (searchList[i] == null || replacementList[i] == null) {
5457                 continue;
5458             }
5459             final int greater = replacementList[i].length() - searchList[i].length();
5460             if (greater > 0) {
5461                 increase += 3 * greater; // assume 3 matches
5462             }
5463         }
5464         // have upper-bound at 20% increase, then let Java take over
5465         increase = Math.min(increase, text.length() / 5);
5466 
5467         final StringBuilder buf = new StringBuilder(text.length() + increase);
5468 
5469         while (textIndex != -1) {
5470 
5471             for (int i = start; i < textIndex; i++) {
5472                 buf.append(text.charAt(i));
5473             }
5474             buf.append(replacementList[replaceIndex]);
5475 
5476             start = textIndex + searchList[replaceIndex].length();
5477 
5478             textIndex = -1;
5479             replaceIndex = -1;
5480             tempIndex = -1;
5481             // find the next earliest match
5482             // NOTE: logic mostly duplicated above START
5483             for (int i = 0; i < searchLength; i++) {
5484                 if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
5485                         searchList[i].isEmpty() || replacementList[i] == null) {
5486                     continue;
5487                 }
5488                 tempIndex = text.indexOf(searchList[i], start);
5489 
5490                 // see if we need to keep searching for this
5491                 if (tempIndex == -1) {
5492                     noMoreMatchesForReplIndex[i] = true;
5493                 } else {
5494                     if (textIndex == -1 || tempIndex < textIndex) {
5495                         textIndex = tempIndex;
5496                         replaceIndex = i;
5497                     }
5498                 }
5499             }
5500             // NOTE: logic duplicated above END
5501 
5502         }
5503         final int textLength = text.length();
5504         for (int i = start; i < textLength; i++) {
5505             buf.append(text.charAt(i));
5506         }
5507         final String result = buf.toString();
5508         if (!repeat) {
5509             return result;
5510         }
5511 
5512         return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
5513     }
5514 
5515     // Replace, character based
5516     //-----------------------------------------------------------------------
5517     /**
5518      * <p>Replaces all occurrences of a character in a String with another.
5519      * This is a null-safe version of {@link String#replace(char, char)}.</p>
5520      *
5521      * <p>A {@code null} string input returns {@code null}.
5522      * An empty ("") string input returns an empty string.</p>
5523      *
5524      * <pre>
5525      * StringUtils.replaceChars(null, *, *)        = null
5526      * StringUtils.replaceChars("", *, *)          = ""
5527      * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
5528      * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
5529      * </pre>
5530      *
5531      * @param str  String to replace characters in, may be null
5532      * @param searchChar  the character to search for, may be null
5533      * @param replaceChar  the character to replace, may be null
5534      * @return modified String, {@code null} if null string input
5535      * @since 2.0
5536      */
5537     public static String replaceChars(final String str, final char searchChar, final char replaceChar) {
5538         if (str == null) {
5539             return null;
5540         }
5541         return str.replace(searchChar, replaceChar);
5542     }
5543 
5544     /**
5545      * <p>Replaces multiple characters in a String in one go.
5546      * This method can also be used to delete characters.</p>
5547      *
5548      * <p>For example:<br>
5549      * <code>replaceChars(&quot;hello&quot;, &quot;ho&quot;, &quot;jy&quot;) = jelly</code>.</p>
5550      *
5551      * <p>A {@code null} string input returns {@code null}.
5552      * An empty ("") string input returns an empty string.
5553      * A null or empty set of search characters returns the input string.</p>
5554      *
5555      * <p>The length of the search characters should normally equal the length
5556      * of the replace characters.
5557      * If the search characters is longer, then the extra search characters
5558      * are deleted.
5559      * If the search characters is shorter, then the extra replace characters
5560      * are ignored.</p>
5561      *
5562      * <pre>
5563      * StringUtils.replaceChars(null, *, *)           = null
5564      * StringUtils.replaceChars("", *, *)             = ""
5565      * StringUtils.replaceChars("abc", null, *)       = "abc"
5566      * StringUtils.replaceChars("abc", "", *)         = "abc"
5567      * StringUtils.replaceChars("abc", "b", null)     = "ac"
5568      * StringUtils.replaceChars("abc", "b", "")       = "ac"
5569      * StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
5570      * StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
5571      * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
5572      * </pre>
5573      *
5574      * @param str  String to replace characters in, may be null
5575      * @param searchChars  a set of characters to search for, may be null
5576      * @param replaceChars  a set of characters to replace, may be null
5577      * @return modified String, {@code null} if null string input
5578      * @since 2.0
5579      */
5580     public static String replaceChars(final String str, final String searchChars, String replaceChars) {
5581         if (isEmpty(str) || isEmpty(searchChars)) {
5582             return str;
5583         }
5584         if (replaceChars == null) {
5585             replaceChars = EMPTY;
5586         }
5587         boolean modified = false;
5588         final int replaceCharsLength = replaceChars.length();
5589         final int strLength = str.length();
5590         final StringBuilder buf = new StringBuilder(strLength);
5591         for (int i = 0; i < strLength; i++) {
5592             final char ch = str.charAt(i);
5593             final int index = searchChars.indexOf(ch);
5594             if (index >= 0) {
5595                 modified = true;
5596                 if (index < replaceCharsLength) {
5597                     buf.append(replaceChars.charAt(index));
5598                 }
5599             } else {
5600                 buf.append(ch);
5601             }
5602         }
5603         if (modified) {
5604             return buf.toString();
5605         }
5606         return str;
5607     }
5608 
5609     // Overlay
5610     //-----------------------------------------------------------------------
5611     /**
5612      * <p>Overlays part of a String with another String.</p>
5613      *
5614      * <p>A {@code null} string input returns {@code null}.
5615      * A negative index is treated as zero.
5616      * An index greater than the string length is treated as the string length.
5617      * The start index is always the smaller of the two indices.</p>
5618      *
5619      * <pre>
5620      * StringUtils.overlay(null, *, *, *)            = null
5621      * StringUtils.overlay("", "abc", 0, 0)          = "abc"
5622      * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
5623      * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
5624      * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
5625      * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
5626      * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
5627      * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
5628      * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
5629      * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
5630      * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
5631      * </pre>
5632      *
5633      * @param str  the String to do overlaying in, may be null
5634      * @param overlay  the String to overlay, may be null
5635      * @param start  the position to start overlaying at
5636      * @param end  the position to stop overlaying before
5637      * @return overlayed String, {@code null} if null String input
5638      * @since 2.0
5639      */
5640     public static String overlay(final String str, String overlay, int start, int end) {
5641         if (str == null) {
5642             return null;
5643         }
5644         if (overlay == null) {
5645             overlay = EMPTY;
5646         }
5647         final int len = str.length();
5648         if (start < 0) {
5649             start = 0;
5650         }
5651         if (start > len) {
5652             start = len;
5653         }
5654         if (end < 0) {
5655             end = 0;
5656         }
5657         if (end > len) {
5658             end = len;
5659         }
5660         if (start > end) {
5661             final int temp = start;
5662             start = end;
5663             end = temp;
5664         }
5665         return new StringBuilder(len + start - end + overlay.length() + 1)
5666             .append(str.substring(0, start))
5667             .append(overlay)
5668             .append(str.substring(end))
5669             .toString();
5670     }
5671 
5672     // Chomping
5673     //-----------------------------------------------------------------------
5674     /**
5675      * <p>Removes one newline from end of a String if it's there,
5676      * otherwise leave it alone.  A newline is &quot;{@code \n}&quot;,
5677      * &quot;{@code \r}&quot;, or &quot;{@code \r\n}&quot;.</p>
5678      *
5679      * <p>NOTE: This method changed in 2.0.
5680      * It now more closely matches Perl chomp.</p>
5681      *
5682      * <pre>
5683      * StringUtils.chomp(null)          = null
5684      * StringUtils.chomp("")            = ""
5685      * StringUtils.chomp("abc \r")      = "abc "
5686      * StringUtils.chomp("abc\n")       = "abc"
5687      * StringUtils.chomp("abc\r\n")     = "abc"
5688      * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
5689      * StringUtils.chomp("abc\n\r")     = "abc\n"
5690      * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
5691      * StringUtils.chomp("\r")          = ""
5692      * StringUtils.chomp("\n")          = ""
5693      * StringUtils.chomp("\r\n")        = ""
5694      * </pre>
5695      *
5696      * @param str  the String to chomp a newline from, may be null
5697      * @return String without newline, {@code null} if null String input
5698      */
5699     public static String chomp(final String str) {
5700         if (isEmpty(str)) {
5701             return str;
5702         }
5703 
5704         if (str.length() == 1) {
5705             final char ch = str.charAt(0);
5706             if (ch == CharUtils.CR || ch == CharUtils.LF) {
5707                 return EMPTY;
5708             }
5709             return str;
5710         }
5711 
5712         int lastIdx = str.length() - 1;
5713         final char last = str.charAt(lastIdx);
5714 
5715         if (last == CharUtils.LF) {
5716             if (str.charAt(lastIdx - 1) == CharUtils.CR) {
5717                 lastIdx--;
5718             }
5719         } else if (last != CharUtils.CR) {
5720             lastIdx++;
5721         }
5722         return str.substring(0, lastIdx);
5723     }
5724 
5725     /**
5726      * <p>Removes {@code separator} from the end of
5727      * {@code str} if it's there, otherwise leave it alone.</p>
5728      *
5729      * <p>NOTE: This method changed in version 2.0.
5730      * It now more closely matches Perl chomp.
5731      * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
5732      * This method uses {@link String#endsWith(String)}.</p>
5733      *
5734      * <pre>
5735      * StringUtils.chomp(null, *)         = null
5736      * StringUtils.chomp("", *)           = ""
5737      * StringUtils.chomp("foobar", "bar") = "foo"
5738      * StringUtils.chomp("foobar", "baz") = "foobar"
5739      * StringUtils.chomp("foo", "foo")    = ""
5740      * StringUtils.chomp("foo ", "foo")   = "foo "
5741      * StringUtils.chomp(" foo", "foo")   = " "
5742      * StringUtils.chomp("foo", "foooo")  = "foo"
5743      * StringUtils.chomp("foo", "")       = "foo"
5744      * StringUtils.chomp("foo", null)     = "foo"
5745      * </pre>
5746      *
5747      * @param str  the String to chomp from, may be null
5748      * @param separator  separator String, may be null
5749      * @return String without trailing separator, {@code null} if null String input
5750      * @deprecated This feature will be removed in Lang 4.0, use {@link StringUtils#removeEnd(String, String)} instead
5751      */
5752     @Deprecated
5753     public static String chomp(final String str, final String separator) {
5754         return removeEnd(str,separator);
5755     }
5756 
5757     // Chopping
5758     //-----------------------------------------------------------------------
5759     /**
5760      * <p>Remove the last character from a String.</p>
5761      *
5762      * <p>If the String ends in {@code \r\n}, then remove both
5763      * of them.</p>
5764      *
5765      * <pre>
5766      * StringUtils.chop(null)          = null
5767      * StringUtils.chop("")            = ""
5768      * StringUtils.chop("abc \r")      = "abc "
5769      * StringUtils.chop("abc\n")       = "abc"
5770      * StringUtils.chop("abc\r\n")     = "abc"
5771      * StringUtils.chop("abc")         = "ab"
5772      * StringUtils.chop("abc\nabc")    = "abc\nab"
5773      * StringUtils.chop("a")           = ""
5774      * StringUtils.chop("\r")          = ""
5775      * StringUtils.chop("\n")          = ""
5776      * StringUtils.chop("\r\n")        = ""
5777      * </pre>
5778      *
5779      * @param str  the String to chop last character from, may be null
5780      * @return String without last character, {@code null} if null String input
5781      */
5782     public static String chop(final String str) {
5783         if (str == null) {
5784             return null;
5785         }
5786         final int strLen = str.length();
5787         if (strLen < 2) {
5788             return EMPTY;
5789         }
5790         final int lastIdx = strLen - 1;
5791         final String ret = str.substring(0, lastIdx);
5792         final char last = str.charAt(lastIdx);
5793         if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
5794             return ret.substring(0, lastIdx - 1);
5795         }
5796         return ret;
5797     }
5798 
5799     // Conversion
5800     //-----------------------------------------------------------------------
5801 
5802     // Padding
5803     //-----------------------------------------------------------------------
5804     /**
5805      * <p>Repeat a String {@code repeat} times to form a
5806      * new String.</p>
5807      *
5808      * <pre>
5809      * StringUtils.repeat(null, 2) = null
5810      * StringUtils.repeat("", 0)   = ""
5811      * StringUtils.repeat("", 2)   = ""
5812      * StringUtils.repeat("a", 3)  = "aaa"
5813      * StringUtils.repeat("ab", 2) = "abab"
5814      * StringUtils.repeat("a", -2) = ""
5815      * </pre>
5816      *
5817      * @param str  the String to repeat, may be null
5818      * @param repeat  number of times to repeat str, negative treated as zero
5819      * @return a new String consisting of the original String repeated,
5820      *  {@code null} if null String input
5821      */
5822     public static String repeat(final String str, final int repeat) {
5823         // Performance tuned for 2.0 (JDK1.4)
5824 
5825         if (str == null) {
5826             return null;
5827         }
5828         if (repeat <= 0) {
5829             return EMPTY;
5830         }
5831         final int inputLength = str.length();
5832         if (repeat == 1 || inputLength == 0) {
5833             return str;
5834         }
5835         if (inputLength == 1 && repeat <= PAD_LIMIT) {
5836             return repeat(str.charAt(0), repeat);
5837         }
5838 
5839         final int outputLength = inputLength * repeat;
5840         switch (inputLength) {
5841             case 1 :
5842                 return repeat(str.charAt(0), repeat);
5843             case 2 :
5844                 final char ch0 = str.charAt(0);
5845                 final char ch1 = str.charAt(1);
5846                 final char[] output2 = new char[outputLength];
5847                 for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
5848                     output2[i] = ch0;
5849                     output2[i + 1] = ch1;
5850                 }
5851                 return new String(output2);
5852             default :
5853                 final StringBuilder buf = new StringBuilder(outputLength);
5854                 for (int i = 0; i < repeat; i++) {
5855                     buf.append(str);
5856                 }
5857                 return buf.toString();
5858         }
5859     }
5860 
5861     /**
5862      * <p>Repeat a String {@code repeat} times to form a
5863      * new String, with a String separator injected each time. </p>
5864      *
5865      * <pre>
5866      * StringUtils.repeat(null, null, 2) = null
5867      * StringUtils.repeat(null, "x", 2)  = null
5868      * StringUtils.repeat("", null, 0)   = ""
5869      * StringUtils.repeat("", "", 2)     = ""
5870      * StringUtils.repeat("", "x", 3)    = "xxx"
5871      * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
5872      * </pre>
5873      *
5874      * @param str        the String to repeat, may be null
5875      * @param separator  the String to inject, may be null
5876      * @param repeat     number of times to repeat str, negative treated as zero
5877      * @return a new String consisting of the original String repeated,
5878      *  {@code null} if null String input
5879      * @since 2.5
5880      */
5881     public static String repeat(final String str, final String separator, final int repeat) {
5882         if(str == null || separator == null) {
5883             return repeat(str, repeat);
5884         }
5885         // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
5886         final String result = repeat(str + separator, repeat);
5887         return removeEnd(result, separator);
5888     }
5889 
5890     /**
5891      * <p>Returns padding using the specified delimiter repeated
5892      * to a given length.</p>
5893      *
5894      * <pre>
5895      * StringUtils.repeat('e', 0)  = ""
5896      * StringUtils.repeat('e', 3)  = "eee"
5897      * StringUtils.repeat('e', -2) = ""
5898      * </pre>
5899      *
5900      * <p>Note: this method doesn't not support padding with
5901      * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
5902      * as they require a pair of {@code char}s to be represented.
5903      * If you are needing to support full I18N of your applications
5904      * consider using {@link #repeat(String, int)} instead.
5905      * </p>
5906      *
5907      * @param ch  character to repeat
5908      * @param repeat  number of times to repeat char, negative treated as zero
5909      * @return String with repeated character
5910      * @see #repeat(String, int)
5911      */
5912     public static String repeat(final char ch, final int repeat) {
5913         if (repeat <= 0) {
5914             return EMPTY;
5915         }
5916         final char[] buf = new char[repeat];
5917         for (int i = repeat - 1; i >= 0; i--) {
5918             buf[i] = ch;
5919         }
5920         return new String(buf);
5921     }
5922 
5923     /**
5924      * <p>Right pad a String with spaces (' ').</p>
5925      *
5926      * <p>The String is padded to the size of {@code size}.</p>
5927      *
5928      * <pre>
5929      * StringUtils.rightPad(null, *)   = null
5930      * StringUtils.rightPad("", 3)     = "   "
5931      * StringUtils.rightPad("bat", 3)  = "bat"
5932      * StringUtils.rightPad("bat", 5)  = "bat  "
5933      * StringUtils.rightPad("bat", 1)  = "bat"
5934      * StringUtils.rightPad("bat", -1) = "bat"
5935      * </pre>
5936      *
5937      * @param str  the String to pad out, may be null
5938      * @param size  the size to pad to
5939      * @return right padded String or original String if no padding is necessary,
5940      *  {@code null} if null String input
5941      */
5942     public static String rightPad(final String str, final int size) {
5943         return rightPad(str, size, ' ');
5944     }
5945 
5946     /**
5947      * <p>Right pad a String with a specified character.</p>
5948      *
5949      * <p>The String is padded to the size of {@code size}.</p>
5950      *
5951      * <pre>
5952      * StringUtils.rightPad(null, *, *)     = null
5953      * StringUtils.rightPad("", 3, 'z')     = "zzz"
5954      * StringUtils.rightPad("bat", 3, 'z')  = "bat"
5955      * StringUtils.rightPad("bat", 5, 'z')  = "batzz"
5956      * StringUtils.rightPad("bat", 1, 'z')  = "bat"
5957      * StringUtils.rightPad("bat", -1, 'z') = "bat"
5958      * </pre>
5959      *
5960      * @param str  the String to pad out, may be null
5961      * @param size  the size to pad to
5962      * @param padChar  the character to pad with
5963      * @return right padded String or original String if no padding is necessary,
5964      *  {@code null} if null String input
5965      * @since 2.0
5966      */
5967     public static String rightPad(final String str, final int size, final char padChar) {
5968         if (str == null) {
5969             return null;
5970         }
5971         final int pads = size - str.length();
5972         if (pads <= 0) {
5973             return str; // returns original String when possible
5974         }
5975         if (pads > PAD_LIMIT) {
5976             return rightPad(str, size, String.valueOf(padChar));
5977         }
5978         return str.concat(repeat(padChar, pads));
5979     }
5980 
5981     /**
5982      * <p>Right pad a String with a specified String.</p>
5983      *
5984      * <p>The String is padded to the size of {@code size}.</p>
5985      *
5986      * <pre>
5987      * StringUtils.rightPad(null, *, *)      = null
5988      * StringUtils.rightPad("", 3, "z")      = "zzz"
5989      * StringUtils.rightPad("bat", 3, "yz")  = "bat"
5990      * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
5991      * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
5992      * StringUtils.rightPad("bat", 1, "yz")  = "bat"
5993      * StringUtils.rightPad("bat", -1, "yz") = "bat"
5994      * StringUtils.rightPad("bat", 5, null)  = "bat  "
5995      * StringUtils.rightPad("bat", 5, "")    = "bat  "
5996      * </pre>
5997      *
5998      * @param str  the String to pad out, may be null
5999      * @param size  the size to pad to
6000      * @param padStr  the String to pad with, null or empty treated as single space
6001      * @return right padded String or original String if no padding is necessary,
6002      *  {@code null} if null String input
6003      */
6004     public static String rightPad(final String str, final int size, String padStr) {
6005         if (str == null) {
6006             return null;
6007         }
6008         if (isEmpty(padStr)) {
6009             padStr = SPACE;
6010         }
6011         final int padLen = padStr.length();
6012         final int strLen = str.length();
6013         final int pads = size - strLen;
6014         if (pads <= 0) {
6015             return str; // returns original String when possible
6016         }
6017         if (padLen == 1 && pads <= PAD_LIMIT) {
6018             return rightPad(str, size, padStr.charAt(0));
6019         }
6020 
6021         if (pads == padLen) {
6022             return str.concat(padStr);
6023         } else if (pads < padLen) {
6024             return str.concat(padStr.substring(0, pads));
6025         } else {
6026             final char[] padding = new char[pads];
6027             final char[] padChars = padStr.toCharArray();
6028             for (int i = 0; i < pads; i++) {
6029                 padding[i] = padChars[i % padLen];
6030             }
6031             return str.concat(new String(padding));
6032         }
6033     }
6034 
6035     /**
6036      * <p>Left pad a String with spaces (' ').</p>
6037      *
6038      * <p>The String is padded to the size of {@code size}.</p>
6039      *
6040      * <pre>
6041      * StringUtils.leftPad(null, *)   = null
6042      * StringUtils.leftPad("", 3)     = "   "
6043      * StringUtils.leftPad("bat", 3)  = "bat"
6044      * StringUtils.leftPad("bat", 5)  = "  bat"
6045      * StringUtils.leftPad("bat", 1)  = "bat"
6046      * StringUtils.leftPad("bat", -1) = "bat"
6047      * </pre>
6048      *
6049      * @param str  the String to pad out, may be null
6050      * @param size  the size to pad to
6051      * @return left padded String or original String if no padding is necessary,
6052      *  {@code null} if null String input
6053      */
6054     public static String leftPad(final String str, final int size) {
6055         return leftPad(str, size, ' ');
6056     }
6057 
6058     /**
6059      * <p>Left pad a String with a specified character.</p>
6060      *
6061      * <p>Pad to a size of {@code size}.</p>
6062      *
6063      * <pre>
6064      * StringUtils.leftPad(null, *, *)     = null
6065      * StringUtils.leftPad("", 3, 'z')     = "zzz"
6066      * StringUtils.leftPad("bat", 3, 'z')  = "bat"
6067      * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"
6068      * StringUtils.leftPad("bat", 1, 'z')  = "bat"
6069      * StringUtils.leftPad("bat", -1, 'z') = "bat"
6070      * </pre>
6071      *
6072      * @param str  the String to pad out, may be null
6073      * @param size  the size to pad to
6074      * @param padChar  the character to pad with
6075      * @return left padded String or original String if no padding is necessary,
6076      *  {@code null} if null String input
6077      * @since 2.0
6078      */
6079     public static String leftPad(final String str, final int size, final char padChar) {
6080         if (str == null) {
6081             return null;
6082         }
6083         final int pads = size - str.length();
6084         if (pads <= 0) {
6085             return str; // returns original String when possible
6086         }
6087         if (pads > PAD_LIMIT) {
6088             return leftPad(str, size, String.valueOf(padChar));
6089         }
6090         return repeat(padChar, pads).concat(str);
6091     }
6092 
6093     /**
6094      * <p>Left pad a String with a specified String.</p>
6095      *
6096      * <p>Pad to a size of {@code size}.</p>
6097      *
6098      * <pre>
6099      * StringUtils.leftPad(null, *, *)      = null
6100      * StringUtils.leftPad("", 3, "z")      = "zzz"
6101      * StringUtils.leftPad("bat", 3, "yz")  = "bat"
6102      * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
6103      * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
6104      * StringUtils.leftPad("bat", 1, "yz")  = "bat"
6105      * StringUtils.leftPad("bat", -1, "yz") = "bat"
6106      * StringUtils.leftPad("bat", 5, null)  = "  bat"
6107      * StringUtils.leftPad("bat", 5, "")    = "  bat"
6108      * </pre>
6109      *
6110      * @param str  the String to pad out, may be null
6111      * @param size  the size to pad to
6112      * @param padStr  the String to pad with, null or empty treated as single space
6113      * @return left padded String or original String if no padding is necessary,
6114      *  {@code null} if null String input
6115      */
6116     public static String leftPad(final String str, final int size, String padStr) {
6117         if (str == null) {
6118             return null;
6119         }
6120         if (isEmpty(padStr)) {
6121             padStr = SPACE;
6122         }
6123         final int padLen = padStr.length();
6124         final int strLen = str.length();
6125         final int pads = size - strLen;
6126         if (pads <= 0) {
6127             return str; // returns original String when possible
6128         }
6129         if (padLen == 1 && pads <= PAD_LIMIT) {
6130             return leftPad(str, size, padStr.charAt(0));
6131         }
6132 
6133         if (pads == padLen) {
6134             return padStr.concat(str);
6135         } else if (pads < padLen) {
6136             return padStr.substring(0, pads).concat(str);
6137         } else {
6138             final char[] padding = new char[pads];
6139             final char[] padChars = padStr.toCharArray();
6140             for (int i = 0; i < pads; i++) {
6141                 padding[i] = padChars[i % padLen];
6142             }
6143             return new String(padding).concat(str);
6144         }
6145     }
6146 
6147     /**
6148      * Gets a CharSequence length or {@code 0} if the CharSequence is
6149      * {@code null}.
6150      *
6151      * @param cs
6152      *            a CharSequence or {@code null}
6153      * @return CharSequence length or {@code 0} if the CharSequence is
6154      *         {@code null}.
6155      * @since 2.4
6156      * @since 3.0 Changed signature from length(String) to length(CharSequence)
6157      */
6158     public static int length(final CharSequence cs) {
6159         return cs == null ? 0 : cs.length();
6160     }
6161 
6162     // Centering
6163     //-----------------------------------------------------------------------
6164     /**
6165      * <p>Centers a String in a larger String of size {@code size}
6166      * using the space character (' ').</p>
6167      *
6168      * <p>If the size is less than the String length, the String is returned.
6169      * A {@code null} String returns {@code null}.
6170      * A negative size is treated as zero.</p>
6171      *
6172      * <p>Equivalent to {@code center(str, size, " ")}.</p>
6173      *
6174      * <pre>
6175      * StringUtils.center(null, *)   = null
6176      * StringUtils.center("", 4)     = "    "
6177      * StringUtils.center("ab", -1)  = "ab"
6178      * StringUtils.center("ab", 4)   = " ab "
6179      * StringUtils.center("abcd", 2) = "abcd"
6180      * StringUtils.center("a", 4)    = " a  "
6181      * </pre>
6182      *
6183      * @param str  the String to center, may be null
6184      * @param size  the int size of new String, negative treated as zero
6185      * @return centered String, {@code null} if null String input
6186      */
6187     public static String center(final String str, final int size) {
6188         return center(str, size, ' ');
6189     }
6190 
6191     /**
6192      * <p>Centers a String in a larger String of size {@code size}.
6193      * Uses a supplied character as the value to pad the String with.</p>
6194      *
6195      * <p>If the size is less than the String length, the String is returned.
6196      * A {@code null} String returns {@code null}.
6197      * A negative size is treated as zero.</p>
6198      *
6199      * <pre>
6200      * StringUtils.center(null, *, *)     = null
6201      * StringUtils.center("", 4, ' ')     = "    "
6202      * StringUtils.center("ab", -1, ' ')  = "ab"
6203      * StringUtils.center("ab", 4, ' ')   = " ab "
6204      * StringUtils.center("abcd", 2, ' ') = "abcd"
6205      * StringUtils.center("a", 4, ' ')    = " a  "
6206      * StringUtils.center("a", 4, 'y')    = "yayy"
6207      * </pre>
6208      *
6209      * @param str  the String to center, may be null
6210      * @param size  the int size of new String, negative treated as zero
6211      * @param padChar  the character to pad the new String with
6212      * @return centered String, {@code null} if null String input
6213      * @since 2.0
6214      */
6215     public static String center(String str, final int size, final char padChar) {
6216         if (str == null || size <= 0) {
6217             return str;
6218         }
6219         final int strLen = str.length();
6220         final int pads = size - strLen;
6221         if (pads <= 0) {
6222             return str;
6223         }
6224         str = leftPad(str, strLen + pads / 2, padChar);
6225         str = rightPad(str, size, padChar);
6226         return str;
6227     }
6228 
6229     /**
6230      * <p>Centers a String in a larger String of size {@code size}.
6231      * Uses a supplied String as the value to pad the String with.</p>
6232      *
6233      * <p>If the size is less than the String length, the String is returned.
6234      * A {@code null} String returns {@code null}.
6235      * A negative size is treated as zero.</p>
6236      *
6237      * <pre>
6238      * StringUtils.center(null, *, *)     = null
6239      * StringUtils.center("", 4, " ")     = "    "
6240      * StringUtils.center("ab", -1, " ")  = "ab"
6241      * StringUtils.center("ab", 4, " ")   = " ab "
6242      * StringUtils.center("abcd", 2, " ") = "abcd"
6243      * StringUtils.center("a", 4, " ")    = " a  "
6244      * StringUtils.center("a", 4, "yz")   = "yayz"
6245      * StringUtils.center("abc", 7, null) = "  abc  "
6246      * StringUtils.center("abc", 7, "")   = "  abc  "
6247      * </pre>
6248      *
6249      * @param str  the String to center, may be null
6250      * @param size  the int size of new String, negative treated as zero
6251      * @param padStr  the String to pad the new String with, must not be null or empty
6252      * @return centered String, {@code null} if null String input
6253      * @throws IllegalArgumentException if padStr is {@code null} or empty
6254      */
6255     public static String center(String str, final int size, String padStr) {
6256         if (str == null || size <= 0) {
6257             return str;
6258         }
6259         if (isEmpty(padStr)) {
6260             padStr = SPACE;
6261         }
6262         final int strLen = str.length();
6263         final int pads = size - strLen;
6264         if (pads <= 0) {
6265             return str;
6266         }
6267         str = leftPad(str, strLen + pads / 2, padStr);
6268         str = rightPad(str, size, padStr);
6269         return str;
6270     }
6271 
6272     // Case conversion
6273     //-----------------------------------------------------------------------
6274     /**
6275      * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p>
6276      *
6277      * <p>A {@code null} input String returns {@code null}.</p>
6278      *
6279      * <pre>
6280      * StringUtils.upperCase(null)  = null
6281      * StringUtils.upperCase("")    = ""
6282      * StringUtils.upperCase("aBc") = "ABC"
6283      * </pre>
6284      *
6285      * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()},
6286      * the result of this method is affected by the current locale.
6287      * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
6288      * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
6289      *
6290      * @param str  the String to upper case, may be null
6291      * @return the upper cased String, {@code null} if null String input
6292      */
6293     public static String upperCase(final String str) {
6294         if (str == null) {
6295             return null;
6296         }
6297         return str.toUpperCase();
6298     }
6299 
6300     /**
6301      * <p>Converts a String to upper case as per {@link String#toUpperCase(Locale)}.</p>
6302      *
6303      * <p>A {@code null} input String returns {@code null}.</p>
6304      *
6305      * <pre>
6306      * StringUtils.upperCase(null, Locale.ENGLISH)  = null
6307      * StringUtils.upperCase("", Locale.ENGLISH)    = ""
6308      * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
6309      * </pre>
6310      *
6311      * @param str  the String to upper case, may be null
6312      * @param locale  the locale that defines the case transformation rules, must not be null
6313      * @return the upper cased String, {@code null} if null String input
6314      * @since 2.5
6315      */
6316     public static String upperCase(final String str, final Locale locale) {
6317         if (str == null) {
6318             return null;
6319         }
6320         return str.toUpperCase(locale);
6321     }
6322 
6323     /**
6324      * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p>
6325      *
6326      * <p>A {@code null} input String returns {@code null}.</p>
6327      *
6328      * <pre>
6329      * StringUtils.lowerCase(null)  = null
6330      * StringUtils.lowerCase("")    = ""
6331      * StringUtils.lowerCase("aBc") = "abc"
6332      * </pre>
6333      *
6334      * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()},
6335      * the result of this method is affected by the current locale.
6336      * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
6337      * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
6338      *
6339      * @param str  the String to lower case, may be null
6340      * @return the lower cased String, {@code null} if null String input
6341      */
6342     public static String lowerCase(final String str) {
6343         if (str == null) {
6344             return null;
6345         }
6346         return str.toLowerCase();
6347     }
6348 
6349     /**
6350      * <p>Converts a String to lower case as per {@link String#toLowerCase(Locale)}.</p>
6351      *
6352      * <p>A {@code null} input String returns {@code null}.</p>
6353      *
6354      * <pre>
6355      * StringUtils.lowerCase(null, Locale.ENGLISH)  = null
6356      * StringUtils.lowerCase("", Locale.ENGLISH)    = ""
6357      * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
6358      * </pre>
6359      *
6360      * @param str  the String to lower case, may be null
6361      * @param locale  the locale that defines the case transformation rules, must not be null
6362      * @return the lower cased String, {@code null} if null String input
6363      * @since 2.5
6364      */
6365     public static String lowerCase(final String str, final Locale locale) {
6366         if (str == null) {
6367             return null;
6368         }
6369         return str.toLowerCase(locale);
6370     }
6371 
6372     /**
6373      * <p>Capitalizes a String changing the first character to title case as
6374      * per {@link Character#toTitleCase(char)}. No other characters are changed.</p>
6375      *
6376      * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#capitalize(String)}.
6377      * A {@code null} input String returns {@code null}.</p>
6378      *
6379      * <pre>
6380      * StringUtils.capitalize(null)  = null
6381      * StringUtils.capitalize("")    = ""
6382      * StringUtils.capitalize("cat") = "Cat"
6383      * StringUtils.capitalize("cAt") = "CAt"
6384      * StringUtils.capitalize("'cat'") = "'cat'"
6385      * </pre>
6386      *
6387      * @param str the String to capitalize, may be null
6388      * @return the capitalized String, {@code null} if null String input
6389      * @see org.apache.commons.lang3.text.WordUtils#capitalize(String)
6390      * @see #uncapitalize(String)
6391      * @since 2.0
6392      */
6393     public static String capitalize(final String str) {
6394         int strLen;
6395         if (str == null || (strLen = str.length()) == 0) {
6396             return str;
6397         }
6398 
6399         final char firstChar = str.charAt(0);
6400         final char newChar = Character.toTitleCase(firstChar);
6401         if (firstChar == newChar) {
6402             // already capitalized
6403             return str;
6404         }
6405 
6406         char[] newChars = new char[strLen];
6407         newChars[0] = newChar;
6408         str.getChars(1,strLen, newChars, 1);
6409         return String.valueOf(newChars);
6410     }
6411 
6412     /**
6413      * <p>Uncapitalizes a String, changing the first character to lower case as
6414      * per {@link Character#toLowerCase(char)}. No other characters are changed.</p>
6415      *
6416      * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#uncapitalize(String)}.
6417      * A {@code null} input String returns {@code null}.</p>
6418      *
6419      * <pre>
6420      * StringUtils.uncapitalize(null)  = null
6421      * StringUtils.uncapitalize("")    = ""
6422      * StringUtils.uncapitalize("cat") = "cat"
6423      * StringUtils.uncapitalize("Cat") = "cat"
6424      * StringUtils.uncapitalize("CAT") = "cAT"
6425      * </pre>
6426      *
6427      * @param str the String to uncapitalize, may be null
6428      * @return the uncapitalized String, {@code null} if null String input
6429      * @see org.apache.commons.lang3.text.WordUtils#uncapitalize(String)
6430      * @see #capitalize(String)
6431      * @since 2.0
6432      */
6433     public static String uncapitalize(final String str) {
6434         int strLen;
6435         if (str == null || (strLen = str.length()) == 0) {
6436             return str;
6437         }
6438 
6439         final char firstChar = str.charAt(0);
6440         final char newChar = Character.toLowerCase(firstChar);
6441         if (firstChar == newChar) {
6442             // already uncapitalized
6443             return str;
6444         }
6445 
6446         char[] newChars = new char[strLen];
6447         newChars[0] = newChar;
6448         str.getChars(1,strLen, newChars, 1);
6449         return String.valueOf(newChars);
6450     }
6451 
6452     /**
6453      * <p>Swaps the case of a String changing upper and title case to
6454      * lower case, and lower case to upper case.</p>
6455      *
6456      * <ul>
6457      *  <li>Upper case character converts to Lower case</li>
6458      *  <li>Title case character converts to Lower case</li>
6459      *  <li>Lower case character converts to Upper case</li>
6460      * </ul>
6461      *
6462      * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#swapCase(String)}.
6463      * A {@code null} input String returns {@code null}.</p>
6464      *
6465      * <pre>
6466      * StringUtils.swapCase(null)                 = null
6467      * StringUtils.swapCase("")                   = ""
6468      * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
6469      * </pre>
6470      *
6471      * <p>NOTE: This method changed in Lang version 2.0.
6472      * It no longer performs a word based algorithm.
6473      * If you only use ASCII, you will notice no change.
6474      * That functionality is available in org.apache.commons.lang3.text.WordUtils.</p>
6475      *
6476      * @param str  the String to swap case, may be null
6477      * @return the changed String, {@code null} if null String input
6478      */
6479     public static String swapCase(final String str) {
6480         if (StringUtils.isEmpty(str)) {
6481             return str;
6482         }
6483 
6484         final char[] buffer = str.toCharArray();
6485 
6486         for (int i = 0; i < buffer.length; i++) {
6487             final char ch = buffer[i];
6488             if (Character.isUpperCase(ch)) {
6489                 buffer[i] = Character.toLowerCase(ch);
6490             } else if (Character.isTitleCase(ch)) {
6491                 buffer[i] = Character.toLowerCase(ch);
6492             } else if (Character.isLowerCase(ch)) {
6493                 buffer[i] = Character.toUpperCase(ch);
6494             }
6495         }
6496         return new String(buffer);
6497     }
6498 
6499     // Count matches
6500     //-----------------------------------------------------------------------
6501     /**
6502      * <p>Counts how many times the substring appears in the larger string.</p>
6503      *
6504      * <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
6505      *
6506      * <pre>
6507      * StringUtils.countMatches(null, *)       = 0
6508      * StringUtils.countMatches("", *)         = 0
6509      * StringUtils.countMatches("abba", null)  = 0
6510      * StringUtils.countMatches("abba", "")    = 0
6511      * StringUtils.countMatches("abba", "a")   = 2
6512      * StringUtils.countMatches("abba", "ab")  = 1
6513      * StringUtils.countMatches("abba", "xxx") = 0
6514      * </pre>
6515      *
6516      * @param str  the CharSequence to check, may be null
6517      * @param sub  the substring to count, may be null
6518      * @return the number of occurrences, 0 if either CharSequence is {@code null}
6519      * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence)
6520      */
6521     public static int countMatches(final CharSequence str, final CharSequence sub) {
6522         if (isEmpty(str) || isEmpty(sub)) {
6523             return 0;
6524         }
6525         int count = 0;
6526         int idx = 0;
6527         while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) {
6528             count++;
6529             idx += sub.length();
6530         }
6531         return count;
6532     }
6533 
6534     /**
6535      * <p>Counts how many times the char appears in the given string.</p>
6536      *
6537      * <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
6538      *
6539      * <pre>
6540      * StringUtils.countMatches(null, *)       = 0
6541      * StringUtils.countMatches("", *)         = 0
6542      * StringUtils.countMatches("abba", 0)  = 0
6543      * StringUtils.countMatches("abba", 'a')   = 2
6544      * StringUtils.countMatches("abba", 'b')  = 2
6545      * StringUtils.countMatches("abba", 'x') = 0
6546      * </pre>
6547      *
6548      * @param str  the CharSequence to check, may be null
6549      * @param ch  the char to count
6550      * @return the number of occurrences, 0 if the CharSequence is {@code null}
6551      * @since 3.4
6552      */
6553     public static int countMatches(final CharSequence str, final char ch) {
6554         if (isEmpty(str)) {
6555             return 0;
6556         }
6557         int count = 0;
6558         // We could also call str.toCharArray() for faster look ups but that would generate more garbage.
6559         for (int i = 0; i < str.length(); i++) {
6560             if (ch == str.charAt(i)) {
6561                 count++;
6562             }
6563         }
6564         return count;
6565     }
6566 
6567     // Character Tests
6568     //-----------------------------------------------------------------------
6569     /**
6570      * <p>Checks if the CharSequence contains only Unicode letters.</p>
6571      *
6572      * <p>{@code null} will return {@code false}.
6573      * An empty CharSequence (length()=0) will return {@code false}.</p>
6574      *
6575      * <pre>
6576      * StringUtils.isAlpha(null)   = false
6577      * StringUtils.isAlpha("")     = false
6578      * StringUtils.isAlpha("  ")   = false
6579      * StringUtils.isAlpha("abc")  = true
6580      * StringUtils.isAlpha("ab2c") = false
6581      * StringUtils.isAlpha("ab-c") = false
6582      * </pre>
6583      *
6584      * @param cs  the CharSequence to check, may be null
6585      * @return {@code true} if only contains letters, and is non-null
6586      * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence)
6587      * @since 3.0 Changed "" to return false and not true
6588      */
6589     public static boolean isAlpha(final CharSequence cs) {
6590         if (isEmpty(cs)) {
6591             return false;
6592         }
6593         final int sz = cs.length();
6594         for (int i = 0; i < sz; i++) {
6595             if (Character.isLetter(cs.charAt(i)) == false) {
6596                 return false;
6597             }
6598         }
6599         return true;
6600     }
6601 
6602     /**
6603      * <p>Checks if the CharSequence contains only Unicode letters and
6604      * space (' ').</p>
6605      *
6606      * <p>{@code null} will return {@code false}
6607      * An empty CharSequence (length()=0) will return {@code true}.</p>
6608      *
6609      * <pre>
6610      * StringUtils.isAlphaSpace(null)   = false
6611      * StringUtils.isAlphaSpace("")     = true
6612      * StringUtils.isAlphaSpace("  ")   = true
6613      * StringUtils.isAlphaSpace("abc")  = true
6614      * StringUtils.isAlphaSpace("ab c") = true
6615      * StringUtils.isAlphaSpace("ab2c") = false
6616      * StringUtils.isAlphaSpace("ab-c") = false
6617      * </pre>
6618      *
6619      * @param cs  the CharSequence to check, may be null
6620      * @return {@code true} if only contains letters and space,
6621      *  and is non-null
6622      * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence)
6623      */
6624     public static boolean isAlphaSpace(final CharSequence cs) {
6625         if (cs == null) {
6626             return false;
6627         }
6628         final int sz = cs.length();
6629         for (int i = 0; i < sz; i++) {
6630             if (Character.isLetter(cs.charAt(i)) == false && cs.charAt(i) != ' ') {
6631                 return false;
6632             }
6633         }
6634         return true;
6635     }
6636 
6637     /**
6638      * <p>Checks if the CharSequence contains only Unicode letters or digits.</p>
6639      *
6640      * <p>{@code null} will return {@code false}.
6641      * An empty CharSequence (length()=0) will return {@code false}.</p>
6642      *
6643      * <pre>
6644      * StringUtils.isAlphanumeric(null)   = false
6645      * StringUtils.isAlphanumeric("")     = false
6646      * StringUtils.isAlphanumeric("  ")   = false
6647      * StringUtils.isAlphanumeric("abc")  = true
6648      * StringUtils.isAlphanumeric("ab c") = false
6649      * StringUtils.isAlphanumeric("ab2c") = true
6650      * StringUtils.isAlphanumeric("ab-c") = false
6651      * </pre>
6652      *
6653      * @param cs  the CharSequence to check, may be null
6654      * @return {@code true} if only contains letters or digits,
6655      *  and is non-null
6656      * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence)
6657      * @since 3.0 Changed "" to return false and not true
6658      */
6659     public static boolean isAlphanumeric(final CharSequence cs) {
6660         if (isEmpty(cs)) {
6661             return false;
6662         }
6663         final int sz = cs.length();
6664         for (int i = 0; i < sz; i++) {
6665             if (Character.isLetterOrDigit(cs.charAt(i)) == false) {
6666                 return false;
6667             }
6668         }
6669         return true;
6670     }
6671 
6672     /**
6673      * <p>Checks if the CharSequence contains only Unicode letters, digits
6674      * or space ({@code ' '}).</p>
6675      *
6676      * <p>{@code null} will return {@code false}.
6677      * An empty CharSequence (length()=0) will return {@code true}.</p>
6678      *
6679      * <pre>
6680      * StringUtils.isAlphanumericSpace(null)   = false
6681      * StringUtils.isAlphanumericSpace("")     = true
6682      * StringUtils.isAlphanumericSpace("  ")   = true
6683      * StringUtils.isAlphanumericSpace("abc")  = true
6684      * StringUtils.isAlphanumericSpace("ab c") = true
6685      * StringUtils.isAlphanumericSpace("ab2c") = true
6686      * StringUtils.isAlphanumericSpace("ab-c") = false
6687      * </pre>
6688      *
6689      * @param cs  the CharSequence to check, may be null
6690      * @return {@code true} if only contains letters, digits or space,
6691      *  and is non-null
6692      * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence)
6693      */
6694     public static boolean isAlphanumericSpace(final CharSequence cs) {
6695         if (cs == null) {
6696             return false;
6697         }
6698         final int sz = cs.length();
6699         for (int i = 0; i < sz; i++) {
6700             if (Character.isLetterOrDigit(cs.charAt(i)) == false && cs.charAt(i) != ' ') {
6701                 return false;
6702             }
6703         }
6704         return true;
6705     }
6706 
6707     /**
6708      * <p>Checks if the CharSequence contains only ASCII printable characters.</p>
6709      *
6710      * <p>{@code null} will return {@code false}.
6711      * An empty CharSequence (length()=0) will return {@code true}.</p>
6712      *
6713      * <pre>
6714      * StringUtils.isAsciiPrintable(null)     = false
6715      * StringUtils.isAsciiPrintable("")       = true
6716      * StringUtils.isAsciiPrintable(" ")      = true
6717      * StringUtils.isAsciiPrintable("Ceki")   = true
6718      * StringUtils.isAsciiPrintable("ab2c")   = true
6719      * StringUtils.isAsciiPrintable("!ab-c~") = true
6720      * StringUtils.isAsciiPrintable("\u0020") = true
6721      * StringUtils.isAsciiPrintable("\u0021") = true
6722      * StringUtils.isAsciiPrintable("\u007e") = true
6723      * StringUtils.isAsciiPrintable("\u007f") = false
6724      * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
6725      * </pre>
6726      *
6727      * @param cs the CharSequence to check, may be null
6728      * @return {@code true} if every character is in the range
6729      *  32 thru 126
6730      * @since 2.1
6731      * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence)
6732      */
6733     public static boolean isAsciiPrintable(final CharSequence cs) {
6734         if (cs == null) {
6735             return false;
6736         }
6737         final int sz = cs.length();
6738         for (int i = 0; i < sz; i++) {
6739             if (CharUtils.isAsciiPrintable(cs.charAt(i)) == false) {
6740                 return false;
6741             }
6742         }
6743         return true;
6744     }
6745 
6746     /**
6747      * <p>Checks if the CharSequence contains only Unicode digits.
6748      * A decimal point is not a Unicode digit and returns false.</p>
6749      *
6750      * <p>{@code null} will return {@code false}.
6751      * An empty CharSequence (length()=0) will return {@code false}.</p>
6752      *
6753      * <p>Note that the method does not allow for a leading sign, either positive or negative.
6754      * Also, if a String passes the numeric test, it may still generate a NumberFormatException
6755      * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range
6756      * for int or long respectively.</p>
6757      *
6758      * <pre>
6759      * StringUtils.isNumeric(null)   = false
6760      * StringUtils.isNumeric("")     = false
6761      * StringUtils.isNumeric("  ")   = false
6762      * StringUtils.isNumeric("123")  = true
6763      * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
6764      * StringUtils.isNumeric("12 3") = false
6765      * StringUtils.isNumeric("ab2c") = false
6766      * StringUtils.isNumeric("12-3") = false
6767      * StringUtils.isNumeric("12.3") = false
6768      * StringUtils.isNumeric("-123") = false
6769      * StringUtils.isNumeric("+123") = false
6770      * </pre>
6771      *
6772      * @param cs  the CharSequence to check, may be null
6773      * @return {@code true} if only contains digits, and is non-null
6774      * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
6775      * @since 3.0 Changed "" to return false and not true
6776      */
6777     public static boolean isNumeric(final CharSequence cs) {
6778         if (isEmpty(cs)) {
6779             return false;
6780         }
6781         final int sz = cs.length();
6782         for (int i = 0; i < sz; i++) {
6783             if (!Character.isDigit(cs.charAt(i))) {
6784                 return false;
6785             }
6786         }
6787         return true;
6788     }
6789 
6790     /**
6791      * <p>Checks if the CharSequence contains only Unicode digits or space
6792      * ({@code ' '}).
6793      * A decimal point is not a Unicode digit and returns false.</p>
6794      *
6795      * <p>{@code null} will return {@code false}.
6796      * An empty CharSequence (length()=0) will return {@code true}.</p>
6797      *
6798      * <pre>
6799      * StringUtils.isNumericSpace(null)   = false
6800      * StringUtils.isNumericSpace("")     = true
6801      * StringUtils.isNumericSpace("  ")   = true
6802      * StringUtils.isNumericSpace("123")  = true
6803      * StringUtils.isNumericSpace("12 3") = true
6804      * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
6805      * StringUtils.isNumeric("\u0967\u0968 \u0969")  = true
6806      * StringUtils.isNumericSpace("ab2c") = false
6807      * StringUtils.isNumericSpace("12-3") = false
6808      * StringUtils.isNumericSpace("12.3") = false
6809      * </pre>
6810      *
6811      * @param cs  the CharSequence to check, may be null
6812      * @return {@code true} if only contains digits or space,
6813      *  and is non-null
6814      * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence)
6815      */
6816     public static boolean isNumericSpace(final CharSequence cs) {
6817         if (cs == null) {
6818             return false;
6819         }
6820         final int sz = cs.length();
6821         for (int i = 0; i < sz; i++) {
6822             if (Character.isDigit(cs.charAt(i)) == false && cs.charAt(i) != ' ') {
6823                 return false;
6824             }
6825         }
6826         return true;
6827     }
6828 
6829     /**
6830      * <p>Checks if the CharSequence contains only whitespace.</p>
6831      *
6832      * <p>{@code null} will return {@code false}.
6833      * An empty CharSequence (length()=0) will return {@code true}.</p>
6834      *
6835      * <pre>
6836      * StringUtils.isWhitespace(null)   = false
6837      * StringUtils.isWhitespace("")     = true
6838      * StringUtils.isWhitespace("  ")   = true
6839      * StringUtils.isWhitespace("abc")  = false
6840      * StringUtils.isWhitespace("ab2c") = false
6841      * StringUtils.isWhitespace("ab-c") = false
6842      * </pre>
6843      *
6844      * @param cs  the CharSequence to check, may be null
6845      * @return {@code true} if only contains whitespace, and is non-null
6846      * @since 2.0
6847      * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence)
6848      */
6849     public static boolean isWhitespace(final CharSequence cs) {
6850         if (cs == null) {
6851             return false;
6852         }
6853         final int sz = cs.length();
6854         for (int i = 0; i < sz; i++) {
6855             if (Character.isWhitespace(cs.charAt(i)) == false) {
6856                 return false;
6857             }
6858         }
6859         return true;
6860     }
6861 
6862     /**
6863      * <p>Checks if the CharSequence contains only lowercase characters.</p>
6864      *
6865      * <p>{@code null} will return {@code false}.
6866      * An empty CharSequence (length()=0) will return {@code false}.</p>
6867      *
6868      * <pre>
6869      * StringUtils.isAllLowerCase(null)   = false
6870      * StringUtils.isAllLowerCase("")     = false
6871      * StringUtils.isAllLowerCase("  ")   = false
6872      * StringUtils.isAllLowerCase("abc")  = true
6873      * StringUtils.isAllLowerCase("abC")  = false
6874      * StringUtils.isAllLowerCase("ab c") = false
6875      * StringUtils.isAllLowerCase("ab1c") = false
6876      * StringUtils.isAllLowerCase("ab/c") = false
6877      * </pre>
6878      *
6879      * @param cs  the CharSequence to check, may be null
6880      * @return {@code true} if only contains lowercase characters, and is non-null
6881      * @since 2.5
6882      * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence)
6883      */
6884     public static boolean isAllLowerCase(final CharSequence cs) {
6885         if (cs == null || isEmpty(cs)) {
6886             return false;
6887         }
6888         final int sz = cs.length();
6889         for (int i = 0; i < sz; i++) {
6890             if (Character.isLowerCase(cs.charAt(i)) == false) {
6891                 return false;
6892             }
6893         }
6894         return true;
6895     }
6896 
6897     /**
6898      * <p>Checks if the CharSequence contains only uppercase characters.</p>
6899      *
6900      * <p>{@code null} will return {@code false}.
6901      * An empty String (length()=0) will return {@code false}.</p>
6902      *
6903      * <pre>
6904      * StringUtils.isAllUpperCase(null)   = false
6905      * StringUtils.isAllUpperCase("")     = false
6906      * StringUtils.isAllUpperCase("  ")   = false
6907      * StringUtils.isAllUpperCase("ABC")  = true
6908      * StringUtils.isAllUpperCase("aBC")  = false
6909      * StringUtils.isAllUpperCase("A C")  = false
6910      * StringUtils.isAllUpperCase("A1C")  = false
6911      * StringUtils.isAllUpperCase("A/C")  = false
6912      * </pre>
6913      *
6914      * @param cs the CharSequence to check, may be null
6915      * @return {@code true} if only contains uppercase characters, and is non-null
6916      * @since 2.5
6917      * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence)
6918      */
6919     public static boolean isAllUpperCase(final CharSequence cs) {
6920         if (cs == null || isEmpty(cs)) {
6921             return false;
6922         }
6923         final int sz = cs.length();
6924         for (int i = 0; i < sz; i++) {
6925             if (Character.isUpperCase(cs.charAt(i)) == false) {
6926                 return false;
6927             }
6928         }
6929         return true;
6930     }
6931 
6932     // Defaults
6933     //-----------------------------------------------------------------------
6934     /**
6935      * <p>Returns either the passed in String,
6936      * or if the String is {@code null}, an empty String ("").</p>
6937      *
6938      * <pre>
6939      * StringUtils.defaultString(null)  = ""
6940      * StringUtils.defaultString("")    = ""
6941      * StringUtils.defaultString("bat") = "bat"
6942      * </pre>
6943      *
6944      * @see ObjectUtils#toString(Object)
6945      * @see String#valueOf(Object)
6946      * @param str  the String to check, may be null
6947      * @return the passed in String, or the empty String if it
6948      *  was {@code null}
6949      */
6950     public static String defaultString(final String str) {
6951         return str == null ? EMPTY : str;
6952     }
6953 
6954     /**
6955      * <p>Returns either the passed in String, or if the String is
6956      * {@code null}, the value of {@code defaultStr}.</p>
6957      *
6958      * <pre>
6959      * StringUtils.defaultString(null, "NULL")  = "NULL"
6960      * StringUtils.defaultString("", "NULL")    = ""
6961      * StringUtils.defaultString("bat", "NULL") = "bat"
6962      * </pre>
6963      *
6964      * @see ObjectUtils#toString(Object,String)
6965      * @see String#valueOf(Object)
6966      * @param str  the String to check, may be null
6967      * @param defaultStr  the default String to return
6968      *  if the input is {@code null}, may be null
6969      * @return the passed in String, or the default if it was {@code null}
6970      */
6971     public static String defaultString(final String str, final String defaultStr) {
6972         return str == null ? defaultStr : str;
6973     }
6974 
6975     /**
6976      * <p>Returns either the passed in CharSequence, or if the CharSequence is
6977      * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}.</p>
6978      *
6979      * <pre>
6980      * StringUtils.defaultIfBlank(null, "NULL")  = "NULL"
6981      * StringUtils.defaultIfBlank("", "NULL")    = "NULL"
6982      * StringUtils.defaultIfBlank(" ", "NULL")   = "NULL"
6983      * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
6984      * StringUtils.defaultIfBlank("", null)      = null
6985      * </pre>
6986      * @param <T> the specific kind of CharSequence
6987      * @param str the CharSequence to check, may be null
6988      * @param defaultStr  the default CharSequence to return
6989      *  if the input is whitespace, empty ("") or {@code null}, may be null
6990      * @return the passed in CharSequence, or the default
6991      * @see StringUtils#defaultString(String, String)
6992      */
6993     public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) {
6994         return isBlank(str) ? defaultStr : str;
6995     }
6996 
6997     /**
6998      * <p>Returns either the passed in CharSequence, or if the CharSequence is
6999      * empty or {@code null}, the value of {@code defaultStr}.</p>
7000      *
7001      * <pre>
7002      * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
7003      * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
7004      * StringUtils.defaultIfEmpty(" ", "NULL")   = " "
7005      * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
7006      * StringUtils.defaultIfEmpty("", null)      = null
7007      * </pre>
7008      * @param <T> the specific kind of CharSequence
7009      * @param str  the CharSequence to check, may be null
7010      * @param defaultStr  the default CharSequence to return
7011      *  if the input is empty ("") or {@code null}, may be null
7012      * @return the passed in CharSequence, or the default
7013      * @see StringUtils#defaultString(String, String)
7014      */
7015     public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) {
7016         return isEmpty(str) ? defaultStr : str;
7017     }
7018 
7019     // Rotating (circular shift)
7020     //-----------------------------------------------------------------------
7021     /**
7022      * <p>Rotate (circular shift) a String of {@code shift} characters.</p>
7023      * <ul>
7024      *  <li>If {@code shift > 0}, right circular shift (ex : ABCDEF =&gt; FABCDE)</li>
7025      *  <li>If {@code shift < 0}, left circular shift (ex : ABCDEF =&gt; BCDEFA)</li>
7026      * </ul>
7027      *
7028      * <pre>
7029      * StringUtils.rotate(null, *)        = null
7030      * StringUtils.rotate("", *)          = ""
7031      * StringUtils.rotate("abcdefg", 0)   = "abcdefg"
7032      * StringUtils.rotate("abcdefg", 2)   = "fgabcde"
7033      * StringUtils.rotate("abcdefg", -2)  = "cdefgab"
7034      * StringUtils.rotate("abcdefg", 7)   = "abcdefg"
7035      * StringUtils.rotate("abcdefg", -7)  = "abcdefg"
7036      * StringUtils.rotate("abcdefg", 9)   = "fgabcde"
7037      * StringUtils.rotate("abcdefg", -9)  = "cdefgab"
7038      * </pre>
7039      *
7040      * @param str  the String to rotate, may be null
7041      * @param shift  number of time to shift (positive : right shift, negative : left shift)
7042      * @return the rotated String,
7043      *          or the original String if {@code shift == 0},
7044      *          or {@code null} if null String input
7045      */
7046     public static String rotate(String str, int shift) {
7047         if (str == null) {
7048             return null;
7049         }
7050 
7051         final int strLen = str.length();
7052         if (shift == 0 || strLen == 0 || shift % strLen == 0) {
7053             return str;
7054         }
7055 
7056         final StringBuilder builder = new StringBuilder(strLen);
7057         final int offset = - (shift % strLen);
7058         builder.append(substring(str, offset));
7059         builder.append(substring(str, 0, offset));
7060         return builder.toString();
7061     }
7062 
7063     // Reversing
7064     //-----------------------------------------------------------------------
7065     /**
7066      * <p>Reverses a String as per {@link StringBuilder#reverse()}.</p>
7067      *
7068      * <p>A {@code null} String returns {@code null}.</p>
7069      *
7070      * <pre>
7071      * StringUtils.reverse(null)  = null
7072      * StringUtils.reverse("")    = ""
7073      * StringUtils.reverse("bat") = "tab"
7074      * </pre>
7075      *
7076      * @param str  the String to reverse, may be null
7077      * @return the reversed String, {@code null} if null String input
7078      */
7079     public static String reverse(final String str) {
7080         if (str == null) {
7081             return null;
7082         }
7083         return new StringBuilder(str).reverse().toString();
7084     }
7085 
7086     /**
7087      * <p>Reverses a String that is delimited by a specific character.</p>
7088      *
7089      * <p>The Strings between the delimiters are not reversed.
7090      * Thus java.lang.String becomes String.lang.java (if the delimiter
7091      * is {@code '.'}).</p>
7092      *
7093      * <pre>
7094      * StringUtils.reverseDelimited(null, *)      = null
7095      * StringUtils.reverseDelimited("", *)        = ""
7096      * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
7097      * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
7098      * </pre>
7099      *
7100      * @param str  the String to reverse, may be null
7101      * @param separatorChar  the separator character to use
7102      * @return the reversed String, {@code null} if null String input
7103      * @since 2.0
7104      */
7105     public static String reverseDelimited(final String str, final char separatorChar) {
7106         if (str == null) {
7107             return null;
7108         }
7109         // could implement manually, but simple way is to reuse other,
7110         // probably slower, methods.
7111         final String[] strs = split(str, separatorChar);
7112         ArrayUtils.reverse(strs);
7113         return join(strs, separatorChar);
7114     }
7115 
7116     // Abbreviating
7117     //-----------------------------------------------------------------------
7118     /**
7119      * <p>Abbreviates a String using ellipses. This will turn
7120      * "Now is the time for all good men" into "Now is the time for..."</p>
7121      *
7122      * <p>Specifically:</p>
7123      * <ul>
7124      *   <li>If the number of characters in {@code str} is less than or equal to 
7125      *       {@code maxWidth}, return {@code str}.</li>
7126      *   <li>Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.</li>
7127      *   <li>If {@code maxWidth} is less than {@code 4}, throw an
7128      *       {@code IllegalArgumentException}.</li>
7129      *   <li>In no case will it return a String of length greater than
7130      *       {@code maxWidth}.</li>
7131      * </ul>
7132      *
7133      * <pre>
7134      * StringUtils.abbreviate(null, *)      = null
7135      * StringUtils.abbreviate("", 4)        = ""
7136      * StringUtils.abbreviate("abcdefg", 6) = "abc..."
7137      * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
7138      * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
7139      * StringUtils.abbreviate("abcdefg", 4) = "a..."
7140      * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
7141      * </pre>
7142      *
7143      * @param str  the String to check, may be null
7144      * @param maxWidth  maximum length of result String, must be at least 4
7145      * @return abbreviated String, {@code null} if null String input
7146      * @throws IllegalArgumentException if the width is too small
7147      * @since 2.0
7148      */
7149     public static String abbreviate(final String str, final int maxWidth) {
7150         return abbreviate(str, 0, maxWidth);
7151     }
7152 
7153     /**
7154      * <p>Abbreviates a String using ellipses. This will turn
7155      * "Now is the time for all good men" into "...is the time for..."</p>
7156      *
7157      * <p>Works like {@code abbreviate(String, int)}, but allows you to specify
7158      * a "left edge" offset.  Note that this left edge is not necessarily going to
7159      * be the leftmost character in the result, or the first character following the
7160      * ellipses, but it will appear somewhere in the result.
7161      *
7162      * <p>In no case will it return a String of length greater than
7163      * {@code maxWidth}.</p>
7164      *
7165      * <pre>
7166      * StringUtils.abbreviate(null, *, *)                = null
7167      * StringUtils.abbreviate("", 0, 4)                  = ""
7168      * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
7169      * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
7170      * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
7171      * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
7172      * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
7173      * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
7174      * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
7175      * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
7176      * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
7177      * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
7178      * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
7179      * </pre>
7180      *
7181      * @param str  the String to check, may be null
7182      * @param offset  left edge of source String
7183      * @param maxWidth  maximum length of result String, must be at least 4
7184      * @return abbreviated String, {@code null} if null String input
7185      * @throws IllegalArgumentException if the width is too small
7186      * @since 2.0
7187      */
7188     public static String abbreviate(final String str, int offset, final int maxWidth) {
7189         if (str == null) {
7190             return null;
7191         }
7192         if (maxWidth < 4) {
7193             throw new IllegalArgumentException("Minimum abbreviation width is 4");
7194         }
7195         if (str.length() <= maxWidth) {
7196             return str;
7197         }
7198         if (offset > str.length()) {
7199             offset = str.length();
7200         }
7201         if (str.length() - offset < maxWidth - 3) {
7202             offset = str.length() - (maxWidth - 3);
7203         }
7204         final String abrevMarker = "...";
7205         if (offset <= 4) {
7206             return str.substring(0, maxWidth - 3) + abrevMarker;
7207         }
7208         if (maxWidth < 7) {
7209             throw new IllegalArgumentException("Minimum abbreviation width with offset is 7");
7210         }
7211         if (offset + maxWidth - 3 < str.length()) {
7212             return abrevMarker + abbreviate(str.substring(offset), maxWidth - 3);
7213         }
7214         return abrevMarker + str.substring(str.length() - (maxWidth - 3));
7215     }
7216 
7217     /**
7218      * <p>Abbreviates a String to the length passed, replacing the middle characters with the supplied
7219      * replacement String.</p>
7220      *
7221      * <p>This abbreviation only occurs if the following criteria is met:</p>
7222      * <ul>
7223      * <li>Neither the String for abbreviation nor the replacement String are null or empty </li>
7224      * <li>The length to truncate to is less than the length of the supplied String</li>
7225      * <li>The length to truncate to is greater than 0</li>
7226      * <li>The abbreviated String will have enough room for the length supplied replacement String
7227      * and the first and last characters of the supplied String for abbreviation</li>
7228      * </ul>
7229      * <p>Otherwise, the returned String will be the same as the supplied String for abbreviation.
7230      * </p>
7231      *
7232      * <pre>
7233      * StringUtils.abbreviateMiddle(null, null, 0)      = null
7234      * StringUtils.abbreviateMiddle("abc", null, 0)      = "abc"
7235      * StringUtils.abbreviateMiddle("abc", ".", 0)      = "abc"
7236      * StringUtils.abbreviateMiddle("abc", ".", 3)      = "abc"
7237      * StringUtils.abbreviateMiddle("abcdef", ".", 4)     = "ab.f"
7238      * </pre>
7239      *
7240      * @param str  the String to abbreviate, may be null
7241      * @param middle the String to replace the middle characters with, may be null
7242      * @param length the length to abbreviate {@code str} to.
7243      * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
7244      * @since 2.5
7245      */
7246     public static String abbreviateMiddle(final String str, final String middle, final int length) {
7247         if (isEmpty(str) || isEmpty(middle)) {
7248             return str;
7249         }
7250 
7251         if (length >= str.length() || length < middle.length()+2) {
7252             return str;
7253         }
7254 
7255         final int targetSting = length-middle.length();
7256         final int startOffset = targetSting/2+targetSting%2;
7257         final int endOffset = str.length()-targetSting/2;
7258 
7259         final StringBuilder builder = new StringBuilder(length);
7260         builder.append(str.substring(0,startOffset));
7261         builder.append(middle);
7262         builder.append(str.substring(endOffset));
7263 
7264         return builder.toString();
7265     }
7266 
7267     // Difference
7268     //-----------------------------------------------------------------------
7269     /**
7270      * <p>Compares two Strings, and returns the portion where they differ.
7271      * More precisely, return the remainder of the second String,
7272      * starting from where it's different from the first. This means that
7273      * the difference between "abc" and "ab" is the empty String and not "c". </p>
7274      *
7275      * <p>For example,
7276      * {@code difference("i am a machine", "i am a robot") -> "robot"}.</p>
7277      *
7278      * <pre>
7279      * StringUtils.difference(null, null) = null
7280      * StringUtils.difference("", "") = ""
7281      * StringUtils.difference("", "abc") = "abc"
7282      * StringUtils.difference("abc", "") = ""
7283      * StringUtils.difference("abc", "abc") = ""
7284      * StringUtils.difference("abc", "ab") = ""
7285      * StringUtils.difference("ab", "abxyz") = "xyz"
7286      * StringUtils.difference("abcde", "abxyz") = "xyz"
7287      * StringUtils.difference("abcde", "xyz") = "xyz"
7288      * </pre>
7289      *
7290      * @param str1  the first String, may be null
7291      * @param str2  the second String, may be null
7292      * @return the portion of str2 where it differs from str1; returns the
7293      * empty String if they are equal
7294      * @see #indexOfDifference(CharSequence,CharSequence)
7295      * @since 2.0
7296      */
7297     public static String difference(final String str1, final String str2) {
7298         if (str1 == null) {
7299             return str2;
7300         }
7301         if (str2 == null) {
7302             return str1;
7303         }
7304         final int at = indexOfDifference(str1, str2);
7305         if (at == INDEX_NOT_FOUND) {
7306             return EMPTY;
7307         }
7308         return str2.substring(at);
7309     }
7310 
7311     /**
7312      * <p>Compares two CharSequences, and returns the index at which the
7313      * CharSequences begin to differ.</p>
7314      *
7315      * <p>For example,
7316      * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}</p>
7317      *
7318      * <pre>
7319      * StringUtils.indexOfDifference(null, null) = -1
7320      * StringUtils.indexOfDifference("", "") = -1
7321      * StringUtils.indexOfDifference("", "abc") = 0
7322      * StringUtils.indexOfDifference("abc", "") = 0
7323      * StringUtils.indexOfDifference("abc", "abc") = -1
7324      * StringUtils.indexOfDifference("ab", "abxyz") = 2
7325      * StringUtils.indexOfDifference("abcde", "abxyz") = 2
7326      * StringUtils.indexOfDifference("abcde", "xyz") = 0
7327      * </pre>
7328      *
7329      * @param cs1  the first CharSequence, may be null
7330      * @param cs2  the second CharSequence, may be null
7331      * @return the index where cs1 and cs2 begin to differ; -1 if they are equal
7332      * @since 2.0
7333      * @since 3.0 Changed signature from indexOfDifference(String, String) to
7334      * indexOfDifference(CharSequence, CharSequence)
7335      */
7336     public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) {
7337         if (cs1 == cs2) {
7338             return INDEX_NOT_FOUND;
7339         }
7340         if (cs1 == null || cs2 == null) {
7341             return 0;
7342         }
7343         int i;
7344         for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {
7345             if (cs1.charAt(i) != cs2.charAt(i)) {
7346                 break;
7347             }
7348         }
7349         if (i < cs2.length() || i < cs1.length()) {
7350             return i;
7351         }
7352         return INDEX_NOT_FOUND;
7353     }
7354 
7355     /**
7356      * <p>Compares all CharSequences in an array and returns the index at which the
7357      * CharSequences begin to differ.</p>
7358      *
7359      * <p>For example,
7360      * <code>indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -&gt; 7</code></p>
7361      *
7362      * <pre>
7363      * StringUtils.indexOfDifference(null) = -1
7364      * StringUtils.indexOfDifference(new String[] {}) = -1
7365      * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
7366      * StringUtils.indexOfDifference(new String[] {null, null}) = -1
7367      * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
7368      * StringUtils.indexOfDifference(new String[] {"", null}) = 0
7369      * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
7370      * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
7371      * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
7372      * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
7373      * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
7374      * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
7375      * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
7376      * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
7377      * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
7378      * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
7379      * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
7380      * </pre>
7381      *
7382      * @param css  array of CharSequences, entries may be null
7383      * @return the index where the strings begin to differ; -1 if they are all equal
7384      * @since 2.4
7385      * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...)
7386      */
7387     public static int indexOfDifference(final CharSequence... css) {
7388         if (css == null || css.length <= 1) {
7389             return INDEX_NOT_FOUND;
7390         }
7391         boolean anyStringNull = false;
7392         boolean allStringsNull = true;
7393         final int arrayLen = css.length;
7394         int shortestStrLen = Integer.MAX_VALUE;
7395         int longestStrLen = 0;
7396 
7397         // find the min and max string lengths; this avoids checking to make
7398         // sure we are not exceeding the length of the string each time through
7399         // the bottom loop.
7400         for (int i = 0; i < arrayLen; i++) {
7401             if (css[i] == null) {
7402                 anyStringNull = true;
7403                 shortestStrLen = 0;
7404             } else {
7405                 allStringsNull = false;
7406                 shortestStrLen = Math.min(css[i].length(), shortestStrLen);
7407                 longestStrLen = Math.max(css[i].length(), longestStrLen);
7408             }
7409         }
7410 
7411         // handle lists containing all nulls or all empty strings
7412         if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
7413             return INDEX_NOT_FOUND;
7414         }
7415 
7416         // handle lists containing some nulls or some empty strings
7417         if (shortestStrLen == 0) {
7418             return 0;
7419         }
7420 
7421         // find the position with the first difference across all strings
7422         int firstDiff = -1;
7423         for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
7424             final char comparisonChar = css[0].charAt(stringPos);
7425             for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
7426                 if (css[arrayPos].charAt(stringPos) != comparisonChar) {
7427                     firstDiff = stringPos;
7428                     break;
7429                 }
7430             }
7431             if (firstDiff != -1) {
7432                 break;
7433             }
7434         }
7435 
7436         if (firstDiff == -1 && shortestStrLen != longestStrLen) {
7437             // we compared all of the characters up to the length of the
7438             // shortest string and didn't find a match, but the string lengths
7439             // vary, so return the length of the shortest string.
7440             return shortestStrLen;
7441         }
7442         return firstDiff;
7443     }
7444 
7445     /**
7446      * <p>Compares all Strings in an array and returns the initial sequence of
7447      * characters that is common to all of them.</p>
7448      *
7449      * <p>For example,