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