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