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 acknowlegement:
21   *       "This product includes software developed by the
22   *        Apache Software Foundation (http://www.apache.org/)."
23   *    Alternately, this acknowlegement may appear in the software itself,
24   *    if and wherever such third-party acknowlegements 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 apache@apache.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.apache.org/>.
53   */
54  package org.apache.maven.it.util;
55  
56  import java.util.Iterator;
57  import java.util.Map;
58  import java.util.StringTokenizer;
59  
60  /**
61   * <p>Common <code>String</code> manipulation routines.</p>
62   *
63   * <p>Originally from
64   * <a href="http://jakarta.apache.org/turbine/">Turbine</a> and the
65   * GenerationJavaCore library.</p>
66   *
67   * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
68   * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
69   * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
70   * @author <a href="mailto:bayard@generationjava.com">Henri Yandell</a>
71   * @author <a href="mailto:ed@apache.org">Ed Korthof</a>
72   * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
73   * @author Stephen Colebourne
74   * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
75   * @author Holger Krauth
76   * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
77   * @since 1.0
78   * @version $Id: StringUtils.java 661727 2008-05-30 14:21:49Z bentmann $
79   */
80  public class StringUtils
81  {
82  
83      /**
84       * <p><code>StringUtils</code> instances should NOT be constructed in
85       * standard programming. Instead, the class should be used as
86       * <code>StringUtils.trim(" foo ");</code>.</p>
87       *
88       * <p>This constructor is public to permit tools that require a JavaBean
89       * manager to operate.</p>
90       */
91      public StringUtils()
92      {
93      }
94  
95      // Empty
96      //--------------------------------------------------------------------------
97  
98      /**
99       * <p>Removes control characters, including whitespace, from both
100      * ends of this String, handling <code>null</code> by returning
101      * an empty String.</p>
102      *
103      * @see java.lang.String#trim()
104      * @param str the String to check
105      * @return the trimmed text (never <code>null</code>)
106      */
107     public static String clean( String str )
108     {
109         return ( str == null ? "" : str.trim() );
110     }
111 
112     /**
113      * <p>Removes control characters, including whitespace, from both
114      * ends of this String, handling <code>null</code> by returning
115      * <code>null</code>.</p>
116      *
117      * @see java.lang.String#trim()
118      * @param str the String to check
119      * @return the trimmed text (or <code>null</code>)
120      */
121     public static String trim( String str )
122     {
123         return ( str == null ? null : str.trim() );
124     }
125 
126     /**
127      * <p>Deletes all whitespaces from a String.</p>
128      *
129      * <p>Whitespace is defined by
130      * {@link Character#isWhitespace(char)}.</p>
131      *
132      * @param str String target to delete whitespace from
133      * @return the String without whitespaces
134      * @throws NullPointerException
135      */
136     public static String deleteWhitespace( String str )
137     {
138         StringBuffer buffer = new StringBuffer();
139         int sz = str.length();
140         for ( int i = 0; i < sz; i++ )
141         {
142             if ( !Character.isWhitespace( str.charAt( i ) ) )
143             {
144                 buffer.append( str.charAt( i ) );
145             }
146         }
147         return buffer.toString();
148     }
149 
150     /**
151      * <p>Checks if a String is non <code>null</code> and is
152      * not empty (<code>length > 0</code>).</p>
153      *
154      * @param str the String to check
155      * @return true if the String is non-null, and not length zero
156      */
157     public static boolean isNotEmpty( String str )
158     {
159         return ( str != null && str.length() > 0 );
160     }
161 
162     /**
163      * <p>Checks if a (trimmed) String is <code>null</code> or empty.</p>
164      *
165      * @param str the String to check
166      * @return <code>true</code> if the String is <code>null</code>, or
167      *  length zero once trimmed
168      */
169     public static boolean isEmpty( String str )
170     {
171         return ( str == null || str.trim().length() == 0 );
172     }
173 
174     // Equals and IndexOf
175     //--------------------------------------------------------------------------
176 
177     /**
178      * <p>Compares two Strings, returning <code>true</code> if they are equal.</p>
179      *
180      * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
181      * references are considered to be equal. The comparison is case sensitive.</p>
182      *
183      * @see java.lang.String#equals(Object)
184      * @param str1 the first string
185      * @param str2 the second string
186      * @return <code>true</code> if the Strings are equal, case sensitive, or
187      *  both <code>null</code>
188      */
189     public static boolean equals( String str1, String str2 )
190     {
191         return ( str1 == null ? str2 == null : str1.equals( str2 ) );
192     }
193 
194     /**
195      * <p>Compares two Strings, returning <code>true</code> if they are equal ignoring
196      * the case.</p>
197      *
198      * <p><code>Nulls</code> are handled without exceptions. Two <code>null</code>
199      * references are considered equal. Comparison is case insensitive.</p>
200      *
201      * @see java.lang.String#equalsIgnoreCase(String)
202      * @param str1  the first string
203      * @param str2  the second string
204      * @return <code>true</code> if the Strings are equal, case insensitive, or
205      *  both <code>null</code>
206      */
207     public static boolean equalsIgnoreCase( String str1, String str2 )
208     {
209         return ( str1 == null ? str2 == null : str1.equalsIgnoreCase( str2 ) );
210     }
211 
212     /**
213      * <p>Find the first index of any of a set of potential substrings.</p>
214      *
215      * <p><code>null</code> String will return <code>-1</code>.</p>
216      *
217      * @param str the String to check
218      * @param searchStrs the Strings to search for
219      * @return the first index of any of the searchStrs in str
220      * @throws NullPointerException if any of searchStrs[i] is <code>null</code>
221      */
222     public static int indexOfAny( String str, String[] searchStrs )
223     {
224         if ( ( str == null ) || ( searchStrs == null ) )
225         {
226             return -1;
227         }
228         int sz = searchStrs.length;
229 
230         // String's can't have a MAX_VALUEth index.
231         int ret = Integer.MAX_VALUE;
232 
233         int tmp = 0;
234         for ( int i = 0; i < sz; i++ )
235         {
236             tmp = str.indexOf( searchStrs[i] );
237             if ( tmp == -1 )
238             {
239                 continue;
240             }
241 
242             if ( tmp < ret )
243             {
244                 ret = tmp;
245             }
246         }
247 
248         return ( ret == Integer.MAX_VALUE ) ? -1 : ret;
249     }
250 
251     /**
252      * <p>Find the latest index of any of a set of potential substrings.</p>
253      *
254      * <p><code>null</code> string will return <code>-1</code>.</p>
255      *
256      * @param str  the String to check
257      * @param searchStrs  the Strings to search for
258      * @return the last index of any of the Strings
259      * @throws NullPointerException if any of searchStrs[i] is <code>null</code>
260      */
261     public static int lastIndexOfAny( String str, String[] searchStrs )
262     {
263         if ( ( str == null ) || ( searchStrs == null ) )
264         {
265             return -1;
266         }
267         int sz = searchStrs.length;
268         int ret = -1;
269         int tmp = 0;
270         for ( int i = 0; i < sz; i++ )
271         {
272             tmp = str.lastIndexOf( searchStrs[i] );
273             if ( tmp > ret )
274             {
275                 ret = tmp;
276             }
277         }
278         return ret;
279     }
280 
281     // Substring
282     //--------------------------------------------------------------------------
283 
284     /**
285      * <p>Gets a substring from the specified string avoiding exceptions.</p>
286      *
287      * <p>A negative start position can be used to start <code>n</code>
288      * characters from the end of the String.</p>
289      *
290      * @param str the String to get the substring from
291      * @param start the position to start from, negative means
292      *  count back from the end of the String by this many characters
293      * @return substring from start position
294      */
295     public static String substring( String str, int start )
296     {
297         if ( str == null )
298         {
299             return null;
300         }
301 
302         // handle negatives, which means last n characters
303         if ( start < 0 )
304         {
305             start = str.length() + start; // remember start is negative
306         }
307 
308         if ( start < 0 )
309         {
310             start = 0;
311         }
312         if ( start > str.length() )
313         {
314             return "";
315         }
316 
317         return str.substring( start );
318     }
319 
320     /**
321      * <p>Gets a substring from the specified String avoiding exceptions.</p>
322      *
323      * <p>A negative start position can be used to start/end <code>n</code>
324      * characters from the end of the String.</p>
325      *
326      * @param str the String to get the substring from
327      * @param start the position to start from, negative means
328      *  count back from the end of the string by this many characters
329      * @param end the position to end at (exclusive), negative means
330      *  count back from the end of the String by this many characters
331      * @return substring from start position to end positon
332      */
333     public static String substring( String str, int start, int end )
334     {
335         if ( str == null )
336         {
337             return null;
338         }
339 
340         // handle negatives
341         if ( end < 0 )
342         {
343             end = str.length() + end; // remember end is negative
344         }
345         if ( start < 0 )
346         {
347             start = str.length() + start; // remember start is negative
348         }
349 
350         // check length next
351         if ( end > str.length() )
352         {
353             // check this works.
354             end = str.length();
355         }
356 
357         // if start is greater than end, return ""
358         if ( start > end )
359         {
360             return "";
361         }
362 
363         if ( start < 0 )
364         {
365             start = 0;
366         }
367         if ( end < 0 )
368         {
369             end = 0;
370         }
371 
372         return str.substring( start, end );
373     }
374 
375     /**
376      * <p>Gets the leftmost <code>n</code> characters of a String.</p>
377      *
378      * <p>If <code>n</code> characters are not available, or the
379      * String is <code>null</code>, the String will be returned without
380      * an exception.</p>
381      *
382      * @param str the String to get the leftmost characters from
383      * @param len the length of the required String
384      * @return the leftmost characters
385      * @throws IllegalArgumentException if len is less than zero
386      */
387     public static String left( String str, int len )
388     {
389         if ( len < 0 )
390         {
391             throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
392         }
393         if ( ( str == null ) || ( str.length() <= len ) )
394         {
395             return str;
396         }
397         else
398         {
399             return str.substring( 0, len );
400         }
401     }
402 
403     /**
404      * <p>Gets the rightmost <code>n</code> characters of a String.</p>
405      *
406      * <p>If <code>n</code> characters are not available, or the String
407      * is <code>null</code>, the String will be returned without an
408      * exception.</p>
409      *
410      * @param str the String to get the rightmost characters from
411      * @param len the length of the required String
412      * @return the leftmost characters
413      * @throws IllegalArgumentException if len is less than zero
414      */
415     public static String right( String str, int len )
416     {
417         if ( len < 0 )
418         {
419             throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
420         }
421         if ( ( str == null ) || ( str.length() <= len ) )
422         {
423             return str;
424         }
425         else
426         {
427             return str.substring( str.length() - len );
428         }
429     }
430 
431     /**
432      * <p>Gets <code>n</code> characters from the middle of a String.</p>
433      *
434      * <p>If <code>n</code> characters are not available, the remainder
435      * of the String will be returned without an exception. If the
436      * String is <code>null</code>, <code>null</code> will be returned.</p>
437      *
438      * @param str the String to get the characters from
439      * @param pos the position to start from
440      * @param len the length of the required String
441      * @return the leftmost characters
442      * @throws IndexOutOfBoundsException if pos is out of bounds
443      * @throws IllegalArgumentException if len is less than zero
444      */
445     public static String mid( String str, int pos, int len )
446     {
447         if ( ( pos < 0 ) ||
448             ( str != null && pos > str.length() ) )
449         {
450             throw new StringIndexOutOfBoundsException( "String index " + pos + " is out of bounds" );
451         }
452         if ( len < 0 )
453         {
454             throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
455         }
456         if ( str == null )
457         {
458             return null;
459         }
460         if ( str.length() <= ( pos + len ) )
461         {
462             return str.substring( pos );
463         }
464         else
465         {
466             return str.substring( pos, pos + len );
467         }
468     }
469 
470     // Splitting
471     //--------------------------------------------------------------------------
472 
473     /**
474      * <p>Splits the provided text into a array, using whitespace as the
475      * separator.</p>
476      *
477      * <p>The separator is not included in the returned String array.</p>
478      *
479      * @param str the String to parse
480      * @return an array of parsed Strings
481      */
482     public static String[] split( String str )
483     {
484         return split( str, null, -1 );
485     }
486 
487     /**
488      * @see #split(String, String, int)
489      */
490     public static String[] split( String text, String separator )
491     {
492         return split( text, separator, -1 );
493     }
494 
495     /**
496      * <p>Splits the provided text into a array, based on a given separator.</p>
497      *
498      * <p>The separator is not included in the returned String array. The
499      * maximum number of splits to perfom can be controlled. A <code>null</code>
500      * separator will cause parsing to be on whitespace.</p>
501      *
502      * <p>This is useful for quickly splitting a String directly into
503      * an array of tokens, instead of an enumeration of tokens (as
504      * <code>StringTokenizer</code> does).</p>
505      *
506      * @param str The string to parse.
507      * @param separator Characters used as the delimiters. If
508      *  <code>null</code>, splits on whitespace.
509      * @param max The maximum number of elements to include in the
510      *  array.  A zero or negative value implies no limit.
511      * @return an array of parsed Strings
512      */
513     public static String[] split( String str, String separator, int max )
514     {
515         StringTokenizer tok = null;
516         if ( separator == null )
517         {
518             // Null separator means we're using StringTokenizer's default
519             // delimiter, which comprises all whitespace characters.
520             tok = new StringTokenizer( str );
521         }
522         else
523         {
524             tok = new StringTokenizer( str, separator );
525         }
526 
527         int listSize = tok.countTokens();
528         if ( max > 0 && listSize > max )
529         {
530             listSize = max;
531         }
532 
533         String[] list = new String[listSize];
534         int i = 0;
535         int lastTokenBegin = 0;
536         int lastTokenEnd = 0;
537         while ( tok.hasMoreTokens() )
538         {
539             if ( max > 0 && i == listSize - 1 )
540             {
541                 // In the situation where we hit the max yet have
542                 // tokens left over in our input, the last list
543                 // element gets all remaining text.
544                 String endToken = tok.nextToken();
545                 lastTokenBegin = str.indexOf( endToken, lastTokenEnd );
546                 list[i] = str.substring( lastTokenBegin );
547                 break;
548             }
549             else
550             {
551                 list[i] = tok.nextToken();
552                 lastTokenBegin = str.indexOf( list[i], lastTokenEnd );
553                 lastTokenEnd = lastTokenBegin + list[i].length();
554             }
555             i++;
556         }
557         return list;
558     }
559 
560     // Joining
561     //--------------------------------------------------------------------------
562     /**
563      * <p>Concatenates elements of an array into a single String.</p>
564      *
565      * <p>The difference from join is that concatenate has no delimiter.</p>
566      *
567      * @param array the array of values to concatenate.
568      * @return the concatenated string.
569      */
570     public static String concatenate( Object[] array )
571     {
572         return join( array, "" );
573     }
574 
575     /**
576      * <p>Joins the elements of the provided array into a single String
577      * containing the provided list of elements.</p>
578      *
579      * <p>No delimiter is added before or after the list. A
580      * <code>null</code> separator is the same as a blank String.</p>
581      *
582      * @param array the array of values to join together
583      * @param separator the separator character to use
584      * @return the joined String
585      */
586     public static String join( Object[] array, String separator )
587     {
588         if ( separator == null )
589         {
590             separator = "";
591         }
592         int arraySize = array.length;
593         int bufSize = ( arraySize == 0 ? 0 : ( array[0].toString().length() +
594             separator.length() ) * arraySize );
595         StringBuffer buf = new StringBuffer( bufSize );
596 
597         for ( int i = 0; i < arraySize; i++ )
598         {
599             if ( i > 0 )
600             {
601                 buf.append( separator );
602             }
603             buf.append( array[i] );
604         }
605         return buf.toString();
606     }
607 
608     /**
609      * <p>Joins the elements of the provided <code>Iterator</code> into
610      * a single String containing the provided elements.</p>
611      *
612      * <p>No delimiter is added before or after the list. A
613      * <code>null</code> separator is the same as a blank String.</p>
614      *
615      * @param iterator the <code>Iterator</code> of values to join together
616      * @param separator  the separator character to use
617      * @return the joined String
618      */
619     public static String join( Iterator iterator, String separator )
620     {
621         if ( separator == null )
622         {
623             separator = "";
624         }
625         StringBuffer buf = new StringBuffer( 256 );  // Java default is 16, probably too small
626         while ( iterator.hasNext() )
627         {
628             buf.append( iterator.next() );
629             if ( iterator.hasNext() )
630             {
631                 buf.append( separator );
632             }
633         }
634         return buf.toString();
635     }
636 
637 
638 
639     // Replacing
640     //--------------------------------------------------------------------------
641 
642     /**
643      * <p>Replace a char with another char inside a larger String, once.</p>
644      *
645      * <p>A <code>null</code> reference passed to this method is a no-op.</p>
646      *
647      * @see #replace(String text, char repl, char with, int max)
648      * @param text text to search and replace in
649      * @param repl char to search for
650      * @param with char to replace with
651      * @return the text with any replacements processed
652      */
653     public static String replaceOnce( String text, char repl, char with )
654     {
655         return replace( text, repl, with, 1 );
656     }
657 
658     /**
659      * <p>Replace all occurances of a char within another char.</p>
660      *
661      * <p>A <code>null</code> reference passed to this method is a no-op.</p>
662      *
663      * @see #replace(String text, char repl, char with, int max)
664      * @param text text to search and replace in
665      * @param repl char to search for
666      * @param with char to replace with
667      * @return the text with any replacements processed
668      */
669     public static String replace( String text, char repl, char with )
670     {
671         return replace( text, repl, with, -1 );
672     }
673 
674     /**
675      * <p>Replace a char with another char inside a larger String,
676      * for the first <code>max</code> values of the search char.</p>
677      *
678      * <p>A <code>null</code> reference passed to this method is a no-op.</p>
679      *
680      * @param text text to search and replace in
681      * @param repl char to search for
682      * @param with char to replace with
683      * @param max maximum number of values to replace, or <code>-1</code> if no maximum
684      * @return the text with any replacements processed
685      */
686     public static String replace( String text, char repl, char with, int max )
687     {
688         return replace( text, String.valueOf( repl ), String.valueOf( with ), max );
689     }
690 
691     /**
692      * <p>Replace a String with another String inside a larger String, once.</p>
693      *
694      * <p>A <code>null</code> reference passed to this method is a no-op.</p>
695      *
696      * @see #replace(String text, String repl, String with, int max)
697      * @param text text to search and replace in
698      * @param repl String to search for
699      * @param with String to replace with
700      * @return the text with any replacements processed
701      */
702     public static String replaceOnce( String text, String repl, String with )
703     {
704         return replace( text, repl, with, 1 );
705     }
706 
707     /**
708      * <p>Replace all occurances of a String within another String.</p>
709      *
710      * <p>A <code>null</code> reference passed to this method is a no-op.</p>
711      *
712      * @see #replace(String text, String repl, String with, int max)
713      * @param text text to search and replace in
714      * @param repl String to search for
715      * @param with String to replace with
716      * @return the text with any replacements processed
717      */
718     public static String replace( String text, String repl, String with )
719     {
720         return replace( text, repl, with, -1 );
721     }
722 
723     /**
724      * <p>Replace a String with another String inside a larger String,
725      * for the first <code>max</code> values of the search String.</p>
726      *
727      * <p>A <code>null</code> reference passed to this method is a no-op.</p>
728      *
729      * @param text text to search and replace in
730      * @param repl String to search for
731      * @param with String to replace with
732      * @param max maximum number of values to replace, or <code>-1</code> if no maximum
733      * @return the text with any replacements processed
734      */
735     public static String replace( String text, String repl, String with, int max )
736     {
737         if ( text == null || repl == null || with == null || repl.length() == 0 )
738         {
739             return text;
740         }
741 
742         StringBuffer buf = new StringBuffer( text.length() );
743         int start = 0, end = 0;
744         while ( ( end = text.indexOf( repl, start ) ) != -1 )
745         {
746             buf.append( text.substring( start, end ) ).append( with );
747             start = end + repl.length();
748 
749             if ( --max == 0 )
750             {
751                 break;
752             }
753         }
754         buf.append( text.substring( start ) );
755         return buf.toString();
756     }
757 
758     /**
759      * <p>Overlay a part of a String with another String.</p>
760      *
761      * @param text String to do overlaying in
762      * @param overlay String to overlay
763      * @param start int to start overlaying at
764      * @param end int to stop overlaying before
765      * @return String with overlayed text
766      * @throws NullPointerException if text or overlay is <code>null</code>
767      */
768     public static String overlayString( String text, String overlay, int start, int end )
769     {
770         return new StringBuffer( start + overlay.length() + text.length() - end + 1 )
771             .append( text.substring( 0, start ) )
772             .append( overlay )
773             .append( text.substring( end ) )
774             .toString();
775     }
776 
777     // Centering
778     //--------------------------------------------------------------------------
779 
780     /**
781      * <p>Center a String in a larger String of size <code>n</code>.<p>
782      *
783      * <p>Uses spaces as the value to buffer the String with.
784      * Equivalent to <code>center(str, size, " ")</code>.</p>
785      *
786      * @param str String to center
787      * @param size int size of new String
788      * @return String containing centered String
789      * @throws NullPointerException if str is <code>null</code>
790      */
791     public static String center( String str, int size )
792     {
793         return center( str, size, " " );
794     }
795 
796     /**
797      * <p>Center a String in a larger String of size <code>n</code>.</p>
798      *
799      * <p>Uses a supplied String as the value to buffer the String with.</p>
800      *
801      * @param str String to center
802      * @param size int size of new String
803      * @param delim String to buffer the new String with
804      * @return String containing centered String
805      * @throws NullPointerException if str or delim is <code>null</code>
806      * @throws ArithmeticException if delim is the empty String
807      */
808     public static String center( String str, int size, String delim )
809     {
810         int sz = str.length();
811         int p = size - sz;
812         if ( p < 1 )
813         {
814             return str;
815         }
816         str = leftPad( str, sz + p / 2, delim );
817         str = rightPad( str, size, delim );
818         return str;
819     }
820 
821     // Chomping
822     //--------------------------------------------------------------------------
823 
824     /**
825      * <p>Remove the last newline, and everything after it from a String.</p>
826      *
827      * @param str String to chomp the newline from
828      * @return String without chomped newline
829      * @throws NullPointerException if str is <code>null</code>
830      */
831     public static String chomp( String str )
832     {
833         return chomp( str, "\n" );
834     }
835 
836     /**
837      * <p>Remove the last value of a supplied String, and everything after
838      * it from a String.</p>
839      *
840      * @param str String to chomp from
841      * @param sep String to chomp
842      * @return String without chomped ending
843      * @throws NullPointerException if str or sep is <code>null</code>
844      */
845     public static String chomp( String str, String sep )
846     {
847         int idx = str.lastIndexOf( sep );
848         if ( idx != -1 )
849         {
850             return str.substring( 0, idx );
851         }
852         else
853         {
854             return str;
855         }
856     }
857 
858     /**
859      * <p>Remove a newline if and only if it is at the end
860      * of the supplied String.</p>
861      *
862      * @param str String to chomp from
863      * @return String without chomped ending
864      * @throws NullPointerException if str is <code>null</code>
865      */
866     public static String chompLast( String str )
867     {
868         return chompLast( str, "\n" );
869     }
870 
871     /**
872      * <p>Remove a value if and only if the String ends with that value.</p>
873      *
874      * @param str String to chomp from
875      * @param sep String to chomp
876      * @return String without chomped ending
877      * @throws NullPointerException if str or sep is <code>null</code>
878      */
879     public static String chompLast( String str, String sep )
880     {
881         if ( str.length() == 0 )
882         {
883             return str;
884         }
885         String sub = str.substring( str.length() - sep.length() );
886         if ( sep.equals( sub ) )
887         {
888             return str.substring( 0, str.length() - sep.length() );
889         }
890         else
891         {
892             return str;
893         }
894     }
895 
896     /**
897      * <p>Remove everything and return the last value of a supplied String, and
898      * everything after it from a String.</p>
899      *
900      * @param str String to chomp from
901      * @param sep String to chomp
902      * @return String chomped
903      * @throws NullPointerException if str or sep is <code>null</code>
904      */
905     public static String getChomp( String str, String sep )
906     {
907         int idx = str.lastIndexOf( sep );
908         if ( idx == str.length() - sep.length() )
909         {
910             return sep;
911         }
912         else if ( idx != -1 )
913         {
914             return str.substring( idx );
915         }
916         else
917         {
918             return "";
919         }
920     }
921 
922     /**
923      * <p>Remove the first value of a supplied String, and everything before it
924      * from a String.</p>
925      *
926      * @param str String to chomp from
927      * @param sep String to chomp
928      * @return String without chomped beginning
929      * @throws NullPointerException if str or sep is <code>null</code>
930      */
931     public static String prechomp( String str, String sep )
932     {
933         int idx = str.indexOf( sep );
934         if ( idx != -1 )
935         {
936             return str.substring( idx + sep.length() );
937         }
938         else
939         {
940             return str;
941         }
942     }
943 
944     /**
945      * <p>Remove and return everything before the first value of a
946      * supplied String from another String.</p>
947      *
948      * @param str String to chomp from
949      * @param sep String to chomp
950      * @return String prechomped
951      * @throws NullPointerException if str or sep is <code>null</code>
952      */
953     public static String getPrechomp( String str, String sep )
954     {
955         int idx = str.indexOf( sep );
956         if ( idx != -1 )
957         {
958             return str.substring( 0, idx + sep.length() );
959         }
960         else
961         {
962             return "";
963         }
964     }
965 
966     // Chopping
967     //--------------------------------------------------------------------------
968 
969     /**
970      * <p>Remove the last character from a String.</p>
971      *
972      * <p>If the String ends in <code>\r\n</code>, then remove both
973      * of them.</p>
974      *
975      * @param str String to chop last character from
976      * @return String without last character
977      * @throws NullPointerException if str is <code>null</code>
978      */
979     public static String chop( String str )
980     {
981         if ( "".equals( str ) )
982         {
983             return "";
984         }
985         if ( str.length() == 1 )
986         {
987             return "";
988         }
989         int lastIdx = str.length() - 1;
990         String ret = str.substring( 0, lastIdx );
991         char last = str.charAt( lastIdx );
992         if ( last == '\n' )
993         {
994             if ( ret.charAt( lastIdx - 1 ) == '\r' )
995             {
996                 return ret.substring( 0, lastIdx - 1 );
997             }
998         }
999         return ret;
1000     }
1001 
1002     /**
1003      * <p>Remove <code>\n</code> from end of a String if it's there.
1004      * If a <code>\r</code> precedes it, then remove that too.</p>
1005      *
1006      * @param str String to chop a newline from
1007      * @return String without newline
1008      * @throws NullPointerException if str is <code>null</code>
1009      */
1010     public static String chopNewline( String str )
1011     {
1012         int lastIdx = str.length() - 1;
1013         char last = str.charAt( lastIdx );
1014         if ( last == '\n' )
1015         {
1016             if ( str.charAt( lastIdx - 1 ) == '\r' )
1017             {
1018                 lastIdx--;
1019             }
1020         }
1021         else
1022         {
1023             lastIdx++;
1024         }
1025         return str.substring( 0, lastIdx );
1026     }
1027 
1028 
1029     // Conversion
1030     //--------------------------------------------------------------------------
1031 
1032     // spec 3.10.6
1033     /**
1034      * <p>Escapes any values it finds into their String form.</p>
1035      *
1036      * <p>So a tab becomes the characters <code>'\\'</code> and
1037      * <code>'t'</code>.</p>
1038      *
1039      * @param str String to escape values in
1040      * @return String with escaped values
1041      * @throws NullPointerException if str is <code>null</code>
1042      */
1043     public static String escape( String str )
1044     {
1045         // improved with code from  cybertiger@cyberiantiger.org
1046         // unicode from him, and defaul for < 32's.
1047         int sz = str.length();
1048         StringBuffer buffer = new StringBuffer( 2 * sz );
1049         for ( int i = 0; i < sz; i++ )
1050         {
1051             char ch = str.charAt( i );
1052 
1053             // handle unicode
1054             if ( ch > 0xfff )
1055             {
1056                 buffer.append( "\\u" + Integer.toHexString( ch ) );
1057             }
1058             else if ( ch > 0xff )
1059             {
1060                 buffer.append( "\\u0" + Integer.toHexString( ch ) );
1061             }
1062             else if ( ch > 0x7f )
1063             {
1064                 buffer.append( "\\u00" + Integer.toHexString( ch ) );
1065             }
1066             else if ( ch < 32 )
1067             {
1068                 switch ( ch )
1069                 {
1070                     case '\b':
1071                         buffer.append( '\\' );
1072                         buffer.append( 'b' );
1073                         break;
1074                     case '\n':
1075                         buffer.append( '\\' );
1076                         buffer.append( 'n' );
1077                         break;
1078                     case '\t':
1079                         buffer.append( '\\' );
1080                         buffer.append( 't' );
1081                         break;
1082                     case '\f':
1083                         buffer.append( '\\' );
1084                         buffer.append( 'f' );
1085                         break;
1086                     case '\r':
1087                         buffer.append( '\\' );
1088                         buffer.append( 'r' );
1089                         break;
1090                     default :
1091                         if ( ch > 0xf )
1092                         {
1093                             buffer.append( "\\u00" + Integer.toHexString( ch ) );
1094                         }
1095                         else
1096                         {
1097                             buffer.append( "\\u000" + Integer.toHexString( ch ) );
1098                         }
1099                         break;
1100                 }
1101             }
1102             else
1103             {
1104                 switch ( ch )
1105                 {
1106                     case '\'':
1107                         buffer.append( '\\' );
1108                         buffer.append( '\'' );
1109                         break;
1110                     case '"':
1111                         buffer.append( '\\' );
1112                         buffer.append( '"' );
1113                         break;
1114                     case '\\':
1115                         buffer.append( '\\' );
1116                         buffer.append( '\\' );
1117                         break;
1118                     default :
1119                         buffer.append( ch );
1120                         break;
1121                 }
1122             }
1123         }
1124         return buffer.toString();
1125     }
1126 
1127     // Padding
1128     //--------------------------------------------------------------------------
1129 
1130     /**
1131      * <p>Repeat a String <code>n</code> times to form a
1132      * new string.</p>
1133      *
1134      * @param str String to repeat
1135      * @param repeat number of times to repeat str
1136      * @return String with repeated String
1137      * @throws NegativeArraySizeException if <code>repeat < 0</code>
1138      * @throws NullPointerException if str is <code>null</code>
1139      */
1140     public static String repeat( String str, int repeat )
1141     {
1142         StringBuffer buffer = new StringBuffer( repeat * str.length() );
1143         for ( int i = 0; i < repeat; i++ )
1144         {
1145             buffer.append( str );
1146         }
1147         return buffer.toString();
1148     }
1149 
1150     /**
1151      * <p>Right pad a String with spaces.</p>
1152      *
1153      * <p>The String is padded to the size of <code>n</code>.</p>
1154      *
1155      * @param str String to repeat
1156      * @param size number of times to repeat str
1157      * @return right padded String
1158      * @throws NullPointerException if str is <code>null</code>
1159      */
1160     public static String rightPad( String str, int size )
1161     {
1162         return rightPad( str, size, " " );
1163     }
1164 
1165     /**
1166      * <p>Right pad a String with a specified string.</p>
1167      *
1168      * <p>The String is padded to the size of <code>n</code>.</p>
1169      *
1170      * @param str String to pad out
1171      * @param size size to pad to
1172      * @param delim String to pad with
1173      * @return right padded String
1174      * @throws NullPointerException if str or delim is <code>null</code>
1175      * @throws ArithmeticException if delim is the empty String
1176      */
1177     public static String rightPad( String str, int size, String delim )
1178     {
1179         size = ( size - str.length() ) / delim.length();
1180         if ( size > 0 )
1181         {
1182             str += repeat( delim, size );
1183         }
1184         return str;
1185     }
1186 
1187     /**
1188      * <p>Left pad a String with spaces.</p>
1189      *
1190      * <p>The String is padded to the size of <code>n</code>.</p>
1191      *
1192      * @param str String to pad out
1193      * @param size size to pad to
1194      * @return left padded String
1195      * @throws NullPointerException if str or delim is <code>null</code>
1196      */
1197     public static String leftPad( String str, int size )
1198     {
1199         return leftPad( str, size, " " );
1200     }
1201 
1202     /**
1203      * Left pad a String with a specified string. Pad to a size of n.
1204      *
1205      * @param str String to pad out
1206      * @param size size to pad to
1207      * @param delim String to pad with
1208      * @return left padded String
1209      * @throws NullPointerException if str or delim is null
1210      * @throws ArithmeticException if delim is the empty string
1211      */
1212     public static String leftPad( String str, int size, String delim )
1213     {
1214         size = ( size - str.length() ) / delim.length();
1215         if ( size > 0 )
1216         {
1217             str = repeat( delim, size ) + str;
1218         }
1219         return str;
1220     }
1221 
1222     // Stripping
1223     //--------------------------------------------------------------------------
1224 
1225     /**
1226      * <p>Remove whitespace from the front and back of a String.</p>
1227      *
1228      * @param str the String to remove whitespace from
1229      * @return the stripped String
1230      */
1231     public static String strip( String str )
1232     {
1233         return strip( str, null );
1234     }
1235 
1236     /**
1237      * <p>Remove a specified String from the front and back of a
1238      * String.</p>
1239      *
1240      * <p>If whitespace is wanted to be removed, used the
1241      * {@link #strip(java.lang.String)} method.</p>
1242      *
1243      * @param str the String to remove a string from
1244      * @param delim the String to remove at start and end
1245      * @return the stripped String
1246      */
1247     public static String strip( String str, String delim )
1248     {
1249         str = stripStart( str, delim );
1250         return stripEnd( str, delim );
1251     }
1252 
1253     /**
1254      * <p>Strip whitespace from the front and back of every String
1255      * in the array.</p>
1256      *
1257      * @param strs the Strings to remove whitespace from
1258      * @return the stripped Strings
1259      */
1260     public static String[] stripAll( String[] strs )
1261     {
1262         return stripAll( strs, null );
1263     }
1264 
1265     /**
1266      * <p>Strip the specified delimiter from the front and back of
1267      * every String in the array.</p>
1268      *
1269      * @param strs the Strings to remove a String from
1270      * @param delimiter the String to remove at start and end
1271      * @return the stripped Strings
1272      */
1273     public static String[] stripAll( String[] strs, String delimiter )
1274     {
1275         if ( ( strs == null ) || ( strs.length == 0 ) )
1276         {
1277             return strs;
1278         }
1279         int sz = strs.length;
1280         String[] newArr = new String[sz];
1281         for ( int i = 0; i < sz; i++ )
1282         {
1283             newArr[i] = strip( strs[i], delimiter );
1284         }
1285         return newArr;
1286     }
1287 
1288     /**
1289      * <p>Strip any of a supplied String from the end of a String.</p>
1290      *
1291      * <p>If the strip String is <code>null</code>, whitespace is
1292      * stripped.</p>
1293      *
1294      * @param str the String to remove characters from
1295      * @param strip the String to remove
1296      * @return the stripped String
1297      */
1298     public static String stripEnd( String str, String strip )
1299     {
1300         if ( str == null )
1301         {
1302             return null;
1303         }
1304         int end = str.length();
1305 
1306         if ( strip == null )
1307         {
1308             while ( ( end != 0 ) && Character.isWhitespace( str.charAt( end - 1 ) ) )
1309             {
1310                 end--;
1311             }
1312         }
1313         else
1314         {
1315             while ( ( end != 0 ) && ( strip.indexOf( str.charAt( end - 1 ) ) != -1 ) )
1316             {
1317                 end--;
1318             }
1319         }
1320         return str.substring( 0, end );
1321     }
1322 
1323     /**
1324      * <p>Strip any of a supplied String from the start of a String.</p>
1325      *
1326      * <p>If the strip String is <code>null</code>, whitespace is
1327      * stripped.</p>
1328      *
1329      * @param str the String to remove characters from
1330      * @param strip the String to remove
1331      * @return the stripped String
1332      */
1333     public static String stripStart( String str, String strip )
1334     {
1335         if ( str == null )
1336         {
1337             return null;
1338         }
1339 
1340         int start = 0;
1341 
1342         int sz = str.length();
1343 
1344         if ( strip == null )
1345         {
1346             while ( ( start != sz ) && Character.isWhitespace( str.charAt( start ) ) )
1347             {
1348                 start++;
1349             }
1350         }
1351         else
1352         {
1353             while ( ( start != sz ) && ( strip.indexOf( str.charAt( start ) ) != -1 ) )
1354             {
1355                 start++;
1356             }
1357         }
1358         return str.substring( start );
1359     }
1360 
1361     // Case conversion
1362     //--------------------------------------------------------------------------
1363 
1364     /**
1365      * <p>Convert a String to upper case, <code>null</code> String
1366      * returns <code>null</code>.</p>
1367      *
1368      * @param str the String to uppercase
1369      * @return the upper cased String
1370      */
1371     public static String upperCase( String str )
1372     {
1373         if ( str == null )
1374         {
1375             return null;
1376         }
1377         return str.toUpperCase();
1378     }
1379 
1380     /**
1381      * <p>Convert a String to lower case, <code>null</code> String
1382      * returns <code>null</code>.</p>
1383      *
1384      * @param str the string to lowercase
1385      * @return the lower cased String
1386      */
1387     public static String lowerCase( String str )
1388     {
1389         if ( str == null )
1390         {
1391             return null;
1392         }
1393         return str.toLowerCase();
1394     }
1395 
1396     /**
1397      * <p>Uncapitalise a String.</p>
1398      *
1399      * <p>That is, convert the first character into lower-case.
1400      * <code>null</code> is returned as <code>null</code>.</p>
1401      *
1402      * @param str the String to uncapitalise
1403      * @return uncapitalised String
1404      */
1405     public static String uncapitalise( String str )
1406     {
1407         if ( str == null )
1408         {
1409             return null;
1410         }
1411         else if ( str.length() == 0 )
1412         {
1413             return "";
1414         }
1415         else
1416         {
1417             return new StringBuffer( str.length() )
1418                 .append( Character.toLowerCase( str.charAt( 0 ) ) )
1419                 .append( str.substring( 1 ) )
1420                 .toString();
1421         }
1422     }
1423 
1424     /**
1425      * <p>Capitalise a String.</p>
1426      *
1427      * <p>That is, convert the first character into title-case.
1428      * <code>null</code> is returned as <code>null</code>.</p>
1429      *
1430      * @param str the String to capitalise
1431      * @return capitalised String
1432      */
1433     public static String capitalise( String str )
1434     {
1435         if ( str == null )
1436         {
1437             return null;
1438         }
1439         else if ( str.length() == 0 )
1440         {
1441             return "";
1442         }
1443         else
1444         {
1445             return new StringBuffer( str.length() )
1446                 .append( Character.toTitleCase( str.charAt( 0 ) ) )
1447                 .append( str.substring( 1 ) )
1448                 .toString();
1449         }
1450     }
1451 
1452     /**
1453      * <p>Swaps the case of String.</p>
1454      *
1455      * <p>Properly looks after making sure the start of words
1456      * are Titlecase and not Uppercase.</p>
1457      *
1458      * <p><code>null</code> is returned as <code>null</code>.</p>
1459      *
1460      * @param str the String to swap the case of
1461      * @return the modified String
1462      */
1463     public static String swapCase( String str )
1464     {
1465         if ( str == null )
1466         {
1467             return null;
1468         }
1469         int sz = str.length();
1470         StringBuffer buffer = new StringBuffer( sz );
1471 
1472         boolean whitespace = false;
1473         char ch = 0;
1474         char tmp = 0;
1475 
1476         for ( int i = 0; i < sz; i++ )
1477         {
1478             ch = str.charAt( i );
1479             if ( Character.isUpperCase( ch ) )
1480             {
1481                 tmp = Character.toLowerCase( ch );
1482             }
1483             else if ( Character.isTitleCase( ch ) )
1484             {
1485                 tmp = Character.toLowerCase( ch );
1486             }
1487             else if ( Character.isLowerCase( ch ) )
1488             {
1489                 if ( whitespace )
1490                 {
1491                     tmp = Character.toTitleCase( ch );
1492                 }
1493                 else
1494                 {
1495                     tmp = Character.toUpperCase( ch );
1496                 }
1497             }
1498             else
1499             {
1500                 tmp = ch;
1501             }
1502             buffer.append( tmp );
1503             whitespace = Character.isWhitespace( ch );
1504         }
1505         return buffer.toString();
1506     }
1507 
1508 
1509     /**
1510      * <p>Capitalise all the words in a String.</p>
1511      *
1512      * <p>Uses {@link Character#isWhitespace(char)} as a
1513      * separator between words.</p>
1514      *
1515      * <p><code>null</code> will return <code>null</code>.</p>
1516      *
1517      * @param str the String to capitalise
1518      * @return capitalised String
1519      */
1520     public static String capitaliseAllWords( String str )
1521     {
1522         if ( str == null )
1523         {
1524             return null;
1525         }
1526         int sz = str.length();
1527         StringBuffer buffer = new StringBuffer( sz );
1528         boolean space = true;
1529         for ( int i = 0; i < sz; i++ )
1530         {
1531             char ch = str.charAt( i );
1532             if ( Character.isWhitespace( ch ) )
1533             {
1534                 buffer.append( ch );
1535                 space = true;
1536             }
1537             else if ( space )
1538             {
1539                 buffer.append( Character.toTitleCase( ch ) );
1540                 space = false;
1541             }
1542             else
1543             {
1544                 buffer.append( ch );
1545             }
1546         }
1547         return buffer.toString();
1548     }
1549 
1550     /**
1551      * <p>Uncapitalise all the words in a string.</p>
1552      *
1553      * <p>Uses {@link Character#isWhitespace(char)} as a
1554      * separator between words.</p>
1555      *
1556      * <p><code>null</code> will return <code>null</code>.</p>
1557      *
1558      * @param str  the string to uncapitalise
1559      * @return uncapitalised string
1560      */
1561     public static String uncapitaliseAllWords( String str )
1562     {
1563         if ( str == null )
1564         {
1565             return null;
1566         }
1567         int sz = str.length();
1568         StringBuffer buffer = new StringBuffer( sz );
1569         boolean space = true;
1570         for ( int i = 0; i < sz; i++ )
1571         {
1572             char ch = str.charAt( i );
1573             if ( Character.isWhitespace( ch ) )
1574             {
1575                 buffer.append( ch );
1576                 space = true;
1577             }
1578             else if ( space )
1579             {
1580                 buffer.append( Character.toLowerCase( ch ) );
1581                 space = false;
1582             }
1583             else
1584             {
1585                 buffer.append( ch );
1586             }
1587         }
1588         return buffer.toString();
1589     }
1590 
1591     // Nested extraction
1592     //--------------------------------------------------------------------------
1593 
1594     /**
1595      * <p>Get the String that is nested in between two instances of the
1596      * same String.</p>
1597      *
1598      * <p>If <code>str</code> is <code>null</code>, will
1599      * return <code>null</code>.</p>
1600      *
1601      * @param str the String containing nested-string
1602      * @param tag the String before and after nested-string
1603      * @return the String that was nested, or <code>null</code>
1604      * @throws NullPointerException if tag is <code>null</code>
1605      */
1606     public static String getNestedString( String str, String tag )
1607     {
1608         return getNestedString( str, tag, tag );
1609     }
1610 
1611     /**
1612      * <p>Get the String that is nested in between two Strings.</p>
1613      *
1614      * @param str the String containing nested-string
1615      * @param open the String before nested-string
1616      * @param close the String after nested-string
1617      * @return the String that was nested, or <code>null</code>
1618      * @throws NullPointerException if open or close is <code>null</code>
1619      */
1620     public static String getNestedString( String str, String open, String close )
1621     {
1622         if ( str == null )
1623         {
1624             return null;
1625         }
1626         int start = str.indexOf( open );
1627         if ( start != -1 )
1628         {
1629             int end = str.indexOf( close, start + open.length() );
1630             if ( end != -1 )
1631             {
1632                 return str.substring( start + open.length(), end );
1633             }
1634         }
1635         return null;
1636     }
1637 
1638     /**
1639      * <p>How many times is the substring in the larger String.</p>
1640      *
1641      * <p><code>null</code> returns <code>0</code>.</p>
1642      *
1643      * @param str the String to check
1644      * @param sub the substring to count
1645      * @return the number of occurances, 0 if the String is <code>null</code>
1646      * @throws NullPointerException if sub is <code>null</code>
1647      */
1648     public static int countMatches( String str, String sub )
1649     {
1650         if ( sub.equals( "" ) )
1651         {
1652             return 0;
1653         }
1654         if ( str == null )
1655         {
1656             return 0;
1657         }
1658         int count = 0;
1659         int idx = 0;
1660         while ( ( idx = str.indexOf( sub, idx ) ) != -1 )
1661         {
1662             count++;
1663             idx += sub.length();
1664         }
1665         return count;
1666     }
1667 
1668     // Character Tests
1669     //--------------------------------------------------------------------------
1670 
1671     /**
1672      * <p>Checks if the String contains only unicode letters.</p>
1673      *
1674      * <p><code>null</code> will return <code>false</code>.
1675      * An empty String will return <code>true</code>.</p>
1676      *
1677      * @param str the String to check
1678      * @return <code>true</code> if only contains letters, and is non-null
1679      */
1680     public static boolean isAlpha( String str )
1681     {
1682         if ( str == null )
1683         {
1684             return false;
1685         }
1686         int sz = str.length();
1687         for ( int i = 0; i < sz; i++ )
1688         {
1689             if ( Character.isLetter( str.charAt( i ) ) == false )
1690             {
1691                 return false;
1692             }
1693         }
1694         return true;
1695     }
1696 
1697     /**
1698      * <p>Checks if the String contains only whitespace.</p>
1699      *
1700      * <p><code>null</code> will return <code>false</code>. An
1701      * empty String will return <code>true</code>.</p>
1702      *
1703      * @param str the String to check
1704      * @return <code>true</code> if only contains whitespace, and is non-null
1705      */
1706     public static boolean isWhitespace( String str )
1707     {
1708         if ( str == null )
1709         {
1710             return false;
1711         }
1712         int sz = str.length();
1713         for ( int i = 0; i < sz; i++ )
1714         {
1715             if ( ( Character.isWhitespace( str.charAt( i ) ) == false ) )
1716             {
1717                 return false;
1718             }
1719         }
1720         return true;
1721     }
1722 
1723     /**
1724      * <p>Checks if the String contains only unicode letters and
1725      * space (<code>' '</code>).</p>
1726      *
1727      * <p><code>null</code> will return <code>false</code>. An
1728      * empty String will return <code>true</code>.</p>
1729      *
1730      * @param str the String to check
1731      * @return <code>true</code> if only contains letters and space,
1732      *  and is non-null
1733      */
1734     public static boolean isAlphaSpace( String str )
1735     {
1736         if ( str == null )
1737         {
1738             return false;
1739         }
1740         int sz = str.length();
1741         for ( int i = 0; i < sz; i++ )
1742         {
1743             if ( ( Character.isLetter( str.charAt( i ) ) == false ) &&
1744                 ( str.charAt( i ) != ' ' ) )
1745             {
1746                 return false;
1747             }
1748         }
1749         return true;
1750     }
1751 
1752     /**
1753      * <p>Checks if the String contains only unicode letters or digits.</p>
1754      *
1755      * <p><code>null</code> will return <code>false</code>. An empty
1756      * String will return <code>true</code>.</p>
1757      *
1758      * @param str the String to check
1759      * @return <code>true</code> if only contains letters or digits,
1760      *  and is non-null
1761      */
1762     public static boolean isAlphanumeric( String str )
1763     {
1764         if ( str == null )
1765         {
1766             return false;
1767         }
1768         int sz = str.length();
1769         for ( int i = 0; i < sz; i++ )
1770         {
1771             if ( Character.isLetterOrDigit( str.charAt( i ) ) == false )
1772             {
1773                 return false;
1774             }
1775         }
1776         return true;
1777     }
1778 
1779     /**
1780      * <p>Checks if the String contains only unicode letters, digits
1781      * or space (<code>' '</code>).</p>
1782      *
1783      * <p><code>null</code> will return <code>false</code>. An empty
1784      * String will return <code>true</code>.</p>
1785      *
1786      * @param str the String to check
1787      * @return <code>true</code> if only contains letters, digits or space,
1788      *  and is non-null
1789      */
1790     public static boolean isAlphanumericSpace( String str )
1791     {
1792         if ( str == null )
1793         {
1794             return false;
1795         }
1796         int sz = str.length();
1797         for ( int i = 0; i < sz; i++ )
1798         {
1799             if ( ( Character.isLetterOrDigit( str.charAt( i ) ) == false ) &&
1800                 ( str.charAt( i ) != ' ' ) )
1801             {
1802                 return false;
1803             }
1804         }
1805         return true;
1806     }
1807 
1808     /**
1809      * <p>Checks if the String contains only unicode digits.</p>
1810      *
1811      * <p><code>null</code> will return <code>false</code>.
1812      * An empty String will return <code>true</code>.</p>
1813      *
1814      * @param str the String to check
1815      * @return <code>true</code> if only contains digits, and is non-null
1816      */
1817     public static boolean isNumeric( String str )
1818     {
1819         if ( str == null )
1820         {
1821             return false;
1822         }
1823         int sz = str.length();
1824         for ( int i = 0; i < sz; i++ )
1825         {
1826             if ( Character.isDigit( str.charAt( i ) ) == false )
1827             {
1828                 return false;
1829             }
1830         }
1831         return true;
1832     }
1833 
1834     /**
1835      * <p>Checks if the String contains only unicode digits or space
1836      * (<code>' '</code>).</p>
1837      *
1838      * <p><code>null</code> will return <code>false</code>. An empty
1839      * String will return <code>true</code>.</p>
1840      *
1841      * @param str the String to check
1842      * @return <code>true</code> if only contains digits or space,
1843      *  and is non-null
1844      */
1845     public static boolean isNumericSpace( 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.isDigit( str.charAt( i ) ) == false ) &&
1855                 ( str.charAt( i ) != ' ' ) )
1856             {
1857                 return false;
1858             }
1859         }
1860         return true;
1861     }
1862 
1863     // Defaults
1864     //--------------------------------------------------------------------------
1865 
1866     /**
1867      * <p>Returns either the passed in <code>Object</code> as a String,
1868      * or, if the <code>Object</code> is <code>null</code>, an empty
1869      * String.</p>
1870      *
1871      * @param obj the Object to check
1872      * @return the passed in Object's toString, or blank if it was
1873      *  <code>null</code>
1874      */
1875     public static String defaultString( Object obj )
1876     {
1877         return defaultString( obj, "" );
1878     }
1879 
1880     /**
1881      * <p>Returns either the passed in <code>Object</code> as a String,
1882      * or, if the <code>Object</code> is <code>null</code>, a passed
1883      * in default String.</p>
1884      *
1885      * @param obj the Object to check
1886      * @param defaultString  the default String to return if str is
1887      *  <code>null</code>
1888      * @return the passed in string, or the default if it was
1889      *  <code>null</code>
1890      */
1891     public static String defaultString( Object obj, String defaultString )
1892     {
1893         return ( obj == null ) ? defaultString : obj.toString();
1894     }
1895 
1896     // Reversing
1897     //--------------------------------------------------------------------------
1898 
1899     /**
1900      * <p>Reverse a String.</p>
1901      *
1902      * <p><code>null</code> String returns <code>null</code>.</p>
1903      *
1904      * @param str the String to reverse
1905      * @return the reversed String
1906      */
1907     public static String reverse( String str )
1908     {
1909         if ( str == null )
1910         {
1911             return null;
1912         }
1913         return new StringBuffer( str ).reverse().toString();
1914     }
1915 
1916     /**
1917      * <p>Reverses a String that is delimited by a specific character.</p>
1918      *
1919      * <p>The Strings between the delimiters are not reversed.
1920      * Thus java.lang.String becomes String.lang.java (if the delimiter
1921      * is <code>'.'</code>).</p>
1922      *
1923      * @param str the String to reverse
1924      * @param delimiter the delimiter to use
1925      * @return the reversed String
1926      */
1927     public static String reverseDelimitedString( String str, String delimiter )
1928     {
1929         // could implement manually, but simple way is to reuse other,
1930         // probably slower, methods.
1931         String[] strs = split( str, delimiter );
1932         reverseArray( strs );
1933         return join( strs, delimiter );
1934     }
1935 
1936     /**
1937      * <p>Reverses an array.</p>
1938      *
1939      * <p>TAKEN FROM CollectionsUtils.</p>
1940      *
1941      * @param array  the array to reverse
1942      */
1943     private static void reverseArray( Object[] array )
1944     {
1945         int i = 0;
1946         int j = array.length - 1;
1947         Object tmp;
1948 
1949         while ( j > i )
1950         {
1951             tmp = array[j];
1952             array[j] = array[i];
1953             array[i] = tmp;
1954             j--;
1955             i++;
1956         }
1957     }
1958 
1959     // Abbreviating
1960     //--------------------------------------------------------------------------
1961 
1962     /**
1963      * Turn "Now is the time for all good men" into "Now is the time for..."
1964      * <p>
1965      * Specifically:
1966      * <p>
1967      * If str is less than max characters long, return it.
1968      * Else abbreviate it to (substring(str, 0, max-3) + "...").
1969      * If maxWidth is less than 3, throw an IllegalArgumentException.
1970      * In no case will it return a string of length greater than maxWidth.
1971      *
1972      * @param maxWidth maximum length of result string
1973      **/
1974     public static String abbreviate( String s, int maxWidth )
1975     {
1976         return abbreviate( s, 0, maxWidth );
1977     }
1978 
1979     /**
1980      * Turn "Now is the time for all good men" into "...is the time for..."
1981      * <p>
1982      * Works like abbreviate(String, int), but allows you to specify a "left edge"
1983      * offset.  Note that this left edge is not necessarily going to be the leftmost
1984      * character in the result, or the first
1985      * character following the ellipses, but it will appear somewhere in the result.
1986      * In no case will it return a string of length greater than maxWidth.
1987      *
1988      * @param offset left edge of source string
1989      * @param maxWidth maximum length of result string
1990      **/
1991     public static String abbreviate( String s, int offset, int maxWidth )
1992     {
1993         if ( maxWidth < 4 )
1994             throw new IllegalArgumentException( "Minimum abbreviation width is 4" );
1995         if ( s.length() <= maxWidth )
1996             return s;
1997         if ( offset > s.length() )
1998             offset = s.length();
1999         if ( ( s.length() - offset ) < ( maxWidth - 3 ) )
2000             offset = s.length() - ( maxWidth - 3 );
2001         if ( offset <= 4 )
2002             return s.substring( 0, maxWidth - 3 ) + "...";
2003         if ( maxWidth < 7 )
2004             throw new IllegalArgumentException( "Minimum abbreviation width with offset is 7" );
2005         if ( ( offset + ( maxWidth - 3 ) ) < s.length() )
2006             return "..." + abbreviate( s.substring( offset ), maxWidth - 3 );
2007         return "..." + s.substring( s.length() - ( maxWidth - 3 ) );
2008     }
2009 
2010     // Difference
2011     //--------------------------------------------------------------------------
2012 
2013     /**
2014      * Compare two strings, and return the portion where they differ.
2015      * (More precisely, return the remainder of the second string,
2016      * starting from where it's different from the first.)
2017      * <p>
2018      * E.g. strdiff("i am a machine", "i am a robot") -> "robot"
2019      *
2020      * @return the portion of s2 where it differs from s1; returns the empty string ("") if they are equal
2021      **/
2022     public static String difference( String s1, String s2 )
2023     {
2024         int at = differenceAt( s1, s2 );
2025         if ( at == -1 )
2026             return "";
2027         return s2.substring( at );
2028     }
2029 
2030     /**
2031      * Compare two strings, and return the index at which the strings begin to differ.
2032      * <p>
2033      * E.g. strdiff("i am a machine", "i am a robot") -> 7
2034      * </p>
2035      *
2036      * @return the index where s2 and s1 begin to differ; -1 if they are equal
2037      **/
2038     public static int differenceAt( String s1, String s2 )
2039     {
2040         int i;
2041         for ( i = 0; i < s1.length() && i < s2.length(); ++i )
2042         {
2043             if ( s1.charAt( i ) != s2.charAt( i ) )
2044             {
2045                 break;
2046             }
2047         }
2048         if ( i < s2.length() || i < s1.length() )
2049         {
2050             return i;
2051         }
2052         return -1;
2053     }
2054 
2055     public static String interpolate( String text, Map namespace )
2056     {
2057         Iterator keys = namespace.keySet().iterator();
2058 
2059         while ( keys.hasNext() )
2060         {
2061             String key = keys.next().toString();
2062 
2063             Object obj = namespace.get( key );
2064 
2065             if ( obj == null )
2066             {
2067                 throw new NullPointerException( "The value of the key '" + key + "' is null." );
2068             }
2069 
2070             String value = obj.toString();
2071 
2072             text = StringUtils.replace( text, "${" + key + "}", value );
2073 
2074             if ( key.indexOf( " " ) == -1 )
2075             {
2076                 text = StringUtils.replace( text, "$" + key, value );
2077             }
2078         }
2079         return text;
2080     }
2081 
2082     public static String removeAndHump( String data, String replaceThis )
2083     {
2084         String temp;
2085 
2086         StringBuffer out = new StringBuffer();
2087 
2088         temp = data;
2089 
2090         StringTokenizer st = new StringTokenizer( temp, replaceThis );
2091 
2092         while ( st.hasMoreTokens() )
2093         {
2094             String element = (String) st.nextElement();
2095 
2096             out.append( capitalizeFirstLetter( element ) );
2097         }
2098 
2099         return out.toString();
2100     }
2101 
2102     public static String capitalizeFirstLetter( String data )
2103     {
2104         char firstLetter = Character.toTitleCase( data.substring( 0, 1 ).charAt( 0 ) );
2105 
2106         String restLetters = data.substring( 1 );
2107 
2108         return firstLetter + restLetters;
2109     }
2110 
2111     public static String lowercaseFirstLetter( String data )
2112     {
2113         char firstLetter = Character.toLowerCase( data.substring( 0, 1 ).charAt( 0 ) );
2114 
2115         String restLetters = data.substring( 1 );
2116 
2117         return firstLetter + restLetters;
2118     }
2119 
2120     public static String addAndDeHump( String view )
2121     {
2122         StringBuffer sb = new StringBuffer();
2123 
2124         for ( int i = 0; i < view.length(); i++ )
2125         {
2126             if ( i != 0 && Character.isUpperCase( view.charAt( i ) ) )
2127             {
2128                 sb.append( '-' );
2129             }
2130 
2131             sb.append( view.charAt( i ) );
2132         }
2133 
2134         return sb.toString().trim().toLowerCase();
2135     }
2136 }