View Javadoc
1   /* ====================================================================
2    * The Apache Software License, Version 1.1
3    *
4    * Copyright (c) 2002 The Apache Software Foundation.  All rights
5    * reserved.
6    *
7    * Redistribution and use in source and binary forms, with or without
8    * modification, are permitted provided that the following conditions
9    * are met:
10   *
11   * 1. Redistributions of source code must retain the above copyright
12   *    notice, this list of conditions and the following disclaimer.
13   *
14   * 2. Redistributions in binary form must reproduce the above copyright
15   *    notice, this list of conditions and the following disclaimer in
16   *    the documentation and/or other materials provided with the
17   *    distribution.
18   *
19   * 3. The end-user documentation included with the redistribution, if
20   *    any, must include the following acknowledgement:
21   *       "This product includes software developed by the
22   *        Apache Software Foundation (http://www.codehaus.org/)."
23   *    Alternately, this acknowledgement may appear in the software itself,
24   *    if and wherever such third-party acknowledgements normally appear.
25   *
26   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
27   *    Foundation" must not be used to endorse or promote products derived
28   *    from this software without prior written permission. For written
29   *    permission, please contact codehaus@codehaus.org.
30   *
31   * 5. Products derived from this software may not be called "Apache"
32   *    nor may "Apache" appear in their names without prior written
33   *    permission of the Apache Software Foundation.
34   *
35   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46   * SUCH DAMAGE.
47   * ====================================================================
48   *
49   * This software consists of voluntary contributions made by many
50   * individuals on behalf of the Apache Software Foundation.  For more
51   * information on the Apache Software Foundation, please see
52   * <http://www.codehaus.org/>.
53   */
54  package org.codehaus.plexus.util;
55  
56  import java.util.Arrays;
57  import java.util.Iterator;
58  import java.util.Locale;
59  import java.util.Map;
60  import java.util.Objects;
61  import java.util.StringTokenizer;
62  
63  /**
64   * <p>
65   * Common <code>String</code> manipulation routines.
66   * </p>
67   * <p>
68   * Originally from <a href="http://jakarta.apache.org/turbine/">Turbine</a> and the GenerationJavaCore library.
69   * </p>
70   *
71   * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
72   * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
73   * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
74   * @author <a href="mailto:bayard@generationjava.com">Henri Yandell</a>
75   * @author <a href="mailto:ed@codehaus.org">Ed Korthof</a>
76   * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
77   * @author Stephen Colebourne
78   * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
79   * @author Holger Krauth
80   * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
81   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
82   * @since 1.0
83   *
84   */
85  public class StringUtils
86  {
87      /**
88       * <p>
89       * <code>StringUtils</code> instances should NOT be constructed in standard programming. Instead, the class should
90       * be used as <code>StringUtils.trim(" foo ");</code>.
91       * </p>
92       * <p>
93       * This constructor is public to permit tools that require a JavaBean manager to operate.
94       * </p>
95       */
96      public StringUtils()
97      {
98      }
99  
100     // Empty
101     // --------------------------------------------------------------------------
102 
103     /**
104      * <p>
105      * Removes control characters, including whitespace, from both ends of this String, handling <code>null</code> by
106      * returning an empty String.
107      * </p>
108      *
109      * @see java.lang.String#trim()
110      * @param str the String to check
111      * @return the trimmed text (never <code>null</code>)
112      */
113     public static String clean( String str )
114     {
115         return ( str == null ? "" : str.trim() );
116     }
117 
118     /**
119      * <p>
120      * Removes control characters, including whitespace, from both ends of this String, handling <code>null</code> by
121      * returning <code>null</code>.
122      * </p>
123      *
124      * @see java.lang.String#trim()
125      * @param str the String to check
126      * @return the trimmed text (or <code>null</code>)
127      */
128     public static String trim( String str )
129     {
130         return ( str == null ? null : str.trim() );
131     }
132 
133     /**
134      * <p>
135      * Deletes all whitespaces from a String.
136      * </p>
137      * <p>
138      * Whitespace is defined by {@link Character#isWhitespace(char)}.
139      * </p>
140      *
141      * @param str String target to delete whitespace from
142      * @return the String without whitespaces
143      */
144     public static String deleteWhitespace( String str )
145     {
146         StringBuilder buffer = new StringBuilder();
147         int sz = str.length();
148         for ( int i = 0; i < sz; i++ )
149         {
150             if ( !Character.isWhitespace( str.charAt( i ) ) )
151             {
152                 buffer.append( str.charAt( i ) );
153             }
154         }
155         return buffer.toString();
156     }
157 
158     /**
159      * Checks if a String is non <code>null</code> and is not empty (<code>length &gt; 0</code>).
160      *
161      * @param str the String to check
162      * @return true if the String is non-null, and not length zero
163      */
164     public static boolean isNotEmpty( String str )
165     {
166         return ( ( str != null ) && ( !str.isEmpty() ) );
167     }
168 
169     /**
170      * Checks if a String is <code>null</code> or empty.
171      * <p>
172      * <strong>Note:</strong> In releases prior 3.5.0, this method trimmed the input string such that it worked
173      * the same as {@link #isBlank(String)}. Since release 3.5.0 it no longer returns {@code true} for strings
174      * containing only whitespace characters.
175      *
176      * @param str the String to check
177      * @return <code>true</code> if the String is <code>null</code>, or length zero
178      */
179     public static boolean isEmpty( String str )
180     {
181         return ( ( str == null ) || ( str.isEmpty() ) );
182     }
183 
184     /**
185      * <p>
186      * Checks if a String is whitespace, empty ("") or null.
187      * </p>
188      *
189      * <pre>
190      * StringUtils.isBlank(null)      = true
191      * StringUtils.isBlank("")        = true
192      * StringUtils.isBlank(" ")       = true
193      * StringUtils.isBlank("bob")     = false
194      * StringUtils.isBlank("  bob  ") = false
195      * </pre>
196      *
197      * @param str the String to check, may be null
198      * @return <code>true</code> if the String is null, empty or whitespace
199      * @since 1.5.2
200      */
201     public static boolean isBlank( String str )
202     {
203         int strLen;
204         if ( str == null || ( strLen = str.length() ) == 0 )
205         {
206             return true;
207         }
208         for ( int i = 0; i < strLen; i++ )
209         {
210             if ( !Character.isWhitespace( str.charAt( i ) ) )
211             {
212                 return false;
213             }
214         }
215         return true;
216     }
217 
218     /**
219      * <p>
220      * Checks if a String is not empty (""), not null and not whitespace only.
221      * </p>
222      *
223      * <pre>
224      * StringUtils.isNotBlank(null)      = false
225      * StringUtils.isNotBlank("")        = false
226      * StringUtils.isNotBlank(" ")       = false
227      * StringUtils.isNotBlank("bob")     = true
228      * StringUtils.isNotBlank("  bob  ") = true
229      * </pre>
230      *
231      * @param str the String to check, may be null
232      * @return <code>true</code> if the String is not empty and not null and not whitespace
233      * @since 1.5.2
234      */
235     public static boolean isNotBlank( String str )
236     {
237         return !StringUtils.isBlank( str );
238     }
239 
240     // Equals and IndexOf
241     // --------------------------------------------------------------------------
242 
243     /**
244      * <p>
245      * Compares two Strings, returning <code>true</code> if they are equal.
246      * </p>
247      * <p>
248      * <code>null</code>s are handled without exceptions. Two <code>null</code> references are considered to be equal.
249      * The comparison is case sensitive.
250      * </p>
251      *
252      * @see java.lang.String#equals(Object)
253      * @param str1 the first string
254      * @param str2 the second string
255      * @return <code>true</code> if the Strings are equal, case sensitive, or both <code>null</code>
256      * @see Objects#equals(Object, Object)
257      */
258     @Deprecated
259     public static boolean equals( String str1, String str2 )
260     {
261         return Objects.equals( str1, str2 );
262     }
263 
264     /**
265      * <p>
266      * Compares two Strings, returning <code>true</code> if they are equal ignoring the case.
267      * </p>
268      * <p>
269      * <code>Nulls</code> are handled without exceptions. Two <code>null</code> references are considered equal.
270      * Comparison is case insensitive.
271      * </p>
272      *
273      * @see java.lang.String#equalsIgnoreCase(String)
274      * @param str1 the first string
275      * @param str2 the second string
276      * @return <code>true</code> if the Strings are equal, case insensitive, or both <code>null</code>
277      */
278     public static boolean equalsIgnoreCase( String str1, String str2 )
279     {
280         return ( str1 == null ? str2 == null : str1.equalsIgnoreCase( str2 ) );
281     }
282 
283     /**
284      * <p>
285      * Find the first index of any of a set of potential substrings.
286      * </p>
287      * <p>
288      * <code>null</code> String will return <code>-1</code>.
289      * </p>
290      *
291      * @param str the String to check
292      * @param searchStrs the Strings to search for
293      * @return the first index of any of the searchStrs in str
294      * @throws NullPointerException if any of searchStrs[i] is <code>null</code>
295      */
296     public static int indexOfAny( String str, String[] searchStrs )
297     {
298         if ( ( str == null ) || ( searchStrs == null ) )
299         {
300             return -1;
301         }
302         int sz = searchStrs.length;
303 
304         // String's can't have a MAX_VALUEth index.
305         int ret = Integer.MAX_VALUE;
306 
307         int tmp;
308         for ( String searchStr : searchStrs )
309         {
310             tmp = str.indexOf( searchStr );
311             if ( tmp == -1 )
312             {
313                 continue;
314             }
315 
316             if ( tmp < ret )
317             {
318                 ret = tmp;
319             }
320         }
321 
322         return ( ret == Integer.MAX_VALUE ) ? -1 : ret;
323     }
324 
325     /**
326      * <p>
327      * Find the latest index of any of a set of potential substrings.
328      * </p>
329      * <p>
330      * <code>null</code> string will return <code>-1</code>.
331      * </p>
332      *
333      * @param str the String to check
334      * @param searchStrs the Strings to search for
335      * @return the last index of any of the Strings
336      * @throws NullPointerException if any of searchStrs[i] is <code>null</code>
337      */
338     public static int lastIndexOfAny( String str, String[] searchStrs )
339     {
340         if ( ( str == null ) || ( searchStrs == null ) )
341         {
342             return -1;
343         }
344         int ret = -1;
345         int tmp;
346         for ( String searchStr : searchStrs )
347         {
348             tmp = str.lastIndexOf( searchStr );
349             if ( tmp > ret )
350             {
351                 ret = tmp;
352             }
353         }
354         return ret;
355     }
356 
357     // Substring
358     // --------------------------------------------------------------------------
359 
360     /**
361      * <p>
362      * Gets a substring from the specified string avoiding exceptions.
363      * </p>
364      * <p>
365      * A negative start position can be used to start <code>n</code> characters from the end of the String.
366      * </p>
367      *
368      * @param str the String to get the substring from
369      * @param start the position to start from, negative means count back from the end of the String by this many
370      *            characters
371      * @return substring from start position
372      */
373     public static String substring( String str, int start )
374     {
375         if ( str == null )
376         {
377             return null;
378         }
379 
380         // handle negatives, which means last n characters
381         if ( start < 0 )
382         {
383             start = str.length() + start; // remember start is negative
384         }
385 
386         if ( start < 0 )
387         {
388             start = 0;
389         }
390         if ( start > str.length() )
391         {
392             return "";
393         }
394 
395         return str.substring( start );
396     }
397 
398     /**
399      * <p>
400      * Gets a substring from the specified String avoiding exceptions.
401      * </p>
402      * <p>
403      * A negative start position can be used to start/end <code>n</code> characters from the end of the String.
404      * </p>
405      *
406      * @param str the String to get the substring from
407      * @param start the position to start from, negative means count back from the end of the string by this many
408      *            characters
409      * @param end the position to end at (exclusive), negative means count back from the end of the String by this many
410      *            characters
411      * @return substring from start position to end position
412      */
413     public static String substring( String str, int start, int end )
414     {
415         if ( str == null )
416         {
417             return null;
418         }
419 
420         // handle negatives
421         if ( end < 0 )
422         {
423             end = str.length() + end; // remember end is negative
424         }
425         if ( start < 0 )
426         {
427             start = str.length() + start; // remember start is negative
428         }
429 
430         // check length next
431         if ( end > str.length() )
432         {
433             // check this works.
434             end = str.length();
435         }
436 
437         // if start is greater than end, return ""
438         if ( start > end )
439         {
440             return "";
441         }
442 
443         if ( start < 0 )
444         {
445             start = 0;
446         }
447         if ( end < 0 )
448         {
449             end = 0;
450         }
451 
452         return str.substring( start, end );
453     }
454 
455     /**
456      * <p>
457      * Gets the leftmost <code>n</code> characters of a String.
458      * </p>
459      * <p>
460      * If <code>n</code> characters are not available, or the String is <code>null</code>, the String will be returned
461      * without an exception.
462      * </p>
463      *
464      * @param str the String to get the leftmost characters from
465      * @param len the length of the required String
466      * @return the leftmost characters
467      * @throws IllegalArgumentException if len is less than zero
468      */
469     public static String left( String str, int len )
470     {
471         if ( len < 0 )
472         {
473             throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
474         }
475         if ( ( str == null ) || ( str.length() <= len ) )
476         {
477             return str;
478         }
479         else
480         {
481             return str.substring( 0, len );
482         }
483     }
484 
485     /**
486      * <p>
487      * Gets the rightmost <code>n</code> characters of a String.
488      * </p>
489      * <p>
490      * If <code>n</code> characters are not available, or the String is <code>null</code>, the String will be returned
491      * without an exception.
492      * </p>
493      *
494      * @param str the String to get the rightmost characters from
495      * @param len the length of the required String
496      * @return the leftmost characters
497      * @throws IllegalArgumentException if len is less than zero
498      */
499     public static String right( String str, int len )
500     {
501         if ( len < 0 )
502         {
503             throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
504         }
505         if ( ( str == null ) || ( str.length() <= len ) )
506         {
507             return str;
508         }
509         else
510         {
511             return str.substring( str.length() - len );
512         }
513     }
514 
515     /**
516      * <p>
517      * Gets <code>n</code> characters from the middle of a String.
518      * </p>
519      * <p>
520      * If <code>n</code> characters are not available, the remainder of the String will be returned without an
521      * exception. If the String is <code>null</code>, <code>null</code> will be returned.
522      * </p>
523      *
524      * @param str the String to get the characters from
525      * @param pos the position to start from
526      * @param len the length of the required String
527      * @return the leftmost characters
528      * @throws IndexOutOfBoundsException if pos is out of bounds
529      * @throws IllegalArgumentException if len is less than zero
530      */
531     public static String mid( String str, int pos, int len )
532     {
533         if ( ( pos < 0 ) || ( ( str != null ) && ( pos > str.length() ) ) )
534         {
535             throw new StringIndexOutOfBoundsException( "String index " + pos + " is out of bounds" );
536         }
537         if ( len < 0 )
538         {
539             throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
540         }
541         if ( str == null )
542         {
543             return null;
544         }
545         if ( str.length() <= ( pos + len ) )
546         {
547             return str.substring( pos );
548         }
549         else
550         {
551             return str.substring( pos, pos + len );
552         }
553     }
554 
555     // Splitting
556     // --------------------------------------------------------------------------
557 
558     /**
559      * <p>
560      * Splits the provided text into a array, using whitespace as the separator.
561      * </p>
562      * <p>
563      * The separator is not included in the returned String array.
564      * </p>
565      *
566      * @param str the String to parse
567      * @return an array of parsed Strings
568      */
569     public static String[] split( String str )
570     {
571         return split( str, null, -1 );
572     }
573 
574     /**
575      * @param text The string to parse.
576      * @param separator Characters used as the delimiters. If <code>null</code>, splits on whitespace.
577      * @return an array of parsed Strings
578      */
579     public static String[] split( String text, String separator )
580     {
581         return split( text, separator, -1 );
582     }
583 
584     /**
585      * <p>
586      * Splits the provided text into a array, based on a given separator.
587      * </p>
588      * <p>
589      * The separator is not included in the returned String array. The maximum number of splits to perform can be
590      * controlled. A <code>null</code> separator will cause parsing to be on whitespace.
591      * </p>
592      * <p>
593      * This is useful for quickly splitting a String directly into an array of tokens, instead of an enumeration of
594      * tokens (as <code>StringTokenizer</code> does).
595      * </p>
596      *
597      * @param str The string to parse.
598      * @param separator Characters used as the delimiters. If <code>null</code>, splits on whitespace.
599      * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit.
600      * @return an array of parsed Strings
601      */
602     public static String[] split( String str, String separator, int max )
603     {
604         StringTokenizer tok;
605         if ( separator == null )
606         {
607             // Null separator means we're using StringTokenizer's default
608             // delimiter, which comprises all whitespace characters.
609             tok = new StringTokenizer( str );
610         }
611         else
612         {
613             tok = new StringTokenizer( str, separator );
614         }
615 
616         int listSize = tok.countTokens();
617         if ( ( max > 0 ) && ( listSize > max ) )
618         {
619             listSize = max;
620         }
621 
622         String[] list = new String[listSize];
623         int i = 0;
624         int lastTokenBegin;
625         int lastTokenEnd = 0;
626         while ( tok.hasMoreTokens() )
627         {
628             if ( ( max > 0 ) && ( i == listSize - 1 ) )
629             {
630                 // In the situation where we hit the max yet have
631                 // tokens left over in our input, the last list
632                 // element gets all remaining text.
633                 String endToken = tok.nextToken();
634                 lastTokenBegin = str.indexOf( endToken, lastTokenEnd );
635                 list[i] = str.substring( lastTokenBegin );
636                 break;
637             }
638             else
639             {
640                 list[i] = tok.nextToken();
641                 lastTokenBegin = str.indexOf( list[i], lastTokenEnd );
642                 lastTokenEnd = lastTokenBegin + list[i].length();
643             }
644             i++;
645         }
646         return list;
647     }
648 
649     // Joining
650     // --------------------------------------------------------------------------
651     /**
652      * <p>
653      * Concatenates elements of an array into a single String.
654      * </p>
655      * <p>
656      * The difference from join is that concatenate has no delimiter.
657      * </p>
658      *
659      * @param array the array of values to concatenate.
660      * @return the concatenated string.
661      */
662     public static String concatenate( Object[] array )
663     {
664         return join( array, "" );
665     }
666 
667     /**
668      * <p>
669      * Joins the elements of the provided array into a single String containing the provided list of elements.
670      * </p>
671      * <p>
672      * No delimiter is added before or after the list. A <code>null</code> separator is the same as a blank String.
673      * </p>
674      *
675      * @param array the array of values to join together
676      * @param separator the separator character to use
677      * @return the joined String
678      */
679     public static String join( Object[] array, String separator )
680     {
681         if ( separator == null )
682         {
683             separator = "";
684         }
685         int arraySize = array.length;
686         int bufSize = ( arraySize == 0 ? 0 : ( array[0].toString().length() + separator.length() ) * arraySize );
687         StringBuilder buf = new StringBuilder( bufSize );
688 
689         for ( int i = 0; i < arraySize; i++ )
690         {
691             if ( i > 0 )
692             {
693                 buf.append( separator );
694             }
695             buf.append( array[i] );
696         }
697         return buf.toString();
698     }
699 
700     /**
701      * <p>
702      * Joins the elements of the provided <code>Iterator</code> into a single String containing the provided elements.
703      * </p>
704      * <p>
705      * No delimiter is added before or after the list. A <code>null</code> separator is the same as a blank String.
706      * </p>
707      *
708      * @param iterator the <code>Iterator</code> of values to join together
709      * @param separator the separator character to use
710      * @return the joined String
711      */
712     public static String join( Iterator<?> iterator, String separator )
713     {
714         if ( separator == null )
715         {
716             separator = "";
717         }
718         StringBuilder buf = new StringBuilder( 256 ); // Java default is 16, probably too small
719         while ( iterator.hasNext() )
720         {
721             buf.append( iterator.next() );
722             if ( iterator.hasNext() )
723             {
724                 buf.append( separator );
725             }
726         }
727         return buf.toString();
728     }
729 
730     // Replacing
731     // --------------------------------------------------------------------------
732 
733     /**
734      * <p>
735      * Replace a char with another char inside a larger String, once.
736      * </p>
737      * <p>
738      * A <code>null</code> reference passed to this method is a no-op.
739      * </p>
740      *
741      * @see #replace(String text, char repl, char with, int max)
742      * @param text text to search and replace in
743      * @param repl char to search for
744      * @param with char to replace with
745      * @return the text with any replacements processed
746      */
747     public static String replaceOnce( String text, char repl, char with )
748     {
749         return replace( text, repl, with, 1 );
750     }
751 
752     /**
753      * <p>
754      * Replace all occurrences of a char within another char.
755      * </p>
756      * <p>
757      * A <code>null</code> reference passed to this method is a no-op.
758      * </p>
759      *
760      * @see #replace(String text, char repl, char with, int max)
761      * @param text text to search and replace in
762      * @param repl char to search for
763      * @param with char to replace with
764      * @return the text with any replacements processed
765      */
766     public static String replace( String text, char repl, char with )
767     {
768         return replace( text, repl, with, -1 );
769     }
770 
771     /**
772      * <p>
773      * Replace a char with another char inside a larger String, for the first <code>max</code> values of the search
774      * char.
775      * </p>
776      * <p>
777      * A <code>null</code> reference passed to this method is a no-op.
778      * </p>
779      *
780      * @param text text to search and replace in
781      * @param repl char to search for
782      * @param with char to replace with
783      * @param max maximum number of values to replace, or <code>-1</code> if no maximum
784      * @return the text with any replacements processed
785      */
786     public static String replace( String text, char repl, char with, int max )
787     {
788         return replace( text, String.valueOf( repl ), String.valueOf( with ), max );
789     }
790 
791     /**
792      * <p>
793      * Replace a String with another String inside a larger String, once.
794      * </p>
795      * <p>
796      * A <code>null</code> reference passed to this method is a no-op.
797      * </p>
798      *
799      * @see #replace(String text, String repl, String with, int max)
800      * @param text text to search and replace in
801      * @param repl String to search for
802      * @param with String to replace with
803      * @return the text with any replacements processed
804      */
805     public static String replaceOnce( String text, String repl, String with )
806     {
807         return replace( text, repl, with, 1 );
808     }
809 
810     /**
811      * <p>
812      * Replace all occurrences of a String within another String.
813      * </p>
814      * <p>
815      * A <code>null</code> reference passed to this method is a no-op.
816      * </p>
817      *
818      * @see #replace(String text, String repl, String with, int max)
819      * @param text text to search and replace in
820      * @param repl String to search for
821      * @param with String to replace with
822      * @return the text with any replacements processed
823      */
824     public static String replace( String text, String repl, String with )
825     {
826         return replace( text, repl, with, -1 );
827     }
828 
829     /**
830      * <p>
831      * Replace a String with another String inside a larger String, for the first <code>max</code> values of the search
832      * String.
833      * </p>
834      * <p>
835      * A <code>null</code> reference passed to this method is a no-op.
836      * </p>
837      *
838      * @param text text to search and replace in
839      * @param repl String to search for
840      * @param with String to replace with
841      * @param max maximum number of values to replace, or <code>-1</code> if no maximum
842      * @return the text with any replacements processed
843      */
844     public static String replace( String text, String repl, String with, int max )
845     {
846         if ( ( text == null ) || ( repl == null ) || ( with == null ) || ( repl.length() == 0 ) )
847         {
848             return text;
849         }
850 
851         StringBuilder buf = new StringBuilder( text.length() );
852         int start = 0, end;
853         while ( ( end = text.indexOf( repl, start ) ) != -1 )
854         {
855             buf.append( text, start, end ).append( with );
856             start = end + repl.length();
857 
858             if ( --max == 0 )
859             {
860                 break;
861             }
862         }
863         buf.append( text, start, text.length() );
864         return buf.toString();
865     }
866 
867     /**
868      * <p>
869      * Overlay a part of a String with another String.
870      * </p>
871      *
872      * @param text String to do overlaying in
873      * @param overlay String to overlay
874      * @param start int to start overlaying at
875      * @param end int to stop overlaying before
876      * @return String with overlayed text
877      * @throws NullPointerException if text or overlay is <code>null</code>
878      */
879     public static String overlayString( String text, String overlay, int start, int end )
880     {
881         return new StringBuilder( start + overlay.length() + text.length() - end
882             + 1 ).append( text, 0, start ).append( overlay ).append( text, end, text.length() ).toString();
883     }
884 
885     // Centering
886     // --------------------------------------------------------------------------
887 
888     /**
889      * <p>
890      * Center a String in a larger String of size <code>n</code>.
891      * </p>
892      * <p>
893      * Uses spaces as the value to buffer the String with. Equivalent to <code>center(str, size, " ")</code>.
894      * </p>
895      *
896      * @param str String to center
897      * @param size int size of new String
898      * @return String containing centered String
899      * @throws NullPointerException if str is <code>null</code>
900      */
901     public static String center( String str, int size )
902     {
903         return center( str, size, " " );
904     }
905 
906     /**
907      * <p>
908      * Center a String in a larger String of size <code>n</code>.
909      * </p>
910      * <p>
911      * Uses a supplied String as the value to buffer the String with.
912      * </p>
913      *
914      * @param str String to center
915      * @param size int size of new String
916      * @param delim String to buffer the new String with
917      * @return String containing centered String
918      * @throws NullPointerException if str or delim is <code>null</code>
919      * @throws ArithmeticException if delim is the empty String
920      */
921     public static String center( String str, int size, String delim )
922     {
923         int sz = str.length();
924         int p = size - sz;
925         if ( p < 1 )
926         {
927             return str;
928         }
929         str = leftPad( str, sz + p / 2, delim );
930         str = rightPad( str, size, delim );
931         return str;
932     }
933 
934     // Chomping
935     // --------------------------------------------------------------------------
936 
937     /**
938      * <p>
939      * Remove the last newline, and everything after it from a String.
940      * </p>
941      *
942      * @param str String to chomp the newline from
943      * @return String without chomped newline
944      * @throws NullPointerException if str is <code>null</code>
945      */
946     public static String chomp( String str )
947     {
948         return chomp( str, "\n" );
949     }
950 
951     /**
952      * <p>
953      * Remove the last value of a supplied String, and everything after it from a String.
954      * </p>
955      *
956      * @param str String to chomp from
957      * @param sep String to chomp
958      * @return String without chomped ending
959      * @throws NullPointerException if str or sep is <code>null</code>
960      */
961     public static String chomp( String str, String sep )
962     {
963         int idx = str.lastIndexOf( sep );
964         if ( idx != -1 )
965         {
966             return str.substring( 0, idx );
967         }
968         else
969         {
970             return str;
971         }
972     }
973 
974     /**
975      * <p>
976      * Remove a newline if and only if it is at the end of the supplied String.
977      * </p>
978      *
979      * @param str String to chomp from
980      * @return String without chomped ending
981      * @throws NullPointerException if str is <code>null</code>
982      */
983     public static String chompLast( String str )
984     {
985         return chompLast( str, "\n" );
986     }
987 
988     /**
989      * <p>
990      * Remove a value if and only if the String ends with that value.
991      * </p>
992      *
993      * @param str String to chomp from
994      * @param sep String to chomp
995      * @return String without chomped ending
996      * @throws NullPointerException if str or sep is <code>null</code>
997      */
998     public static String chompLast( String str, String sep )
999     {
1000         if ( str.length() == 0 )
1001         {
1002             return str;
1003         }
1004         String sub = str.substring( str.length() - sep.length() );
1005         if ( sep.equals( sub ) )
1006         {
1007             return str.substring( 0, str.length() - sep.length() );
1008         }
1009         else
1010         {
1011             return str;
1012         }
1013     }
1014 
1015     /**
1016      * <p>
1017      * Remove everything and return the last value of a supplied String, and everything after it from a String.
1018      * </p>
1019      *
1020      * @param str String to chomp from
1021      * @param sep String to chomp
1022      * @return String chomped
1023      * @throws NullPointerException if str or sep is <code>null</code>
1024      */
1025     public static String getChomp( String str, String sep )
1026     {
1027         int idx = str.lastIndexOf( sep );
1028         if ( idx == str.length() - sep.length() )
1029         {
1030             return sep;
1031         }
1032         else if ( idx != -1 )
1033         {
1034             return str.substring( idx );
1035         }
1036         else
1037         {
1038             return "";
1039         }
1040     }
1041 
1042     /**
1043      * <p>
1044      * Remove the first value of a supplied String, and everything before it from a String.
1045      * </p>
1046      *
1047      * @param str String to chomp from
1048      * @param sep String to chomp
1049      * @return String without chomped beginning
1050      * @throws NullPointerException if str or sep is <code>null</code>
1051      */
1052     public static String prechomp( String str, String sep )
1053     {
1054         int idx = str.indexOf( sep );
1055         if ( idx != -1 )
1056         {
1057             return str.substring( idx + sep.length() );
1058         }
1059         else
1060         {
1061             return str;
1062         }
1063     }
1064 
1065     /**
1066      * <p>
1067      * Remove and return everything before the first value of a supplied String from another String.
1068      * </p>
1069      *
1070      * @param str String to chomp from
1071      * @param sep String to chomp
1072      * @return String prechomped
1073      * @throws NullPointerException if str or sep is <code>null</code>
1074      */
1075     public static String getPrechomp( String str, String sep )
1076     {
1077         int idx = str.indexOf( sep );
1078         if ( idx != -1 )
1079         {
1080             return str.substring( 0, idx + sep.length() );
1081         }
1082         else
1083         {
1084             return "";
1085         }
1086     }
1087 
1088     // Chopping
1089     // --------------------------------------------------------------------------
1090 
1091     /**
1092      * <p>
1093      * Remove the last character from a String.
1094      * </p>
1095      * <p>
1096      * If the String ends in <code>\r\n</code>, then remove both of them.
1097      * </p>
1098      *
1099      * @param str String to chop last character from
1100      * @return String without last character
1101      * @throws NullPointerException if str is <code>null</code>
1102      */
1103     public static String chop( String str )
1104     {
1105         if ( "".equals( str ) )
1106         {
1107             return "";
1108         }
1109         if ( str.length() == 1 )
1110         {
1111             return "";
1112         }
1113         int lastIdx = str.length() - 1;
1114         String ret = str.substring( 0, lastIdx );
1115         char last = str.charAt( lastIdx );
1116         if ( last == '\n' )
1117         {
1118             if ( ret.charAt( lastIdx - 1 ) == '\r' )
1119             {
1120                 return ret.substring( 0, lastIdx - 1 );
1121             }
1122         }
1123         return ret;
1124     }
1125 
1126     /**
1127      * <p>
1128      * Remove <code>\n</code> from end of a String if it's there. If a <code>\r</code> precedes it, then remove that
1129      * too.
1130      * </p>
1131      *
1132      * @param str String to chop a newline from
1133      * @return String without newline
1134      * @throws NullPointerException if str is <code>null</code>
1135      */
1136     public static String chopNewline( String str )
1137     {
1138         int lastIdx = str.length() - 1;
1139         char last = str.charAt( lastIdx );
1140         if ( last == '\n' )
1141         {
1142             if ( str.charAt( lastIdx - 1 ) == '\r' )
1143             {
1144                 lastIdx--;
1145             }
1146         }
1147         else
1148         {
1149             lastIdx++;
1150         }
1151         return str.substring( 0, lastIdx );
1152     }
1153 
1154     // Conversion
1155     // --------------------------------------------------------------------------
1156 
1157     // spec 3.10.6
1158     /**
1159      * <p>
1160      * Escapes any values it finds into their String form.
1161      * </p>
1162      * <p>
1163      * So a tab becomes the characters <code>'\\'</code> and <code>'t'</code>.
1164      * </p>
1165      *
1166      * @param str String to escape values in
1167      * @return String with escaped values
1168      * @throws NullPointerException if str is <code>null</code>
1169      */
1170     public static String escape( String str )
1171     {
1172         // improved with code from cybertiger@cyberiantiger.org
1173         // unicode from him, and default for < 32's.
1174         int sz = str.length();
1175         StringBuilder buffer = new StringBuilder( 2 * sz );
1176         for ( int i = 0; i < sz; i++ )
1177         {
1178             char ch = str.charAt( i );
1179 
1180             // handle unicode
1181             if ( ch > 0xfff )
1182             {
1183                 buffer.append( "\\u" + Integer.toHexString( ch ) );
1184             }
1185             else if ( ch > 0xff )
1186             {
1187                 buffer.append( "\\u0" + Integer.toHexString( ch ) );
1188             }
1189             else if ( ch > 0x7f )
1190             {
1191                 buffer.append( "\\u00" + Integer.toHexString( ch ) );
1192             }
1193             else if ( ch < 32 )
1194             {
1195                 switch ( ch )
1196                 {
1197                     case '\b':
1198                         buffer.append( '\\' );
1199                         buffer.append( 'b' );
1200                         break;
1201                     case '\n':
1202                         buffer.append( '\\' );
1203                         buffer.append( 'n' );
1204                         break;
1205                     case '\t':
1206                         buffer.append( '\\' );
1207                         buffer.append( 't' );
1208                         break;
1209                     case '\f':
1210                         buffer.append( '\\' );
1211                         buffer.append( 'f' );
1212                         break;
1213                     case '\r':
1214                         buffer.append( '\\' );
1215                         buffer.append( 'r' );
1216                         break;
1217                     default:
1218                         if ( ch > 0xf )
1219                         {
1220                             buffer.append( "\\u00" + Integer.toHexString( ch ) );
1221                         }
1222                         else
1223                         {
1224                             buffer.append( "\\u000" + Integer.toHexString( ch ) );
1225                         }
1226                         break;
1227                 }
1228             }
1229             else
1230             {
1231                 switch ( ch )
1232                 {
1233                     case '\'':
1234                         buffer.append( '\\' );
1235                         buffer.append( '\'' );
1236                         break;
1237                     case '"':
1238                         buffer.append( '\\' );
1239                         buffer.append( '"' );
1240                         break;
1241                     case '\\':
1242                         buffer.append( '\\' );
1243                         buffer.append( '\\' );
1244                         break;
1245                     default:
1246                         buffer.append( ch );
1247                         break;
1248                 }
1249             }
1250         }
1251         return buffer.toString();
1252     }
1253 
1254     // Padding
1255     // --------------------------------------------------------------------------
1256 
1257     /**
1258      * <p>
1259      * Repeat a String <code>n</code> times to form a new string.
1260      * </p>
1261      *
1262      * @param str String to repeat
1263      * @param repeat number of times to repeat str
1264      * @return String with repeated String
1265      * @throws NegativeArraySizeException if <code>repeat &lt; 0</code>
1266      * @throws NullPointerException if str is <code>null</code>
1267      */
1268     public static String repeat( String str, int repeat )
1269     {
1270         StringBuilder buffer = new StringBuilder( repeat * str.length() );
1271         for ( int i = 0; i < repeat; i++ )
1272         {
1273             buffer.append( str );
1274         }
1275         return buffer.toString();
1276     }
1277 
1278     /**
1279      * <p>
1280      * Right pad a String with spaces.
1281      * </p>
1282      * <p>
1283      * The String is padded to the size of <code>n</code>.
1284      * </p>
1285      *
1286      * @param str String to repeat
1287      * @param size number of times to repeat str
1288      * @return right padded String
1289      * @throws NullPointerException if str is <code>null</code>
1290      */
1291     public static String rightPad( String str, int size )
1292     {
1293         return rightPad( str, size, " " );
1294     }
1295 
1296     /**
1297      * <p>
1298      * Right pad a String with a specified string.
1299      * </p>
1300      * <p>
1301      * The String is padded to the size of <code>n</code>.
1302      * </p>
1303      *
1304      * @param str String to pad out
1305      * @param size size to pad to
1306      * @param delim String to pad with
1307      * @return right padded String
1308      * @throws NullPointerException if str or delim is <code>null</code>
1309      * @throws ArithmeticException if delim is the empty String
1310      */
1311     public static String rightPad( String str, int size, String delim )
1312     {
1313         size = ( size - str.length() ) / delim.length();
1314         if ( size > 0 )
1315         {
1316             str += repeat( delim, size );
1317         }
1318         return str;
1319     }
1320 
1321     /**
1322      * <p>
1323      * Left pad a String with spaces.
1324      * </p>
1325      * <p>
1326      * The String is padded to the size of <code>n</code>.
1327      * </p>
1328      *
1329      * @param str String to pad out
1330      * @param size size to pad to
1331      * @return left padded String
1332      * @throws NullPointerException if str or delim is <code>null</code>
1333      */
1334     public static String leftPad( String str, int size )
1335     {
1336         return leftPad( str, size, " " );
1337     }
1338 
1339     /**
1340      * Left pad a String with a specified string. Pad to a size of n.
1341      *
1342      * @param str String to pad out
1343      * @param size size to pad to
1344      * @param delim String to pad with
1345      * @return left padded String
1346      * @throws NullPointerException if str or delim is null
1347      * @throws ArithmeticException if delim is the empty string
1348      */
1349     public static String leftPad( String str, int size, String delim )
1350     {
1351         size = ( size - str.length() ) / delim.length();
1352         if ( size > 0 )
1353         {
1354             str = repeat( delim, size ) + str;
1355         }
1356         return str;
1357     }
1358 
1359     // Stripping
1360     // --------------------------------------------------------------------------
1361 
1362     /**
1363      * <p>
1364      * Remove whitespace from the front and back of a String.
1365      * </p>
1366      *
1367      * @param str the String to remove whitespace from
1368      * @return the stripped String
1369      */
1370     public static String strip( String str )
1371     {
1372         return strip( str, null );
1373     }
1374 
1375     /**
1376      * <p>
1377      * Remove a specified String from the front and back of a String.
1378      * </p>
1379      * <p>
1380      * If whitespace is wanted to be removed, used the {@link #strip(java.lang.String)} method.
1381      * </p>
1382      *
1383      * @param str the String to remove a string from
1384      * @param delim the String to remove at start and end
1385      * @return the stripped String
1386      */
1387     public static String strip( String str, String delim )
1388     {
1389         str = stripStart( str, delim );
1390         return stripEnd( str, delim );
1391     }
1392 
1393     /**
1394      * <p>
1395      * Strip whitespace from the front and back of every String in the array.
1396      * </p>
1397      *
1398      * @param strs the Strings to remove whitespace from
1399      * @return the stripped Strings
1400      */
1401     public static String[] stripAll( String[] strs )
1402     {
1403         return stripAll( strs, null );
1404     }
1405 
1406     /**
1407      * <p>
1408      * Strip the specified delimiter from the front and back of every String in the array.
1409      * </p>
1410      *
1411      * @param strs the Strings to remove a String from
1412      * @param delimiter the String to remove at start and end
1413      * @return the stripped Strings
1414      */
1415     public static String[] stripAll( String[] strs, String delimiter )
1416     {
1417         if ( ( strs == null ) || ( strs.length == 0 ) )
1418         {
1419             return strs;
1420         }
1421         int sz = strs.length;
1422         String[] newArr = new String[sz];
1423         for ( int i = 0; i < sz; i++ )
1424         {
1425             newArr[i] = strip( strs[i], delimiter );
1426         }
1427         return newArr;
1428     }
1429 
1430     /**
1431      * <p>
1432      * Strip any of a supplied String from the end of a String.
1433      * </p>
1434      * <p>
1435      * If the strip String is <code>null</code>, whitespace is stripped.
1436      * </p>
1437      *
1438      * @param str the String to remove characters from
1439      * @param strip the String to remove
1440      * @return the stripped String
1441      */
1442     public static String stripEnd( String str, String strip )
1443     {
1444         if ( str == null )
1445         {
1446             return null;
1447         }
1448         int end = str.length();
1449 
1450         if ( strip == null )
1451         {
1452             while ( ( end != 0 ) && Character.isWhitespace( str.charAt( end - 1 ) ) )
1453             {
1454                 end--;
1455             }
1456         }
1457         else
1458         {
1459             while ( ( end != 0 ) && ( strip.indexOf( str.charAt( end - 1 ) ) != -1 ) )
1460             {
1461                 end--;
1462             }
1463         }
1464         return str.substring( 0, end );
1465     }
1466 
1467     /**
1468      * <p>
1469      * Strip any of a supplied String from the start of a String.
1470      * </p>
1471      * <p>
1472      * If the strip String is <code>null</code>, whitespace is stripped.
1473      * </p>
1474      *
1475      * @param str the String to remove characters from
1476      * @param strip the String to remove
1477      * @return the stripped String
1478      */
1479     public static String stripStart( String str, String strip )
1480     {
1481         if ( str == null )
1482         {
1483             return null;
1484         }
1485 
1486         int start = 0;
1487 
1488         int sz = str.length();
1489 
1490         if ( strip == null )
1491         {
1492             while ( ( start != sz ) && Character.isWhitespace( str.charAt( start ) ) )
1493             {
1494                 start++;
1495             }
1496         }
1497         else
1498         {
1499             while ( ( start != sz ) && ( strip.indexOf( str.charAt( start ) ) != -1 ) )
1500             {
1501                 start++;
1502             }
1503         }
1504         return str.substring( start );
1505     }
1506 
1507     // Case conversion
1508     // --------------------------------------------------------------------------
1509 
1510     /**
1511      * <p>
1512      * Convert a String to upper case, <code>null</code> String returns <code>null</code>.
1513      * </p>
1514      *
1515      * @param str the String to uppercase
1516      * @return the upper cased String
1517      */
1518     public static String upperCase( String str )
1519     {
1520         if ( str == null )
1521         {
1522             return null;
1523         }
1524         return str.toUpperCase();
1525     }
1526 
1527     /**
1528      * <p>
1529      * Convert a String to lower case, <code>null</code> String returns <code>null</code>.
1530      * </p>
1531      *
1532      * @param str the string to lowercase
1533      * @return the lower cased String
1534      */
1535     public static String lowerCase( String str )
1536     {
1537         if ( str == null )
1538         {
1539             return null;
1540         }
1541         return str.toLowerCase();
1542     }
1543 
1544     /**
1545      * <p>
1546      * Uncapitalise a String.
1547      * </p>
1548      * <p>
1549      * That is, convert the first character into lower-case. <code>null</code> is returned as <code>null</code>.
1550      * </p>
1551      *
1552      * @param str the String to uncapitalise
1553      * @return uncapitalised String
1554      */
1555     public static String uncapitalise( String str )
1556     {
1557         if ( str == null )
1558         {
1559             return null;
1560         }
1561         else if ( str.length() == 0 )
1562         {
1563             return "";
1564         }
1565         else
1566         {
1567             return new StringBuilder( str.length() ).append( Character.toLowerCase( str.charAt( 0 ) ) ).append( str, 1,
1568                                                                                                                 str.length() ).toString();
1569         }
1570     }
1571 
1572     /**
1573      * <p>
1574      * Capitalise a String.
1575      * </p>
1576      * <p>
1577      * That is, convert the first character into title-case. <code>null</code> is returned as <code>null</code>.
1578      * </p>
1579      *
1580      * @param str the String to capitalise
1581      * @return capitalised String
1582      */
1583     public static String capitalise( String str )
1584     {
1585         if ( str == null )
1586         {
1587             return null;
1588         }
1589         else if ( str.length() == 0 )
1590         {
1591             return "";
1592         }
1593         else
1594         {
1595             return new StringBuilder( str.length() ).append( Character.toTitleCase( str.charAt( 0 ) ) ).append( str, 1,
1596                                                                                                                 str.length() ).toString();
1597         }
1598     }
1599 
1600     /**
1601      * <p>
1602      * Swaps the case of String.
1603      * </p>
1604      * <p>
1605      * Properly looks after making sure the start of words are Titlecase and not Uppercase.
1606      * </p>
1607      * <p>
1608      * <code>null</code> is returned as <code>null</code>.
1609      * </p>
1610      *
1611      * @param str the String to swap the case of
1612      * @return the modified String
1613      */
1614     public static String swapCase( String str )
1615     {
1616         if ( str == null )
1617         {
1618             return null;
1619         }
1620         int sz = str.length();
1621         StringBuilder buffer = new StringBuilder( sz );
1622 
1623         boolean whitespace = false;
1624         char ch;
1625         char tmp;
1626 
1627         for ( int i = 0; i < sz; i++ )
1628         {
1629             ch = str.charAt( i );
1630             if ( Character.isUpperCase( ch ) )
1631             {
1632                 tmp = Character.toLowerCase( ch );
1633             }
1634             else if ( Character.isTitleCase( ch ) )
1635             {
1636                 tmp = Character.toLowerCase( ch );
1637             }
1638             else if ( Character.isLowerCase( ch ) )
1639             {
1640                 if ( whitespace )
1641                 {
1642                     tmp = Character.toTitleCase( ch );
1643                 }
1644                 else
1645                 {
1646                     tmp = Character.toUpperCase( ch );
1647                 }
1648             }
1649             else
1650             {
1651                 tmp = ch;
1652             }
1653             buffer.append( tmp );
1654             whitespace = Character.isWhitespace( ch );
1655         }
1656         return buffer.toString();
1657     }
1658 
1659     /**
1660      * <p>
1661      * Capitalise all the words in a String.
1662      * </p>
1663      * <p>
1664      * Uses {@link Character#isWhitespace(char)} as a separator between words.
1665      * </p>
1666      * <p>
1667      * <code>null</code> will return <code>null</code>.
1668      * </p>
1669      *
1670      * @param str the String to capitalise
1671      * @return capitalised String
1672      */
1673     public static String capitaliseAllWords( String str )
1674     {
1675         if ( str == null )
1676         {
1677             return null;
1678         }
1679         int sz = str.length();
1680         StringBuilder buffer = new StringBuilder( sz );
1681         boolean space = true;
1682         for ( int i = 0; i < sz; i++ )
1683         {
1684             char ch = str.charAt( i );
1685             if ( Character.isWhitespace( ch ) )
1686             {
1687                 buffer.append( ch );
1688                 space = true;
1689             }
1690             else if ( space )
1691             {
1692                 buffer.append( Character.toTitleCase( ch ) );
1693                 space = false;
1694             }
1695             else
1696             {
1697                 buffer.append( ch );
1698             }
1699         }
1700         return buffer.toString();
1701     }
1702 
1703     /**
1704      * <p>
1705      * Uncapitalise all the words in a string.
1706      * </p>
1707      * <p>
1708      * Uses {@link Character#isWhitespace(char)} as a separator between words.
1709      * </p>
1710      * <p>
1711      * <code>null</code> will return <code>null</code>.
1712      * </p>
1713      *
1714      * @param str the string to uncapitalise
1715      * @return uncapitalised string
1716      */
1717     public static String uncapitaliseAllWords( String str )
1718     {
1719         if ( str == null )
1720         {
1721             return null;
1722         }
1723         int sz = str.length();
1724         StringBuilder buffer = new StringBuilder( sz );
1725         boolean space = true;
1726         for ( int i = 0; i < sz; i++ )
1727         {
1728             char ch = str.charAt( i );
1729             if ( Character.isWhitespace( ch ) )
1730             {
1731                 buffer.append( ch );
1732                 space = true;
1733             }
1734             else if ( space )
1735             {
1736                 buffer.append( Character.toLowerCase( ch ) );
1737                 space = false;
1738             }
1739             else
1740             {
1741                 buffer.append( ch );
1742             }
1743         }
1744         return buffer.toString();
1745     }
1746 
1747     // Nested extraction
1748     // --------------------------------------------------------------------------
1749 
1750     /**
1751      * <p>
1752      * Get the String that is nested in between two instances of the same String.
1753      * </p>
1754      * <p>
1755      * If <code>str</code> is <code>null</code>, will return <code>null</code>.
1756      * </p>
1757      *
1758      * @param str the String containing nested-string
1759      * @param tag the String before and after nested-string
1760      * @return the String that was nested, or <code>null</code>
1761      * @throws NullPointerException if tag is <code>null</code>
1762      */
1763     public static String getNestedString( String str, String tag )
1764     {
1765         return getNestedString( str, tag, tag );
1766     }
1767 
1768     /**
1769      * <p>
1770      * Get the String that is nested in between two Strings.
1771      * </p>
1772      *
1773      * @param str the String containing nested-string
1774      * @param open the String before nested-string
1775      * @param close the String after nested-string
1776      * @return the String that was nested, or <code>null</code>
1777      * @throws NullPointerException if open or close is <code>null</code>
1778      */
1779     public static String getNestedString( String str, String open, String close )
1780     {
1781         if ( str == null )
1782         {
1783             return null;
1784         }
1785         int start = str.indexOf( open );
1786         if ( start != -1 )
1787         {
1788             int end = str.indexOf( close, start + open.length() );
1789             if ( end != -1 )
1790             {
1791                 return str.substring( start + open.length(), end );
1792             }
1793         }
1794         return null;
1795     }
1796 
1797     /**
1798      * <p>
1799      * How many times is the substring in the larger String.
1800      * </p>
1801      * <p>
1802      * <code>null</code> returns <code>0</code>.
1803      * </p>
1804      *
1805      * @param str the String to check
1806      * @param sub the substring to count
1807      * @return the number of occurrences, 0 if the String is <code>null</code>
1808      * @throws NullPointerException if sub is <code>null</code>
1809      */
1810     public static int countMatches( String str, String sub )
1811     {
1812         if ( sub.equals( "" ) )
1813         {
1814             return 0;
1815         }
1816         if ( str == null )
1817         {
1818             return 0;
1819         }
1820         int count = 0;
1821         int idx = 0;
1822         while ( ( idx = str.indexOf( sub, idx ) ) != -1 )
1823         {
1824             count++;
1825             idx += sub.length();
1826         }
1827         return count;
1828     }
1829 
1830     // Character Tests
1831     // --------------------------------------------------------------------------
1832 
1833     /**
1834      * <p>
1835      * Checks if the String contains only unicode letters.
1836      * </p>
1837      * <p>
1838      * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1839      * </p>
1840      *
1841      * @param str the String to check
1842      * @return <code>true</code> if only contains letters, and is non-null
1843      */
1844     public static boolean isAlpha( String str )
1845     {
1846         if ( str == null )
1847         {
1848             return false;
1849         }
1850         int sz = str.length();
1851         for ( int i = 0; i < sz; i++ )
1852         {
1853             if ( Character.isLetter( str.charAt( i ) ) == false )
1854             {
1855                 return false;
1856             }
1857         }
1858         return true;
1859     }
1860 
1861     /**
1862      * <p>
1863      * Checks if the String contains only whitespace.
1864      * </p>
1865      * <p>
1866      * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1867      * </p>
1868      *
1869      * @param str the String to check
1870      * @return <code>true</code> if only contains whitespace, and is non-null
1871      */
1872     public static boolean isWhitespace( String str )
1873     {
1874         if ( str == null )
1875         {
1876             return false;
1877         }
1878         int sz = str.length();
1879         for ( int i = 0; i < sz; i++ )
1880         {
1881             if ( ( Character.isWhitespace( str.charAt( i ) ) == false ) )
1882             {
1883                 return false;
1884             }
1885         }
1886         return true;
1887     }
1888 
1889     /**
1890      * <p>
1891      * Checks if the String contains only unicode letters and space (<code>' '</code>).
1892      * </p>
1893      * <p>
1894      * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1895      * </p>
1896      *
1897      * @param str the String to check
1898      * @return <code>true</code> if only contains letters and space, and is non-null
1899      */
1900     public static boolean isAlphaSpace( String str )
1901     {
1902         if ( str == null )
1903         {
1904             return false;
1905         }
1906         int sz = str.length();
1907         for ( int i = 0; i < sz; i++ )
1908         {
1909             if ( ( Character.isLetter( str.charAt( i ) ) == false ) && ( str.charAt( i ) != ' ' ) )
1910             {
1911                 return false;
1912             }
1913         }
1914         return true;
1915     }
1916 
1917     /**
1918      * <p>
1919      * Checks if the String contains only unicode letters or digits.
1920      * </p>
1921      * <p>
1922      * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1923      * </p>
1924      *
1925      * @param str the String to check
1926      * @return <code>true</code> if only contains letters or digits, and is non-null
1927      */
1928     public static boolean isAlphanumeric( String str )
1929     {
1930         if ( str == null )
1931         {
1932             return false;
1933         }
1934         int sz = str.length();
1935         for ( int i = 0; i < sz; i++ )
1936         {
1937             if ( Character.isLetterOrDigit( str.charAt( i ) ) == false )
1938             {
1939                 return false;
1940             }
1941         }
1942         return true;
1943     }
1944 
1945     /**
1946      * <p>
1947      * Checks if the String contains only unicode letters, digits or space (<code>' '</code>).
1948      * </p>
1949      * <p>
1950      * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1951      * </p>
1952      *
1953      * @param str the String to check
1954      * @return <code>true</code> if only contains letters, digits or space, and is non-null
1955      */
1956     public static boolean isAlphanumericSpace( String str )
1957     {
1958         if ( str == null )
1959         {
1960             return false;
1961         }
1962         int sz = str.length();
1963         for ( int i = 0; i < sz; i++ )
1964         {
1965             if ( ( Character.isLetterOrDigit( str.charAt( i ) ) == false ) && ( str.charAt( i ) != ' ' ) )
1966             {
1967                 return false;
1968             }
1969         }
1970         return true;
1971     }
1972 
1973     /**
1974      * <p>
1975      * Checks if the String contains only unicode digits.
1976      * </p>
1977      * <p>
1978      * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1979      * </p>
1980      *
1981      * @param str the String to check
1982      * @return <code>true</code> if only contains digits, and is non-null
1983      */
1984     public static boolean isNumeric( String str )
1985     {
1986         if ( str == null )
1987         {
1988             return false;
1989         }
1990         int sz = str.length();
1991         for ( int i = 0; i < sz; i++ )
1992         {
1993             if ( Character.isDigit( str.charAt( i ) ) == false )
1994             {
1995                 return false;
1996             }
1997         }
1998         return true;
1999     }
2000 
2001     /**
2002      * <p>
2003      * Checks if the String contains only unicode digits or space (<code>' '</code>).
2004      * </p>
2005      * <p>
2006      * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
2007      * </p>
2008      *
2009      * @param str the String to check
2010      * @return <code>true</code> if only contains digits or space, and is non-null
2011      */
2012     public static boolean isNumericSpace( String str )
2013     {
2014         if ( str == null )
2015         {
2016             return false;
2017         }
2018         int sz = str.length();
2019         for ( int i = 0; i < sz; i++ )
2020         {
2021             if ( ( Character.isDigit( str.charAt( i ) ) == false ) && ( str.charAt( i ) != ' ' ) )
2022             {
2023                 return false;
2024             }
2025         }
2026         return true;
2027     }
2028 
2029     // Defaults
2030     // --------------------------------------------------------------------------
2031 
2032     /**
2033      * <p>
2034      * Returns either the passed in <code>Object</code> as a String, or, if the <code>Object</code> is
2035      * <code>null</code>, an empty String.
2036      * </p>
2037      *
2038      * @param obj the Object to check
2039      * @return the passed in Object's toString, or blank if it was <code>null</code>
2040      * @see Objects#toString(Object, String)
2041      */
2042     @Deprecated
2043     public static String defaultString( Object obj )
2044     {
2045         return defaultString( obj, "" );
2046     }
2047 
2048     /**
2049      * <p>
2050      * Returns either the passed in <code>Object</code> as a String, or, if the <code>Object</code> is
2051      * <code>null</code>, a passed in default String.
2052      * </p>
2053      *
2054      * @param obj the Object to check
2055      * @param defaultString the default String to return if str is <code>null</code>
2056      * @return the passed in string, or the default if it was <code>null</code>
2057      * @see Objects#toString(Object, String)
2058      */
2059     @Deprecated
2060     public static String defaultString( Object obj, String defaultString )
2061     {
2062         return Objects.toString( obj, defaultString );
2063     }
2064 
2065     // Reversing
2066     // --------------------------------------------------------------------------
2067 
2068     /**
2069      * <p>
2070      * Reverse a String.
2071      * </p>
2072      * <p>
2073      * <code>null</code> String returns <code>null</code>.
2074      * </p>
2075      *
2076      * @param str the String to reverse
2077      * @return the reversed String
2078      */
2079     public static String reverse( String str )
2080     {
2081         if ( str == null )
2082         {
2083             return null;
2084         }
2085         return new StringBuilder( str ).reverse().toString();
2086     }
2087 
2088     /**
2089      * <p>
2090      * Reverses a String that is delimited by a specific character.
2091      * </p>
2092      * <p>
2093      * The Strings between the delimiters are not reversed. Thus java.lang.String becomes String.lang.java (if the
2094      * delimiter is <code>'.'</code>).
2095      * </p>
2096      *
2097      * @param str the String to reverse
2098      * @param delimiter the delimiter to use
2099      * @return the reversed String
2100      */
2101     public static String reverseDelimitedString( String str, String delimiter )
2102     {
2103         // could implement manually, but simple way is to reuse other,
2104         // probably slower, methods.
2105         String[] strs = split( str, delimiter );
2106         reverseArray( strs );
2107         return join( strs, delimiter );
2108     }
2109 
2110     /**
2111      * <p>
2112      * Reverses an array.
2113      * </p>
2114      * <p>
2115      * TAKEN FROM CollectionsUtils.
2116      * </p>
2117      *
2118      * @param array the array to reverse
2119      */
2120     private static void reverseArray( Object[] array )
2121     {
2122         int i = 0;
2123         int j = array.length - 1;
2124         Object tmp;
2125 
2126         while ( j > i )
2127         {
2128             tmp = array[j];
2129             array[j] = array[i];
2130             array[i] = tmp;
2131             j--;
2132             i++;
2133         }
2134     }
2135 
2136     // Abbreviating
2137     // --------------------------------------------------------------------------
2138 
2139     /**
2140      * @return Turn "Now is the time for all good men" into "Now is the time for..."
2141      * <p>
2142      * Specifically:
2143      * <p>
2144      * If str is less than max characters long, return it. Else abbreviate it to (substring(str, 0, max-3) + "..."). If
2145      * maxWidth is less than 3, throw an IllegalArgumentException. In no case will it return a string of length greater
2146      * than maxWidth.
2147      * @param s string
2148      * @param maxWidth maximum length of result string
2149      **/
2150     public static String abbreviate( String s, int maxWidth )
2151     {
2152         return abbreviate( s, 0, maxWidth );
2153     }
2154 
2155     /**
2156      * @return Turn "Now is the time for all good men" into "...is the time for..."
2157      *
2158      * Works like abbreviate(String, int), but allows you to specify a "left edge" offset. Note that this left edge is
2159      * not necessarily going to be the leftmost character in the result, or the first character following the ellipses,
2160      * but it will appear somewhere in the result. In no case will it return a string of length greater than maxWidth.
2161      * @param s string
2162      * @param offset left edge of source string
2163      * @param maxWidth maximum length of result string
2164      **/
2165     public static String abbreviate( String s, int offset, int maxWidth )
2166     {
2167         if ( maxWidth < 4 )
2168         {
2169             throw new IllegalArgumentException( "Minimum abbreviation width is 4" );
2170         }
2171         if ( s.length() <= maxWidth )
2172         {
2173             return s;
2174         }
2175         if ( offset > s.length() )
2176         {
2177             offset = s.length();
2178         }
2179         if ( ( s.length() - offset ) < ( maxWidth - 3 ) )
2180         {
2181             offset = s.length() - ( maxWidth - 3 );
2182         }
2183         if ( offset <= 4 )
2184         {
2185             return s.substring( 0, maxWidth - 3 ) + "...";
2186         }
2187         if ( maxWidth < 7 )
2188         {
2189             throw new IllegalArgumentException( "Minimum abbreviation width with offset is 7" );
2190         }
2191         if ( ( offset + ( maxWidth - 3 ) ) < s.length() )
2192         {
2193             return "..." + abbreviate( s.substring( offset ), maxWidth - 3 );
2194         }
2195         return "..." + s.substring( s.length() - ( maxWidth - 3 ) );
2196     }
2197 
2198     // Difference
2199     // --------------------------------------------------------------------------
2200 
2201     /**
2202      * Compare two strings, and return the portion where they differ. (More precisely, return the remainder of the
2203      * second string, starting from where it's different from the first.)
2204      * <p>
2205      * E.g. strdiff("i am a machine", "i am a robot") -&gt; "robot"
2206      * @param s1 string
2207      * @param s2 string
2208      * @return the portion of s2 where it differs from s1; returns the empty string ("") if they are equal
2209      **/
2210     public static String difference( String s1, String s2 )
2211     {
2212         int at = differenceAt( s1, s2 );
2213         if ( at == -1 )
2214         {
2215             return "";
2216         }
2217         return s2.substring( at );
2218     }
2219 
2220     /**
2221      * Compare two strings, and return the index at which the strings begin to differ.
2222      * <p>
2223      * E.g. strdiff("i am a machine", "i am a robot") -&gt; 7
2224      * </p>
2225      * @param s1 string
2226      * @param s2 string
2227      * @return the index where s2 and s1 begin to differ; -1 if they are equal
2228      **/
2229     public static int differenceAt( String s1, String s2 )
2230     {
2231         int i;
2232         for ( i = 0; ( i < s1.length() ) && ( i < s2.length() ); ++i )
2233         {
2234             if ( s1.charAt( i ) != s2.charAt( i ) )
2235             {
2236                 break;
2237             }
2238         }
2239         if ( ( i < s2.length() ) || ( i < s1.length() ) )
2240         {
2241             return i;
2242         }
2243         return -1;
2244     }
2245 
2246     public static String interpolate( String text, Map<?, ?> namespace )
2247     {
2248         Iterator<?> keys = namespace.keySet().iterator();
2249 
2250         while ( keys.hasNext() )
2251         {
2252             String key = keys.next().toString();
2253 
2254             Object obj = namespace.get( key );
2255 
2256             if ( obj == null )
2257             {
2258                 throw new NullPointerException( "The value of the key '" + key + "' is null." );
2259             }
2260 
2261             String value = obj.toString();
2262 
2263             text = replace( text, "${" + key + "}", value );
2264 
2265             if ( !key.contains( " " ) )
2266             {
2267                 text = replace( text, "$" + key, value );
2268             }
2269         }
2270         return text;
2271     }
2272 
2273     public static String removeAndHump( String data, String replaceThis )
2274     {
2275         String temp;
2276 
2277         StringBuilder out = new StringBuilder();
2278 
2279         temp = data;
2280 
2281         StringTokenizer st = new StringTokenizer( temp, replaceThis );
2282 
2283         while ( st.hasMoreTokens() )
2284         {
2285             String element = (String) st.nextElement();
2286 
2287             out.append( capitalizeFirstLetter( element ) );
2288         }
2289 
2290         return out.toString();
2291     }
2292 
2293     public static String capitalizeFirstLetter( String data )
2294     {
2295         char firstLetter = Character.toTitleCase( data.substring( 0, 1 ).charAt( 0 ) );
2296 
2297         String restLetters = data.substring( 1 );
2298 
2299         return firstLetter + restLetters;
2300     }
2301 
2302     public static String lowercaseFirstLetter( String data )
2303     {
2304         char firstLetter = Character.toLowerCase( data.substring( 0, 1 ).charAt( 0 ) );
2305 
2306         String restLetters = data.substring( 1 );
2307 
2308         return firstLetter + restLetters;
2309     }
2310 
2311     public static String addAndDeHump( String view )
2312     {
2313         StringBuilder sb = new StringBuilder();
2314 
2315         for ( int i = 0; i < view.length(); i++ )
2316         {
2317             if ( ( i != 0 ) && Character.isUpperCase( view.charAt( i ) ) )
2318             {
2319                 sb.append( '-' );
2320             }
2321 
2322             sb.append( view.charAt( i ) );
2323         }
2324 
2325         return sb.toString().trim().toLowerCase( Locale.ENGLISH );
2326     }
2327 
2328     /**
2329      * <p>
2330      * Quote and escape a String with the given character, handling <code>null</code>.
2331      * </p>
2332      *
2333      * <pre>
2334      * StringUtils.quoteAndEscape(null, *)    = null
2335      * StringUtils.quoteAndEscape("", *)      = ""
2336      * StringUtils.quoteAndEscape("abc", '"') = abc
2337      * StringUtils.quoteAndEscape("a\"bc", '"') = "a\"bc"
2338      * StringUtils.quoteAndEscape("a\"bc", '\'') = 'a\"bc'
2339      * </pre>
2340      *
2341      * @param source the source String
2342      * @param quoteChar the char used to quote
2343      * @return the String quoted and escaped
2344      * @since 1.5.1
2345      * @see #quoteAndEscape(String, char, char[], char[], char, boolean)
2346      */
2347     public static String quoteAndEscape( String source, char quoteChar )
2348     {
2349         return quoteAndEscape( source, quoteChar, new char[] { quoteChar }, new char[] { ' ' }, '\\', false );
2350     }
2351 
2352     /**
2353      * <p>
2354      * Quote and escape a String with the given character, handling <code>null</code>.
2355      * </p>
2356      *
2357      * @param source the source String
2358      * @param quoteChar the char used to quote
2359      * @param quotingTriggers chars generating a quote
2360      * @return the String quoted and escaped
2361      * @since 1.5.1
2362      * @see #quoteAndEscape(String, char, char[], char[], char, boolean)
2363      */
2364     public static String quoteAndEscape( String source, char quoteChar, char[] quotingTriggers )
2365     {
2366         return quoteAndEscape( source, quoteChar, new char[] { quoteChar }, quotingTriggers, '\\', false );
2367     }
2368 
2369     /**
2370      * @param source the source String
2371      * @param quoteChar the char used to quote
2372      * @param escapedChars chars to escape
2373      * @param escapeChar char used for escaping
2374      * @param force force the quoting
2375      * @return the String quoted and escaped
2376      * @since 1.5.1
2377      * @see #quoteAndEscape(String, char, char[], char[], char, boolean)
2378      */
2379     public static String quoteAndEscape( String source, char quoteChar, final char[] escapedChars, char escapeChar,
2380                                          boolean force )
2381     {
2382         return quoteAndEscape( source, quoteChar, escapedChars, new char[] { ' ' }, escapeChar, force );
2383     }
2384 
2385     /**
2386      * @param source the source String
2387      * @param quoteChar the char used to quote
2388      * @param escapedChars chars to escape
2389      * @param quotingTriggers chars generating a quote
2390      * @param escapeChar char used for escaping
2391      * @param force force the quoting
2392      * @return the String quoted and escaped
2393      * @since 1.5.1
2394      */
2395     public static String quoteAndEscape( String source, char quoteChar, final char[] escapedChars,
2396                                          final char[] quotingTriggers, char escapeChar, boolean force )
2397     {
2398         return quoteAndEscape( source, quoteChar, escapedChars, quotingTriggers, escapeChar + "%s", force );
2399     }
2400 
2401     /**
2402      * @param source the source String
2403      * @param quoteChar the char used to quote
2404      * @param escapedChars chars to escape
2405      * @param quotingTriggers chars generating a quote
2406      * @param escapePattern pattern used for escaping
2407      * @param force force the quoting
2408      * @return the String quoted and escaped
2409      * @since 3.0.4
2410      */
2411     public static String quoteAndEscape( String source, char quoteChar, final char[] escapedChars,
2412                                          final char[] quotingTriggers, String escapePattern, boolean force )
2413     {
2414         if ( source == null )
2415         {
2416             return null;
2417         }
2418 
2419         if ( !force && source.startsWith( Character.toString( quoteChar ) )
2420             && source.endsWith( Character.toString( quoteChar ) ) )
2421         {
2422             return source;
2423         }
2424 
2425         String escaped = escape( source, escapedChars, escapePattern );
2426 
2427         boolean quote = false;
2428         if ( force )
2429         {
2430             quote = true;
2431         }
2432         else if ( !escaped.equals( source ) )
2433         {
2434             quote = true;
2435         }
2436         else
2437         {
2438             for ( char quotingTrigger : quotingTriggers )
2439             {
2440                 if ( escaped.indexOf( quotingTrigger ) > -1 )
2441                 {
2442                     quote = true;
2443                     break;
2444                 }
2445             }
2446         }
2447 
2448         if ( quote )
2449         {
2450             return quoteChar + escaped + quoteChar;
2451         }
2452 
2453         return escaped;
2454     }
2455 
2456     /**
2457      * @param source the source String
2458      * @param escapedChars chars to escape
2459      * @param escapeChar char used for escaping
2460      * @return the String escaped
2461      * @since 1.5.1
2462      */
2463     public static String escape( String source, final char[] escapedChars, char escapeChar )
2464     {
2465         return escape( source, escapedChars, escapeChar + "%s" );
2466     }
2467 
2468     /**
2469      * @param source the source String
2470      * @param escapedChars chars to escape
2471      * @param escapePattern pattern used for escaping
2472      * @return the String escaped
2473      * @since 3.0.4
2474      */
2475     public static String escape( String source, final char[] escapedChars, String escapePattern )
2476     {
2477         if ( source == null )
2478         {
2479             return null;
2480         }
2481 
2482         char[] eqc = new char[escapedChars.length];
2483         System.arraycopy( escapedChars, 0, eqc, 0, escapedChars.length );
2484         Arrays.sort( eqc );
2485 
2486         StringBuilder buffer = new StringBuilder( source.length() );
2487 
2488         for ( int i = 0; i < source.length(); i++ )
2489         {
2490             final char c = source.charAt( i );
2491             int result = Arrays.binarySearch( eqc, c );
2492 
2493             if ( result > -1 )
2494             {
2495                 buffer.append( String.format( escapePattern, c ) );
2496             }
2497             else
2498             {
2499                 buffer.append( c );
2500             }
2501         }
2502 
2503         return buffer.toString();
2504     }
2505 
2506     /**
2507      * Remove all duplicate whitespace characters and line terminators are replaced with a single space.
2508      *
2509      * @param s a not null String
2510      * @return a string with unique whitespace.
2511      * @since 1.5.7
2512      */
2513     public static String removeDuplicateWhitespace( String s )
2514     {
2515         StringBuilder result = new StringBuilder();
2516         int length = s.length();
2517         boolean isPreviousWhiteSpace = false;
2518         for ( int i = 0; i < length; i++ )
2519         {
2520             char c = s.charAt( i );
2521             boolean thisCharWhiteSpace = Character.isWhitespace( c );
2522             if ( !( isPreviousWhiteSpace && thisCharWhiteSpace ) )
2523             {
2524                 result.append( c );
2525             }
2526             isPreviousWhiteSpace = thisCharWhiteSpace;
2527         }
2528         return result.toString();
2529     }
2530 
2531     /**
2532      * Parses the given String and replaces all occurrences of '\n', '\r' and '\r\n' with the system line separator.
2533      *
2534      * @param s a not null String
2535      * @return a String that contains only System line separators.
2536      * @see #unifyLineSeparators(String, String)
2537      * @since 1.5.7
2538      */
2539     public static String unifyLineSeparators( String s )
2540     {
2541         return unifyLineSeparators( s, System.getProperty( "line.separator" ) );
2542     }
2543 
2544     /**
2545      * Parses the given String and replaces all occurrences of '\n', '\r' and '\r\n' with the system line separator.
2546      *
2547      * @param s a not null String
2548      * @param ls the wanted line separator ("\n" on UNIX), if null using the System line separator.
2549      * @return a String that contains only System line separators.
2550      * @throws IllegalArgumentException if ls is not '\n', '\r' and '\r\n' characters.
2551      * @since 1.5.7
2552      */
2553     public static String unifyLineSeparators( String s, String ls )
2554     {
2555         if ( s == null )
2556         {
2557             return null;
2558         }
2559 
2560         if ( ls == null )
2561         {
2562             ls = System.getProperty( "line.separator" );
2563         }
2564 
2565         if ( !( ls.equals( "\n" ) || ls.equals( "\r" ) || ls.equals( "\r\n" ) ) )
2566         {
2567             throw new IllegalArgumentException( "Requested line separator is invalid." );
2568         }
2569 
2570         int length = s.length();
2571 
2572         StringBuilder buffer = new StringBuilder( length );
2573         for ( int i = 0; i < length; i++ )
2574         {
2575             if ( s.charAt( i ) == '\r' )
2576             {
2577                 if ( ( i + 1 ) < length && s.charAt( i + 1 ) == '\n' )
2578                 {
2579                     i++;
2580                 }
2581 
2582                 buffer.append( ls );
2583             }
2584             else if ( s.charAt( i ) == '\n' )
2585             {
2586                 buffer.append( ls );
2587             }
2588             else
2589             {
2590                 buffer.append( s.charAt( i ) );
2591             }
2592         }
2593 
2594         return buffer.toString();
2595     }
2596 
2597     /**
2598      * <p>
2599      * Checks if String contains a search character, handling <code>null</code>. This method uses
2600      * {@link String#indexOf(int)}.
2601      * </p>
2602      * <p>
2603      * A <code>null</code> or empty ("") String will return <code>false</code>.
2604      * </p>
2605      *
2606      * <pre>
2607      * StringUtils.contains(null, *)    = false
2608      * StringUtils.contains("", *)      = false
2609      * StringUtils.contains("abc", 'a') = true
2610      * StringUtils.contains("abc", 'z') = false
2611      * </pre>
2612      *
2613      * @param str the String to check, may be null
2614      * @param searchChar the character to find
2615      * @return true if the String contains the search character, false if not or <code>null</code> string input
2616      * @since 1.5.7
2617      */
2618     public static boolean contains( String str, char searchChar )
2619     {
2620         if ( isEmpty( str ) )
2621         {
2622             return false;
2623         }
2624         return str.indexOf( searchChar ) >= 0;
2625     }
2626 
2627     /**
2628      * <p>
2629      * Checks if String contains a search String, handling <code>null</code>. This method uses
2630      * {@link String#indexOf(int)}.
2631      * </p>
2632      * <p>
2633      * A <code>null</code> String will return <code>false</code>.
2634      * </p>
2635      *
2636      * <pre>
2637      * StringUtils.contains(null, *)     = false
2638      * StringUtils.contains(*, null)     = false
2639      * StringUtils.contains("", "")      = true
2640      * StringUtils.contains("abc", "")   = true
2641      * StringUtils.contains("abc", "a")  = true
2642      * StringUtils.contains("abc", "z")  = false
2643      * </pre>
2644      *
2645      * @param str the String to check, may be null
2646      * @param searchStr the String to find, may be null
2647      * @return true if the String contains the search String, false if not or <code>null</code> string input
2648      * @since 1.5.7
2649      */
2650     public static boolean contains( String str, String searchStr )
2651     {
2652         if ( str == null || searchStr == null )
2653         {
2654             return false;
2655         }
2656         return str.contains( searchStr );
2657     }
2658 }