Coverage Report - org.apache.maven.it.util.StringUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
StringUtils
0%
0/488
0%
0/361
3.598
 
 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  0
     {
 93  0
     }
 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  0
         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  0
         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  0
         StringBuffer buffer = new StringBuffer();
 139  0
         int sz = str.length();
 140  0
         for ( int i = 0; i < sz; i++ )
 141  
         {
 142  0
             if ( !Character.isWhitespace( str.charAt( i ) ) )
 143  
             {
 144  0
                 buffer.append( str.charAt( i ) );
 145  
             }
 146  
         }
 147  0
         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  0
         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  0
         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  0
         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  0
         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  0
         if ( ( str == null ) || ( searchStrs == null ) )
 225  
         {
 226  0
             return -1;
 227  
         }
 228  0
         int sz = searchStrs.length;
 229  
 
 230  
         // String's can't have a MAX_VALUEth index.
 231  0
         int ret = Integer.MAX_VALUE;
 232  
 
 233  0
         int tmp = 0;
 234  0
         for ( int i = 0; i < sz; i++ )
 235  
         {
 236  0
             tmp = str.indexOf( searchStrs[i] );
 237  0
             if ( tmp == -1 )
 238  
             {
 239  0
                 continue;
 240  
             }
 241  
 
 242  0
             if ( tmp < ret )
 243  
             {
 244  0
                 ret = tmp;
 245  
             }
 246  
         }
 247  
 
 248  0
         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  0
         if ( ( str == null ) || ( searchStrs == null ) )
 264  
         {
 265  0
             return -1;
 266  
         }
 267  0
         int sz = searchStrs.length;
 268  0
         int ret = -1;
 269  0
         int tmp = 0;
 270  0
         for ( int i = 0; i < sz; i++ )
 271  
         {
 272  0
             tmp = str.lastIndexOf( searchStrs[i] );
 273  0
             if ( tmp > ret )
 274  
             {
 275  0
                 ret = tmp;
 276  
             }
 277  
         }
 278  0
         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  0
         if ( str == null )
 298  
         {
 299  0
             return null;
 300  
         }
 301  
 
 302  
         // handle negatives, which means last n characters
 303  0
         if ( start < 0 )
 304  
         {
 305  0
             start = str.length() + start; // remember start is negative
 306  
         }
 307  
 
 308  0
         if ( start < 0 )
 309  
         {
 310  0
             start = 0;
 311  
         }
 312  0
         if ( start > str.length() )
 313  
         {
 314  0
             return "";
 315  
         }
 316  
 
 317  0
         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  0
         if ( str == null )
 336  
         {
 337  0
             return null;
 338  
         }
 339  
 
 340  
         // handle negatives
 341  0
         if ( end < 0 )
 342  
         {
 343  0
             end = str.length() + end; // remember end is negative
 344  
         }
 345  0
         if ( start < 0 )
 346  
         {
 347  0
             start = str.length() + start; // remember start is negative
 348  
         }
 349  
 
 350  
         // check length next
 351  0
         if ( end > str.length() )
 352  
         {
 353  
             // check this works.
 354  0
             end = str.length();
 355  
         }
 356  
 
 357  
         // if start is greater than end, return ""
 358  0
         if ( start > end )
 359  
         {
 360  0
             return "";
 361  
         }
 362  
 
 363  0
         if ( start < 0 )
 364  
         {
 365  0
             start = 0;
 366  
         }
 367  0
         if ( end < 0 )
 368  
         {
 369  0
             end = 0;
 370  
         }
 371  
 
 372  0
         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  0
         if ( len < 0 )
 390  
         {
 391  0
             throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
 392  
         }
 393  0
         if ( ( str == null ) || ( str.length() <= len ) )
 394  
         {
 395  0
             return str;
 396  
         }
 397  
         else
 398  
         {
 399  0
             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  0
         if ( len < 0 )
 418  
         {
 419  0
             throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
 420  
         }
 421  0
         if ( ( str == null ) || ( str.length() <= len ) )
 422  
         {
 423  0
             return str;
 424  
         }
 425  
         else
 426  
         {
 427  0
             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  0
         if ( ( pos < 0 ) ||
 448  
             ( str != null && pos > str.length() ) )
 449  
         {
 450  0
             throw new StringIndexOutOfBoundsException( "String index " + pos + " is out of bounds" );
 451  
         }
 452  0
         if ( len < 0 )
 453  
         {
 454  0
             throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
 455  
         }
 456  0
         if ( str == null )
 457  
         {
 458  0
             return null;
 459  
         }
 460  0
         if ( str.length() <= ( pos + len ) )
 461  
         {
 462  0
             return str.substring( pos );
 463  
         }
 464  
         else
 465  
         {
 466  0
             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  0
         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  0
         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  0
         StringTokenizer tok = null;
 516  0
         if ( separator == null )
 517  
         {
 518  
             // Null separator means we're using StringTokenizer's default
 519  
             // delimiter, which comprises all whitespace characters.
 520  0
             tok = new StringTokenizer( str );
 521  
         }
 522  
         else
 523  
         {
 524  0
             tok = new StringTokenizer( str, separator );
 525  
         }
 526  
 
 527  0
         int listSize = tok.countTokens();
 528  0
         if ( max > 0 && listSize > max )
 529  
         {
 530  0
             listSize = max;
 531  
         }
 532  
 
 533  0
         String[] list = new String[listSize];
 534  0
         int i = 0;
 535  0
         int lastTokenBegin = 0;
 536  0
         int lastTokenEnd = 0;
 537  0
         while ( tok.hasMoreTokens() )
 538  
         {
 539  0
             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  0
                 String endToken = tok.nextToken();
 545  0
                 lastTokenBegin = str.indexOf( endToken, lastTokenEnd );
 546  0
                 list[i] = str.substring( lastTokenBegin );
 547  0
                 break;
 548  
             }
 549  
             else
 550  
             {
 551  0
                 list[i] = tok.nextToken();
 552  0
                 lastTokenBegin = str.indexOf( list[i], lastTokenEnd );
 553  0
                 lastTokenEnd = lastTokenBegin + list[i].length();
 554  
             }
 555  0
             i++;
 556  
         }
 557  0
         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  0
         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  0
         if ( separator == null )
 589  
         {
 590  0
             separator = "";
 591  
         }
 592  0
         int arraySize = array.length;
 593  0
         int bufSize = ( arraySize == 0 ? 0 : ( array[0].toString().length() +
 594  
             separator.length() ) * arraySize );
 595  0
         StringBuffer buf = new StringBuffer( bufSize );
 596  
 
 597  0
         for ( int i = 0; i < arraySize; i++ )
 598  
         {
 599  0
             if ( i > 0 )
 600  
             {
 601  0
                 buf.append( separator );
 602  
             }
 603  0
             buf.append( array[i] );
 604  
         }
 605  0
         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  0
         if ( separator == null )
 622  
         {
 623  0
             separator = "";
 624  
         }
 625  0
         StringBuffer buf = new StringBuffer( 256 );  // Java default is 16, probably too small
 626  0
         while ( iterator.hasNext() )
 627  
         {
 628  0
             buf.append( iterator.next() );
 629  0
             if ( iterator.hasNext() )
 630  
             {
 631  0
                 buf.append( separator );
 632  
             }
 633  
         }
 634  0
         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  0
         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  0
         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  0
         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  0
         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  0
         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  0
         if ( text == null || repl == null || with == null || repl.length() == 0 )
 738  
         {
 739  0
             return text;
 740  
         }
 741  
 
 742  0
         StringBuffer buf = new StringBuffer( text.length() );
 743  0
         int start = 0, end = 0;
 744  0
         while ( ( end = text.indexOf( repl, start ) ) != -1 )
 745  
         {
 746  0
             buf.append( text.substring( start, end ) ).append( with );
 747  0
             start = end + repl.length();
 748  
 
 749  0
             if ( --max == 0 )
 750  
             {
 751  0
                 break;
 752  
             }
 753  
         }
 754  0
         buf.append( text.substring( start ) );
 755  0
         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  0
         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  0
         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  0
         int sz = str.length();
 811  0
         int p = size - sz;
 812  0
         if ( p < 1 )
 813  
         {
 814  0
             return str;
 815  
         }
 816  0
         str = leftPad( str, sz + p / 2, delim );
 817  0
         str = rightPad( str, size, delim );
 818  0
         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  0
         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  0
         int idx = str.lastIndexOf( sep );
 848  0
         if ( idx != -1 )
 849  
         {
 850  0
             return str.substring( 0, idx );
 851  
         }
 852  
         else
 853  
         {
 854  0
             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  0
         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  0
         if ( str.length() == 0 )
 882  
         {
 883  0
             return str;
 884  
         }
 885  0
         String sub = str.substring( str.length() - sep.length() );
 886  0
         if ( sep.equals( sub ) )
 887  
         {
 888  0
             return str.substring( 0, str.length() - sep.length() );
 889  
         }
 890  
         else
 891  
         {
 892  0
             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  0
         int idx = str.lastIndexOf( sep );
 908  0
         if ( idx == str.length() - sep.length() )
 909  
         {
 910  0
             return sep;
 911  
         }
 912  0
         else if ( idx != -1 )
 913  
         {
 914  0
             return str.substring( idx );
 915  
         }
 916  
         else
 917  
         {
 918  0
             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  0
         int idx = str.indexOf( sep );
 934  0
         if ( idx != -1 )
 935  
         {
 936  0
             return str.substring( idx + sep.length() );
 937  
         }
 938  
         else
 939  
         {
 940  0
             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  0
         int idx = str.indexOf( sep );
 956  0
         if ( idx != -1 )
 957  
         {
 958  0
             return str.substring( 0, idx + sep.length() );
 959  
         }
 960  
         else
 961  
         {
 962  0
             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  0
         if ( "".equals( str ) )
 982  
         {
 983  0
             return "";
 984  
         }
 985  0
         if ( str.length() == 1 )
 986  
         {
 987  0
             return "";
 988  
         }
 989  0
         int lastIdx = str.length() - 1;
 990  0
         String ret = str.substring( 0, lastIdx );
 991  0
         char last = str.charAt( lastIdx );
 992  0
         if ( last == '\n' )
 993  
         {
 994  0
             if ( ret.charAt( lastIdx - 1 ) == '\r' )
 995  
             {
 996  0
                 return ret.substring( 0, lastIdx - 1 );
 997  
             }
 998  
         }
 999  0
         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  0
         int lastIdx = str.length() - 1;
 1013  0
         char last = str.charAt( lastIdx );
 1014  0
         if ( last == '\n' )
 1015  
         {
 1016  0
             if ( str.charAt( lastIdx - 1 ) == '\r' )
 1017  
             {
 1018  0
                 lastIdx--;
 1019  
             }
 1020  
         }
 1021  
         else
 1022  
         {
 1023  0
             lastIdx++;
 1024  
         }
 1025  0
         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  0
         int sz = str.length();
 1048  0
         StringBuffer buffer = new StringBuffer( 2 * sz );
 1049  0
         for ( int i = 0; i < sz; i++ )
 1050  
         {
 1051  0
             char ch = str.charAt( i );
 1052  
 
 1053  
             // handle unicode
 1054  0
             if ( ch > 0xfff )
 1055  
             {
 1056  0
                 buffer.append( "\\u" + Integer.toHexString( ch ) );
 1057  
             }
 1058  0
             else if ( ch > 0xff )
 1059  
             {
 1060  0
                 buffer.append( "\\u0" + Integer.toHexString( ch ) );
 1061  
             }
 1062  0
             else if ( ch > 0x7f )
 1063  
             {
 1064  0
                 buffer.append( "\\u00" + Integer.toHexString( ch ) );
 1065  
             }
 1066  0
             else if ( ch < 32 )
 1067  
             {
 1068  0
                 switch ( ch )
 1069  
                 {
 1070  
                     case '\b':
 1071  0
                         buffer.append( '\\' );
 1072  0
                         buffer.append( 'b' );
 1073  0
                         break;
 1074  
                     case '\n':
 1075  0
                         buffer.append( '\\' );
 1076  0
                         buffer.append( 'n' );
 1077  0
                         break;
 1078  
                     case '\t':
 1079  0
                         buffer.append( '\\' );
 1080  0
                         buffer.append( 't' );
 1081  0
                         break;
 1082  
                     case '\f':
 1083  0
                         buffer.append( '\\' );
 1084  0
                         buffer.append( 'f' );
 1085  0
                         break;
 1086  
                     case '\r':
 1087  0
                         buffer.append( '\\' );
 1088  0
                         buffer.append( 'r' );
 1089  0
                         break;
 1090  
                     default :
 1091  0
                         if ( ch > 0xf )
 1092  
                         {
 1093  0
                             buffer.append( "\\u00" + Integer.toHexString( ch ) );
 1094  
                         }
 1095  
                         else
 1096  
                         {
 1097  0
                             buffer.append( "\\u000" + Integer.toHexString( ch ) );
 1098  
                         }
 1099  0
                         break;
 1100  
                 }
 1101  
             }
 1102  
             else
 1103  
             {
 1104  0
                 switch ( ch )
 1105  
                 {
 1106  
                     case '\'':
 1107  0
                         buffer.append( '\\' );
 1108  0
                         buffer.append( '\'' );
 1109  0
                         break;
 1110  
                     case '"':
 1111  0
                         buffer.append( '\\' );
 1112  0
                         buffer.append( '"' );
 1113  0
                         break;
 1114  
                     case '\\':
 1115  0
                         buffer.append( '\\' );
 1116  0
                         buffer.append( '\\' );
 1117  0
                         break;
 1118  
                     default :
 1119  0
                         buffer.append( ch );
 1120  
                         break;
 1121  
                 }
 1122  
             }
 1123  
         }
 1124  0
         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  0
         StringBuffer buffer = new StringBuffer( repeat * str.length() );
 1143  0
         for ( int i = 0; i < repeat; i++ )
 1144  
         {
 1145  0
             buffer.append( str );
 1146  
         }
 1147  0
         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  0
         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  0
         size = ( size - str.length() ) / delim.length();
 1180  0
         if ( size > 0 )
 1181  
         {
 1182  0
             str += repeat( delim, size );
 1183  
         }
 1184  0
         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  0
         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  0
         size = ( size - str.length() ) / delim.length();
 1215  0
         if ( size > 0 )
 1216  
         {
 1217  0
             str = repeat( delim, size ) + str;
 1218  
         }
 1219  0
         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  0
         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  0
         str = stripStart( str, delim );
 1250  0
         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  0
         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  0
         if ( ( strs == null ) || ( strs.length == 0 ) )
 1276  
         {
 1277  0
             return strs;
 1278  
         }
 1279  0
         int sz = strs.length;
 1280  0
         String[] newArr = new String[sz];
 1281  0
         for ( int i = 0; i < sz; i++ )
 1282  
         {
 1283  0
             newArr[i] = strip( strs[i], delimiter );
 1284  
         }
 1285  0
         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  0
         if ( str == null )
 1301  
         {
 1302  0
             return null;
 1303  
         }
 1304  0
         int end = str.length();
 1305  
 
 1306  0
         if ( strip == null )
 1307  
         {
 1308  0
             while ( ( end != 0 ) && Character.isWhitespace( str.charAt( end - 1 ) ) )
 1309  
             {
 1310  0
                 end--;
 1311  
             }
 1312  
         }
 1313  
         else
 1314  
         {
 1315  0
             while ( ( end != 0 ) && ( strip.indexOf( str.charAt( end - 1 ) ) != -1 ) )
 1316  
             {
 1317  0
                 end--;
 1318  
             }
 1319  
         }
 1320  0
         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  0
         if ( str == null )
 1336  
         {
 1337  0
             return null;
 1338  
         }
 1339  
 
 1340  0
         int start = 0;
 1341  
 
 1342  0
         int sz = str.length();
 1343  
 
 1344  0
         if ( strip == null )
 1345  
         {
 1346  0
             while ( ( start != sz ) && Character.isWhitespace( str.charAt( start ) ) )
 1347  
             {
 1348  0
                 start++;
 1349  
             }
 1350  
         }
 1351  
         else
 1352  
         {
 1353  0
             while ( ( start != sz ) && ( strip.indexOf( str.charAt( start ) ) != -1 ) )
 1354  
             {
 1355  0
                 start++;
 1356  
             }
 1357  
         }
 1358  0
         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  0
         if ( str == null )
 1374  
         {
 1375  0
             return null;
 1376  
         }
 1377  0
         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  0
         if ( str == null )
 1390  
         {
 1391  0
             return null;
 1392  
         }
 1393  0
         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  0
         if ( str == null )
 1408  
         {
 1409  0
             return null;
 1410  
         }
 1411  0
         else if ( str.length() == 0 )
 1412  
         {
 1413  0
             return "";
 1414  
         }
 1415  
         else
 1416  
         {
 1417  0
             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  0
         if ( str == null )
 1436  
         {
 1437  0
             return null;
 1438  
         }
 1439  0
         else if ( str.length() == 0 )
 1440  
         {
 1441  0
             return "";
 1442  
         }
 1443  
         else
 1444  
         {
 1445  0
             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  0
         if ( str == null )
 1466  
         {
 1467  0
             return null;
 1468  
         }
 1469  0
         int sz = str.length();
 1470  0
         StringBuffer buffer = new StringBuffer( sz );
 1471  
 
 1472  0
         boolean whitespace = false;
 1473  0
         char ch = 0;
 1474  0
         char tmp = 0;
 1475  
 
 1476  0
         for ( int i = 0; i < sz; i++ )
 1477  
         {
 1478  0
             ch = str.charAt( i );
 1479  0
             if ( Character.isUpperCase( ch ) )
 1480  
             {
 1481  0
                 tmp = Character.toLowerCase( ch );
 1482  
             }
 1483  0
             else if ( Character.isTitleCase( ch ) )
 1484  
             {
 1485  0
                 tmp = Character.toLowerCase( ch );
 1486  
             }
 1487  0
             else if ( Character.isLowerCase( ch ) )
 1488  
             {
 1489  0
                 if ( whitespace )
 1490  
                 {
 1491  0
                     tmp = Character.toTitleCase( ch );
 1492  
                 }
 1493  
                 else
 1494  
                 {
 1495  0
                     tmp = Character.toUpperCase( ch );
 1496  
                 }
 1497  
             }
 1498  
             else
 1499  
             {
 1500  0
                 tmp = ch;
 1501  
             }
 1502  0
             buffer.append( tmp );
 1503  0
             whitespace = Character.isWhitespace( ch );
 1504  
         }
 1505  0
         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  0
         if ( str == null )
 1523  
         {
 1524  0
             return null;
 1525  
         }
 1526  0
         int sz = str.length();
 1527  0
         StringBuffer buffer = new StringBuffer( sz );
 1528  0
         boolean space = true;
 1529  0
         for ( int i = 0; i < sz; i++ )
 1530  
         {
 1531  0
             char ch = str.charAt( i );
 1532  0
             if ( Character.isWhitespace( ch ) )
 1533  
             {
 1534  0
                 buffer.append( ch );
 1535  0
                 space = true;
 1536  
             }
 1537  0
             else if ( space )
 1538  
             {
 1539  0
                 buffer.append( Character.toTitleCase( ch ) );
 1540  0
                 space = false;
 1541  
             }
 1542  
             else
 1543  
             {
 1544  0
                 buffer.append( ch );
 1545  
             }
 1546  
         }
 1547  0
         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  0
         if ( str == null )
 1564  
         {
 1565  0
             return null;
 1566  
         }
 1567  0
         int sz = str.length();
 1568  0
         StringBuffer buffer = new StringBuffer( sz );
 1569  0
         boolean space = true;
 1570  0
         for ( int i = 0; i < sz; i++ )
 1571  
         {
 1572  0
             char ch = str.charAt( i );
 1573  0
             if ( Character.isWhitespace( ch ) )
 1574  
             {
 1575  0
                 buffer.append( ch );
 1576  0
                 space = true;
 1577  
             }
 1578  0
             else if ( space )
 1579  
             {
 1580  0
                 buffer.append( Character.toLowerCase( ch ) );
 1581  0
                 space = false;
 1582  
             }
 1583  
             else
 1584  
             {
 1585  0
                 buffer.append( ch );
 1586  
             }
 1587  
         }
 1588  0
         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  0
         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  0
         if ( str == null )
 1623  
         {
 1624  0
             return null;
 1625  
         }
 1626  0
         int start = str.indexOf( open );
 1627  0
         if ( start != -1 )
 1628  
         {
 1629  0
             int end = str.indexOf( close, start + open.length() );
 1630  0
             if ( end != -1 )
 1631  
             {
 1632  0
                 return str.substring( start + open.length(), end );
 1633  
             }
 1634  
         }
 1635  0
         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  0
         if ( sub.equals( "" ) )
 1651  
         {
 1652  0
             return 0;
 1653  
         }
 1654  0
         if ( str == null )
 1655  
         {
 1656  0
             return 0;
 1657  
         }
 1658  0
         int count = 0;
 1659  0
         int idx = 0;
 1660  0
         while ( ( idx = str.indexOf( sub, idx ) ) != -1 )
 1661  
         {
 1662  0
             count++;
 1663  0
             idx += sub.length();
 1664  
         }
 1665  0
         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  0
         if ( str == null )
 1683  
         {
 1684  0
             return false;
 1685  
         }
 1686  0
         int sz = str.length();
 1687  0
         for ( int i = 0; i < sz; i++ )
 1688  
         {
 1689  0
             if ( Character.isLetter( str.charAt( i ) ) == false )
 1690  
             {
 1691  0
                 return false;
 1692  
             }
 1693  
         }
 1694  0
         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  0
         if ( str == null )
 1709  
         {
 1710  0
             return false;
 1711  
         }
 1712  0
         int sz = str.length();
 1713  0
         for ( int i = 0; i < sz; i++ )
 1714  
         {
 1715  0
             if ( ( Character.isWhitespace( str.charAt( i ) ) == false ) )
 1716  
             {
 1717  0
                 return false;
 1718  
             }
 1719  
         }
 1720  0
         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  0
         if ( str == null )
 1737  
         {
 1738  0
             return false;
 1739  
         }
 1740  0
         int sz = str.length();
 1741  0
         for ( int i = 0; i < sz; i++ )
 1742  
         {
 1743  0
             if ( ( Character.isLetter( str.charAt( i ) ) == false ) &&
 1744  
                 ( str.charAt( i ) != ' ' ) )
 1745  
             {
 1746  0
                 return false;
 1747  
             }
 1748  
         }
 1749  0
         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  0
         if ( str == null )
 1765  
         {
 1766  0
             return false;
 1767  
         }
 1768  0
         int sz = str.length();
 1769  0
         for ( int i = 0; i < sz; i++ )
 1770  
         {
 1771  0
             if ( Character.isLetterOrDigit( str.charAt( i ) ) == false )
 1772  
             {
 1773  0
                 return false;
 1774  
             }
 1775  
         }
 1776  0
         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  0
         if ( str == null )
 1793  
         {
 1794  0
             return false;
 1795  
         }
 1796  0
         int sz = str.length();
 1797  0
         for ( int i = 0; i < sz; i++ )
 1798  
         {
 1799  0
             if ( ( Character.isLetterOrDigit( str.charAt( i ) ) == false ) &&
 1800  
                 ( str.charAt( i ) != ' ' ) )
 1801  
             {
 1802  0
                 return false;
 1803  
             }
 1804  
         }
 1805  0
         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  0
         if ( str == null )
 1820  
         {
 1821  0
             return false;
 1822  
         }
 1823  0
         int sz = str.length();
 1824  0
         for ( int i = 0; i < sz; i++ )
 1825  
         {
 1826  0
             if ( Character.isDigit( str.charAt( i ) ) == false )
 1827  
             {
 1828  0
                 return false;
 1829  
             }
 1830  
         }
 1831  0
         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  0
         if ( str == null )
 1848  
         {
 1849  0
             return false;
 1850  
         }
 1851  0
         int sz = str.length();
 1852  0
         for ( int i = 0; i < sz; i++ )
 1853  
         {
 1854  0
             if ( ( Character.isDigit( str.charAt( i ) ) == false ) &&
 1855  
                 ( str.charAt( i ) != ' ' ) )
 1856  
             {
 1857  0
                 return false;
 1858  
             }
 1859  
         }
 1860  0
         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  0
         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  0
         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  0
         if ( str == null )
 1910  
         {
 1911  0
             return null;
 1912  
         }
 1913  0
         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  0
         String[] strs = split( str, delimiter );
 1932  0
         reverseArray( strs );
 1933  0
         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  0
         int i = 0;
 1946  0
         int j = array.length - 1;
 1947  
         Object tmp;
 1948  
 
 1949  0
         while ( j > i )
 1950  
         {
 1951  0
             tmp = array[j];
 1952  0
             array[j] = array[i];
 1953  0
             array[i] = tmp;
 1954  0
             j--;
 1955  0
             i++;
 1956  
         }
 1957  0
     }
 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  0
         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  0
         if ( maxWidth < 4 )
 1994  0
             throw new IllegalArgumentException( "Minimum abbreviation width is 4" );
 1995  0
         if ( s.length() <= maxWidth )
 1996  0
             return s;
 1997  0
         if ( offset > s.length() )
 1998  0
             offset = s.length();
 1999  0
         if ( ( s.length() - offset ) < ( maxWidth - 3 ) )
 2000  0
             offset = s.length() - ( maxWidth - 3 );
 2001  0
         if ( offset <= 4 )
 2002  0
             return s.substring( 0, maxWidth - 3 ) + "...";
 2003  0
         if ( maxWidth < 7 )
 2004  0
             throw new IllegalArgumentException( "Minimum abbreviation width with offset is 7" );
 2005  0
         if ( ( offset + ( maxWidth - 3 ) ) < s.length() )
 2006  0
             return "..." + abbreviate( s.substring( offset ), maxWidth - 3 );
 2007  0
         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  0
         int at = differenceAt( s1, s2 );
 2025  0
         if ( at == -1 )
 2026  0
             return "";
 2027  0
         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  0
         for ( i = 0; i < s1.length() && i < s2.length(); ++i )
 2042  
         {
 2043  0
             if ( s1.charAt( i ) != s2.charAt( i ) )
 2044  
             {
 2045  0
                 break;
 2046  
             }
 2047  
         }
 2048  0
         if ( i < s2.length() || i < s1.length() )
 2049  
         {
 2050  0
             return i;
 2051  
         }
 2052  0
         return -1;
 2053  
     }
 2054  
 
 2055  
     public static String interpolate( String text, Map namespace )
 2056  
     {
 2057  0
         Iterator keys = namespace.keySet().iterator();
 2058  
 
 2059  0
         while ( keys.hasNext() )
 2060  
         {
 2061  0
             String key = keys.next().toString();
 2062  
 
 2063  0
             Object obj = namespace.get( key );
 2064  
 
 2065  0
             if ( obj == null )
 2066  
             {
 2067  0
                 throw new NullPointerException( "The value of the key '" + key + "' is null." );
 2068  
             }
 2069  
 
 2070  0
             String value = obj.toString();
 2071  
 
 2072  0
             text = StringUtils.replace( text, "${" + key + "}", value );
 2073  
 
 2074  0
             if ( key.indexOf( " " ) == -1 )
 2075  
             {
 2076  0
                 text = StringUtils.replace( text, "$" + key, value );
 2077  
             }
 2078  0
         }
 2079  0
         return text;
 2080  
     }
 2081  
 
 2082  
     public static String removeAndHump( String data, String replaceThis )
 2083  
     {
 2084  
         String temp;
 2085  
 
 2086  0
         StringBuffer out = new StringBuffer();
 2087  
 
 2088  0
         temp = data;
 2089  
 
 2090  0
         StringTokenizer st = new StringTokenizer( temp, replaceThis );
 2091  
 
 2092  0
         while ( st.hasMoreTokens() )
 2093  
         {
 2094  0
             String element = (String) st.nextElement();
 2095  
 
 2096  0
             out.append( capitalizeFirstLetter( element ) );
 2097  0
         }
 2098  
 
 2099  0
         return out.toString();
 2100  
     }
 2101  
 
 2102  
     public static String capitalizeFirstLetter( String data )
 2103  
     {
 2104  0
         char firstLetter = Character.toTitleCase( data.substring( 0, 1 ).charAt( 0 ) );
 2105  
 
 2106  0
         String restLetters = data.substring( 1 );
 2107  
 
 2108  0
         return firstLetter + restLetters;
 2109  
     }
 2110  
 
 2111  
     public static String lowercaseFirstLetter( String data )
 2112  
     {
 2113  0
         char firstLetter = Character.toLowerCase( data.substring( 0, 1 ).charAt( 0 ) );
 2114  
 
 2115  0
         String restLetters = data.substring( 1 );
 2116  
 
 2117  0
         return firstLetter + restLetters;
 2118  
     }
 2119  
 
 2120  
     public static String addAndDeHump( String view )
 2121  
     {
 2122  0
         StringBuffer sb = new StringBuffer();
 2123  
 
 2124  0
         for ( int i = 0; i < view.length(); i++ )
 2125  
         {
 2126  0
             if ( i != 0 && Character.isUpperCase( view.charAt( i ) ) )
 2127  
             {
 2128  0
                 sb.append( '-' );
 2129  
             }
 2130  
 
 2131  0
             sb.append( view.charAt( i ) );
 2132  
         }
 2133  
 
 2134  0
         return sb.toString().trim().toLowerCase();
 2135  
     }
 2136  
 }