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