Save This Page
Home » commons-lang-2.5-src » org.apache.commons » lang » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   package org.apache.commons.lang;
   18   
   19   import java.util.ArrayList;
   20   import java.util.Collection;
   21   import java.util.Iterator;
   22   import java.util.List;
   23   import java.util.Locale;
   24   
   25   /**
   26    * <p>Operations on {@link java.lang.String} that are
   27    * <code>null</code> safe.</p>
   28    *
   29    * <ul>
   30    *  <li><b>IsEmpty/IsBlank</b>
   31    *      - checks if a String contains text</li>
   32    *  <li><b>Trim/Strip</b>
   33    *      - removes leading and trailing whitespace</li>
   34    *  <li><b>Equals</b>
   35    *      - compares two strings null-safe</li>
   36    *  <li><b>startsWith</b>
   37    *      - check if a String starts with a prefix null-safe</li>
   38    *  <li><b>endsWith</b>
   39    *      - check if a String ends with a suffix null-safe</li>
   40    *  <li><b>IndexOf/LastIndexOf/Contains</b>
   41    *      - null-safe index-of checks
   42    *  <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>
   43    *      - index-of any of a set of Strings</li>
   44    *  <li><b>ContainsOnly/ContainsNone/ContainsAny</b>
   45    *      - does String contains only/none/any of these characters</li>
   46    *  <li><b>Substring/Left/Right/Mid</b>
   47    *      - null-safe substring extractions</li>
   48    *  <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>
   49    *      - substring extraction relative to other strings</li>
   50    *  <li><b>Split/Join</b>
   51    *      - splits a String into an array of substrings and vice versa</li>
   52    *  <li><b>Remove/Delete</b>
   53    *      - removes part of a String</li>
   54    *  <li><b>Replace/Overlay</b>
   55    *      - Searches a String and replaces one String with another</li>
   56    *  <li><b>Chomp/Chop</b>
   57    *      - removes the last part of a String</li>
   58    *  <li><b>LeftPad/RightPad/Center/Repeat</b>
   59    *      - pads a String</li>
   60    *  <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>
   61    *      - changes the case of a String</li>
   62    *  <li><b>CountMatches</b>
   63    *      - counts the number of occurrences of one String in another</li>
   64    *  <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>
   65    *      - checks the characters in a String</li>
   66    *  <li><b>DefaultString</b>
   67    *      - protects against a null input String</li>
   68    *  <li><b>Reverse/ReverseDelimited</b>
   69    *      - reverses a String</li>
   70    *  <li><b>Abbreviate</b>
   71    *      - abbreviates a string using ellipsis</li>
   72    *  <li><b>Difference</b>
   73    *      - compares Strings and reports on their differences</li>
   74    *  <li><b>LevensteinDistance</b>
   75    *      - the number of changes needed to change one String into another</li>
   76    * </ul>
   77    *
   78    * <p>The <code>StringUtils</code> class defines certain words related to
   79    * String handling.</p>
   80    *
   81    * <ul>
   82    *  <li>null - <code>null</code></li>
   83    *  <li>empty - a zero-length string (<code>""</code>)</li>
   84    *  <li>space - the space character (<code>' '</code>, char 32)</li>
   85    *  <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
   86    *  <li>trim - the characters &lt;= 32 as in {@link String#trim()}</li>
   87    * </ul>
   88    *
   89    * <p><code>StringUtils</code> handles <code>null</code> input Strings quietly.
   90    * That is to say that a <code>null</code> input will return <code>null</code>.
   91    * Where a <code>boolean</code> or <code>int</code> is being returned
   92    * details vary by method.</p>
   93    *
   94    * <p>A side effect of the <code>null</code> handling is that a
   95    * <code>NullPointerException</code> should be considered a bug in
   96    * <code>StringUtils</code> (except for deprecated methods).</p>
   97    *
   98    * <p>Methods in this class give sample code to explain their operation.
   99    * The symbol <code>*</code> is used to indicate any input including <code>null</code>.</p>
  100    *
  101    * @see java.lang.String
  102    * @author Apache Software Foundation
  103    * @author <a href="http://jakarta.apache.org/turbine/">Apache Jakarta Turbine</a>
  104    * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
  105    * @author Daniel L. Rall
  106    * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
  107    * @author <a href="mailto:ed@apache.org">Ed Korthof</a>
  108    * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
  109    * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
  110    * @author Holger Krauth
  111    * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
  112    * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  113    * @author Arun Mammen Thomas
  114    * @author Gary Gregory
  115    * @author Phil Steitz
  116    * @author Al Chou
  117    * @author Michael Davey
  118    * @author Reuben Sivan
  119    * @author Chris Hyzer
  120    * @author Scott Johnson
  121    * @since 1.0
  122    * @version $Id: StringUtils.java 911986 2010-02-19 21:19:05Z niallp $
  123    */
  124   public class StringUtils {
  125       // Performance testing notes (JDK 1.4, Jul03, scolebourne)
  126       // Whitespace:
  127       // Character.isWhitespace() is faster than WHITESPACE.indexOf()
  128       // where WHITESPACE is a string of all whitespace characters
  129       //
  130       // Character access:
  131       // String.charAt(n) versus toCharArray(), then array[n]
  132       // String.charAt(n) is about 15% worse for a 10K string
  133       // They are about equal for a length 50 string
  134       // String.charAt(n) is about 4 times better for a length 3 string
  135       // String.charAt(n) is best bet overall
  136       //
  137       // Append:
  138       // String.concat about twice as fast as StringBuffer.append
  139       // (not sure who tested this)
  140   
  141       /**
  142        * The empty String <code>""</code>.
  143        * @since 2.0
  144        */
  145       public static final String EMPTY = "";
  146   
  147       /**
  148        * Represents a failed index search.
  149        * @since 2.1
  150        */
  151       public static final int INDEX_NOT_FOUND = -1;
  152   
  153       /**
  154        * <p>The maximum size to which the padding constant(s) can expand.</p>
  155        */
  156       private static final int PAD_LIMIT = 8192;
  157   
  158       /**
  159        * <p><code>StringUtils</code> instances should NOT be constructed in
  160        * standard programming. Instead, the class should be used as
  161        * <code>StringUtils.trim(" foo ");</code>.</p>
  162        *
  163        * <p>This constructor is public to permit tools that require a JavaBean
  164        * instance to operate.</p>
  165        */
  166       public StringUtils() {
  167           super();
  168       }
  169   
  170       // Empty checks
  171       //-----------------------------------------------------------------------
  172       /**
  173        * <p>Checks if a String is empty ("") or null.</p>
  174        *
  175        * <pre>
  176        * StringUtils.isEmpty(null)      = true
  177        * StringUtils.isEmpty("")        = true
  178        * StringUtils.isEmpty(" ")       = false
  179        * StringUtils.isEmpty("bob")     = false
  180        * StringUtils.isEmpty("  bob  ") = false
  181        * </pre>
  182        *
  183        * <p>NOTE: This method changed in Lang version 2.0.
  184        * It no longer trims the String.
  185        * That functionality is available in isBlank().</p>
  186        *
  187        * @param str  the String to check, may be null
  188        * @return <code>true</code> if the String is empty or null
  189        */
  190       public static boolean isEmpty(String str) {
  191           return str == null || str.length() == 0;
  192       }
  193   
  194       /**
  195        * <p>Checks if a String is not empty ("") and not null.</p>
  196        *
  197        * <pre>
  198        * StringUtils.isNotEmpty(null)      = false
  199        * StringUtils.isNotEmpty("")        = false
  200        * StringUtils.isNotEmpty(" ")       = true
  201        * StringUtils.isNotEmpty("bob")     = true
  202        * StringUtils.isNotEmpty("  bob  ") = true
  203        * </pre>
  204        *
  205        * @param str  the String to check, may be null
  206        * @return <code>true</code> if the String is not empty and not null
  207        */
  208       public static boolean isNotEmpty(String str) {
  209           return !StringUtils.isEmpty(str);
  210       }
  211   
  212       /**
  213        * <p>Checks if a String is whitespace, empty ("") or null.</p>
  214        *
  215        * <pre>
  216        * StringUtils.isBlank(null)      = true
  217        * StringUtils.isBlank("")        = true
  218        * StringUtils.isBlank(" ")       = true
  219        * StringUtils.isBlank("bob")     = false
  220        * StringUtils.isBlank("  bob  ") = false
  221        * </pre>
  222        *
  223        * @param str  the String to check, may be null
  224        * @return <code>true</code> if the String is null, empty or whitespace
  225        * @since 2.0
  226        */
  227       public static boolean isBlank(String str) {
  228           int strLen;
  229           if (str == null || (strLen = str.length()) == 0) {
  230               return true;
  231           }
  232           for (int i = 0; i < strLen; i++) {
  233               if ((Character.isWhitespace(str.charAt(i)) == false)) {
  234                   return false;
  235               }
  236           }
  237           return true;
  238       }
  239   
  240       /**
  241        * <p>Checks if a String is not empty (""), not null and not whitespace only.</p>
  242        *
  243        * <pre>
  244        * StringUtils.isNotBlank(null)      = false
  245        * StringUtils.isNotBlank("")        = false
  246        * StringUtils.isNotBlank(" ")       = false
  247        * StringUtils.isNotBlank("bob")     = true
  248        * StringUtils.isNotBlank("  bob  ") = true
  249        * </pre>
  250        *
  251        * @param str  the String to check, may be null
  252        * @return <code>true</code> if the String is
  253        *  not empty and not null and not whitespace
  254        * @since 2.0
  255        */
  256       public static boolean isNotBlank(String str) {
  257           return !StringUtils.isBlank(str);
  258       }
  259   
  260       // Trim
  261       //-----------------------------------------------------------------------
  262       /**
  263        * <p>Removes control characters (char &lt;= 32) from both
  264        * ends of this String, handling <code>null</code> by returning
  265        * an empty String ("").</p>
  266        *
  267        * <pre>
  268        * StringUtils.clean(null)          = ""
  269        * StringUtils.clean("")            = ""
  270        * StringUtils.clean("abc")         = "abc"
  271        * StringUtils.clean("    abc    ") = "abc"
  272        * StringUtils.clean("     ")       = ""
  273        * </pre>
  274        *
  275        * @see java.lang.String#trim()
  276        * @param str  the String to clean, may be null
  277        * @return the trimmed text, never <code>null</code>
  278        * @deprecated Use the clearer named {@link #trimToEmpty(String)}.
  279        *             Method will be removed in Commons Lang 3.0.
  280        */
  281       public static String clean(String str) {
  282           return str == null ? EMPTY : str.trim();
  283       }
  284   
  285       /**
  286        * <p>Removes control characters (char &lt;= 32) from both
  287        * ends of this String, handling <code>null</code> by returning
  288        * <code>null</code>.</p>
  289        *
  290        * <p>The String is trimmed using {@link String#trim()}.
  291        * Trim removes start and end characters &lt;= 32.
  292        * To strip whitespace use {@link #strip(String)}.</p>
  293        *
  294        * <p>To trim your choice of characters, use the
  295        * {@link #strip(String, String)} methods.</p>
  296        *
  297        * <pre>
  298        * StringUtils.trim(null)          = null
  299        * StringUtils.trim("")            = ""
  300        * StringUtils.trim("     ")       = ""
  301        * StringUtils.trim("abc")         = "abc"
  302        * StringUtils.trim("    abc    ") = "abc"
  303        * </pre>
  304        *
  305        * @param str  the String to be trimmed, may be null
  306        * @return the trimmed string, <code>null</code> if null String input
  307        */
  308       public static String trim(String str) {
  309           return str == null ? null : str.trim();
  310       }
  311   
  312       /**
  313        * <p>Removes control characters (char &lt;= 32) from both
  314        * ends of this String returning <code>null</code> if the String is
  315        * empty ("") after the trim or if it is <code>null</code>.
  316        *
  317        * <p>The String is trimmed using {@link String#trim()}.
  318        * Trim removes start and end characters &lt;= 32.
  319        * To strip whitespace use {@link #stripToNull(String)}.</p>
  320        *
  321        * <pre>
  322        * StringUtils.trimToNull(null)          = null
  323        * StringUtils.trimToNull("")            = null
  324        * StringUtils.trimToNull("     ")       = null
  325        * StringUtils.trimToNull("abc")         = "abc"
  326        * StringUtils.trimToNull("    abc    ") = "abc"
  327        * </pre>
  328        *
  329        * @param str  the String to be trimmed, may be null
  330        * @return the trimmed String,
  331        *  <code>null</code> if only chars &lt;= 32, empty or null String input
  332        * @since 2.0
  333        */
  334       public static String trimToNull(String str) {
  335           String ts = trim(str);
  336           return isEmpty(ts) ? null : ts;
  337       }
  338   
  339       /**
  340        * <p>Removes control characters (char &lt;= 32) from both
  341        * ends of this String returning an empty String ("") if the String
  342        * is empty ("") after the trim or if it is <code>null</code>.
  343        *
  344        * <p>The String is trimmed using {@link String#trim()}.
  345        * Trim removes start and end characters &lt;= 32.
  346        * To strip whitespace use {@link #stripToEmpty(String)}.</p>
  347        *
  348        * <pre>
  349        * StringUtils.trimToEmpty(null)          = ""
  350        * StringUtils.trimToEmpty("")            = ""
  351        * StringUtils.trimToEmpty("     ")       = ""
  352        * StringUtils.trimToEmpty("abc")         = "abc"
  353        * StringUtils.trimToEmpty("    abc    ") = "abc"
  354        * </pre>
  355        *
  356        * @param str  the String to be trimmed, may be null
  357        * @return the trimmed String, or an empty String if <code>null</code> input
  358        * @since 2.0
  359        */
  360       public static String trimToEmpty(String str) {
  361           return str == null ? EMPTY : str.trim();
  362       }
  363   
  364       // Stripping
  365       //-----------------------------------------------------------------------
  366       /**
  367        * <p>Strips whitespace from the start and end of a String.</p>
  368        *
  369        * <p>This is similar to {@link #trim(String)} but removes whitespace.
  370        * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  371        *
  372        * <p>A <code>null</code> input String returns <code>null</code>.</p>
  373        *
  374        * <pre>
  375        * StringUtils.strip(null)     = null
  376        * StringUtils.strip("")       = ""
  377        * StringUtils.strip("   ")    = ""
  378        * StringUtils.strip("abc")    = "abc"
  379        * StringUtils.strip("  abc")  = "abc"
  380        * StringUtils.strip("abc  ")  = "abc"
  381        * StringUtils.strip(" abc ")  = "abc"
  382        * StringUtils.strip(" ab c ") = "ab c"
  383        * </pre>
  384        *
  385        * @param str  the String to remove whitespace from, may be null
  386        * @return the stripped String, <code>null</code> if null String input
  387        */
  388       public static String strip(String str) {
  389           return strip(str, null);
  390       }
  391   
  392       /**
  393        * <p>Strips whitespace from the start and end of a String  returning
  394        * <code>null</code> if the String is empty ("") after the strip.</p>
  395        *
  396        * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.
  397        * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  398        *
  399        * <pre>
  400        * StringUtils.stripToNull(null)     = null
  401        * StringUtils.stripToNull("")       = null
  402        * StringUtils.stripToNull("   ")    = null
  403        * StringUtils.stripToNull("abc")    = "abc"
  404        * StringUtils.stripToNull("  abc")  = "abc"
  405        * StringUtils.stripToNull("abc  ")  = "abc"
  406        * StringUtils.stripToNull(" abc ")  = "abc"
  407        * StringUtils.stripToNull(" ab c ") = "ab c"
  408        * </pre>
  409        *
  410        * @param str  the String to be stripped, may be null
  411        * @return the stripped String,
  412        *  <code>null</code> if whitespace, empty or null String input
  413        * @since 2.0
  414        */
  415       public static String stripToNull(String str) {
  416           if (str == null) {
  417               return null;
  418           }
  419           str = strip(str, null);
  420           return str.length() == 0 ? null : str;
  421       }
  422   
  423       /**
  424        * <p>Strips whitespace from the start and end of a String  returning
  425        * an empty String if <code>null</code> input.</p>
  426        *
  427        * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.
  428        * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  429        *
  430        * <pre>
  431        * StringUtils.stripToEmpty(null)     = ""
  432        * StringUtils.stripToEmpty("")       = ""
  433        * StringUtils.stripToEmpty("   ")    = ""
  434        * StringUtils.stripToEmpty("abc")    = "abc"
  435        * StringUtils.stripToEmpty("  abc")  = "abc"
  436        * StringUtils.stripToEmpty("abc  ")  = "abc"
  437        * StringUtils.stripToEmpty(" abc ")  = "abc"
  438        * StringUtils.stripToEmpty(" ab c ") = "ab c"
  439        * </pre>
  440        *
  441        * @param str  the String to be stripped, may be null
  442        * @return the trimmed String, or an empty String if <code>null</code> input
  443        * @since 2.0
  444        */
  445       public static String stripToEmpty(String str) {
  446           return str == null ? EMPTY : strip(str, null);
  447       }
  448   
  449       /**
  450        * <p>Strips any of a set of characters from the start and end of a String.
  451        * This is similar to {@link String#trim()} but allows the characters
  452        * to be stripped to be controlled.</p>
  453        *
  454        * <p>A <code>null</code> input String returns <code>null</code>.
  455        * An empty string ("") input returns the empty string.</p>
  456        *
  457        * <p>If the stripChars String is <code>null</code>, whitespace is
  458        * stripped as defined by {@link Character#isWhitespace(char)}.
  459        * Alternatively use {@link #strip(String)}.</p>
  460        *
  461        * <pre>
  462        * StringUtils.strip(null, *)          = null
  463        * StringUtils.strip("", *)            = ""
  464        * StringUtils.strip("abc", null)      = "abc"
  465        * StringUtils.strip("  abc", null)    = "abc"
  466        * StringUtils.strip("abc  ", null)    = "abc"
  467        * StringUtils.strip(" abc ", null)    = "abc"
  468        * StringUtils.strip("  abcyx", "xyz") = "  abc"
  469        * </pre>
  470        *
  471        * @param str  the String to remove characters from, may be null
  472        * @param stripChars  the characters to remove, null treated as whitespace
  473        * @return the stripped String, <code>null</code> if null String input
  474        */
  475       public static String strip(String str, String stripChars) {
  476           if (isEmpty(str)) {
  477               return str;
  478           }
  479           str = stripStart(str, stripChars);
  480           return stripEnd(str, stripChars);
  481       }
  482   
  483       /**
  484        * <p>Strips any of a set of characters from the start of a String.</p>
  485        *
  486        * <p>A <code>null</code> input String returns <code>null</code>.
  487        * An empty string ("") input returns the empty string.</p>
  488        *
  489        * <p>If the stripChars String is <code>null</code>, whitespace is
  490        * stripped as defined by {@link Character#isWhitespace(char)}.</p>
  491        *
  492        * <pre>
  493        * StringUtils.stripStart(null, *)          = null
  494        * StringUtils.stripStart("", *)            = ""
  495        * StringUtils.stripStart("abc", "")        = "abc"
  496        * StringUtils.stripStart("abc", null)      = "abc"
  497        * StringUtils.stripStart("  abc", null)    = "abc"
  498        * StringUtils.stripStart("abc  ", null)    = "abc  "
  499        * StringUtils.stripStart(" abc ", null)    = "abc "
  500        * StringUtils.stripStart("yxabc  ", "xyz") = "abc  "
  501        * </pre>
  502        *
  503        * @param str  the String to remove characters from, may be null
  504        * @param stripChars  the characters to remove, null treated as whitespace
  505        * @return the stripped String, <code>null</code> if null String input
  506        */
  507       public static String stripStart(String str, String stripChars) {
  508           int strLen;
  509           if (str == null || (strLen = str.length()) == 0) {
  510               return str;
  511           }
  512           int start = 0;
  513           if (stripChars == null) {
  514               while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {
  515                   start++;
  516               }
  517           } else if (stripChars.length() == 0) {
  518               return str;
  519           } else {
  520               while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != -1)) {
  521                   start++;
  522               }
  523           }
  524           return str.substring(start);
  525       }
  526   
  527       /**
  528        * <p>Strips any of a set of characters from the end of a String.</p>
  529        *
  530        * <p>A <code>null</code> input String returns <code>null</code>.
  531        * An empty string ("") input returns the empty string.</p>
  532        *
  533        * <p>If the stripChars String is <code>null</code>, whitespace is
  534        * stripped as defined by {@link Character#isWhitespace(char)}.</p>
  535        *
  536        * <pre>
  537        * StringUtils.stripEnd(null, *)          = null
  538        * StringUtils.stripEnd("", *)            = ""
  539        * StringUtils.stripEnd("abc", "")        = "abc"
  540        * StringUtils.stripEnd("abc", null)      = "abc"
  541        * StringUtils.stripEnd("  abc", null)    = "  abc"
  542        * StringUtils.stripEnd("abc  ", null)    = "abc"
  543        * StringUtils.stripEnd(" abc ", null)    = " abc"
  544        * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
  545        * </pre>
  546        *
  547        * @param str  the String to remove characters from, may be null
  548        * @param stripChars  the characters to remove, null treated as whitespace
  549        * @return the stripped String, <code>null</code> if null String input
  550        */
  551       public static String stripEnd(String str, String stripChars) {
  552           int end;
  553           if (str == null || (end = str.length()) == 0) {
  554               return str;
  555           }
  556   
  557           if (stripChars == null) {
  558               while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
  559                   end--;
  560               }
  561           } else if (stripChars.length() == 0) {
  562               return str;
  563           } else {
  564               while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) {
  565                   end--;
  566               }
  567           }
  568           return str.substring(0, end);
  569       }
  570   
  571       // StripAll
  572       //-----------------------------------------------------------------------
  573       /**
  574        * <p>Strips whitespace from the start and end of every String in an array.
  575        * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  576        *
  577        * <p>A new array is returned each time, except for length zero.
  578        * A <code>null</code> array will return <code>null</code>.
  579        * An empty array will return itself.
  580        * A <code>null</code> array entry will be ignored.</p>
  581        *
  582        * <pre>
  583        * StringUtils.stripAll(null)             = null
  584        * StringUtils.stripAll([])               = []
  585        * StringUtils.stripAll(["abc", "  abc"]) = ["abc", "abc"]
  586        * StringUtils.stripAll(["abc  ", null])  = ["abc", null]
  587        * </pre>
  588        *
  589        * @param strs  the array to remove whitespace from, may be null
  590        * @return the stripped Strings, <code>null</code> if null array input
  591        */
  592       public static String[] stripAll(String[] strs) {
  593           return stripAll(strs, null);
  594       }
  595   
  596       /**
  597        * <p>Strips any of a set of characters from the start and end of every
  598        * String in an array.</p>
  599        * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  600        *
  601        * <p>A new array is returned each time, except for length zero.
  602        * A <code>null</code> array will return <code>null</code>.
  603        * An empty array will return itself.
  604        * A <code>null</code> array entry will be ignored.
  605        * A <code>null</code> stripChars will strip whitespace as defined by
  606        * {@link Character#isWhitespace(char)}.</p>
  607        *
  608        * <pre>
  609        * StringUtils.stripAll(null, *)                = null
  610        * StringUtils.stripAll([], *)                  = []
  611        * StringUtils.stripAll(["abc", "  abc"], null) = ["abc", "abc"]
  612        * StringUtils.stripAll(["abc  ", null], null)  = ["abc", null]
  613        * StringUtils.stripAll(["abc  ", null], "yz")  = ["abc  ", null]
  614        * StringUtils.stripAll(["yabcz", null], "yz")  = ["abc", null]
  615        * </pre>
  616        *
  617        * @param strs  the array to remove characters from, may be null
  618        * @param stripChars  the characters to remove, null treated as whitespace
  619        * @return the stripped Strings, <code>null</code> if null array input
  620        */
  621       public static String[] stripAll(String[] strs, String stripChars) {
  622           int strsLen;
  623           if (strs == null || (strsLen = strs.length) == 0) {
  624               return strs;
  625           }
  626           String[] newArr = new String[strsLen];
  627           for (int i = 0; i < strsLen; i++) {
  628               newArr[i] = strip(strs[i], stripChars);
  629           }
  630           return newArr;
  631       }
  632   
  633       // Equals
  634       //-----------------------------------------------------------------------
  635       /**
  636        * <p>Compares two Strings, returning <code>true</code> if they are equal.</p>
  637        *
  638        * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
  639        * references are considered to be equal. The comparison is case sensitive.</p>
  640        *
  641        * <pre>
  642        * StringUtils.equals(null, null)   = true
  643        * StringUtils.equals(null, "abc")  = false
  644        * StringUtils.equals("abc", null)  = false
  645        * StringUtils.equals("abc", "abc") = true
  646        * StringUtils.equals("abc", "ABC") = false
  647        * </pre>
  648        *
  649        * @see java.lang.String#equals(Object)
  650        * @param str1  the first String, may be null
  651        * @param str2  the second String, may be null
  652        * @return <code>true</code> if the Strings are equal, case sensitive, or
  653        *  both <code>null</code>
  654        */
  655       public static boolean equals(String str1, String str2) {
  656           return str1 == null ? str2 == null : str1.equals(str2);
  657       }
  658   
  659       /**
  660        * <p>Compares two Strings, returning <code>true</code> if they are equal ignoring
  661        * the case.</p>
  662        *
  663        * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
  664        * references are considered equal. Comparison is case insensitive.</p>
  665        *
  666        * <pre>
  667        * StringUtils.equalsIgnoreCase(null, null)   = true
  668        * StringUtils.equalsIgnoreCase(null, "abc")  = false
  669        * StringUtils.equalsIgnoreCase("abc", null)  = false
  670        * StringUtils.equalsIgnoreCase("abc", "abc") = true
  671        * StringUtils.equalsIgnoreCase("abc", "ABC") = true
  672        * </pre>
  673        *
  674        * @see java.lang.String#equalsIgnoreCase(String)
  675        * @param str1  the first String, may be null
  676        * @param str2  the second String, may be null
  677        * @return <code>true</code> if the Strings are equal, case insensitive, or
  678        *  both <code>null</code>
  679        */
  680       public static boolean equalsIgnoreCase(String str1, String str2) {
  681           return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
  682       }
  683   
  684       // IndexOf
  685       //-----------------------------------------------------------------------
  686       /**
  687        * <p>Finds the first index within a String, handling <code>null</code>.
  688        * This method uses {@link String#indexOf(int)}.</p>
  689        *
  690        * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.</p>
  691        *
  692        * <pre>
  693        * StringUtils.indexOf(null, *)         = -1
  694        * StringUtils.indexOf("", *)           = -1
  695        * StringUtils.indexOf("aabaabaa", 'a') = 0
  696        * StringUtils.indexOf("aabaabaa", 'b') = 2
  697        * </pre>
  698        *
  699        * @param str  the String to check, may be null
  700        * @param searchChar  the character to find
  701        * @return the first index of the search character,
  702        *  -1 if no match or <code>null</code> string input
  703        * @since 2.0
  704        */
  705       public static int indexOf(String str, char searchChar) {
  706           if (isEmpty(str)) {
  707               return -1;
  708           }
  709           return str.indexOf(searchChar);
  710       }
  711   
  712       /**
  713        * <p>Finds the first index within a String from a start position,
  714        * handling <code>null</code>.
  715        * This method uses {@link String#indexOf(int, int)}.</p>
  716        *
  717        * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.
  718        * A negative start position is treated as zero.
  719        * A start position greater than the string length returns <code>-1</code>.</p>
  720        *
  721        * <pre>
  722        * StringUtils.indexOf(null, *, *)          = -1
  723        * StringUtils.indexOf("", *, *)            = -1
  724        * StringUtils.indexOf("aabaabaa", 'b', 0)  = 2
  725        * StringUtils.indexOf("aabaabaa", 'b', 3)  = 5
  726        * StringUtils.indexOf("aabaabaa", 'b', 9)  = -1
  727        * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
  728        * </pre>
  729        *
  730        * @param str  the String to check, may be null
  731        * @param searchChar  the character to find
  732        * @param startPos  the start position, negative treated as zero
  733        * @return the first index of the search character,
  734        *  -1 if no match or <code>null</code> string input
  735        * @since 2.0
  736        */
  737       public static int indexOf(String str, char searchChar, int startPos) {
  738           if (isEmpty(str)) {
  739               return -1;
  740           }
  741           return str.indexOf(searchChar, startPos);
  742       }
  743   
  744       /**
  745        * <p>Finds the first index within a String, handling <code>null</code>.
  746        * This method uses {@link String#indexOf(String)}.</p>
  747        *
  748        * <p>A <code>null</code> String will return <code>-1</code>.</p>
  749        *
  750        * <pre>
  751        * StringUtils.indexOf(null, *)          = -1
  752        * StringUtils.indexOf(*, null)          = -1
  753        * StringUtils.indexOf("", "")           = 0
  754        * StringUtils.indexOf("aabaabaa", "a")  = 0
  755        * StringUtils.indexOf("aabaabaa", "b")  = 2
  756        * StringUtils.indexOf("aabaabaa", "ab") = 1
  757        * StringUtils.indexOf("aabaabaa", "")   = 0
  758        * </pre>
  759        *
  760        * @param str  the String to check, may be null
  761        * @param searchStr  the String to find, may be null
  762        * @return the first index of the search String,
  763        *  -1 if no match or <code>null</code> string input
  764        * @since 2.0
  765        */
  766       public static int indexOf(String str, String searchStr) {
  767           if (str == null || searchStr == null) {
  768               return -1;
  769           }
  770           return str.indexOf(searchStr);
  771       }
  772   
  773       /**
  774        * <p>Finds the n-th index within a String, handling <code>null</code>.
  775        * This method uses {@link String#indexOf(String)}.</p>
  776        *
  777        * <p>A <code>null</code> String will return <code>-1</code>.</p>
  778        *
  779        * <pre>
  780        * StringUtils.ordinalIndexOf(null, *, *)          = -1
  781        * StringUtils.ordinalIndexOf(*, null, *)          = -1
  782        * StringUtils.ordinalIndexOf("", "", *)           = 0
  783        * StringUtils.ordinalIndexOf("aabaabaa", "a", 1)  = 0
  784        * StringUtils.ordinalIndexOf("aabaabaa", "a", 2)  = 1
  785        * StringUtils.ordinalIndexOf("aabaabaa", "b", 1)  = 2
  786        * StringUtils.ordinalIndexOf("aabaabaa", "b", 2)  = 5
  787        * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
  788        * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
  789        * StringUtils.ordinalIndexOf("aabaabaa", "", 1)   = 0
  790        * StringUtils.ordinalIndexOf("aabaabaa", "", 2)   = 0
  791        * </pre>
  792        *
  793        * <p>Note that 'head(String str, int n)' may be implemented as: </p>
  794        *
  795        * <pre>
  796        *   str.substring(0, lastOrdinalIndexOf(str, "\n", n))
  797        * </pre>
  798        *
  799        * @param str  the String to check, may be null
  800        * @param searchStr  the String to find, may be null
  801        * @param ordinal  the n-th <code>searchStr</code> to find
  802        * @return the n-th index of the search String,
  803        *  <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
  804        * @since 2.1
  805        */
  806       public static int ordinalIndexOf(String str, String searchStr, int ordinal) {
  807           return ordinalIndexOf(str, searchStr, ordinal, false);
  808       }
  809   
  810       /**
  811        * <p>Finds the n-th index within a String, handling <code>null</code>.
  812        * This method uses {@link String#indexOf(String)}.</p>
  813        *
  814        * <p>A <code>null</code> String will return <code>-1</code>.</p>
  815        *
  816        * @param str  the String to check, may be null
  817        * @param searchStr  the String to find, may be null
  818        * @param ordinal  the n-th <code>searchStr</code> to find
  819        * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
  820        * @return the n-th index of the search String,
  821        *  <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
  822        */
  823       // Shared code between ordinalIndexOf(String,String,int) and lastOrdinalIndexOf(String,String,int)
  824       private static int ordinalIndexOf(String str, String searchStr, int ordinal, boolean lastIndex) {
  825           if (str == null || searchStr == null || ordinal <= 0) {
  826               return INDEX_NOT_FOUND;
  827           }
  828           if (searchStr.length() == 0) {
  829               return lastIndex ? str.length() : 0;
  830           }
  831           int found = 0;
  832           int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
  833           do {
  834               if(lastIndex) {
  835                   index = str.lastIndexOf(searchStr, index - 1);
  836               } else {
  837                   index = str.indexOf(searchStr, index + 1);
  838               }
  839               if (index < 0) {
  840                   return index;
  841               }
  842               found++;
  843           } while (found < ordinal);
  844           return index;
  845       }
  846   
  847       /**
  848        * <p>Finds the first index within a String, handling <code>null</code>.
  849        * This method uses {@link String#indexOf(String, int)}.</p>
  850        *
  851        * <p>A <code>null</code> String will return <code>-1</code>.
  852        * A negative start position is treated as zero.
  853        * An empty ("") search String always matches.
  854        * A start position greater than the string length only matches
  855        * an empty search String.</p>
  856        *
  857        * <pre>
  858        * StringUtils.indexOf(null, *, *)          = -1
  859        * StringUtils.indexOf(*, null, *)          = -1
  860        * StringUtils.indexOf("", "", 0)           = 0
  861        * StringUtils.indexOf("aabaabaa", "a", 0)  = 0
  862        * StringUtils.indexOf("aabaabaa", "b", 0)  = 2
  863        * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
  864        * StringUtils.indexOf("aabaabaa", "b", 3)  = 5
  865        * StringUtils.indexOf("aabaabaa", "b", 9)  = -1
  866        * StringUtils.indexOf("aabaabaa", "b", -1) = 2
  867        * StringUtils.indexOf("aabaabaa", "", 2)   = 2
  868        * StringUtils.indexOf("abc", "", 9)        = 3
  869        * </pre>
  870        *
  871        * @param str  the String to check, may be null
  872        * @param searchStr  the String to find, may be null
  873        * @param startPos  the start position, negative treated as zero
  874        * @return the first index of the search String,
  875        *  -1 if no match or <code>null</code> string input
  876        * @since 2.0
  877        */
  878       public static int indexOf(String str, String searchStr, int startPos) {
  879           if (str == null || searchStr == null) {
  880               return -1;
  881           }
  882           // JDK1.2/JDK1.3 have a bug, when startPos > str.length for "", hence
  883           if (searchStr.length() == 0 && startPos >= str.length()) {
  884               return str.length();
  885           }
  886           return str.indexOf(searchStr, startPos);
  887       }
  888   
  889       /**
  890        * <p>Case in-sensitive find of the first index within a String.</p>
  891        *
  892        * <p>A <code>null</code> String will return <code>-1</code>.
  893        * A negative start position is treated as zero.
  894        * An empty ("") search String always matches.
  895        * A start position greater than the string length only matches
  896        * an empty search String.</p>
  897        *
  898        * <pre>
  899        * StringUtils.indexOfIgnoreCase(null, *)          = -1
  900        * StringUtils.indexOfIgnoreCase(*, null)          = -1
  901        * StringUtils.indexOfIgnoreCase("", "")           = 0
  902        * StringUtils.indexOfIgnoreCase("aabaabaa", "a")  = 0
  903        * StringUtils.indexOfIgnoreCase("aabaabaa", "b")  = 2
  904        * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
  905        * </pre>
  906        *
  907        * @param str  the String to check, may be null
  908        * @param searchStr  the String to find, may be null
  909        * @return the first index of the search String,
  910        *  -1 if no match or <code>null</code> string input
  911        * @since 2.5
  912        */
  913       public static int indexOfIgnoreCase(String str, String searchStr) {
  914           return indexOfIgnoreCase(str, searchStr, 0);
  915       }
  916   
  917       /**
  918        * <p>Case in-sensitive find of the first index within a String
  919        * from the specified position.</p>
  920        *
  921        * <p>A <code>null</code> String will return <code>-1</code>.
  922        * A negative start position is treated as zero.
  923        * An empty ("") search String always matches.
  924        * A start position greater than the string length only matches
  925        * an empty search String.</p>
  926        *
  927        * <pre>
  928        * StringUtils.indexOfIgnoreCase(null, *, *)          = -1
  929        * StringUtils.indexOfIgnoreCase(*, null, *)          = -1
  930        * StringUtils.indexOfIgnoreCase("", "", 0)           = 0
  931        * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
  932        * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
  933        * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
  934        * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
  935        * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
  936        * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
  937        * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
  938        * StringUtils.indexOfIgnoreCase("abc", "", 9)        = 3
  939        * </pre>
  940        *
  941        * @param str  the String to check, may be null
  942        * @param searchStr  the String to find, may be null
  943        * @param startPos  the start position, negative treated as zero
  944        * @return the first index of the search String,
  945        *  -1 if no match or <code>null</code> string input
  946        * @since 2.5
  947        */
  948       public static int indexOfIgnoreCase(String str, String searchStr, int startPos) {
  949           if (str == null || searchStr == null) {
  950               return -1;
  951           }
  952           if (startPos < 0) {
  953               startPos = 0;
  954           }
  955           int endLimit = (str.length() - searchStr.length()) + 1;
  956           if (startPos > endLimit) {
  957               return -1;
  958           }
  959           if (searchStr.length() == 0) {
  960               return startPos;
  961           }
  962           for (int i = startPos; i < endLimit; i++) {
  963               if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {
  964                   return i;
  965               }
  966           }
  967           return -1;
  968       }
  969   
  970       // LastIndexOf
  971       //-----------------------------------------------------------------------
  972       /**
  973        * <p>Finds the last index within a String, handling <code>null</code>.
  974        * This method uses {@link String#lastIndexOf(int)}.</p>
  975        *
  976        * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.</p>
  977        *
  978        * <pre>
  979        * StringUtils.lastIndexOf(null, *)         = -1
  980        * StringUtils.lastIndexOf("", *)           = -1
  981        * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
  982        * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
  983        * </pre>
  984        *
  985        * @param str  the String to check, may be null
  986        * @param searchChar  the character to find
  987        * @return the last index of the search character,
  988        *  -1 if no match or <code>null</code> string input
  989        * @since 2.0
  990        */
  991       public static int lastIndexOf(String str, char searchChar) {
  992           if (isEmpty(str)) {
  993               return -1;
  994           }
  995           return str.lastIndexOf(searchChar);
  996       }
  997   
  998       /**
  999        * <p>Finds the last index within a String from a start position,
 1000        * handling <code>null</code>.
 1001        * This method uses {@link String#lastIndexOf(int, int)}.</p>
 1002        *
 1003        * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.
 1004        * A negative start position returns <code>-1</code>.
 1005        * A start position greater than the string length searches the whole string.</p>
 1006        *
 1007        * <pre>
 1008        * StringUtils.lastIndexOf(null, *, *)          = -1
 1009        * StringUtils.lastIndexOf("", *,  *)           = -1
 1010        * StringUtils.lastIndexOf("aabaabaa", 'b', 8)  = 5
 1011        * StringUtils.lastIndexOf("aabaabaa", 'b', 4)  = 2
 1012        * StringUtils.lastIndexOf("aabaabaa", 'b', 0)  = -1
 1013        * StringUtils.lastIndexOf("aabaabaa", 'b', 9)  = 5
 1014        * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
 1015        * StringUtils.lastIndexOf("aabaabaa", 'a', 0)  = 0
 1016        * </pre>
 1017        *
 1018        * @param str  the String to check, may be null
 1019        * @param searchChar  the character to find
 1020        * @param startPos  the start position
 1021        * @return the last index of the search character,
 1022        *  -1 if no match or <code>null</code> string input
 1023        * @since 2.0
 1024        */
 1025       public static int lastIndexOf(String str, char searchChar, int startPos) {
 1026           if (isEmpty(str)) {
 1027               return -1;
 1028           }
 1029           return str.lastIndexOf(searchChar, startPos);
 1030       }
 1031   
 1032       /**
 1033        * <p>Finds the last index within a String, handling <code>null</code>.
 1034        * This method uses {@link String#lastIndexOf(String)}.</p>
 1035        *
 1036        * <p>A <code>null</code> String will return <code>-1</code>.</p>
 1037        *
 1038        * <pre>
 1039        * StringUtils.lastIndexOf(null, *)          = -1
 1040        * StringUtils.lastIndexOf(*, null)          = -1
 1041        * StringUtils.lastIndexOf("", "")           = 0
 1042        * StringUtils.lastIndexOf("aabaabaa", "a")  = 0
 1043        * StringUtils.lastIndexOf("aabaabaa", "b")  = 2
 1044        * StringUtils.lastIndexOf("aabaabaa", "ab") = 1
 1045        * StringUtils.lastIndexOf("aabaabaa", "")   = 8
 1046        * </pre>
 1047        *
 1048        * @param str  the String to check, may be null
 1049        * @param searchStr  the String to find, may be null
 1050        * @return the last index of the search String,
 1051        *  -1 if no match or <code>null</code> string input
 1052        * @since 2.0
 1053        */
 1054       public static int lastIndexOf(String str, String searchStr) {
 1055           if (str == null || searchStr == null) {
 1056               return -1;
 1057           }
 1058           return str.lastIndexOf(searchStr);
 1059       }
 1060   
 1061       /**
 1062        * <p>Finds the n-th last index within a String, handling <code>null</code>.
 1063        * This method uses {@link String#lastIndexOf(String)}.</p>
 1064        *
 1065        * <p>A <code>null</code> String will return <code>-1</code>.</p>
 1066        *
 1067        * <pre>
 1068        * StringUtils.lastOrdinalIndexOf(null, *, *)          = -1
 1069        * StringUtils.lastOrdinalIndexOf(*, null, *)          = -1
 1070        * StringUtils.lastOrdinalIndexOf("", "", *)           = 0
 1071        * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1)  = 7
 1072        * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2)  = 6
 1073        * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1)  = 5
 1074        * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2)  = 2
 1075        * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
 1076        * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
 1077        * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1)   = 8
 1078        * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2)   = 8
 1079        * </pre>
 1080        *
 1081        * <p>Note that 'tail(String str, int n)' may be implemented as: </p>
 1082        *
 1083        * <pre>
 1084        *   str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
 1085        * </pre>
 1086        *
 1087        * @param str  the String to check, may be null
 1088        * @param searchStr  the String to find, may be null
 1089        * @param ordinal  the n-th last <code>searchStr</code> to find
 1090        * @return the n-th last index of the search String,
 1091        *  <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
 1092        * @since 2.5
 1093        */
 1094       public static int lastOrdinalIndexOf(String str, String searchStr, int ordinal) {
 1095           return ordinalIndexOf(str, searchStr, ordinal, true);
 1096       }
 1097   
 1098       /**
 1099        * <p>Finds the first index within a String, handling <code>null</code>.
 1100        * This method uses {@link String#lastIndexOf(String, int)}.</p>
 1101        *
 1102        * <p>A <code>null</code> String will return <code>-1</code>.
 1103        * A negative start position returns <code>-1</code>.
 1104        * An empty ("") search String always matches unless the start position is negative.
 1105        * A start position greater than the string length searches the whole string.</p>
 1106        *
 1107        * <pre>
 1108        * StringUtils.lastIndexOf(null, *, *)          = -1
 1109        * StringUtils.lastIndexOf(*, null, *)          = -1
 1110        * StringUtils.lastIndexOf("aabaabaa", "a", 8)  = 7
 1111        * StringUtils.lastIndexOf("aabaabaa", "b", 8)  = 5
 1112        * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
 1113        * StringUtils.lastIndexOf("aabaabaa", "b", 9)  = 5
 1114        * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
 1115        * StringUtils.lastIndexOf("aabaabaa", "a", 0)  = 0
 1116        * StringUtils.lastIndexOf("aabaabaa", "b", 0)  = -1
 1117        * </pre>
 1118        *
 1119        * @param str  the String to check, may be null
 1120        * @param searchStr  the String to find, may be null
 1121        * @param startPos  the start position, negative treated as zero
 1122        * @return the first index of the search String,
 1123        *  -1 if no match or <code>null</code> string input
 1124        * @since 2.0
 1125        */
 1126       public static int lastIndexOf(String str, String searchStr, int startPos) {
 1127           if (str == null || searchStr == null) {
 1128               return -1;
 1129           }
 1130           return str.lastIndexOf(searchStr, startPos);
 1131       }
 1132   
 1133       /**
 1134        * <p>Case in-sensitive find of the last index within a String.</p>
 1135        *
 1136        * <p>A <code>null</code> String will return <code>-1</code>.
 1137        * A negative start position returns <code>-1</code>.
 1138        * An empty ("") search String always matches unless the start position is negative.
 1139        * A start position greater than the string length searches the whole string.</p>
 1140        *
 1141        * <pre>
 1142        * StringUtils.lastIndexOfIgnoreCase(null, *)          = -1
 1143        * StringUtils.lastIndexOfIgnoreCase(*, null)          = -1
 1144        * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A")  = 7
 1145        * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B")  = 5
 1146        * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
 1147        * </pre>
 1148        *
 1149        * @param str  the String to check, may be null
 1150        * @param searchStr  the String to find, may be null
 1151        * @return the first index of the search String,
 1152        *  -1 if no match or <code>null</code> string input
 1153        * @since 2.5
 1154        */
 1155       public static int lastIndexOfIgnoreCase(String str, String searchStr) {
 1156           if (str == null || searchStr == null) {
 1157               return -1;
 1158           }
 1159           return lastIndexOfIgnoreCase(str, searchStr, str.length());
 1160       }
 1161   
 1162       /**
 1163        * <p>Case in-sensitive find of the last index within a String
 1164        * from the specified position.</p>
 1165        *
 1166        * <p>A <code>null</code> String will return <code>-1</code>.
 1167        * A negative start position returns <code>-1</code>.
 1168        * An empty ("") search String always matches unless the start position is negative.
 1169        * A start position greater than the string length searches the whole string.</p>
 1170        *
 1171        * <pre>
 1172        * StringUtils.lastIndexOfIgnoreCase(null, *, *)          = -1
 1173        * StringUtils.lastIndexOfIgnoreCase(*, null, *)          = -1
 1174        * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8)  = 7
 1175        * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8)  = 5
 1176        * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
 1177        * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9)  = 5
 1178        * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
 1179        * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0)  = 0
 1180        * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0)  = -1
 1181        * </pre>
 1182        *
 1183        * @param str  the String to check, may be null
 1184        * @param searchStr  the String to find, may be null
 1185        * @param startPos  the start position
 1186        * @return the first index of the search String,
 1187        *  -1 if no match or <code>null</code> string input
 1188        * @since 2.5
 1189        */
 1190       public static int lastIndexOfIgnoreCase(String str, String searchStr, int startPos) {
 1191           if (str == null || searchStr == null) {
 1192               return -1;
 1193           }
 1194           if (startPos > (str.length() - searchStr.length())) {
 1195               startPos = str.length() - searchStr.length();
 1196           }
 1197           if (startPos < 0) {
 1198               return -1;
 1199           }
 1200           if (searchStr.length() == 0) {
 1201               return startPos;
 1202           }
 1203   
 1204           for (int i = startPos; i >= 0; i--) {
 1205               if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {
 1206                   return i;
 1207               }
 1208           }
 1209           return -1;
 1210       }
 1211   
 1212       // Contains
 1213       //-----------------------------------------------------------------------
 1214       /**
 1215        * <p>Checks if String contains a search character, handling <code>null</code>.
 1216        * This method uses {@link String#indexOf(int)}.</p>
 1217        *
 1218        * <p>A <code>null</code> or empty ("") String will return <code>false</code>.</p>
 1219        *
 1220        * <pre>
 1221        * StringUtils.contains(null, *)    = false
 1222        * StringUtils.contains("", *)      = false
 1223        * StringUtils.contains("abc", 'a') = true
 1224        * StringUtils.contains("abc", 'z') = false
 1225        * </pre>
 1226        *
 1227        * @param str  the String to check, may be null
 1228        * @param searchChar  the character to find
 1229        * @return true if the String contains the search character,
 1230        *  false if not or <code>null</code> string input
 1231        * @since 2.0
 1232        */
 1233       public static boolean contains(String str, char searchChar) {
 1234           if (isEmpty(str)) {
 1235               return false;
 1236           }
 1237           return str.indexOf(searchChar) >= 0;
 1238       }
 1239   
 1240       /**
 1241        * <p>Checks if String contains a search String, handling <code>null</code>.
 1242        * This method uses {@link String#indexOf(String)}.</p>
 1243        *
 1244        * <p>A <code>null</code> String will return <code>false</code>.</p>
 1245        *
 1246        * <pre>
 1247        * StringUtils.contains(null, *)     = false
 1248        * StringUtils.contains(*, null)     = false
 1249        * StringUtils.contains("", "")      = true
 1250        * StringUtils.contains("abc", "")   = true
 1251        * StringUtils.contains("abc", "a")  = true
 1252        * StringUtils.contains("abc", "z")  = false
 1253        * </pre>
 1254        *
 1255        * @param str  the String to check, may be null
 1256        * @param searchStr  the String to find, may be null
 1257        * @return true if the String contains the search String,
 1258        *  false if not or <code>null</code> string input
 1259        * @since 2.0
 1260        */
 1261       public static boolean contains(String str, String searchStr) {
 1262           if (str == null || searchStr == null) {
 1263               return false;
 1264           }
 1265           return str.indexOf(searchStr) >= 0;
 1266       }
 1267   
 1268       /**
 1269        * <p>Checks if String contains a search String irrespective of case,
 1270        * handling <code>null</code>. Case-insensitivity is defined as by
 1271        * {@link String#equalsIgnoreCase(String)}.
 1272        *
 1273        * <p>A <code>null</code> String will return <code>false</code>.</p>
 1274        *
 1275        * <pre>
 1276        * StringUtils.contains(null, *) = false
 1277        * StringUtils.contains(*, null) = false
 1278        * StringUtils.contains("", "") = true
 1279        * StringUtils.contains("abc", "") = true
 1280        * StringUtils.contains("abc", "a") = true
 1281        * StringUtils.contains("abc", "z") = false
 1282        * StringUtils.contains("abc", "A") = true
 1283        * StringUtils.contains("abc", "Z") = false
 1284        * </pre>
 1285        *
 1286        * @param str  the String to check, may be null
 1287        * @param searchStr  the String to find, may be null
 1288        * @return true if the String contains the search String irrespective of
 1289        * case or false if not or <code>null</code> string input
 1290        */
 1291       public static boolean containsIgnoreCase(String str, String searchStr) {
 1292           if (str == null || searchStr == null) {
 1293               return false;
 1294           }
 1295           int len = searchStr.length();
 1296           int max = str.length() - len;
 1297           for (int i = 0; i <= max; i++) {
 1298               if (str.regionMatches(true, i, searchStr, 0, len)) {
 1299                   return true;
 1300               }
 1301           }
 1302           return false;
 1303       }
 1304   
 1305       // IndexOfAny chars
 1306       //-----------------------------------------------------------------------
 1307       /**
 1308        * <p>Search a String to find the first index of any
 1309        * character in the given set of characters.</p>
 1310        *
 1311        * <p>A <code>null</code> String will return <code>-1</code>.
 1312        * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
 1313        *
 1314        * <pre>
 1315        * StringUtils.indexOfAny(null, *)                = -1
 1316        * StringUtils.indexOfAny("", *)                  = -1
 1317        * StringUtils.indexOfAny(*, null)                = -1
 1318        * StringUtils.indexOfAny(*, [])                  = -1
 1319        * StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0
 1320        * StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3
 1321        * StringUtils.indexOfAny("aba", ['z'])           = -1
 1322        * </pre>
 1323        *
 1324        * @param str  the String to check, may be null
 1325        * @param searchChars  the chars to search for, may be null
 1326        * @return the index of any of the chars, -1 if no match or null input
 1327        * @since 2.0
 1328        */
 1329       public static int indexOfAny(String str, char[] searchChars) {
 1330           if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
 1331               return -1;
 1332           }
 1333           for (int i = 0; i < str.length(); i++) {
 1334               char ch = str.charAt(i);
 1335               for (int j = 0; j < searchChars.length; j++) {
 1336                   if (searchChars[j] == ch) {
 1337                       return i;
 1338                   }
 1339               }
 1340           }
 1341           return -1;
 1342       }
 1343   
 1344       /**
 1345        * <p>Search a String to find the first index of any
 1346        * character in the given set of characters.</p>
 1347        *
 1348        * <p>A <code>null</code> String will return <code>-1</code>.
 1349        * A <code>null</code> search string will return <code>-1</code>.</p>
 1350        *
 1351        * <pre>
 1352        * StringUtils.indexOfAny(null, *)            = -1
 1353        * StringUtils.indexOfAny("", *)              = -1
 1354        * StringUtils.indexOfAny(*, null)            = -1
 1355        * StringUtils.indexOfAny(*, "")              = -1
 1356        * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
 1357        * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
 1358        * StringUtils.indexOfAny("aba","z")          = -1
 1359        * </pre>
 1360        *
 1361        * @param str  the String to check, may be null
 1362        * @param searchChars  the chars to search for, may be null
 1363        * @return the index of any of the chars, -1 if no match or null input
 1364        * @since 2.0
 1365        */
 1366       public static int indexOfAny(String str, String searchChars) {
 1367           if (isEmpty(str) || isEmpty(searchChars)) {
 1368               return -1;
 1369           }
 1370           return indexOfAny(str, searchChars.toCharArray());
 1371       }
 1372   
 1373       // ContainsAny
 1374       //-----------------------------------------------------------------------
 1375       /**
 1376        * <p>Checks if the String contains any character in the given
 1377        * set of characters.</p>
 1378        *
 1379        * <p>A <code>null</code> String will return <code>false</code>.
 1380        * A <code>null</code> or zero length search array will return <code>false</code>.</p>
 1381        *
 1382        * <pre>
 1383        * StringUtils.containsAny(null, *)                = false
 1384        * StringUtils.containsAny("", *)                  = false
 1385        * StringUtils.containsAny(*, null)                = false
 1386        * StringUtils.containsAny(*, [])                  = false
 1387        * StringUtils.containsAny("zzabyycdxx",['z','a']) = true
 1388        * StringUtils.containsAny("zzabyycdxx",['b','y']) = true
 1389        * StringUtils.containsAny("aba", ['z'])           = false
 1390        * </pre>
 1391        *
 1392        * @param str  the String to check, may be null
 1393        * @param searchChars  the chars to search for, may be null
 1394        * @return the <code>true</code> if any of the chars are found,
 1395        * <code>false</code> if no match or null input
 1396        * @since 2.4
 1397        */
 1398       public static boolean containsAny(String str, char[] searchChars) {
 1399           if (str == null || str.length() == 0 || searchChars == null || searchChars.length == 0) {
 1400               return false;
 1401           }
 1402           for (int i = 0; i < str.length(); i++) {
 1403               char ch = str.charAt(i);
 1404               for (int j = 0; j < searchChars.length; j++) {
 1405                   if (searchChars[j] == ch) {
 1406                       return true;
 1407                   }
 1408               }
 1409           }
 1410           return false;
 1411       }
 1412   
 1413       /**
 1414        * <p>
 1415        * Checks if the String contains any character in the given set of characters.
 1416        * </p>
 1417        * 
 1418        * <p>
 1419        * A <code>null</code> String will return <code>false</code>. A <code>null</code> search string will return
 1420        * <code>false</code>.
 1421        * </p>
 1422        * 
 1423        * <pre>
 1424        * StringUtils.containsAny(null, *)            = false
 1425        * StringUtils.containsAny("", *)              = false
 1426        * StringUtils.containsAny(*, null)            = false
 1427        * StringUtils.containsAny(*, "")              = false
 1428        * StringUtils.containsAny("zzabyycdxx", "za") = true
 1429        * StringUtils.containsAny("zzabyycdxx", "by") = true
 1430        * StringUtils.containsAny("aba","z")          = false
 1431        * </pre>
 1432        * 
 1433        * @param str
 1434        *            the String to check, may be null
 1435        * @param searchChars
 1436        *            the chars to search for, may be null
 1437        * @return the <code>true</code> if any of the chars are found, <code>false</code> if no match or null input
 1438        * @since 2.4
 1439        */
 1440       public static boolean containsAny(String str, String searchChars) {
 1441           if (searchChars == null) {
 1442               return false;
 1443           }
 1444           return containsAny(str, searchChars.toCharArray());
 1445       }
 1446   
 1447       // IndexOfAnyBut chars
 1448       //-----------------------------------------------------------------------
 1449       /**
 1450        * <p>Search a String to find the first index of any
 1451        * character not in the given set of characters.</p>
 1452        *
 1453        * <p>A <code>null</code> String will return <code>-1</code>.
 1454        * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
 1455        *
 1456        * <pre>
 1457        * StringUtils.indexOfAnyBut(null, *)           = -1
 1458        * StringUtils.indexOfAnyBut("", *)             = -1
 1459        * StringUtils.indexOfAnyBut(*, null)           = -1
 1460        * StringUtils.indexOfAnyBut(*, [])             = -1
 1461        * StringUtils.indexOfAnyBut("zzabyycdxx",'za') = 3
 1462        * StringUtils.indexOfAnyBut("zzabyycdxx", '')  = 0
 1463        * StringUtils.indexOfAnyBut("aba", 'ab')       = -1
 1464        * </pre>
 1465        *
 1466        * @param str  the String to check, may be null
 1467        * @param searchChars  the chars to search for, may be null
 1468        * @return the index of any of the chars, -1 if no match or null input
 1469        * @since 2.0
 1470        */
 1471       public static int indexOfAnyBut(String str, char[] searchChars) {
 1472           if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
 1473               return -1;
 1474           }
 1475           outer : for (int i = 0; i < str.length(); i++) {
 1476               char ch = str.charAt(i);
 1477               for (int j = 0; j < searchChars.length; j++) {
 1478                   if (searchChars[j] == ch) {
 1479                       continue outer;
 1480                   }
 1481               }
 1482               return i;
 1483           }
 1484           return -1;
 1485       }
 1486   
 1487       /**
 1488        * <p>Search a String to find the first index of any
 1489        * character not in the given set of characters.</p>
 1490        *
 1491        * <p>A <code>null</code> String will return <code>-1</code>.
 1492        * A <code>null</code> search string will return <code>-1</code>.</p>
 1493        *
 1494        * <pre>
 1495        * StringUtils.indexOfAnyBut(null, *)            = -1
 1496        * StringUtils.indexOfAnyBut("", *)              = -1
 1497        * StringUtils.indexOfAnyBut(*, null)            = -1
 1498        * StringUtils.indexOfAnyBut(*, "")              = -1
 1499        * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
 1500        * StringUtils.indexOfAnyBut("zzabyycdxx", "")   = 0
 1501        * StringUtils.indexOfAnyBut("aba","ab")         = -1
 1502        * </pre>
 1503        *
 1504        * @param str  the String to check, may be null
 1505        * @param searchChars  the chars to search for, may be null
 1506        * @return the index of any of the chars, -1 if no match or null input
 1507        * @since 2.0
 1508        */
 1509       public static int indexOfAnyBut(String str, String searchChars) {
 1510           if (isEmpty(str) || isEmpty(searchChars)) {
 1511               return -1;
 1512           }
 1513           for (int i = 0; i < str.length(); i++) {
 1514               if (searchChars.indexOf(str.charAt(i)) < 0) {
 1515                   return i;
 1516               }
 1517           }
 1518           return -1;
 1519       }
 1520   
 1521       // ContainsOnly
 1522       //-----------------------------------------------------------------------
 1523       /**
 1524        * <p>Checks if the String contains only certain characters.</p>
 1525        *
 1526        * <p>A <code>null</code> String will return <code>false</code>.
 1527        * A <code>null</code> valid character array will return <code>false</code>.
 1528        * An empty String ("") always returns <code>true</code>.</p>
 1529        *
 1530        * <pre>
 1531        * StringUtils.containsOnly(null, *)       = false
 1532        * StringUtils.containsOnly(*, null)       = false
 1533        * StringUtils.containsOnly("", *)         = true
 1534        * StringUtils.containsOnly("ab", '')      = false
 1535        * StringUtils.containsOnly("abab", 'abc') = true
 1536        * StringUtils.containsOnly("ab1", 'abc')  = false
 1537        * StringUtils.containsOnly("abz", 'abc')  = false
 1538        * </pre>
 1539        *
 1540        * @param str  the String to check, may be null
 1541        * @param valid  an array of valid chars, may be null
 1542        * @return true if it only contains valid chars and is non-null
 1543        */
 1544       public static boolean containsOnly(String str, char[] valid) {
 1545           // All these pre-checks are to maintain API with an older version
 1546           if ((valid == null) || (str == null)) {
 1547               return false;
 1548           }
 1549           if (str.length() == 0) {
 1550               return true;
 1551           }
 1552           if (valid.length == 0) {
 1553               return false;
 1554           }
 1555           return indexOfAnyBut(str, valid) == -1;
 1556       }
 1557   
 1558       /**
 1559        * <p>Checks if the String contains only certain characters.</p>
 1560        *
 1561        * <p>A <code>null</code> String will return <code>false</code>.
 1562        * A <code>null</code> valid character String will return <code>false</code>.
 1563        * An empty String ("") always returns <code>true</code>.</p>
 1564        *
 1565        * <pre>
 1566        * StringUtils.containsOnly(null, *)       = false
 1567        * StringUtils.containsOnly(*, null)       = false
 1568        * StringUtils.containsOnly("", *)         = true
 1569        * StringUtils.containsOnly("ab", "")      = false
 1570        * StringUtils.containsOnly("abab", "abc") = true
 1571        * StringUtils.containsOnly("ab1", "abc")  = false
 1572        * StringUtils.containsOnly("abz", "abc")  = false
 1573        * </pre>
 1574        *
 1575        * @param str  the String to check, may be null
 1576        * @param validChars  a String of valid chars, may be null
 1577        * @return true if it only contains valid chars and is non-null
 1578        * @since 2.0
 1579        */
 1580       public static boolean containsOnly(String str, String validChars) {
 1581           if (str == null || validChars == null) {
 1582               return false;
 1583           }
 1584           return containsOnly(str, validChars.toCharArray());
 1585       }
 1586   
 1587       // ContainsNone
 1588       //-----------------------------------------------------------------------
 1589       /**
 1590        * <p>Checks that the String does not contain certain characters.</p>
 1591        *
 1592        * <p>A <code>null</code> String will return <code>true</code>.
 1593        * A <code>null</code> invalid character array will return <code>true</code>.
 1594        * An empty String ("") always returns true.</p>
 1595        *
 1596        * <pre>
 1597        * StringUtils.containsNone(null, *)       = true
 1598        * StringUtils.containsNone(*, null)       = true
 1599        * StringUtils.containsNone("", *)         = true
 1600        * StringUtils.containsNone("ab", '')      = true
 1601        * StringUtils.containsNone("abab", 'xyz') = true
 1602        * StringUtils.containsNone("ab1", 'xyz')  = true
 1603        * StringUtils.containsNone("abz", 'xyz')  = false
 1604        * </pre>
 1605        *
 1606        * @param str  the String to check, may be null
 1607        * @param invalidChars  an array of invalid chars, may be null
 1608        * @return true if it contains none of the invalid chars, or is null
 1609        * @since 2.0
 1610        */
 1611       public static boolean containsNone(String str, char[] invalidChars) {
 1612           if (str == null || invalidChars == null) {
 1613               return true;
 1614           }
 1615           int strSize = str.length();
 1616           int validSize = invalidChars.length;
 1617           for (int i = 0; i < strSize; i++) {
 1618               char ch = str.charAt(i);
 1619               for (int j = 0; j < validSize; j++) {
 1620                   if (invalidChars[j] == ch) {
 1621                       return false;
 1622                   }
 1623               }
 1624           }
 1625           return true;
 1626       }
 1627   
 1628       /**
 1629        * <p>Checks that the String does not contain certain characters.</p>
 1630        *
 1631        * <p>A <code>null</code> String will return <code>true</code>.
 1632        * A <code>null</code> invalid character array will return <code>true</code>.
 1633        * An empty String ("") always returns true.</p>
 1634        *
 1635        * <pre>
 1636        * StringUtils.containsNone(null, *)       = true
 1637        * StringUtils.containsNone(*, null)       = true
 1638        * StringUtils.containsNone("", *)         = true
 1639        * StringUtils.containsNone("ab", "")      = true
 1640        * StringUtils.containsNone("abab", "xyz") = true
 1641        * StringUtils.containsNone("ab1", "xyz")  = true
 1642        * StringUtils.containsNone("abz", "xyz")  = false
 1643        * </pre>
 1644        *
 1645        * @param str  the String to check, may be null
 1646        * @param invalidChars  a String of invalid chars, may be null
 1647        * @return true if it contains none of the invalid chars, or is null
 1648        * @since 2.0
 1649        */
 1650       public static boolean containsNone(String str, String invalidChars) {
 1651           if (str == null || invalidChars == null) {
 1652               return true;
 1653           }
 1654           return containsNone(str, invalidChars.toCharArray());
 1655       }
 1656   
 1657       // IndexOfAny strings
 1658       //-----------------------------------------------------------------------
 1659       /**
 1660        * <p>Find the first index of any of a set of potential substrings.</p>
 1661        *
 1662        * <p>A <code>null</code> String will return <code>-1</code>.
 1663        * A <code>null</code> or zero length search array will return <code>-1</code>.
 1664        * A <code>null</code> search array entry will be ignored, but a search
 1665        * array containing "" will return <code>0</code> if <code>str</code> is not
 1666        * null. This method uses {@link String#indexOf(String)}.</p>
 1667        *
 1668        * <pre>
 1669        * StringUtils.indexOfAny(null, *)                     = -1
 1670        * StringUtils.indexOfAny(*, null)                     = -1
 1671        * StringUtils.indexOfAny(*, [])                       = -1
 1672        * StringUtils.indexOfAny("zzabyycdxx", ["ab","cd"])   = 2
 1673        * StringUtils.indexOfAny("zzabyycdxx", ["cd","ab"])   = 2
 1674        * StringUtils.indexOfAny("zzabyycdxx", ["mn","op"])   = -1
 1675        * StringUtils.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1
 1676        * StringUtils.indexOfAny("zzabyycdxx", [""])          = 0
 1677        * StringUtils.indexOfAny("", [""])                    = 0
 1678        * StringUtils.indexOfAny("", ["a"])                   = -1
 1679        * </pre>
 1680        *
 1681        * @param str  the String to check, may be null
 1682        * @param searchStrs  the Strings to search for, may be null
 1683        * @return the first index of any of the searchStrs in str, -1 if no match
 1684        */
 1685       public static int indexOfAny(String str, String[] searchStrs) {
 1686           if ((str == null) || (searchStrs == null)) {
 1687               return -1;
 1688           }
 1689           int sz = searchStrs.length;
 1690   
 1691           // String's can't have a MAX_VALUEth index.
 1692           int ret = Integer.MAX_VALUE;
 1693   
 1694           int tmp = 0;
 1695           for (int i = 0; i < sz; i++) {
 1696               String search = searchStrs[i];
 1697               if (search == null) {
 1698                   continue;
 1699               }
 1700               tmp = str.indexOf(search);
 1701               if (tmp == -1) {
 1702                   continue;
 1703               }
 1704   
 1705               if (tmp < ret) {
 1706                   ret = tmp;
 1707               }
 1708           }
 1709   
 1710           return (ret == Integer.MAX_VALUE) ? -1 : ret;
 1711       }
 1712   
 1713       /**
 1714        * <p>Find the latest index of any of a set of potential substrings.</p>
 1715        *
 1716        * <p>A <code>null</code> String will return <code>-1</code>.
 1717        * A <code>null</code> search array will return <code>-1</code>.
 1718        * A <code>null</code> or zero length search array entry will be ignored,
 1719        * but a search array containing "" will return the length of <code>str</code>
 1720        * if <code>str</code> is not null. This method uses {@link String#indexOf(String)}</p>
 1721        *
 1722        * <pre>
 1723        * StringUtils.lastIndexOfAny(null, *)                   = -1
 1724        * StringUtils.lastIndexOfAny(*, null)                   = -1
 1725        * StringUtils.lastIndexOfAny(*, [])                     = -1
 1726        * StringUtils.lastIndexOfAny(*, [null])                 = -1
 1727        * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6
 1728        * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6
 1729        * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
 1730        * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
 1731        * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn",""])   = 10
 1732        * </pre>
 1733        *
 1734        * @param str  the String to check, may be null
 1735        * @param searchStrs  the Strings to search for, may be null
 1736        * @return the last index of any of the Strings, -1 if no match
 1737        */
 1738       public static int lastIndexOfAny(String str, String[] searchStrs) {
 1739           if ((str == null) || (searchStrs == null)) {
 1740               return -1;
 1741           }
 1742           int sz = searchStrs.length;
 1743           int ret = -1;
 1744           int tmp = 0;
 1745           for (int i = 0; i < sz; i++) {
 1746               String search = searchStrs[i];
 1747               if (search == null) {
 1748                   continue;
 1749               }
 1750               tmp = str.lastIndexOf(search);
 1751               if (tmp > ret) {
 1752                   ret = tmp;
 1753               }
 1754           }
 1755           return ret;
 1756       }
 1757   
 1758       // Substring
 1759       //-----------------------------------------------------------------------
 1760       /**
 1761        * <p>Gets a substring from the specified String avoiding exceptions.</p>
 1762        *
 1763        * <p>A negative start position can be used to start <code>n</code>
 1764        * characters from the end of the String.</p>
 1765        *
 1766        * <p>A <code>null</code> String will return <code>null</code>.
 1767        * An empty ("") String will return "".</p>
 1768        *
 1769        * <pre>
 1770        * StringUtils.substring(null, *)   = null
 1771        * StringUtils.substring("", *)     = ""
 1772        * StringUtils.substring("abc", 0)  = "abc"
 1773        * StringUtils.substring("abc", 2)  = "c"
 1774        * StringUtils.substring("abc", 4)  = ""
 1775        * StringUtils.substring("abc", -2) = "bc"
 1776        * StringUtils.substring("abc", -4) = "abc"
 1777        * </pre>
 1778        *
 1779        * @param str  the String to get the substring from, may be null
 1780        * @param start  the position to start from, negative means
 1781        *  count back from the end of the String by this many characters
 1782        * @return substring from start position, <code>null</code> if null String input
 1783        */
 1784       public static String substring(String str, int start) {
 1785           if (str == null) {
 1786               return null;
 1787           }
 1788   
 1789           // handle negatives, which means last n characters
 1790           if (start < 0) {
 1791               start = str.length() + start; // remember start is negative
 1792           }
 1793   
 1794           if (start < 0) {
 1795               start = 0;
 1796           }
 1797           if (start > str.length()) {
 1798               return EMPTY;
 1799           }
 1800   
 1801           return str.substring(start);
 1802       }
 1803   
 1804       /**
 1805        * <p>Gets a substring from the specified String avoiding exceptions.</p>
 1806        *
 1807        * <p>A negative start position can be used to start/end <code>n</code>
 1808        * characters from the end of the String.</p>
 1809        *
 1810        * <p>The returned substring starts with the character in the <code>start</code>
 1811        * position and ends before the <code>end</code> position. All position counting is
 1812        * zero-based -- i.e., to start at the beginning of the string use
 1813        * <code>start = 0</code>. Negative start and end positions can be used to
 1814        * specify offsets relative to the end of the String.</p>
 1815        *
 1816        * <p>If <code>start</code> is not strictly to the left of <code>end</code>, ""
 1817        * is returned.</p>
 1818        *
 1819        * <pre>
 1820        * StringUtils.substring(null, *, *)    = null
 1821        * StringUtils.substring("", * ,  *)    = "";
 1822        * StringUtils.substring("abc", 0, 2)   = "ab"
 1823        * StringUtils.substring("abc", 2, 0)   = ""
 1824        * StringUtils.substring("abc", 2, 4)   = "c"
 1825        * StringUtils.substring("abc", 4, 6)   = ""
 1826        * StringUtils.substring("abc", 2, 2)   = ""
 1827        * StringUtils.substring("abc", -2, -1) = "b"
 1828        * StringUtils.substring("abc", -4, 2)  = "ab"
 1829        * </pre>
 1830        *
 1831        * @param str  the String to get the substring from, may be null
 1832        * @param start  the position to start from, negative means
 1833        *  count back from the end of the String by this many characters
 1834        * @param end  the position to end at (exclusive), negative means
 1835        *  count back from the end of the String by this many characters
 1836        * @return substring from start position to end positon,
 1837        *  <code>null</code> if null String input
 1838        */
 1839       public static String substring(String str, int start, int end) {
 1840           if (str == null) {
 1841               return null;
 1842           }
 1843   
 1844           // handle negatives
 1845           if (end < 0) {
 1846               end = str.length() + end; // remember end is negative
 1847           }
 1848           if (start < 0) {
 1849               start = str.length() + start; // remember start is negative
 1850           }
 1851   
 1852           // check length next
 1853           if (end > str.length()) {
 1854               end = str.length();
 1855           }
 1856   
 1857           // if start is greater than end, return ""
 1858           if (start > end) {
 1859               return EMPTY;
 1860           }
 1861   
 1862           if (start < 0) {
 1863               start = 0;
 1864           }
 1865           if (end < 0) {
 1866               end = 0;
 1867           }
 1868   
 1869           return str.substring(start, end);
 1870       }
 1871   
 1872       // Left/Right/Mid
 1873       //-----------------------------------------------------------------------
 1874       /**
 1875        * <p>Gets the leftmost <code>len</code> characters of a String.</p>
 1876        *
 1877        * <p>If <code>len</code> characters are not available, or the
 1878        * String is <code>null</code>, the String will be returned without
 1879        * an exception. An exception is thrown if len is negative.</p>
 1880        *
 1881        * <pre>
 1882        * StringUtils.left(null, *)    = null
 1883        * StringUtils.left(*, -ve)     = ""
 1884        * StringUtils.left("", *)      = ""
 1885        * StringUtils.left("abc", 0)   = ""
 1886        * StringUtils.left("abc", 2)   = "ab"
 1887        * StringUtils.left("abc", 4)   = "abc"
 1888        * </pre>
 1889        *
 1890        * @param str  the String to get the leftmost characters from, may be null
 1891        * @param len  the length of the required String, must be zero or positive
 1892        * @return the leftmost characters, <code>null</code> if null String input
 1893        */
 1894       public static String left(String str, int len) {
 1895           if (str == null) {
 1896               return null;
 1897           }
 1898           if (len < 0) {
 1899               return EMPTY;
 1900           }
 1901           if (str.length() <= len) {
 1902               return str;
 1903           }
 1904           return str.substring(0, len);
 1905       }
 1906   
 1907       /**
 1908        * <p>Gets the rightmost <code>len</code> characters of a String.</p>
 1909        *
 1910        * <p>If <code>len</code> characters are not available, or the String
 1911        * is <code>null</code>, the String will be returned without an
 1912        * an exception. An exception is thrown if len is negative.</p>
 1913        *
 1914        * <pre>
 1915        * StringUtils.right(null, *)    = null
 1916        * StringUtils.right(*, -ve)     = ""
 1917        * StringUtils.right("", *)      = ""
 1918        * StringUtils.right("abc", 0)   = ""
 1919        * StringUtils.right("abc", 2)   = "bc"
 1920        * StringUtils.right("abc", 4)   = "abc"
 1921        * </pre>
 1922        *
 1923        * @param str  the String to get the rightmost characters from, may be null
 1924        * @param len  the length of the required String, must be zero or positive
 1925        * @return the rightmost characters, <code>null</code> if null String input
 1926        */
 1927       public static String right(String str, int len) {
 1928           if (str == null) {
 1929               return null;
 1930           }
 1931           if (len < 0) {
 1932               return EMPTY;
 1933           }
 1934           if (str.length() <= len) {
 1935               return str;
 1936           }
 1937           return str.substring(str.length() - len);
 1938       }
 1939   
 1940       /**
 1941        * <p>Gets <code>len</code> characters from the middle of a String.</p>
 1942        *
 1943        * <p>If <code>len</code> characters are not available, the remainder
 1944        * of the String will be returned without an exception. If the
 1945        * String is <code>null</code>, <code>null</code> will be returned.
 1946        * An exception is thrown if len is negative.</p>
 1947        *
 1948        * <pre>
 1949        * StringUtils.mid(null, *, *)    = null
 1950        * StringUtils.mid(*, *, -ve)     = ""
 1951        * StringUtils.mid("", 0, *)      = ""
 1952        * StringUtils.mid("abc", 0, 2)   = "ab"
 1953        * StringUtils.mid("abc", 0, 4)   = "abc"
 1954        * StringUtils.mid("abc", 2, 4)   = "c"
 1955        * StringUtils.mid("abc", 4, 2)   = ""
 1956        * StringUtils.mid("abc", -2, 2)  = "ab"
 1957        * </pre>
 1958        *
 1959        * @param str  the String to get the characters from, may be null
 1960        * @param pos  the position to start from, negative treated as zero
 1961        * @param len  the length of the required String, must be zero or positive
 1962        * @return the middle characters, <code>null</code> if null String input
 1963        */
 1964       public static String mid(String str, int pos, int len) {
 1965           if (str == null) {
 1966               return null;
 1967           }
 1968           if (len < 0 || pos > str.length()) {
 1969               return EMPTY;
 1970           }
 1971           if (pos < 0) {
 1972               pos = 0;
 1973           }
 1974           if (str.length() <= (pos + len)) {
 1975               return str.substring(pos);
 1976           }
 1977           return str.substring(pos, pos + len);
 1978       }
 1979   
 1980       // SubStringAfter/SubStringBefore
 1981       //-----------------------------------------------------------------------
 1982       /**
 1983        * <p>Gets the substring before the first occurrence of a separator.
 1984        * The separator is not returned.</p>
 1985        *
 1986        * <p>A <code>null</code> string input will return <code>null</code>.
 1987        * An empty ("") string input will return the empty string.
 1988        * A <code>null</code> separator will return the input string.</p>
 1989        *
 1990        * <p>If nothing is found, the string input is returned.</p>
 1991        *
 1992        * <pre>
 1993        * StringUtils.substringBefore(null, *)      = null
 1994        * StringUtils.substringBefore("", *)        = ""
 1995        * StringUtils.substringBefore("abc", "a")   = ""
 1996        * StringUtils.substringBefore("abcba", "b") = "a"
 1997        * StringUtils.substringBefore("abc", "c")   = "ab"
 1998        * StringUtils.substringBefore("abc", "d")   = "abc"
 1999        * StringUtils.substringBefore("abc", "")    = ""
 2000        * StringUtils.substringBefore("abc", null)  = "abc"
 2001        * </pre>
 2002        *
 2003        * @param str  the String to get a substring from, may be null
 2004        * @param separator  the String to search for, may be null
 2005        * @return the substring before the first occurrence of the separator,
 2006        *  <code>null</code> if null String input
 2007        * @since 2.0
 2008        */
 2009       public static String substringBefore(String str, String separator) {
 2010           if (isEmpty(str) || separator == null) {
 2011               return str;
 2012           }
 2013           if (separator.length() == 0) {
 2014               return EMPTY;
 2015           }
 2016           int pos = str.indexOf(separator);
 2017           if (pos == -1) {
 2018               return str;
 2019           }
 2020           return str.substring(0, pos);
 2021       }
 2022   
 2023       /**
 2024        * <p>Gets the substring after the first occurrence of a separator.
 2025        * The separator is not returned.</p>
 2026        *
 2027        * <p>A <code>null</code> string input will return <code>null</code>.
 2028        * An empty ("") string input will return the empty string.
 2029        * A <code>null</code> separator will return the empty string if the
 2030        * input string is not <code>null</code>.</p>
 2031        *
 2032        * <p>If nothing is found, the empty string is returned.</p>
 2033        *
 2034        * <pre>
 2035        * StringUtils.substringAfter(null, *)      = null
 2036        * StringUtils.substringAfter("", *)        = ""
 2037        * StringUtils.substringAfter(*, null)      = ""
 2038        * StringUtils.substringAfter("abc", "a")   = "bc"
 2039        * StringUtils.substringAfter("abcba", "b") = "cba"
 2040        * StringUtils.substringAfter("abc", "c")   = ""
 2041        * StringUtils.substringAfter("abc", "d")   = ""
 2042        * StringUtils.substringAfter("abc", "")    = "abc"
 2043        * </pre>
 2044        *
 2045        * @param str  the String to get a substring from, may be null
 2046        * @param separator  the String to search for, may be null
 2047        * @return the substring after the first occurrence of the separator,
 2048        *  <code>null</code> if null String input
 2049        * @since 2.0
 2050        */
 2051       public static String substringAfter(String str, String separator) {
 2052           if (isEmpty(str)) {
 2053               return str;
 2054           }
 2055           if (separator == null) {
 2056               return EMPTY;
 2057           }
 2058           int pos = str.indexOf(separator);
 2059           if (pos == -1) {
 2060               return EMPTY;
 2061           }
 2062           return str.substring(pos + separator.length());
 2063       }
 2064   
 2065       /**
 2066        * <p>Gets the substring before the last occurrence of a separator.
 2067        * The separator is not returned.</p>
 2068        *
 2069        * <p>A <code>null</code> string input will return <code>null</code>.
 2070        * An empty ("") string input will return the empty string.
 2071        * An empty or <code>null</code> separator will return the input string.</p>
 2072        *
 2073        * <p>If nothing is found, the string input is returned.</p>
 2074        *
 2075        * <pre>
 2076        * StringUtils.substringBeforeLast(null, *)      = null
 2077        * StringUtils.substringBeforeLast("", *)        = ""
 2078        * StringUtils.substringBeforeLast("abcba", "b") = "abc"
 2079        * StringUtils.substringBeforeLast("abc", "c")   = "ab"
 2080        * StringUtils.substringBeforeLast("a", "a")     = ""
 2081        * StringUtils.substringBeforeLast("a", "z")     = "a"
 2082        * StringUtils.substringBeforeLast("a", null)    = "a"
 2083        * StringUtils.substringBeforeLast("a", "")      = "a"
 2084        * </pre>
 2085        *
 2086        * @param str  the String to get a substring from, may be null
 2087        * @param separator  the String to search for, may be null
 2088        * @return the substring before the last occurrence of the separator,
 2089        *  <code>null</code> if null String input
 2090        * @since 2.0
 2091        */
 2092       public static String substringBeforeLast(String str, String separator) {
 2093           if (isEmpty(str) || isEmpty(separator)) {
 2094               return str;
 2095           }
 2096           int pos = str.lastIndexOf(separator);
 2097           if (pos == -1) {
 2098               return str;
 2099           }
 2100           return str.substring(0, pos);
 2101       }
 2102   
 2103       /**
 2104        * <p>Gets the substring after the last occurrence of a separator.
 2105        * The separator is not returned.</p>
 2106        *
 2107        * <p>A <code>null</code> string input will return <code>null</code>.
 2108        * An empty ("") string input will return the empty string.
 2109        * An empty or <code>null</code> separator will return the empty string if
 2110        * the input string is not <code>null</code>.</p>
 2111        *
 2112        * <p>If nothing is found, the empty string is returned.</p>
 2113        *
 2114        * <pre>
 2115        * StringUtils.substringAfterLast(null, *)      = null
 2116        * StringUtils.substringAfterLast("", *)        = ""
 2117        * StringUtils.substringAfterLast(*, "")        = ""
 2118        * StringUtils.substringAfterLast(*, null)      = ""
 2119        * StringUtils.substringAfterLast("abc", "a")   = "bc"
 2120        * StringUtils.substringAfterLast("abcba", "b") = "a"
 2121        * StringUtils.substringAfterLast("abc", "c")   = ""
 2122        * StringUtils.substringAfterLast("a", "a")     = ""
 2123        * StringUtils.substringAfterLast("a", "z")     = ""
 2124        * </pre>
 2125        *
 2126        * @param str  the String to get a substring from, may be null
 2127        * @param separator  the String to search for, may be null
 2128        * @return the substring after the last occurrence of the separator,
 2129        *  <code>null</code> if null String input
 2130        * @since 2.0
 2131        */
 2132       public static String substringAfterLast(String str, String separator) {
 2133           if (isEmpty(str)) {
 2134               return str;
 2135           }
 2136           if (isEmpty(separator)) {
 2137               return EMPTY;
 2138           }
 2139           int pos = str.lastIndexOf(separator);
 2140           if (pos == -1 || pos == (str.length() - separator.length())) {
 2141               return EMPTY;
 2142           }
 2143           return str.substring(pos + separator.length());
 2144       }
 2145   
 2146       // Substring between
 2147       //-----------------------------------------------------------------------
 2148       /**
 2149        * <p>Gets the String that is nested in between two instances of the
 2150        * same String.</p>
 2151        *
 2152        * <p>A <code>null</code> input String returns <code>null</code>.
 2153        * A <code>null</code> tag returns <code>null</code>.</p>
 2154        *
 2155        * <pre>
 2156        * StringUtils.substringBetween(null, *)            = null
 2157        * StringUtils.substringBetween("", "")             = ""
 2158        * StringUtils.substringBetween("", "tag")          = null
 2159        * StringUtils.substringBetween("tagabctag", null)  = null
 2160        * StringUtils.substringBetween("tagabctag", "")    = ""
 2161        * StringUtils.substringBetween("tagabctag", "tag") = "abc"
 2162        * </pre>
 2163        *
 2164        * @param str  the String containing the substring, may be null
 2165        * @param tag  the String before and after the substring, may be null
 2166        * @return the substring, <code>null</code> if no match
 2167        * @since 2.0
 2168        */
 2169       public static String substringBetween(String str, String tag) {
 2170           return substringBetween(str, tag, tag);
 2171       }
 2172   
 2173       /**
 2174        * <p>Gets the String that is nested in between two Strings.
 2175        * Only the first match is returned.</p>
 2176        *
 2177        * <p>A <code>null</code> input String returns <code>null</code>.
 2178        * A <code>null</code> open/close returns <code>null</code> (no match).
 2179        * An empty ("") open and close returns an empty string.</p>
 2180        *
 2181        * <pre>
 2182        * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
 2183        * StringUtils.substringBetween(null, *, *)          = null
 2184        * StringUtils.substringBetween(*, null, *)          = null
 2185        * StringUtils.substringBetween(*, *, null)          = null
 2186        * StringUtils.substringBetween("", "", "")          = ""
 2187        * StringUtils.substringBetween("", "", "]")         = null
 2188        * StringUtils.substringBetween("", "[", "]")        = null
 2189        * StringUtils.substringBetween("yabcz", "", "")     = ""
 2190        * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
 2191        * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
 2192        * </pre>
 2193        *
 2194        * @param str  the String containing the substring, may be null
 2195        * @param open  the String before the substring, may be null
 2196        * @param close  the String after the substring, may be null
 2197        * @return the substring, <code>null</code> if no match
 2198        * @since 2.0
 2199        */
 2200       public static String substringBetween(String str, String open, String close) {
 2201           if (str == null || open == null || close == null) {
 2202               return null;
 2203           }
 2204           int start = str.indexOf(open);
 2205           if (start != -1) {
 2206               int end = str.indexOf(close, start + open.length());
 2207               if (end != -1) {
 2208                   return str.substring(start + open.length(), end);
 2209               }
 2210           }
 2211           return null;
 2212       }
 2213   
 2214       /**
 2215        * <p>Searches a String for substrings delimited by a start and end tag,
 2216        * returning all matching substrings in an array.</p>
 2217        *
 2218        * <p>A <code>null</code> input String returns <code>null</code>.
 2219        * A <code>null</code> open/close returns <code>null</code> (no match).
 2220        * An empty ("") open/close returns <code>null</code> (no match).</p>
 2221        *
 2222        * <pre>
 2223        * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
 2224        * StringUtils.substringsBetween(null, *, *)            = null
 2225        * StringUtils.substringsBetween(*, null, *)            = null
 2226        * StringUtils.substringsBetween(*, *, null)            = null
 2227        * StringUtils.substringsBetween("", "[", "]")          = []
 2228        * </pre>
 2229        *
 2230        * @param str  the String containing the substrings, null returns null, empty returns empty
 2231        * @param open  the String identifying the start of the substring, empty returns null
 2232        * @param close  the String identifying the end of the substring, empty returns null
 2233        * @return a String Array of substrings, or <code>null</code> if no match
 2234        * @since 2.3
 2235        */
 2236       public static String[] substringsBetween(String str, String open, String close) {
 2237           if (str == null || isEmpty(open) || isEmpty(close)) {
 2238               return null;
 2239           }
 2240           int strLen = str.length();
 2241           if (strLen == 0) {
 2242               return ArrayUtils.EMPTY_STRING_ARRAY;
 2243           }
 2244           int closeLen = close.length();
 2245           int openLen = open.length();
 2246           List list = new ArrayList();
 2247           int pos = 0;
 2248           while (pos < (strLen - closeLen)) {
 2249               int start = str.indexOf(open, pos);
 2250               if (start < 0) {
 2251                   break;
 2252               }
 2253               start += openLen;
 2254               int end = str.indexOf(close, start);
 2255               if (end < 0) {
 2256                   break;
 2257               }
 2258               list.add(str.substring(start, end));
 2259               pos = end + closeLen;
 2260           }
 2261           if (list.isEmpty()) {
 2262               return null;
 2263           } 
 2264           return (String[]) list.toArray(new String [list.size()]);
 2265       }
 2266   
 2267       // Nested extraction
 2268       //-----------------------------------------------------------------------
 2269       /**
 2270        * <p>Gets the String that is nested in between two instances of the
 2271        * same String.</p>
 2272        *
 2273        * <p>A <code>null</code> input String returns <code>null</code>.
 2274        * A <code>null</code> tag returns <code>null</code>.</p>
 2275        *
 2276        * <pre>
 2277        * StringUtils.getNestedString(null, *)            = null
 2278        * StringUtils.getNestedString("", "")             = ""
 2279        * StringUtils.getNestedString("", "tag")          = null
 2280        * StringUtils.getNestedString("tagabctag", null)  = null
 2281        * StringUtils.getNestedString("tagabctag", "")    = ""
 2282        * StringUtils.getNestedString("tagabctag", "tag") = "abc"
 2283        * </pre>
 2284        *
 2285        * @param str  the String containing nested-string, may be null
 2286        * @param tag  the String before and after nested-string, may be null
 2287        * @return the nested String, <code>null</code> if no match
 2288        * @deprecated Use the better named {@link #substringBetween(String, String)}.
 2289        *             Method will be removed in Commons Lang 3.0.
 2290        */
 2291       public static String getNestedString(String str, String tag) {
 2292           return substringBetween(str, tag, tag);
 2293       }
 2294   
 2295       /**
 2296        * <p>Gets the String that is nested in between two Strings.
 2297        * Only the first match is returned.</p>
 2298        *
 2299        * <p>A <code>null</code> input String returns <code>null</code>.
 2300        * A <code>null</code> open/close returns <code>null</code> (no match).
 2301        * An empty ("") open/close returns an empty string.</p>
 2302        *
 2303        * <pre>
 2304        * StringUtils.getNestedString(null, *, *)          = null
 2305        * StringUtils.getNestedString("", "", "")          = ""
 2306        * StringUtils.getNestedString("", "", "tag")       = null
 2307        * StringUtils.getNestedString("", "tag", "tag")    = null
 2308        * StringUtils.getNestedString("yabcz", null, null) = null
 2309        * StringUtils.getNestedString("yabcz", "", "")     = ""
 2310        * StringUtils.getNestedString("yabcz", "y", "z")   = "abc"
 2311        * StringUtils.getNestedString("yabczyabcz", "y", "z")   = "abc"
 2312        * </pre>
 2313        *
 2314        * @param str  the String containing nested-string, may be null
 2315        * @param open  the String before nested-string, may be null
 2316        * @param close  the String after nested-string, may be null
 2317        * @return the nested String, <code>null</code> if no match
 2318        * @deprecated Use the better named {@link #substringBetween(String, String, String)}.
 2319        *             Method will be removed in Commons Lang 3.0.
 2320        */
 2321       public static String getNestedString(String str, String open, String close) {
 2322           return substringBetween(str, open, close);
 2323       }
 2324   
 2325       // Splitting
 2326       //-----------------------------------------------------------------------
 2327       /**
 2328        * <p>Splits the provided text into an array, using whitespace as the
 2329        * separator.
 2330        * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
 2331        *
 2332        * <p>The separator is not included in the returned String array.
 2333        * Adjacent separators are treated as one separator.
 2334        * For more control over the split use the StrTokenizer class.</p>
 2335        *
 2336        * <p>A <code>null</code> input String returns <code>null</code>.</p>
 2337        *
 2338        * <pre>
 2339        * StringUtils.split(null)       = null
 2340        * StringUtils.split("")         = []
 2341        * StringUtils.split("abc def")  = ["abc", "def"]
 2342        * StringUtils.split("abc  def") = ["abc", "def"]
 2343        * StringUtils.split(" abc ")    = ["abc"]
 2344        * </pre>
 2345        *
 2346        * @param str  the String to parse, may be null
 2347        * @return an array of parsed Strings, <code>null</code> if null String input
 2348        */
 2349       public static String[] split(String str) {
 2350           return split(str, null, -1);
 2351       }
 2352   
 2353       /**
 2354        * <p>Splits the provided text into an array, separator specified.
 2355        * This is an alternative to using StringTokenizer.</p>
 2356        *
 2357        * <p>The separator is not included in the returned String array.
 2358        * Adjacent separators are treated as one separator.
 2359        * For more control over the split use the StrTokenizer class.</p>
 2360        *
 2361        * <p>A <code>null</code> input String returns <code>null</code>.</p>
 2362        *
 2363        * <pre>
 2364        * StringUtils.split(null, *)         = null
 2365        * StringUtils.split("", *)           = []
 2366        * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
 2367        * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
 2368        * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
 2369        * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
 2370        * </pre>
 2371        *
 2372        * @param str  the String to parse, may be null
 2373        * @param separatorChar  the character used as the delimiter
 2374        * @return an array of parsed Strings, <code>null</code> if null String input
 2375        * @since 2.0
 2376        */
 2377       public static String[] split(String str, char separatorChar) {
 2378           return splitWorker(str, separatorChar, false);
 2379       }
 2380   
 2381       /**
 2382        * <p>Splits the provided text into an array, separators specified.
 2383        * This is an alternative to using StringTokenizer.</p>
 2384        *
 2385        * <p>The separator is not included in the returned String array.
 2386        * Adjacent separators are treated as one separator.
 2387        * For more control over the split use the StrTokenizer class.</p>
 2388        *
 2389        * <p>A <code>null</code> input String returns <code>null</code>.
 2390        * A <code>null</code> separatorChars splits on whitespace.</p>
 2391        *
 2392        * <pre>
 2393        * StringUtils.split(null, *)         = null
 2394        * StringUtils.split("", *)           = []
 2395        * StringUtils.split("abc def", null) = ["abc", "def"]
 2396        * StringUtils.split("abc def", " ")  = ["abc", "def"]
 2397        * StringUtils.split("abc  def", " ") = ["abc", "def"]
 2398        * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
 2399        * </pre>
 2400        *
 2401        * @param str  the String to parse, may be null
 2402        * @param separatorChars  the characters used as the delimiters,
 2403        *  <code>null</code> splits on whitespace
 2404        * @return an array of parsed Strings, <code>null</code> if null String input
 2405        */
 2406       public static String[] split(String str, String separatorChars) {
 2407           return splitWorker(str, separatorChars, -1, false);
 2408       }
 2409   
 2410       /**
 2411        * <p>Splits the provided text into an array with a maximum length,
 2412        * separators specified.</p>
 2413        *
 2414        * <p>The separator is not included in the returned String array.
 2415        * Adjacent separators are treated as one separator.</p>
 2416        *
 2417        * <p>A <code>null</code> input String returns <code>null</code>.
 2418        * A <code>null</code> separatorChars splits on whitespace.</p>
 2419        *
 2420        * <p>If more than <code>max</code> delimited substrings are found, the last
 2421        * returned string includes all characters after the first <code>max - 1</code>
 2422        * returned strings (including separator characters).</p>
 2423        *
 2424        * <pre>
 2425        * StringUtils.split(null, *, *)            = null
 2426        * StringUtils.split("", *, *)              = []
 2427        * StringUtils.split("ab de fg", null, 0)   = ["ab", "cd", "ef"]
 2428        * StringUtils.split("ab   de fg", null, 0) = ["ab", "cd", "ef"]
 2429        * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
 2430        * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
 2431        * </pre>
 2432        *
 2433        * @param str  the String to parse, may be null
 2434        * @param separatorChars  the characters used as the delimiters,
 2435        *  <code>null</code> splits on whitespace
 2436        * @param max  the maximum number of elements to include in the
 2437        *  array. A zero or negative value implies no limit
 2438        * @return an array of parsed Strings, <code>null</code> if null String input
 2439        */
 2440       public static String[] split(String str, String separatorChars, int max) {
 2441           return splitWorker(str, separatorChars, max, false);
 2442       }
 2443   
 2444       /**
 2445        * <p>Splits the provided text into an array, separator string specified.</p>
 2446        *
 2447        * <p>The separator(s) will not be included in the returned String array.
 2448        * Adjacent separators are treated as one separator.</p>
 2449        *
 2450        * <p>A <code>null</code> input String returns <code>null</code>.
 2451        * A <code>null</code> separator splits on whitespace.</p>
 2452        *
 2453        * <pre>
 2454        * StringUtils.splitByWholeSeparator(null, *)               = null
 2455        * StringUtils.splitByWholeSeparator("", *)                 = []
 2456        * StringUtils.splitByWholeSeparator("ab de fg", null)      = ["ab", "de", "fg"]
 2457        * StringUtils.splitByWholeSeparator("ab   de fg", null)    = ["ab", "de", "fg"]
 2458        * StringUtils.splitByWholeSeparator("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
 2459        * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
 2460        * </pre>
 2461        *
 2462        * @param str  the String to parse, may be null
 2463        * @param separator  String containing the String to be used as a delimiter,
 2464        *  <code>null</code> splits on whitespace
 2465        * @return an array of parsed Strings, <code>null</code> if null String was input
 2466        */
 2467       public static String[] splitByWholeSeparator(String str, String separator) {
 2468           return splitByWholeSeparatorWorker( str, separator, -1, false ) ;
 2469       }
 2470   
 2471       /**
 2472        * <p>Splits the provided text into an array, separator string specified.
 2473        * Returns a maximum of <code>max</code> substrings.</p>
 2474        *
 2475        * <p>The separator(s) will not be included in the returned String array.
 2476        * Adjacent separators are treated as one separator.</p>
 2477        *
 2478        * <p>A <code>null</code> input String returns <code>null</code>.
 2479        * A <code>null</code> separator splits on whitespace.</p>
 2480        *
 2481        * <pre>
 2482        * StringUtils.splitByWholeSeparator(null, *, *)               = null
 2483        * StringUtils.splitByWholeSeparator("", *, *)                 = []
 2484        * StringUtils.splitByWholeSeparator("ab de fg", null, 0)      = ["ab", "de", "fg"]
 2485        * StringUtils.splitByWholeSeparator("ab   de fg", null, 0)    = ["ab", "de", "fg"]
 2486        * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
 2487        * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
 2488        * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
 2489        * </pre>
 2490        *
 2491        * @param str  the String to parse, may be null
 2492        * @param separator  String containing the String to be used as a delimiter,
 2493        *  <code>null</code> splits on whitespace
 2494        * @param max  the maximum number of elements to include in the returned
 2495        *  array. A zero or negative value implies no limit.
 2496        * @return an array of parsed Strings, <code>null</code> if null String was input
 2497        */
 2498       public static String[] splitByWholeSeparator( String str, String separator, int max ) {
 2499           return splitByWholeSeparatorWorker(str, separator, max, false);
 2500       }
 2501   
 2502       /**
 2503        * <p>Splits the provided text into an array, separator string specified. </p>
 2504        *
 2505        * <p>The separator is not included in the returned String array.
 2506        * Adjacent separators are treated as separators for empty tokens.
 2507        * For more control over the split use the StrTokenizer class.</p>
 2508        *
 2509        * <p>A <code>null</code> input String returns <code>null</code>.
 2510        * A <code>null</code> separator splits on whitespace.</p>
 2511        *
 2512        * <pre>
 2513        * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *)               = null
 2514        * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *)                 = []
 2515        * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null)      = ["ab", "de", "fg"]
 2516        * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null)    = ["ab", "", "", "de", "fg"]
 2517        * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
 2518        * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
 2519        * </pre>
 2520        *
 2521        * @param str  the String to parse, may be null
 2522        * @param separator  String containing the String to be used as a delimiter,
 2523        *  <code>null</code> splits on whitespace
 2524        * @return an array of parsed Strings, <code>null</code> if null String was input
 2525        * @since 2.4
 2526        */
 2527       public static String[] splitByWholeSeparatorPreserveAllTokens(String str, String separator) {
 2528           return splitByWholeSeparatorWorker(str, separator, -1, true);
 2529       }
 2530   
 2531       /**
 2532        * <p>Splits the provided text into an array, separator string specified.
 2533        * Returns a maximum of <code>max</code> substrings.</p>
 2534        *
 2535        * <p>The separator is not included in the returned String array.
 2536        * Adjacent separators are treated as separators for empty tokens.
 2537        * For more control over the split use the StrTokenizer class.</p>
 2538        *
 2539        * <p>A <code>null</code> input String returns <code>null</code>.
 2540        * A <code>null</code> separator splits on whitespace.</p>
 2541        *
 2542        * <pre>
 2543        * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *)               = null
 2544        * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *)                 = []
 2545        * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0)      = ["ab", "de", "fg"]
 2546        * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null, 0)    = ["ab", "", "", "de", "fg"]
 2547        * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
 2548        * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
 2549        * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
 2550        * </pre>
 2551        *
 2552        * @param str  the String to parse, may be null
 2553        * @param separator  String containing the String to be used as a delimiter,
 2554        *  <code>null</code> splits on whitespace
 2555        * @param max  the maximum number of elements to include in the returned
 2556        *  array. A zero or negative value implies no limit.
 2557        * @return an array of parsed Strings, <code>null</code> if null String was input
 2558        * @since 2.4
 2559        */
 2560       public static String[] splitByWholeSeparatorPreserveAllTokens(String str, String separator, int max) {
 2561           return splitByWholeSeparatorWorker(str, separator, max, true);
 2562       }
 2563   
 2564       /**
 2565        * Performs the logic for the <code>splitByWholeSeparatorPreserveAllTokens</code> methods.
 2566        *
 2567        * @param str  the String to parse, may be <code>null</code>
 2568        * @param separator  String containing the String to be used as a delimiter,
 2569        *  <code>null</code> splits on whitespace
 2570        * @param max  the maximum number of elements to include in the returned
 2571        *  array. A zero or negative value implies no limit.
 2572        * @param preserveAllTokens if <code>true</code>, adjacent separators are
 2573        * treated as empty token separators; if <code>false</code>, adjacent
 2574        * separators are treated as one separator.
 2575        * @return an array of parsed Strings, <code>null</code> if null String input
 2576        * @since 2.4
 2577        */
 2578       private static String[] splitByWholeSeparatorWorker(String str, String separator, int max, 
 2579                                                           boolean preserveAllTokens) 
 2580       {
 2581           if (str == null) {
 2582               return null;
 2583           }
 2584   
 2585           int len = str.length();
 2586   
 2587           if (len == 0) {
 2588               return ArrayUtils.EMPTY_STRING_ARRAY;
 2589           }
 2590   
 2591           if ((separator == null) || (EMPTY.equals(separator))) {
 2592               // Split on whitespace.
 2593               return splitWorker(str, null, max, preserveAllTokens);
 2594           }
 2595   
 2596           int separatorLength = separator.length();
 2597   
 2598           ArrayList substrings = new ArrayList();
 2599           int numberOfSubstrings = 0;
 2600           int beg = 0;
 2601           int end = 0;
 2602           while (end < len) {
 2603               end = str.indexOf(separator, beg);
 2604   
 2605               if (end > -1) {
 2606                   if (end > beg) {
 2607                       numberOfSubstrings += 1;
 2608   
 2609                       if (numberOfSubstrings == max) {
 2610                           end = len;
 2611                           substrings.add(str.substring(beg));
 2612                       } else {
 2613                           // The following is OK, because String.substring( beg, end ) excludes
 2614                           // the character at the position 'end'.
 2615                           substrings.add(str.substring(beg, end));
 2616   
 2617                           // Set the starting point for the next search.
 2618                           // The following is equivalent to beg = end + (separatorLength - 1) + 1,
 2619                           // which is the right calculation:
 2620                           beg = end + separatorLength;
 2621                       }
 2622                   } else {
 2623                       // We found a consecutive occurrence of the separator, so skip it.
 2624                       if (preserveAllTokens) {
 2625                           numberOfSubstrings += 1;
 2626                           if (numberOfSubstrings == max) {
 2627                               end = len;
 2628                               substrings.add(str.substring(beg));
 2629                           } else {
 2630                               substrings.add(EMPTY);
 2631                           }
 2632                       }
 2633                       beg = end + separatorLength;
 2634                   }
 2635               } else {
 2636                   // String.substring( beg ) goes from 'beg' to the end of the String.
 2637                   substrings.add(str.substring(beg));
 2638                   end = len;
 2639               }
 2640           }
 2641   
 2642           return (String[]) substrings.toArray(new String[substrings.size()]);
 2643       }
 2644   
 2645       // -----------------------------------------------------------------------
 2646       /**
 2647        * <p>Splits the provided text into an array, using whitespace as the
 2648        * separator, preserving all tokens, including empty tokens created by 
 2649        * adjacent separators. This is an alternative to using StringTokenizer.
 2650        * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
 2651        *
 2652        * <p>The separator is not included in the returned String array.
 2653        * Adjacent separators are treated as separators for empty tokens.
 2654        * For more control over the split use the StrTokenizer class.</p>
 2655        *
 2656        * <p>A <code>null</code> input String returns <code>null</code>.</p>
 2657        *
 2658        * <pre>
 2659        * StringUtils.splitPreserveAllTokens(null)       = null
 2660        * StringUtils.splitPreserveAllTokens("")         = []
 2661        * StringUtils.splitPreserveAllTokens("abc def")  = ["abc", "def"]
 2662        * StringUtils.splitPreserveAllTokens("abc  def") = ["abc", "", "def"]
 2663        * StringUtils.splitPreserveAllTokens(" abc ")    = ["", "abc", ""]
 2664        * </pre>
 2665        *
 2666        * @param str  the String to parse, may be <code>null</code>
 2667        * @return an array of parsed Strings, <code>null</code> if null String input
 2668        * @since 2.1
 2669        */
 2670       public static String[] splitPreserveAllTokens(String str) {
 2671           return splitWorker(str, null, -1, true);
 2672       }
 2673   
 2674       /**
 2675        * <p>Splits the provided text into an array, separator specified,
 2676        * preserving all tokens, including empty tokens created by adjacent
 2677        * separators. This is an alternative to using StringTokenizer.</p>
 2678        *
 2679        * <p>The separator is not included in the returned String array.
 2680        * Adjacent separators are treated as separators for empty tokens.
 2681        * For more control over the split use the StrTokenizer class.</p>
 2682        *
 2683        * <p>A <code>null</code> input String returns <code>null</code>.</p>
 2684        *
 2685        * <pre>
 2686        * StringUtils.splitPreserveAllTokens(null, *)         = null
 2687        * StringUtils.splitPreserveAllTokens("", *)           = []
 2688        * StringUtils.splitPreserveAllTokens("a.b.c", '.')    = ["a", "b", "c"]
 2689        * StringUtils.splitPreserveAllTokens("a..b.c", '.')   = ["a", "", "b", "c"]
 2690        * StringUtils.splitPreserveAllTokens("a:b:c", '.')    = ["a:b:c"]
 2691        * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
 2692        * StringUtils.splitPreserveAllTokens("a b c", ' ')    = ["a", "b", "c"]
 2693        * StringUtils.splitPreserveAllTokens("a b c ", ' ')   = ["a", "b", "c", ""]
 2694        * StringUtils.splitPreserveAllTokens("a b c  ", ' ')   = ["a", "b", "c", "", ""]
 2695        * StringUtils.splitPreserveAllTokens(" a b c", ' ')   = ["", a", "b", "c"]
 2696        * StringUtils.splitPreserveAllTokens("  a b c", ' ')  = ["", "", a", "b", "c"]
 2697        * StringUtils.splitPreserveAllTokens(" a b c ", ' ')  = ["", a", "b", "c", ""]
 2698        * </pre>
 2699        *
 2700        * @param str  the String to parse, may be <code>null</code>
 2701        * @param separatorChar  the character used as the delimiter,
 2702        *  <code>null</code> splits on whitespace
 2703        * @return an array of parsed Strings, <code>null</code> if null String input
 2704        * @since 2.1
 2705        */
 2706       public static String[] splitPreserveAllTokens(String str, char separatorChar) {
 2707           return splitWorker(str, separatorChar, true);
 2708       }
 2709   
 2710       /**
 2711        * Performs the logic for the <code>split</code> and 
 2712        * <code>splitPreserveAllTokens</code> methods that do not return a
 2713        * maximum array length.
 2714        *
 2715        * @param str  the String to parse, may be <code>null</code>
 2716        * @param separatorChar the separate character
 2717        * @param preserveAllTokens if <code>true</code>, adjacent separators are
 2718        * treated as empty token separators; if <code>false</code>, adjacent
 2719        * separators are treated as one separator.
 2720        * @return an array of parsed Strings, <code>null</code> if null String input
 2721        */
 2722       private static String[] splitWorker(String str, char separatorChar, boolean preserveAllTokens) {
 2723           // Performance tuned for 2.0 (JDK1.4)
 2724   
 2725           if (str == null) {
 2726               return null;
 2727           }
 2728           int len = str.length();
 2729           if (len == 0) {
 2730               return ArrayUtils.EMPTY_STRING_ARRAY;
 2731           }
 2732           List list = new ArrayList();
 2733           int i = 0, start = 0;
 2734           boolean match = false;
 2735           boolean lastMatch = false;
 2736           while (i < len) {
 2737               if (str.charAt(i) == separatorChar) {
 2738                   if (match || preserveAllTokens) {
 2739                       list.add(str.substring(start, i));
 2740                       match = false;
 2741                       lastMatch = true;
 2742                   }
 2743                   start = ++i;
 2744                   continue;
 2745               }
 2746               lastMatch = false;
 2747               match = true;
 2748               i++;
 2749           }
 2750           if (match || (preserveAllTokens && lastMatch)) {
 2751               list.add(str.substring(start, i));
 2752           }
 2753           return (String[]) list.toArray(new String[list.size()]);
 2754       }
 2755   
 2756       /**
 2757        * <p>Splits the provided text into an array, separators specified, 
 2758        * preserving all tokens, including empty tokens created by adjacent
 2759        * separators. This is an alternative to using StringTokenizer.</p>
 2760        *
 2761        * <p>The separator is not included in the returned String array.
 2762        * Adjacent separators are treated as separators for empty tokens.
 2763        * For more control over the split use the StrTokenizer class.</p>
 2764        *
 2765        * <p>A <code>null</code> input String returns <code>null</code>.
 2766        * A <code>null</code> separatorChars splits on whitespace.</p>
 2767        *
 2768        * <pre>
 2769        * StringUtils.splitPreserveAllTokens(null, *)           = null
 2770        * StringUtils.splitPreserveAllTokens("", *)             = []
 2771        * StringUtils.splitPreserveAllTokens("abc def", null)   = ["abc", "def"]
 2772        * StringUtils.splitPreserveAllTokens("abc def", " ")    = ["abc", "def"]
 2773        * StringUtils.splitPreserveAllTokens("abc  def", " ")   = ["abc", "", def"]
 2774        * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":")   = ["ab", "cd", "ef"]
 2775        * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":")  = ["ab", "cd", "ef", ""]
 2776        * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
 2777        * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":")  = ["ab", "", cd", "ef"]
 2778        * StringUtils.splitPreserveAllTokens(":cd:ef", ":")     = ["", cd", "ef"]
 2779        * StringUtils.splitPreserveAllTokens("::cd:ef", ":")    = ["", "", cd", "ef"]
 2780        * StringUtils.splitPreserveAllTokens(":cd:ef:", ":")    = ["", cd", "ef", ""]
 2781        * </pre>
 2782        *
 2783        * @param str  the String to parse, may be <code>null</code>
 2784        * @param separatorChars  the characters used as the delimiters,
 2785        *  <code>null</code> splits on whitespace
 2786        * @return an array of parsed Strings, <code>null</code> if null String input
 2787        * @since 2.1
 2788        */
 2789       public static String[] splitPreserveAllTokens(String str, String separatorChars) {
 2790           return splitWorker(str, separatorChars, -1, true);
 2791       }
 2792   
 2793       /**
 2794        * <p>Splits the provided text into an array with a maximum length,
 2795        * separators specified, preserving all tokens, including empty tokens 
 2796        * created by adjacent separators.</p>
 2797        *
 2798        * <p>The separator is not included in the returned String array.
 2799        * Adjacent separators are treated as separators for empty tokens.
 2800        * Adjacent separators are treated as one separator.</p>
 2801        *
 2802        * <p>A <code>null</code> input String returns <code>null</code>.
 2803        * A <code>null</code> separatorChars splits on whitespace.</p>
 2804        *
 2805        * <p>If more than <code>max</code> delimited substrings are found, the last
 2806        * returned string includes all characters after the first <code>max - 1</code>
 2807        * returned strings (including separator characters).</p>
 2808        *
 2809        * <pre>
 2810        * StringUtils.splitPreserveAllTokens(null, *, *)            = null
 2811        * StringUtils.splitPreserveAllTokens("", *, *)              = []
 2812        * StringUtils.splitPreserveAllTokens("ab de fg", null, 0)   = ["ab", "cd", "ef"]
 2813        * StringUtils.splitPreserveAllTokens("ab   de fg", null, 0) = ["ab", "cd", "ef"]
 2814        * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
 2815        * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
 2816        * StringUtils.splitPreserveAllTokens("ab   de fg", null, 2) = ["ab", "  de fg"]
 2817        * StringUtils.splitPreserveAllTokens("ab   de fg", null, 3) = ["ab", "", " de fg"]
 2818        * StringUtils.splitPreserveAllTokens("ab   de fg", null, 4) = ["ab", "", "", "de fg"]
 2819        * </pre>
 2820        *
 2821        * @param str  the String to parse, may be <code>null</code>
 2822        * @param separatorChars  the characters used as the delimiters,
 2823        *  <code>null</code> splits on whitespace
 2824        * @param max  the maximum number of elements to include in the
 2825        *  array. A zero or negative value implies no limit
 2826        * @return an array of parsed Strings, <code>null</code> if null String input
 2827        * @since 2.1
 2828        */
 2829       public static String[] splitPreserveAllTokens(String str, String separatorChars, int max) {
 2830           return splitWorker(str, separatorChars, max, true);
 2831       }
 2832   
 2833       /**
 2834        * Performs the logic for the <code>split</code> and 
 2835        * <code>splitPreserveAllTokens</code> methods that return a maximum array 
 2836        * length.
 2837        *
 2838        * @param str  the String to parse, may be <code>null</code>
 2839        * @param separatorChars the separate character
 2840        * @param max  the maximum number of elements to include in the
 2841        *  array. A zero or negative value implies no limit.
 2842        * @param preserveAllTokens if <code>true</code>, adjacent separators are
 2843        * treated as empty token separators; if <code>false</code>, adjacent
 2844        * separators are treated as one separator.
 2845        * @return an array of parsed Strings, <code>null</code> if null String input
 2846        */
 2847       private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens) {
 2848           // Performance tuned for 2.0 (JDK1.4)
 2849           // Direct code is quicker than StringTokenizer.
 2850           // Also, StringTokenizer uses isSpace() not isWhitespace()
 2851   
 2852           if (str == null) {
 2853               return null;
 2854           }
 2855           int len = str.length();
 2856           if (len == 0) {
 2857               return ArrayUtils.EMPTY_STRING_ARRAY;
 2858           }
 2859           List list = new ArrayList();
 2860           int sizePlus1 = 1;
 2861           int i = 0, start = 0;
 2862           boolean match = false;
 2863           boolean lastMatch = false;
 2864           if (separatorChars == null) {
 2865               // Null separator means use whitespace
 2866               while (i < len) {
 2867                   if (Character.isWhitespace(str.charAt(i))) {
 2868                       if (match || preserveAllTokens) {
 2869                           lastMatch = true;
 2870                           if (sizePlus1++ == max) {
 2871                               i = len;
 2872                               lastMatch = false;
 2873                           }
 2874                           list.add(str.substring(start, i));
 2875                           match = false;
 2876                       }
 2877                       start = ++i;
 2878                       continue;
 2879                   }
 2880                   lastMatch = false;
 2881                   match = true;
 2882                   i++;
 2883               }
 2884           } else if (separatorChars.length() == 1) {
 2885               // Optimise 1 character case
 2886               char sep = separatorChars.charAt(0);
 2887               while (i < len) {
 2888                   if (str.charAt(i) == sep) {
 2889                       if (match || preserveAllTokens) {
 2890                           lastMatch = true;
 2891                           if (sizePlus1++ == max) {
 2892                               i = len;
 2893                               lastMatch = false;
 2894                           }
 2895                           list.add(str.substring(start, i));
 2896                           match = false;
 2897                       }
 2898                       start = ++i;
 2899                       continue;
 2900                   }
 2901                   lastMatch = false;
 2902                   match = true;
 2903                   i++;
 2904               }
 2905           } else {
 2906               // standard case
 2907               while (i < len) {
 2908                   if (separatorChars.indexOf(str.charAt(i)) >= 0) {
 2909                       if (match || preserveAllTokens) {
 2910                           lastMatch = true;
 2911                           if (sizePlus1++ == max) {
 2912                               i = len;
 2913                               lastMatch = false;
 2914                           }
 2915                           list.add(str.substring(start, i));
 2916                           match = false;
 2917                       }
 2918                       start = ++i;
 2919                       continue;
 2920                   }
 2921                   lastMatch = false;
 2922                   match = true;
 2923                   i++;
 2924               }
 2925           }
 2926           if (match || (preserveAllTokens && lastMatch)) {
 2927               list.add(str.substring(start, i));
 2928           }
 2929           return (String[]) list.toArray(new String[list.size()]);
 2930       }
 2931   
 2932       /**
 2933        * <p>Splits a String by Character type as returned by
 2934        * <code>java.lang.Character.getType(char)</code>. Groups of contiguous
 2935        * characters of the same type are returned as complete tokens. 
 2936        * <pre>
 2937        * StringUtils.splitByCharacterType(null)         = null
 2938        * StringUtils.splitByCharacterType("")           = []
 2939        * StringUtils.splitByCharacterType("ab de fg")   = ["ab", " ", "de", " ", "fg"]
 2940        * StringUtils.splitByCharacterType("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
 2941        * StringUtils.splitByCharacterType("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
 2942        * StringUtils.splitByCharacterType("number5")    = ["number", "5"]
 2943        * StringUtils.splitByCharacterType("fooBar")     = ["foo", "B", "ar"]
 2944        * StringUtils.splitByCharacterType("foo200Bar")  = ["foo", "200", "B", "ar"]
 2945        * StringUtils.splitByCharacterType("ASFRules")   = ["ASFR", "ules"]
 2946        * </pre>
 2947        * @param str the String to split, may be <code>null</code>
 2948        * @return an array of parsed Strings, <code>null</code> if null String input
 2949        * @since 2.4
 2950        */
 2951       public static String[] splitByCharacterType(String str) {
 2952           return splitByCharacterType(str, false);
 2953       }
 2954   
 2955       /**
 2956        * <p>Splits a String by Character type as returned by
 2957        * <code>java.lang.Character.getType(char)</code>. Groups of contiguous
 2958        * characters of the same type are returned as complete tokens, with the
 2959        * following exception: the character of type
 2960        * <code>Character.UPPERCASE_LETTER</code>, if any, immediately
 2961        * preceding a token of type <code>Character.LOWERCASE_LETTER</code>
 2962        * will belong to the following token rather than to the preceding, if any,
 2963        * <code>Character.UPPERCASE_LETTER</code> token. 
 2964        * <pre>
 2965        * StringUtils.splitByCharacterTypeCamelCase(null)         = null
 2966        * StringUtils.splitByCharacterTypeCamelCase("")           = []
 2967        * StringUtils.splitByCharacterTypeCamelCase("ab de fg")   = ["ab", " ", "de", " ", "fg"]
 2968        * StringUtils.splitByCharacterTypeCamelCase("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
 2969        * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
 2970        * StringUtils.splitByCharacterTypeCamelCase("number5")    = ["number", "5"]
 2971        * StringUtils.splitByCharacterTypeCamelCase("fooBar")     = ["foo", "Bar"]
 2972        * StringUtils.splitByCharacterTypeCamelCase("foo200Bar")  = ["foo", "200", "Bar"]
 2973        * StringUtils.splitByCharacterTypeCamelCase("ASFRules")   = ["ASF", "Rules"]
 2974        * </pre>
 2975        * @param str the String to split, may be <code>null</code>
 2976        * @return an array of parsed Strings, <code>null</code> if null String input
 2977        * @since 2.4
 2978        */
 2979       public static String[] splitByCharacterTypeCamelCase(String str) {
 2980           return splitByCharacterType(str, true);
 2981       }
 2982   
 2983       /**
 2984        * <p>Splits a String by Character type as returned by
 2985        * <code>java.lang.Character.getType(char)</code>. Groups of contiguous
 2986        * characters of the same type are returned as complete tokens, with the
 2987        * following exception: if <code>camelCase</code> is <code>true</code>,
 2988        * the character of type <code>Character.UPPERCASE_LETTER</code>, if any,
 2989        * immediately preceding a token of type <code>Character.LOWERCASE_LETTER</code>
 2990        * will belong to the following token rather than to the preceding, if any,
 2991        * <code>Character.UPPERCASE_LETTER</code> token. 
 2992        * @param str the String to split, may be <code>null</code>
 2993        * @param camelCase whether to use so-called "camel-case" for letter types
 2994        * @return an array of parsed Strings, <code>null</code> if null String input
 2995        * @since 2.4
 2996        */
 2997       private static String[] splitByCharacterType(String str, boolean camelCase) {
 2998           if (str == null) {
 2999               return null;
 3000           }
 3001           if (str.length() == 0) {
 3002               return ArrayUtils.EMPTY_STRING_ARRAY;
 3003           }
 3004           char[] c = str.toCharArray();
 3005           List list = new ArrayList();
 3006           int tokenStart = 0;
 3007           int currentType = Character.getType(c[tokenStart]);
 3008           for (int pos = tokenStart + 1; pos < c.length; pos++) {
 3009               int type = Character.getType(c[pos]);
 3010               if (type == currentType) {
 3011                   continue;
 3012               }
 3013               if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
 3014                   int newTokenStart = pos - 1;
 3015                   if (newTokenStart != tokenStart) {
 3016                       list.add(new String(c, tokenStart, newTokenStart - tokenStart));
 3017                       tokenStart = newTokenStart;
 3018                   }
 3019               } else {
 3020                   list.add(new String(c, tokenStart, pos - tokenStart));
 3021                   tokenStart = pos;
 3022               }
 3023               currentType = type;
 3024           }
 3025           list.add(new String(c, tokenStart, c.length - tokenStart));
 3026           return (String[]) list.toArray(new String[list.size()]);
 3027       }
 3028   
 3029       // Joining
 3030       //-----------------------------------------------------------------------
 3031       /**
 3032        * <p>Concatenates elements of an array into a single String.
 3033        * Null objects or empty strings within the array are represented by
 3034        * empty strings.</p>
 3035        *
 3036        * <pre>
 3037        * StringUtils.concatenate(null)            = null
 3038        * StringUtils.concatenate([])              = ""
 3039        * StringUtils.concatenate([null])          = ""
 3040        * StringUtils.concatenate(["a", "b", "c"]) = "abc"
 3041        * StringUtils.concatenate([null, "", "a"]) = "a"
 3042        * </pre>
 3043        *
 3044        * @param array  the array of values to concatenate, may be null
 3045        * @return the concatenated String, <code>null</code> if null array input
 3046        * @deprecated Use the better named {@link #join(Object[])} instead.
 3047        *             Method will be removed in Commons Lang 3.0.
 3048        */
 3049       public static String concatenate(Object[] array) {
 3050           return join(array, null);
 3051       }
 3052   
 3053       /**
 3054        * <p>Joins the elements of the provided array into a single String
 3055        * containing the provided list of elements.</p>
 3056        *
 3057        * <p>No separator is added to the joined String.
 3058        * Null objects or empty strings within the array are represented by
 3059        * empty strings.</p>
 3060        *
 3061        * <pre>
 3062        * StringUtils.join(null)            = null
 3063        * StringUtils.join([])              = ""
 3064        * StringUtils.join([null])          = ""
 3065        * StringUtils.join(["a", "b", "c"]) = "abc"
 3066        * StringUtils.join([null, "", "a"]) = "a"
 3067        * </pre>
 3068        *
 3069        * @param array  the array of values to join together, may be null
 3070        * @return the joined String, <code>null</code> if null array input
 3071        * @since 2.0
 3072        */
 3073       public static String join(Object[] array) {
 3074           return join(array, null);
 3075       }
 3076   
 3077       /**
 3078        * <p>Joins the elements of the provided array into a single String
 3079        * containing the provided list of elements.</p>
 3080        *
 3081        * <p>No delimiter is added before or after the list.
 3082        * Null objects or empty strings within the array are represented by
 3083        * empty strings.</p>
 3084        *
 3085        * <pre>
 3086        * StringUtils.join(null, *)               = null
 3087        * StringUtils.join([], *)                 = ""
 3088        * StringUtils.join([null], *)             = ""
 3089        * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
 3090        * StringUtils.join(["a", "b", "c"], null) = "abc"
 3091        * StringUtils.join([null, "", "a"], ';')  = ";;a"
 3092        * </pre>
 3093        *
 3094        * @param array  the array of values to join together, may be null
 3095        * @param separator  the separator character to use
 3096        * @return the joined String, <code>null</code> if null array input
 3097        * @since 2.0
 3098        */
 3099       public static String join(Object[] array, char separator) {
 3100           if (array == null) {
 3101               return null;
 3102           }
 3103   
 3104           return join(array, separator, 0, array.length);
 3105       }
 3106   
 3107       /**
 3108        * <p>Joins the elements of the provided array into a single String
 3109        * containing the provided list of elements.</p>
 3110        *
 3111        * <p>No delimiter is added before or after the list.
 3112        * Null objects or empty strings within the array are represented by
 3113        * empty strings.</p>
 3114        *
 3115        * <pre>
 3116        * StringUtils.join(null, *)               = null
 3117        * StringUtils.join([], *)                 = ""
 3118        * StringUtils.join([null], *)             = ""
 3119        * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
 3120        * StringUtils.join(["a", "b", "c"], null) = "abc"
 3121        * StringUtils.join([null, "", "a"], ';')  = ";;a"
 3122        * </pre>
 3123        *
 3124        * @param array  the array of values to join together, may be null
 3125        * @param separator  the separator character to use
 3126        * @param startIndex the first index to start joining from.  It is
 3127        * an error to pass in an end index past the end of the array
 3128        * @param endIndex the index to stop joining from (exclusive). It is
 3129        * an error to pass in an end index past the end of the array
 3130        * @return the joined String, <code>null</code> if null array input
 3131        * @since 2.0
 3132        */
 3133       public static String join(Object[] array, char separator, int startIndex, int endIndex) {
 3134           if (array == null) {
 3135               return null;
 3136           }
 3137           int bufSize = (endIndex - startIndex);
 3138           if (bufSize <= 0) {
 3139               return EMPTY;
 3140           }
 3141   
 3142           bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length()) + 1);
 3143           StringBuffer buf = new StringBuffer(bufSize);
 3144   
 3145           for (int i = startIndex; i < endIndex; i++) {
 3146               if (i > startIndex) {
 3147                   buf.append(separator);
 3148               }
 3149               if (array[i] != null) {
 3150                   buf.append(array[i]);
 3151               }
 3152           }
 3153           return buf.toString();
 3154       }
 3155   
 3156   
 3157       /**
 3158        * <p>Joins the elements of the provided array into a single String
 3159        * containing the provided list of elements.</p>
 3160        *
 3161        * <p>No delimiter is added before or after the list.
 3162        * A <code>null</code> separator is the same as an empty String ("").
 3163        * Null objects or empty strings within the array are represented by
 3164        * empty strings.</p>
 3165        *
 3166        * <pre>
 3167        * StringUtils.join(null, *)                = null
 3168        * StringUtils.join([], *)                  = ""
 3169        * StringUtils.join([null], *)              = ""
 3170        * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
 3171        * StringUtils.join(["a", "b", "c"], null)  = "abc"
 3172        * StringUtils.join(["a", "b", "c"], "")    = "abc"
 3173        * StringUtils.join([null, "", "a"], ',')   = ",,a"
 3174        * </pre>
 3175        *
 3176        * @param array  the array of values to join together, may be null
 3177        * @param separator  the separator character to use, null treated as ""
 3178        * @return the joined String, <code>null</code> if null array input
 3179        */
 3180       public static String join(Object[] array, String separator) {
 3181           if (array == null) {
 3182               return null;
 3183           }
 3184           return join(array, separator, 0, array.length);
 3185       }
 3186   
 3187       /**
 3188        * <p>Joins the elements of the provided array into a single String
 3189        * containing the provided list of elements.</p>
 3190        *
 3191        * <p>No delimiter is added before or after the list.
 3192        * A <code>null</code> separator is the same as an empty String ("").
 3193        * Null objects or empty strings within the array are represented by
 3194        * empty strings.</p>
 3195        *
 3196        * <pre>
 3197        * StringUtils.join(null, *)                = null
 3198        * StringUtils.join([], *)                  = ""
 3199        * StringUtils.join([null], *)              = ""
 3200        * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
 3201        * StringUtils.join(["a", "b", "c"], null)  = "abc"
 3202        * StringUtils.join(["a", "b", "c"], "")    = "abc"
 3203        * StringUtils.join([null, "", "a"], ',')   = ",,a"
 3204        * </pre>
 3205        *
 3206        * @param array  the array of values to join together, may be null
 3207        * @param separator  the separator character to use, null treated as ""
 3208        * @param startIndex the first index to start joining from.  It is
 3209        * an error to pass in an end index past the end of the array
 3210        * @param endIndex the index to stop joining from (exclusive). It is
 3211        * an error to pass in an end index past the end of the array
 3212        * @return the joined String, <code>null</code> if null array input
 3213        */
 3214       public static String join(Object[] array, String separator, int startIndex, int endIndex) {
 3215           if (array == null) {
 3216               return null;
 3217           }
 3218           if (separator == null) {
 3219               separator = EMPTY;
 3220           }
 3221   
 3222           // endIndex - startIndex > 0:   Len = NofStrings *(len(firstString) + len(separator))
 3223           //           (Assuming that all Strings are roughly equally long)
 3224           int bufSize = (endIndex - startIndex);
 3225           if (bufSize <= 0) {
 3226               return EMPTY;
 3227           }
 3228   
 3229           bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length())
 3230                           + separator.length());
 3231   
 3232           StringBuffer buf = new StringBuffer(bufSize);
 3233   
 3234           for (int i = startIndex; i < endIndex; i++) {
 3235               if (i > startIndex) {
 3236                   buf.append(separator);
 3237               }
 3238               if (array[i] != null) {
 3239                   buf.append(array[i]);
 3240               }
 3241           }
 3242           return buf.toString();
 3243       }
 3244   
 3245       /**
 3246        * <p>Joins the elements of the provided <code>Iterator</code> into
 3247        * a single String containing the provided elements.</p>
 3248        *
 3249        * <p>No delimiter is added before or after the list. Null objects or empty
 3250        * strings within the iteration are represented by empty strings.</p>
 3251        *
 3252        * <p>See the examples here: {@link #join(Object[],char)}. </p>
 3253        *
 3254        * @param iterator  the <code>Iterator</code> of values to join together, may be null
 3255        * @param separator  the separator character to use
 3256        * @return the joined String, <code>null</code> if null iterator input
 3257        * @since 2.0
 3258        */
 3259       public static String join(Iterator iterator, char separator) {
 3260   
 3261           // handle null, zero and one elements before building a buffer
 3262           if (iterator == null) {
 3263               return null;
 3264           }
 3265           if (!iterator.hasNext()) {
 3266               return EMPTY;
 3267           }
 3268           Object first = iterator.next();
 3269           if (!iterator.hasNext()) {
 3270               return ObjectUtils.toString(first);
 3271           }
 3272   
 3273           // two or more elements
 3274           StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
 3275           if (first != null) {
 3276               buf.append(first);
 3277           }
 3278   
 3279           while (iterator.hasNext()) {
 3280               buf.append(separator);
 3281               Object obj = iterator.next();
 3282               if (obj != null) {
 3283                   buf.append(obj);
 3284               }
 3285           }
 3286   
 3287           return buf.toString();
 3288       }
 3289   
 3290       /**
 3291        * <p>Joins the elements of the provided <code>Iterator</code> into
 3292        * a single String containing the provided elements.</p>
 3293        *
 3294        * <p>No delimiter is added before or after the list.
 3295        * A <code>null</code> separator is the same as an empty String ("").</p>
 3296        *
 3297        * <p>See the examples here: {@link #join(Object[],String)}. </p>
 3298        *
 3299        * @param iterator  the <code>Iterator</code> of values to join together, may be null
 3300        * @param separator  the separator character to use, null treated as ""
 3301        * @return the joined String, <code>null</code> if null iterator input
 3302        */
 3303       public static String join(Iterator iterator, String separator) {
 3304   
 3305           // handle null, zero and one elements before building a buffer
 3306           if (iterator == null) {
 3307               return null;
 3308           }
 3309           if (!iterator.hasNext()) {
 3310               return EMPTY;
 3311           }
 3312           Object first = iterator.next();
 3313           if (!iterator.hasNext()) {
 3314               return ObjectUtils.toString(first);
 3315           }
 3316   
 3317           // two or more elements
 3318           StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
 3319           if (first != null) {
 3320               buf.append(first);
 3321           }
 3322   
 3323           while (iterator.hasNext()) {
 3324               if (separator != null) {
 3325                   buf.append(separator);
 3326               }
 3327               Object obj = iterator.next();
 3328               if (obj != null) {
 3329                   buf.append(obj);
 3330               }
 3331           }
 3332           return buf.toString();
 3333       }
 3334   
 3335       /**
 3336        * <p>Joins the elements of the provided <code>Collection</code> into
 3337        * a single String containing the provided elements.</p>
 3338        *
 3339        * <p>No delimiter is added before or after the list. Null objects or empty
 3340        * strings within the iteration are represented by empty strings.</p>
 3341        *
 3342        * <p>See the examples here: {@link #join(Object[],char)}. </p>
 3343        *
 3344        * @param collection  the <code>Collection</code> of values to join together, may be null
 3345        * @param separator  the separator character to use
 3346        * @return the joined String, <code>null</code> if null iterator input
 3347        * @since 2.3
 3348        */
 3349       public static String join(Collection collection, char separator) {
 3350           if (collection == null) {
 3351               return null;
 3352           }
 3353           return join(collection.iterator(), separator);
 3354       }
 3355   
 3356       /**
 3357        * <p>Joins the elements of the provided <code>Collection</code> into
 3358        * a single String containing the provided elements.</p>
 3359        *
 3360        * <p>No delimiter is added before or after the list.
 3361        * A <code>null</code> separator is the same as an empty String ("").</p>
 3362        *
 3363        * <p>See the examples here: {@link #join(Object[],String)}. </p>
 3364        *
 3365        * @param collection  the <code>Collection</code> of values to join together, may be null
 3366        * @param separator  the separator character to use, null treated as ""
 3367        * @return the joined String, <code>null</code> if null iterator input
 3368        * @since 2.3
 3369        */
 3370       public static String join(Collection collection, String separator) {
 3371           if (collection == null) {
 3372               return null;
 3373           }
 3374           return join(collection.iterator(), separator);
 3375       }
 3376   
 3377       // Delete
 3378       //-----------------------------------------------------------------------
 3379       /**
 3380        * <p>Deletes all 'space' characters from a String as defined by
 3381        * {@link Character#isSpace(char)}.</p>
 3382        *
 3383        * <p>This is the only StringUtils method that uses the
 3384        * <code>isSpace</code> definition. You are advised to use
 3385        * {@link #deleteWhitespace(String)} instead as whitespace is much
 3386        * better localized.</p>
 3387        *
 3388        * <pre>
 3389        * StringUtils.deleteSpaces(null)           = null
 3390        * StringUtils.deleteSpaces("")             = ""
 3391        * StringUtils.deleteSpaces("abc")          = "abc"
 3392        * StringUtils.deleteSpaces(" \t  abc \n ") = "abc"
 3393        * StringUtils.deleteSpaces("ab  c")        = "abc"
 3394        * StringUtils.deleteSpaces("a\nb\tc     ") = "abc"
 3395        * </pre>
 3396        *
 3397        * <p>Spaces are defined as <code>{' ', '\t', '\r', '\n', '\b'}</code>
 3398        * in line with the deprecated <code>isSpace</code> method.</p>
 3399        *
 3400        * @param str  the String to delete spaces from, may be null
 3401        * @return the String without 'spaces', <code>null</code> if null String input
 3402        * @deprecated Use the better localized {@link #deleteWhitespace(String)}.
 3403        *             Method will be removed in Commons Lang 3.0.
 3404        */
 3405       public static String deleteSpaces(String str) {
 3406           if (str == null) {
 3407               return null;
 3408           }
 3409           return CharSetUtils.delete(str, " \t\r\n\b");
 3410       }
 3411   
 3412       /**
 3413        * <p>Deletes all whitespaces from a String as defined by
 3414        * {@link Character#isWhitespace(char)}.</p>
 3415        *
 3416        * <pre>
 3417        * StringUtils.deleteWhitespace(null)         = null
 3418        * StringUtils.deleteWhitespace("")           = ""
 3419        * StringUtils.deleteWhitespace("abc")        = "abc"
 3420        * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
 3421        * </pre>
 3422        *
 3423        * @param str  the String to delete whitespace from, may be null
 3424        * @return the String without whitespaces, <code>null</code> if null String input
 3425        */
 3426       public static String deleteWhitespace(String str) {
 3427           if (isEmpty(str)) {
 3428               return str;
 3429           }
 3430           int sz = str.length();
 3431           char[] chs = new char[sz];
 3432           int count = 0;
 3433           for (int i = 0; i < sz; i++) {
 3434               if (!Character.isWhitespace(str.charAt(i))) {
 3435                   chs[count++] = str.charAt(i);
 3436               }
 3437           }
 3438           if (count == sz) {
 3439               return str;
 3440           }
 3441           return new String(chs, 0, count);
 3442       }
 3443   
 3444       // Remove
 3445       //-----------------------------------------------------------------------
 3446       /**
 3447        * <p>Removes a substring only if it is at the begining of a source string,
 3448        * otherwise returns the source string.</p>
 3449        *
 3450        * <p>A <code>null</code> source string will return <code>null</code>.
 3451        * An empty ("") source string will return the empty string.
 3452        * A <code>null</code> search string will return the source string.</p>
 3453        *
 3454        * <pre>
 3455        * StringUtils.removeStart(null, *)      = null
 3456        * StringUtils.removeStart("", *)        = ""
 3457        * StringUtils.removeStart(*, null)      = *
 3458        * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
 3459        * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
 3460        * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
 3461        * StringUtils.removeStart("abc", "")    = "abc"
 3462        * </pre>
 3463        *
 3464        * @param str  the source String to search, may be null
 3465        * @param remove  the String to search for and remove, may be null
 3466        * @return the substring with the string removed if found,
 3467        *  <code>null</code> if null String input
 3468        * @since 2.1
 3469        */
 3470       public static String removeStart(String str, String remove) {
 3471           if (isEmpty(str) || isEmpty(remove)) {
 3472               return str;
 3473           }
 3474           if (str.startsWith(remove)){
 3475               return str.substring(remove.length());
 3476           }
 3477           return str;
 3478       }
 3479   
 3480       /**
 3481        * <p>Case insensitive removal of a substring if it is at the begining of a source string,
 3482        * otherwise returns the source string.</p>
 3483        *
 3484        * <p>A <code>null</code> source string will return <code>null</code>.
 3485        * An empty ("") source string will return the empty string.
 3486        * A <code>null</code> search string will return the source string.</p>
 3487        *
 3488        * <pre>
 3489        * StringUtils.removeStartIgnoreCase(null, *)      = null
 3490        * StringUtils.removeStartIgnoreCase("", *)        = ""
 3491        * StringUtils.removeStartIgnoreCase(*, null)      = *
 3492        * StringUtils.removeStartIgnoreCase("www.domain.com", "www.")   = "domain.com"
 3493        * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.")   = "domain.com"
 3494        * StringUtils.removeStartIgnoreCase("domain.com", "www.")       = "domain.com"
 3495        * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
 3496        * StringUtils.removeStartIgnoreCase("abc", "")    = "abc"
 3497        * </pre>
 3498        *
 3499        * @param str  the source String to search, may be null
 3500        * @param remove  the String to search for (case insensitive) and remove, may be null
 3501        * @return the substring with the string removed if found,
 3502        *  <code>null</code> if null String input
 3503        * @since 2.4
 3504        */
 3505       public static String removeStartIgnoreCase(String str, String remove) {
 3506           if (isEmpty(str) || isEmpty(remove)) {
 3507               return str;
 3508           }
 3509           if (startsWithIgnoreCase(str, remove)) {
 3510               return str.substring(remove.length());
 3511           }
 3512           return str;
 3513       }
 3514   
 3515       /**
 3516        * <p>Removes a substring only if it is at the end of a source string,
 3517        * otherwise returns the source string.</p>
 3518        *
 3519        * <p>A <code>null</code> source string will return <code>null</code>.
 3520        * An empty ("") source string will return the empty string.
 3521        * A <code>null</code> search string will return the source string.</p>
 3522        *
 3523        * <pre>
 3524        * StringUtils.removeEnd(null, *)      = null
 3525        * StringUtils.removeEnd("", *)        = ""
 3526        * StringUtils.removeEnd(*, null)      = *
 3527        * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
 3528        * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
 3529        * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
 3530        * StringUtils.removeEnd("abc", "")    = "abc"
 3531        * </pre>
 3532        *
 3533        * @param str  the source String to search, may be null
 3534        * @param remove  the String to search for and remove, may be null
 3535        * @return the substring with the string removed if found,
 3536        *  <code>null</code> if null String input
 3537        * @since 2.1
 3538        */
 3539       public static String removeEnd(String str, String remove) {
 3540           if (isEmpty(str) || isEmpty(remove)) {
 3541               return str;
 3542           }
 3543           if (str.endsWith(remove)) {
 3544               return str.substring(0, str.length() - remove.length());
 3545           }
 3546           return str;
 3547       }
 3548   
 3549       /**
 3550        * <p>Case insensitive removal of a substring if it is at the end of a source string,
 3551        * otherwise returns the source string.</p>
 3552        *
 3553        * <p>A <code>null</code> source string will return <code>null</code>.
 3554        * An empty ("") source string will return the empty string.
 3555        * A <code>null</code> search string will return the source string.</p>
 3556        *
 3557        * <pre>
 3558        * StringUtils.removeEndIgnoreCase(null, *)      = null
 3559        * StringUtils.removeEndIgnoreCase("", *)        = ""
 3560        * StringUtils.removeEndIgnoreCase(*, null)      = *
 3561        * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.")  = "www.domain.com"
 3562        * StringUtils.removeEndIgnoreCase("www.domain.com", ".com")   = "www.domain"
 3563        * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
 3564        * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"
 3565        * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
 3566        * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
 3567        * </pre>
 3568        *
 3569        * @param str  the source String to search, may be null
 3570        * @param remove  the String to search for (case insensitive) and remove, may be null
 3571        * @return the substring with the string removed if found,
 3572        *  <code>null</code> if null String input
 3573        * @since 2.4
 3574        */
 3575       public static String removeEndIgnoreCase(String str, String remove) {
 3576           if (isEmpty(str) || isEmpty(remove)) {
 3577               return str;
 3578           }
 3579           if (endsWithIgnoreCase(str, remove)) {
 3580               return str.substring(0, str.length() - remove.length());
 3581           }
 3582           return str;
 3583       }
 3584   
 3585       /**
 3586        * <p>Removes all occurrences of a substring from within the source string.</p>
 3587        *
 3588        * <p>A <code>null</code> source string will return <code>null</code>.
 3589        * An empty ("") source string will return the empty string.
 3590        * A <code>null</code> remove string will return the source string.
 3591        * An empty ("") remove string will return the source string.</p>
 3592        *
 3593        * <pre>
 3594        * StringUtils.remove(null, *)        = null
 3595        * StringUtils.remove("", *)          = ""
 3596        * StringUtils.remove(*, null)        = *
 3597        * StringUtils.remove(*, "")          = *
 3598        * StringUtils.remove("queued", "ue") = "qd"
 3599        * StringUtils.remove("queued", "zz") = "queued"
 3600        * </pre>
 3601        *
 3602        * @param str  the source String to search, may be null
 3603        * @param remove  the String to search for and remove, may be null
 3604        * @return the substring with the string removed if found,
 3605        *  <code>null</code> if null String input
 3606        * @since 2.1
 3607        */
 3608       public static String remove(String str, String remove) {
 3609           if (isEmpty(str) || isEmpty(remove)) {
 3610               return str;
 3611           }
 3612           return replace(str, remove, EMPTY, -1);
 3613       }
 3614   
 3615       /**
 3616        * <p>Removes all occurrences of a character from within the source string.</p>
 3617        *
 3618        * <p>A <code>null</code> source string will return <code>null</code>.
 3619        * An empty ("") source string will return the empty string.</p>
 3620        *
 3621        * <pre>
 3622        * StringUtils.remove(null, *)       = null
 3623        * StringUtils.remove("", *)         = ""
 3624        * StringUtils.remove("queued", 'u') = "qeed"
 3625        * StringUtils.remove("queued", 'z') = "queued"
 3626        * </pre>
 3627        *
 3628        * @param str  the source String to search, may be null
 3629        * @param remove  the char to search for and remove, may be null
 3630        * @return the substring with the char removed if found,
 3631        *  <code>null</code> if null String input
 3632        * @since 2.1
 3633        */
 3634       public static String remove(String str, char remove) {
 3635           if (isEmpty(str) || str.indexOf(remove) == -1) {
 3636               return str;
 3637           }
 3638           char[] chars = str.toCharArray();
 3639           int pos = 0;
 3640           for (int i = 0; i < chars.length; i++) {
 3641               if (chars[i] != remove) {
 3642                   chars[pos++] = chars[i];
 3643               }
 3644           }
 3645           return new String(chars, 0, pos);
 3646       }
 3647   
 3648       // Replacing
 3649       //-----------------------------------------------------------------------
 3650       /**
 3651        * <p>Replaces a String with another String inside a larger String, once.</p>
 3652        *
 3653        * <p>A <code>null</code> reference passed to this method is a no-op.</p>
 3654        *
 3655        * <pre>
 3656        * StringUtils.replaceOnce(null, *, *)        = null
 3657        * StringUtils.replaceOnce("", *, *)          = ""
 3658        * StringUtils.replaceOnce("any", null, *)    = "any"
 3659        * StringUtils.replaceOnce("any", *, null)    = "any"
 3660        * StringUtils.replaceOnce("any", "", *)      = "any"
 3661        * StringUtils.replaceOnce("aba", "a", null)  = "aba"
 3662        * StringUtils.replaceOnce("aba", "a", "")    = "ba"
 3663        * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
 3664        * </pre>
 3665        *
 3666        * @see #replace(String text, String searchString, String replacement, int max)
 3667        * @param text  text to search and replace in, may be null
 3668        * @param searchString  the String to search for, may be null
 3669        * @param replacement  the String to replace with, may be null
 3670        * @return the text with any replacements processed,
 3671        *  <code>null</code> if null String input
 3672        */
 3673       public static String replaceOnce(String text, String searchString, String replacement) {
 3674           return replace(text, searchString, replacement, 1);
 3675       }
 3676   
 3677       /**
 3678        * <p>Replaces all occurrences of a String within another String.</p>
 3679        *
 3680        * <p>A <code>null</code> reference passed to this method is a no-op.</p>
 3681        *
 3682        * <pre>
 3683        * StringUtils.replace(null, *, *)        = null
 3684        * StringUtils.replace("", *, *)          = ""
 3685        * StringUtils.replace("any", null, *)    = "any"
 3686        * StringUtils.replace("any", *, null)    = "any"
 3687        * StringUtils.replace("any", "", *)      = "any"
 3688        * StringUtils.replace("aba", "a", null)  = "aba"
 3689        * StringUtils.replace("aba", "a", "")    = "b"
 3690        * StringUtils.replace("aba", "a", "z")   = "zbz"
 3691        * </pre>
 3692        *
 3693        * @see #replace(String text, String searchString, String replacement, int max)
 3694        * @param text  text to search and replace in, may be null
 3695        * @param searchString  the String to search for, may be null
 3696        * @param replacement  the String to replace it with, may be null
 3697        * @return the text with any replacements processed,
 3698        *  <code>null</code> if null String input
 3699        */
 3700       public static String replace(String text, String searchString, String replacement) {
 3701           return replace(text, searchString, replacement, -1);
 3702       }
 3703   
 3704       /**
 3705        * <p>Replaces a String with another String inside a larger String,
 3706        * for the first <code>max</code> values of the search String.</p>
 3707        *
 3708        * <p>A <code>null</code> reference passed to this method is a no-op.</p>
 3709        *
 3710        * <pre>
 3711        * StringUtils.replace(null, *, *, *)         = null
 3712        * StringUtils.replace("", *, *, *)           = ""
 3713        * StringUtils.replace("any", null, *, *)     = "any"
 3714        * StringUtils.replace("any", *, null, *)     = "any"
 3715        * StringUtils.replace("any", "", *, *)       = "any"
 3716        * StringUtils.replace("any", *, *, 0)        = "any"
 3717        * StringUtils.replace("abaa", "a", null, -1) = "abaa"
 3718        * StringUtils.replace("abaa", "a", "", -1)   = "b"
 3719        * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
 3720        * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
 3721        * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
 3722        * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
 3723        * </pre>
 3724        *
 3725        * @param text  text to search and replace in, may be null
 3726        * @param searchString  the String to search for, may be null
 3727        * @param replacement  the String to replace it with, may be null
 3728        * @param max  maximum number of values to replace, or <code>-1</code> if no maximum
 3729        * @return the text with any replacements processed,
 3730        *  <code>null</code> if null String input
 3731        */
 3732       public static String replace(String text, String searchString, String replacement, int max) {
 3733           if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) {
 3734               return text;
 3735           }
 3736           int start = 0;
 3737           int end = text.indexOf(searchString, start);
 3738           if (end == -1) {
 3739               return text;
 3740           }
 3741           int replLength = searchString.length();
 3742           int increase = replacement.length() - replLength;
 3743           increase = (increase < 0 ? 0 : increase);
 3744           increase *= (max < 0 ? 16 : (max > 64 ? 64 : max));
 3745           StringBuffer buf = new StringBuffer(text.length() + increase);
 3746           while (end != -1) {
 3747               buf.append(text.substring(start, end)).append(replacement);
 3748               start = end + replLength;
 3749               if (--max == 0) {
 3750                   break;
 3751               }
 3752               end = text.indexOf(searchString, start);
 3753           }
 3754           buf.append(text.substring(start));
 3755           return buf.toString();
 3756       }
 3757   
 3758       /**
 3759        * <p>
 3760        * Replaces all occurrences of Strings within another String.
 3761        * </p>
 3762        * 
 3763        * <p>
 3764        * A <code>null</code> reference passed to this method is a no-op, or if
 3765        * any "search string" or "string to replace" is null, that replace will be
 3766        * ignored. This will not repeat. For repeating replaces, call the
 3767        * overloaded method.
 3768        * </p>
 3769        * 
 3770        * <pre>
 3771        *  StringUtils.replaceEach(null, *, *)        = null
 3772        *  StringUtils.replaceEach("", *, *)          = ""
 3773        *  StringUtils.replaceEach("aba", null, null) = "aba"
 3774        *  StringUtils.replaceEach("aba", new String[0], null) = "aba"
 3775        *  StringUtils.replaceEach("aba", null, new String[0]) = "aba"
 3776        *  StringUtils.replaceEach("aba", new String[]{"a"}, null)  = "aba"
 3777        *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""})  = "b"
 3778        *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"})  = "aba"
 3779        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"})  = "wcte"
 3780        *  (example of how it does not repeat)
 3781        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"})  = "dcte"
 3782        * </pre>
 3783        * 
 3784        * @param text
 3785        *            text to search and replace in, no-op if null
 3786        * @param searchList
 3787        *            the Strings to search for, no-op if null
 3788        * @param replacementList
 3789        *            the Strings to replace them with, no-op if null
 3790        * @return the text with any replacements processed, <code>null</code> if
 3791        *         null String input
 3792        * @throws IndexOutOfBoundsException
 3793        *             if the lengths of the arrays are not the same (null is ok,
 3794        *             and/or size 0)
 3795        * @since 2.4
 3796        */
 3797       public static String replaceEach(String text, String[] searchList, String[] replacementList) {
 3798           return replaceEach(text, searchList, replacementList, false, 0);
 3799       }
 3800   
 3801       /**
 3802        * <p>
 3803        * Replaces all occurrences of Strings within another String.
 3804        * </p>
 3805        * 
 3806        * <p>
 3807        * A <code>null</code> reference passed to this method is a no-op, or if
 3808        * any "search string" or "string to replace" is null, that replace will be
 3809        * ignored. This will not repeat. For repeating replaces, call the
 3810        * overloaded method.
 3811        * </p>
 3812        * 
 3813        * <pre>
 3814        *  StringUtils.replaceEach(null, *, *, *) = null
 3815        *  StringUtils.replaceEach("", *, *, *) = ""
 3816        *  StringUtils.replaceEach("aba", null, null, *) = "aba"
 3817        *  StringUtils.replaceEach("aba", new String[0], null, *) = "aba"
 3818        *  StringUtils.replaceEach("aba", null, new String[0], *) = "aba"
 3819        *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba"
 3820        *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b"
 3821        *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba"
 3822        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte"
 3823        *  (example of how it repeats)
 3824        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte"
 3825        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte"
 3826        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, true) = IllegalArgumentException
 3827        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, false) = "dcabe"
 3828        * </pre>
 3829        * 
 3830        * @param text
 3831        *            text to search and replace in, no-op if null
 3832        * @param searchList
 3833        *            the Strings to search for, no-op if null
 3834        * @param replacementList
 3835        *            the Strings to replace them with, no-op if null
 3836        * @return the text with any replacements processed, <code>null</code> if
 3837        *         null String input
 3838        * @throws IllegalArgumentException
 3839        *             if the search is repeating and there is an endless loop due
 3840        *             to outputs of one being inputs to another
 3841        * @throws IndexOutOfBoundsException
 3842        *             if the lengths of the arrays are not the same (null is ok,
 3843        *             and/or size 0)
 3844        * @since 2.4
 3845        */
 3846       public static String replaceEachRepeatedly(String text, String[] searchList, String[] replacementList) {
 3847           // timeToLive should be 0 if not used or nothing to replace, else it's
 3848           // the length of the replace array
 3849           int timeToLive = searchList == null ? 0 : searchList.length;
 3850           return replaceEach(text, searchList, replacementList, true, timeToLive);
 3851       }
 3852   
 3853       /**
 3854        * <p>
 3855        * Replaces all occurrences of Strings within another String.
 3856        * </p>
 3857        * 
 3858        * <p>
 3859        * A <code>null</code> reference passed to this method is a no-op, or if
 3860        * any "search string" or "string to replace" is null, that replace will be
 3861        * ignored. 
 3862        * </p>
 3863        * 
 3864        * <pre>
 3865        *  StringUtils.replaceEach(null, *, *, *) = null
 3866        *  StringUtils.replaceEach("", *, *, *) = ""
 3867        *  StringUtils.replaceEach("aba", null, null, *) = "aba"
 3868        *  StringUtils.replaceEach("aba", new String[0], null, *) = "aba"
 3869        *  StringUtils.replaceEach("aba", null, new String[0], *) = "aba"
 3870        *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba"
 3871        *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b"
 3872        *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba"
 3873        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte"
 3874        *  (example of how it repeats)
 3875        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte"
 3876        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte"
 3877        *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *) = IllegalArgumentException
 3878        * </pre>
 3879        * 
 3880        * @param text
 3881        *            text to search and replace in, no-op if null
 3882        * @param searchList
 3883        *            the Strings to search for, no-op if null
 3884        * @param replacementList
 3885        *            the Strings to replace them with, no-op if null
 3886        * @param repeat if true, then replace repeatedly 
 3887        *       until there are no more possible replacements or timeToLive < 0
 3888        * @param timeToLive
 3889        *            if less than 0 then there is a circular reference and endless
 3890        *            loop
 3891        * @return the text with any replacements processed, <code>null</code> if
 3892        *         null String input
 3893        * @throws IllegalArgumentException
 3894        *             if the search is repeating and there is an endless loop due
 3895        *             to outputs of one being inputs to another
 3896        * @throws IndexOutOfBoundsException
 3897        *             if the lengths of the arrays are not the same (null is ok,
 3898        *             and/or size 0)
 3899        * @since 2.4
 3900        */
 3901       private static String replaceEach(String text, String[] searchList, String[] replacementList, 
 3902                                         boolean repeat, int timeToLive) 
 3903       {
 3904   
 3905           // mchyzer Performance note: This creates very few new objects (one major goal)
 3906           // let me know if there are performance requests, we can create a harness to measure
 3907   
 3908           if (text == null || text.length() == 0 || searchList == null || 
 3909               searchList.length == 0 || replacementList == null || replacementList.length == 0) 
 3910           {
 3911               return text;
 3912           }
 3913   
 3914           // if recursing, this shouldnt be less than 0
 3915           if (timeToLive < 0) {
 3916               throw new IllegalStateException("TimeToLive of " + timeToLive + " is less than 0: " + text);
 3917           }
 3918   
 3919           int searchLength = searchList.length;
 3920           int replacementLength = replacementList.length;
 3921   
 3922           // make sure lengths are ok, these need to be equal
 3923           if (searchLength != replacementLength) {
 3924               throw new IllegalArgumentException("Search and Replace array lengths don't match: "
 3925                   + searchLength
 3926                   + " vs "
 3927                   + replacementLength);
 3928           }
 3929   
 3930           // keep track of which still have matches
 3931           boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
 3932   
 3933           // index on index that the match was found
 3934           int textIndex = -1;
 3935           int replaceIndex = -1;
 3936           int tempIndex = -1;
 3937   
 3938           // index of replace array that will replace the search string found
 3939           // NOTE: logic duplicated below START
 3940           for (int i = 0; i < searchLength; i++) {
 3941               if (noMoreMatchesForReplIndex[i] || searchList[i] == null || 
 3942                   searchList[i].length() == 0 || replacementList[i] == null) 
 3943               {
 3944                   continue;
 3945               }
 3946               tempIndex = text.indexOf(searchList[i]);
 3947   
 3948               // see if we need to keep searching for this
 3949               if (tempIndex == -1) {
 3950                   noMoreMatchesForReplIndex[i] = true;
 3951               } else {
 3952                   if (textIndex == -1 || tempIndex < textIndex) {
 3953                       textIndex = tempIndex;
 3954                       replaceIndex = i;
 3955                   }
 3956               }
 3957           }
 3958           // NOTE: logic mostly below END
 3959   
 3960           // no search strings found, we are done
 3961           if (textIndex == -1) {
 3962               return text;
 3963           }
 3964   
 3965           int start = 0;
 3966   
 3967           // get a good guess on the size of the result buffer so it doesnt have to double if it goes over a bit
 3968           int increase = 0;
 3969   
 3970           // count the replacement text elements that are larger than their corresponding text being replaced
 3971           for (int i = 0; i < searchList.length; i++) {
 3972               if (searchList[i] == null || replacementList[i] == null) {
 3973                   continue;
 3974               }
 3975               int greater = replacementList[i].length() - searchList[i].length();
 3976               if (greater > 0) {
 3977                   increase += 3 * greater; // assume 3 matches
 3978               }
 3979           }
 3980           // have upper-bound at 20% increase, then let Java take over
 3981           increase = Math.min(increase, text.length() / 5);
 3982   
 3983           StringBuffer buf = new StringBuffer(text.length() + increase);
 3984   
 3985           while (textIndex != -1) {
 3986   
 3987               for (int i = start; i < textIndex; i++) {
 3988                   buf.append(text.charAt(i));
 3989               }
 3990               buf.append(replacementList[replaceIndex]);
 3991   
 3992               start = textIndex + searchList[replaceIndex].length();
 3993   
 3994               textIndex = -1;
 3995               replaceIndex = -1;
 3996               tempIndex = -1;
 3997               // find the next earliest match
 3998               // NOTE: logic mostly duplicated above START
 3999               for (int i = 0; i < searchLength; i++) {
 4000                   if (noMoreMatchesForReplIndex[i] || searchList[i] == null || 
 4001                       searchList[i].length() == 0 || replacementList[i] == null) 
 4002                   {
 4003                       continue;
 4004                   }
 4005                   tempIndex = text.indexOf(searchList[i], start);
 4006   
 4007                   // see if we need to keep searching for this
 4008                   if (tempIndex == -1) {
 4009                       noMoreMatchesForReplIndex[i] = true;
 4010                   } else {
 4011                       if (textIndex == -1 || tempIndex < textIndex) {
 4012                           textIndex = tempIndex;
 4013                           replaceIndex = i;
 4014                       }
 4015                   }
 4016               }
 4017               // NOTE: logic duplicated above END
 4018   
 4019           }
 4020           int textLength = text.length();
 4021           for (int i = start; i < textLength; i++) {
 4022               buf.append(text.charAt(i));
 4023           }
 4024           String result = buf.toString();
 4025           if (!repeat) {
 4026               return result;
 4027           }
 4028   
 4029           return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
 4030       }
 4031   
 4032       // Replace, character based
 4033       //-----------------------------------------------------------------------
 4034       /**
 4035        * <p>Replaces all occurrences of a character in a String with another.
 4036        * This is a null-safe version of {@link String#replace(char, char)}.</p>
 4037        *
 4038        * <p>A <code>null</code> string input returns <code>null</code>.
 4039        * An empty ("") string input returns an empty string.</p>
 4040        *
 4041        * <pre>
 4042        * StringUtils.replaceChars(null, *, *)        = null
 4043        * StringUtils.replaceChars("", *, *)          = ""
 4044        * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
 4045        * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
 4046        * </pre>
 4047        *
 4048        * @param str  String to replace characters in, may be null
 4049        * @param searchChar  the character to search for, may be null
 4050        * @param replaceChar  the character to replace, may be null
 4051        * @return modified String, <code>null</code> if null string input
 4052        * @since 2.0
 4053        */
 4054       public static String replaceChars(String str, char searchChar, char replaceChar) {
 4055           if (str == null) {
 4056               return null;
 4057           }
 4058           return str.replace(searchChar, replaceChar);
 4059       }
 4060   
 4061       /**
 4062        * <p>Replaces multiple characters in a String in one go.
 4063        * This method can also be used to delete characters.</p>
 4064        *
 4065        * <p>For example:<br />
 4066        * <code>replaceChars(&quot;hello&quot;, &quot;ho&quot;, &quot;jy&quot;) = jelly</code>.</p>
 4067        *
 4068        * <p>A <code>null</code> string input returns <code>null</code>.
 4069        * An empty ("") string input returns an empty string.
 4070        * A null or empty set of search characters returns the input string.</p>
 4071        *
 4072        * <p>The length of the search characters should normally equal the length
 4073        * of the replace characters.
 4074        * If the search characters is longer, then the extra search characters
 4075        * are deleted.
 4076        * If the search characters is shorter, then the extra replace characters
 4077        * are ignored.</p>
 4078        *
 4079        * <pre>
 4080        * StringUtils.replaceChars(null, *, *)           = null
 4081        * StringUtils.replaceChars("", *, *)             = ""
 4082        * StringUtils.replaceChars("abc", null, *)       = "abc"
 4083        * StringUtils.replaceChars("abc", "", *)         = "abc"
 4084        * StringUtils.replaceChars("abc", "b", null)     = "ac"
 4085        * StringUtils.replaceChars("abc", "b", "")       = "ac"
 4086        * StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
 4087        * StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
 4088        * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
 4089        * </pre>
 4090        *
 4091        * @param str  String to replace characters in, may be null
 4092        * @param searchChars  a set of characters to search for, may be null
 4093        * @param replaceChars  a set of characters to replace, may be null
 4094        * @return modified String, <code>null</code> if null string input
 4095        * @since 2.0
 4096        */
 4097       public static String replaceChars(String str, String searchChars, String replaceChars) {
 4098           if (isEmpty(str) || isEmpty(searchChars)) {
 4099               return str;
 4100           }
 4101           if (replaceChars == null) {
 4102               replaceChars = EMPTY;
 4103           }
 4104           boolean modified = false;
 4105           int replaceCharsLength = replaceChars.length();
 4106           int strLength = str.length();
 4107           StringBuffer buf = new StringBuffer(strLength);
 4108           for (int i = 0; i < strLength; i++) {
 4109               char ch = str.charAt(i);
 4110               int index = searchChars.indexOf(ch);
 4111               if (index >= 0) {
 4112                   modified = true;
 4113                   if (index < replaceCharsLength) {
 4114                       buf.append(replaceChars.charAt(index));
 4115                   }
 4116               } else {
 4117                   buf.append(ch);
 4118               }
 4119           }
 4120           if (modified) {
 4121               return buf.toString();
 4122           }
 4123           return str;
 4124       }
 4125   
 4126       // Overlay
 4127       //-----------------------------------------------------------------------
 4128       /**
 4129        * <p>Overlays part of a String with another String.</p>
 4130        *
 4131        * <pre>
 4132        * StringUtils.overlayString(null, *, *, *)           = NullPointerException
 4133        * StringUtils.overlayString(*, null, *, *)           = NullPointerException
 4134        * StringUtils.overlayString("", "abc", 0, 0)         = "abc"
 4135        * StringUtils.overlayString("abcdef", null, 2, 4)    = "abef"
 4136        * StringUtils.overlayString("abcdef", "", 2, 4)      = "abef"
 4137        * StringUtils.overlayString("abcdef", "zzzz", 2, 4)  = "abzzzzef"
 4138        * StringUtils.overlayString("abcdef", "zzzz", 4, 2)  = "abcdzzzzcdef"
 4139        * StringUtils.overlayString("abcdef", "zzzz", -1, 4) = IndexOutOfBoundsException
 4140        * StringUtils.overlayString("abcdef", "zzzz", 2, 8)  = IndexOutOfBoundsException
 4141        * </pre>
 4142        *
 4143        * @param text  the String to do overlaying in, may be null
 4144        * @param overlay  the String to overlay, may be null
 4145        * @param start  the position to start overlaying at, must be valid
 4146        * @param end  the position to stop overlaying before, must be valid
 4147        * @return overlayed String, <code>null</code> if null String input
 4148        * @throws NullPointerException if text or overlay is null
 4149        * @throws IndexOutOfBoundsException if either position is invalid
 4150        * @deprecated Use better named {@link #overlay(String, String, int, int)} instead.
 4151        *             Method will be removed in Commons Lang 3.0.
 4152        */
 4153       public static String overlayString(String text, String overlay, int start, int end) {
 4154           return new StringBuffer(start + overlay.length() + text.length() - end + 1)
 4155               .append(text.substring(0, start))
 4156               .append(overlay)
 4157               .append(text.substring(end))
 4158               .toString();
 4159       }
 4160   
 4161       /**
 4162        * <p>Overlays part of a String with another String.</p>
 4163        *
 4164        * <p>A <code>null</code> string input returns <code>null</code>.
 4165        * A negative index is treated as zero.
 4166        * An index greater than the string length is treated as the string length.
 4167        * The start index is always the smaller of the two indices.</p>
 4168        *
 4169        * <pre>
 4170        * StringUtils.overlay(null, *, *, *)            = null
 4171        * StringUtils.overlay("", "abc", 0, 0)          = "abc"
 4172        * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
 4173        * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
 4174        * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
 4175        * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
 4176        * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
 4177        * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
 4178        * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
 4179        * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
 4180        * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
 4181        * </pre>
 4182        *
 4183        * @param str  the String to do overlaying in, may be null
 4184        * @param overlay  the String to overlay, may be null
 4185        * @param start  the position to start overlaying at
 4186        * @param end  the position to stop overlaying before
 4187        * @return overlayed String, <code>null</code> if null String input
 4188        * @since 2.0
 4189        */
 4190       public static String overlay(String str, String overlay, int start, int end) {
 4191           if (str == null) {
 4192               return null;
 4193           }
 4194           if (overlay == null) {
 4195               overlay = EMPTY;
 4196           }
 4197           int len = str.length();
 4198           if (start < 0) {
 4199               start = 0;
 4200           }
 4201           if (start > len) {
 4202               start = len;
 4203           }
 4204           if (end < 0) {
 4205               end = 0;
 4206           }
 4207           if (end > len) {
 4208               end = len;
 4209           }
 4210           if (start > end) {
 4211               int temp = start;
 4212               start = end;
 4213               end = temp;
 4214           }
 4215           return new StringBuffer(len + start - end + overlay.length() + 1)
 4216               .append(str.substring(0, start))
 4217               .append(overlay)
 4218               .append(str.substring(end))
 4219               .toString();
 4220       }
 4221   
 4222       // Chomping
 4223       //-----------------------------------------------------------------------
 4224       /**
 4225        * <p>Removes one newline from end of a String if it's there,
 4226        * otherwise leave it alone.  A newline is &quot;<code>\n</code>&quot;,
 4227        * &quot;<code>\r</code>&quot;, or &quot;<code>\r\n</code>&quot;.</p>
 4228        *
 4229        * <p>NOTE: This method changed in 2.0.
 4230        * It now more closely matches Perl chomp.</p>
 4231        *
 4232        * <pre>
 4233        * StringUtils.chomp(null)          = null
 4234        * StringUtils.chomp("")            = ""
 4235        * StringUtils.chomp("abc \r")      = "abc "
 4236        * StringUtils.chomp("abc\n")       = "abc"
 4237        * StringUtils.chomp("abc\r\n")     = "abc"
 4238        * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
 4239        * StringUtils.chomp("abc\n\r")     = "abc\n"
 4240        * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
 4241        * StringUtils.chomp("\r")          = ""
 4242        * StringUtils.chomp("\n")          = ""
 4243        * StringUtils.chomp("\r\n")        = ""
 4244        * </pre>
 4245        *
 4246        * @param str  the String to chomp a newline from, may be null
 4247        * @return String without newline, <code>null</code> if null String input
 4248        */
 4249       public static String chomp(String str) {
 4250           if (isEmpty(str)) {
 4251               return str;
 4252           }
 4253   
 4254           if (str.length() == 1) {
 4255               char ch = str.charAt(0);
 4256               if (ch == CharUtils.CR || ch == CharUtils.LF) {
 4257                   return EMPTY;
 4258               }
 4259               return str;
 4260           }
 4261   
 4262           int lastIdx = str.length() - 1;
 4263           char last = str.charAt(lastIdx);
 4264   
 4265           if (last == CharUtils.LF) {
 4266               if (str.charAt(lastIdx - 1) == CharUtils.CR) {
 4267                   lastIdx--;
 4268               }
 4269           } else if (last != CharUtils.CR) {
 4270               lastIdx++;
 4271           }
 4272           return str.substring(0, lastIdx);
 4273       }
 4274   
 4275       /**
 4276        * <p>Removes <code>separator</code> from the end of
 4277        * <code>str</code> if it's there, otherwise leave it alone.</p>
 4278        *
 4279        * <p>NOTE: This method changed in version 2.0.
 4280        * It now more closely matches Perl chomp.
 4281        * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
 4282        * This method uses {@link String#endsWith(String)}.</p>
 4283        *
 4284        * <pre>
 4285        * StringUtils.chomp(null, *)         = null
 4286        * StringUtils.chomp("", *)           = ""
 4287        * StringUtils.chomp("foobar", "bar") = "foo"
 4288        * StringUtils.chomp("foobar", "baz") = "foobar"
 4289        * StringUtils.chomp("foo", "foo")    = ""
 4290        * StringUtils.chomp("foo ", "foo")   = "foo "
 4291        * StringUtils.chomp(" foo", "foo")   = " "
 4292        * StringUtils.chomp("foo", "foooo")  = "foo"
 4293        * StringUtils.chomp("foo", "")       = "foo"
 4294        * StringUtils.chomp("foo", null)     = "foo"
 4295        * </pre>
 4296        *
 4297        * @param str  the String to chomp from, may be null
 4298        * @param separator  separator String, may be null
 4299        * @return String without trailing separator, <code>null</code> if null String input
 4300        */
 4301       public static String chomp(String str, String separator) {
 4302           if (isEmpty(str) || separator == null) {
 4303               return str;
 4304           }
 4305           if (str.endsWith(separator)) {
 4306               return str.substring(0, str.length() - separator.length());
 4307           }
 4308           return str;
 4309       }
 4310   
 4311       /**
 4312        * <p>Remove any &quot;\n&quot; if and only if it is at the end
 4313        * of the supplied String.</p>
 4314        *
 4315        * @param str  the String to chomp from, must not be null
 4316        * @return String without chomped ending
 4317        * @throws NullPointerException if str is <code>null</code>
 4318        * @deprecated Use {@link #chomp(String)} instead.
 4319        *             Method will be removed in Commons Lang 3.0.
 4320        */
 4321       public static String chompLast(String str) {
 4322           return chompLast(str, "\n");
 4323       }
 4324   
 4325       /**
 4326        * <p>Remove a value if and only if the String ends with that value.</p>
 4327        *
 4328        * @param str  the String to chomp from, must not be null
 4329        * @param sep  the String to chomp, must not be null
 4330        * @return String without chomped ending
 4331        * @throws NullPointerException if str or sep is <code>null</code>
 4332        * @deprecated Use {@link #chomp(String,String)} instead.
 4333        *             Method will be removed in Commons Lang 3.0.
 4334        */
 4335       public static String chompLast(String str, String sep) {
 4336           if (str.length() == 0) {
 4337               return str;
 4338           }
 4339           String sub = str.substring(str.length() - sep.length());
 4340           if (sep.equals(sub)) {
 4341               return str.substring(0, str.length() - sep.length());
 4342           }
 4343           return str;
 4344       }
 4345   
 4346       /**
 4347        * <p>Remove everything and return the last value of a supplied String, and
 4348        * everything after it from a String.</p>
 4349        *
 4350        * @param str  the String to chomp from, must not be null
 4351        * @param sep  the String to chomp, must not be null
 4352        * @return String chomped
 4353        * @throws NullPointerException if str or sep is <code>null</code>
 4354        * @deprecated Use {@link #substringAfterLast(String, String)} instead
 4355        *             (although this doesn't include the separator)
 4356        *             Method will be removed in Commons Lang 3.0.
 4357        */
 4358       public static String getChomp(String str, String sep) {
 4359           int idx = str.lastIndexOf(sep);
 4360           if (idx == str.length() - sep.length()) {
 4361               return sep;
 4362           } else if (idx != -1) {
 4363               return str.substring(idx);
 4364           } else {
 4365               return EMPTY;
 4366           }
 4367       }
 4368   
 4369       /**
 4370        * <p>Remove the first value of a supplied String, and everything before it
 4371        * from a String.</p>
 4372        *
 4373        * @param str  the String to chomp from, must not be null
 4374        * @param sep  the String to chomp, must not be null
 4375        * @return String without chomped beginning
 4376        * @throws NullPointerException if str or sep is <code>null</code>
 4377        * @deprecated Use {@link #substringAfter(String,String)} instead.
 4378        *             Method will be removed in Commons Lang 3.0.
 4379        */
 4380       public static String prechomp(String str, String sep) {
 4381           int idx = str.indexOf(sep);
 4382           if (idx == -1) {
 4383               return str;
 4384           }             
 4385           return str.substring(idx + sep.length());
 4386       }
 4387   
 4388       /**
 4389        * <p>Remove and return everything before the first value of a
 4390        * supplied String from another String.</p>
 4391        *
 4392        * @param str  the String to chomp from, must not be null
 4393        * @param sep  the String to chomp, must not be null
 4394        * @return String prechomped
 4395        * @throws NullPointerException if str or sep is <code>null</code>
 4396        * @deprecated Use {@link #substringBefore(String,String)} instead
 4397        *             (although this doesn't include the separator).
 4398        *             Method will be removed in Commons Lang 3.0.
 4399        */
 4400       public static String getPrechomp(String str, String sep) {
 4401           int idx = str.indexOf(sep);
 4402           if (idx == -1) {
 4403               return EMPTY;
 4404           } 
 4405           return str.substring(0, idx + sep.length());
 4406       }
 4407   
 4408       // Chopping
 4409       //-----------------------------------------------------------------------
 4410       /**
 4411        * <p>Remove the last character from a String.</p>
 4412        *
 4413        * <p>If the String ends in <code>\r\n</code>, then remove both
 4414        * of them.</p>
 4415        *
 4416        * <pre>
 4417        * StringUtils.chop(null)          = null
 4418        * StringUtils.chop("")            = ""
 4419        * StringUtils.chop("abc \r")      = "abc "
 4420        * StringUtils.chop("abc\n")       = "abc"
 4421        * StringUtils.chop("abc\r\n")     = "abc"
 4422        * StringUtils.chop("abc")         = "ab"
 4423        * StringUtils.chop("abc\nabc")    = "abc\nab"
 4424        * StringUtils.chop("a")           = ""
 4425        * StringUtils.chop("\r")          = ""
 4426        * StringUtils.chop("\n")          = ""
 4427        * StringUtils.chop("\r\n")        = ""
 4428        * </pre>
 4429        *
 4430        * @param str  the String to chop last character from, may be null
 4431        * @return String without last character, <code>null</code> if null String input
 4432        */
 4433       public static String chop(String str) {
 4434           if (str == null) {
 4435               return null;
 4436           }
 4437           int strLen = str.length();
 4438           if (strLen < 2) {
 4439               return EMPTY;
 4440           }
 4441           int lastIdx = strLen - 1;
 4442           String ret = str.substring(0, lastIdx);
 4443           char last = str.charAt(lastIdx);
 4444           if (last == CharUtils.LF) {
 4445               if (ret.charAt(lastIdx - 1) == CharUtils.CR) {
 4446                   return ret.substring(0, lastIdx - 1);
 4447               }
 4448           }
 4449           return ret;
 4450       }
 4451   
 4452       /**
 4453        * <p>Removes <code>\n</code> from end of a String if it's there.
 4454        * If a <code>\r</code> precedes it, then remove that too.</p>
 4455        *
 4456        * @param str  the String to chop a newline from, must not be null
 4457        * @return String without newline
 4458        * @throws NullPointerException if str is <code>null</code>
 4459        * @deprecated Use {@link #chomp(String)} instead.
 4460        *             Method will be removed in Commons Lang 3.0.
 4461        */
 4462       public static String chopNewline(String str) {
 4463           int lastIdx = str.length() - 1;
 4464           if (lastIdx <= 0) {
 4465               return EMPTY;
 4466           }
 4467           char last = str.charAt(lastIdx);
 4468           if (last == CharUtils.LF) {
 4469               if (str.charAt(lastIdx - 1) == CharUtils.CR) {
 4470                   lastIdx--;
 4471               }
 4472           } else {
 4473               lastIdx++;
 4474           }
 4475           return str.substring(0, lastIdx);
 4476       }
 4477   
 4478       // Conversion
 4479       //-----------------------------------------------------------------------
 4480       /**
 4481        * <p>Escapes any values it finds into their String form.</p>
 4482        *
 4483        * <p>So a tab becomes the characters <code>'\\'</code> and
 4484        * <code>'t'</code>.</p>
 4485        *
 4486        * <p>As of Lang 2.0, this calls {@link StringEscapeUtils#escapeJava(String)}
 4487        * behind the scenes.
 4488        * </p>
 4489        * @see StringEscapeUtils#escapeJava(java.lang.String)
 4490        * @param str String to escape values in
 4491        * @return String with escaped values
 4492        * @throws NullPointerException if str is <code>null</code>
 4493        * @deprecated Use {@link StringEscapeUtils#escapeJava(String)}
 4494        *             This method will be removed in Commons Lang 3.0
 4495        */
 4496       public static String escape(String str) {
 4497           return StringEscapeUtils.escapeJava(str);
 4498       }
 4499   
 4500       // Padding
 4501       //-----------------------------------------------------------------------
 4502       /**
 4503        * <p>Repeat a String <code>repeat</code> times to form a
 4504        * new String.</p>
 4505        *
 4506        * <pre>
 4507        * StringUtils.repeat(null, 2) = null
 4508        * StringUtils.repeat("", 0)   = ""
 4509        * StringUtils.repeat("", 2)   = ""
 4510        * StringUtils.repeat("a", 3)  = "aaa"
 4511        * StringUtils.repeat("ab", 2) = "abab"
 4512        * StringUtils.repeat("a", -2) = ""
 4513        * </pre>
 4514        *
 4515        * @param str  the String to repeat, may be null
 4516        * @param repeat  number of times to repeat str, negative treated as zero
 4517        * @return a new String consisting of the original String repeated,
 4518        *  <code>null</code> if null String input
 4519        * @since 2.5
 4520        */
 4521       public static String repeat(String str, int repeat) {
 4522           // Performance tuned for 2.0 (JDK1.4)
 4523   
 4524           if (str == null) {
 4525               return null;
 4526           }
 4527           if (repeat <= 0) {
 4528               return EMPTY;
 4529           }
 4530           int inputLength = str.length();
 4531           if (repeat == 1 || inputLength == 0) {
 4532               return str;
 4533           }
 4534           if (inputLength == 1 && repeat <= PAD_LIMIT) {
 4535               return padding(repeat, str.charAt(0));
 4536           }
 4537   
 4538           int outputLength = inputLength * repeat;
 4539           switch (inputLength) {
 4540               case 1 :
 4541                   char ch = str.charAt(0);
 4542                   char[] output1 = new char[outputLength];
 4543                   for (int i = repeat - 1; i >= 0; i--) {
 4544                       output1[i] = ch;
 4545                   }
 4546                   return new String(output1);
 4547               case 2 :
 4548                   char ch0 = str.charAt(0);
 4549                   char ch1 = str.charAt(1);
 4550                   char[] output2 = new char[outputLength];
 4551                   for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
 4552                       output2[i] = ch0;
 4553                       output2[i + 1] = ch1;
 4554                   }
 4555                   return new String(output2);
 4556               default :
 4557                   StringBuffer buf = new StringBuffer(outputLength);
 4558                   for (int i = 0; i < repeat; i++) {
 4559                       buf.append(str);
 4560                   }
 4561                   return buf.toString();
 4562           }
 4563       }
 4564   
 4565       /**
 4566        * <p>Repeat a String <code>repeat</code> times to form a
 4567        * new String, with a String separator injected each time. </p>
 4568        *
 4569        * <pre>
 4570        * StringUtils.repeat(null, null, 2) = null
 4571        * StringUtils.repeat(null, "x", 2)  = null
 4572        * StringUtils.repeat("", null, 0)   = ""
 4573        * StringUtils.repeat("", "", 2)     = ""
 4574        * StringUtils.repeat("", "x", 3)    = "xxx"
 4575        * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
 4576        * </pre>
 4577        *
 4578        * @param str        the String to repeat, may be null
 4579        * @param separator  the String to inject, may be null
 4580        * @param repeat     number of times to repeat str, negative treated as zero
 4581        * @return a new String consisting of the original String repeated,
 4582        *  <code>null</code> if null String input
 4583        */
 4584       public static String repeat(String str, String separator, int repeat) {
 4585           if(str == null || separator == null) {
 4586               return repeat(str, repeat);
 4587           } else {
 4588               // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
 4589               String result = repeat(str + separator, repeat);
 4590               return removeEnd(result, separator);
 4591           }
 4592       }
 4593   
 4594       /**
 4595        * <p>Returns padding using the specified delimiter repeated
 4596        * to a given length.</p>
 4597        *
 4598        * <pre>
 4599        * StringUtils.padding(0, 'e')  = ""
 4600        * StringUtils.padding(3, 'e')  = "eee"
 4601        * StringUtils.padding(-2, 'e') = IndexOutOfBoundsException
 4602        * </pre>
 4603        *
 4604        * <p>Note: this method doesn't not support padding with
 4605        * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
 4606        * as they require a pair of <code>char</code>s to be represented.
 4607        * If you are needing to support full I18N of your applications
 4608        * consider using {@link #repeat(String, int)} instead. 
 4609        * </p>
 4610        *
 4611        * @param repeat  number of times to repeat delim
 4612        * @param padChar  character to repeat
 4613        * @return String with repeated character
 4614        * @throws IndexOutOfBoundsException if <code>repeat &lt; 0</code>
 4615        * @see #repeat(String, int)
 4616        */
 4617       private static String padding(int repeat, char padChar) throws IndexOutOfBoundsException {
 4618           if (repeat < 0) {
 4619               throw new IndexOutOfBoundsException("Cannot pad a negative amount: " + repeat);
 4620           }
 4621           final char[] buf = new char[repeat];
 4622           for (int i = 0; i < buf.length; i++) {
 4623               buf[i] = padChar;
 4624           }
 4625           return new String(buf);
 4626       }
 4627   
 4628       /**
 4629        * <p>Right pad a String with spaces (' ').</p>
 4630        *
 4631        * <p>The String is padded to the size of <code>size</code>.</p>
 4632        *
 4633        * <pre>
 4634        * StringUtils.rightPad(null, *)   = null
 4635        * StringUtils.rightPad("", 3)     = "   "
 4636        * StringUtils.rightPad("bat", 3)  = "bat"
 4637        * StringUtils.rightPad("bat", 5)  = "bat  "
 4638        * StringUtils.rightPad("bat", 1)  = "bat"
 4639        * StringUtils.rightPad("bat", -1) = "bat"
 4640        * </pre>
 4641        *
 4642        * @param str  the String to pad out, may be null
 4643        * @param size  the size to pad to
 4644        * @return right padded String or original String if no padding is necessary,
 4645        *  <code>null</code> if null String input
 4646        */
 4647       public static String rightPad(String str, int size) {
 4648           return rightPad(str, size, ' ');
 4649       }
 4650   
 4651       /**
 4652        * <p>Right pad a String with a specified character.</p>
 4653        *
 4654        * <p>The String is padded to the size of <code>size</code>.</p>
 4655        *
 4656        * <pre>
 4657        * StringUtils.rightPad(null, *, *)     = null
 4658        * StringUtils.rightPad("", 3, 'z')     = "zzz"
 4659        * StringUtils.rightPad("bat", 3, 'z')  = "bat"
 4660        * StringUtils.rightPad("bat", 5, 'z')  = "batzz"
 4661        * StringUtils.rightPad("bat", 1, 'z')  = "bat"
 4662        * StringUtils.rightPad("bat", -1, 'z') = "bat"
 4663        * </pre>
 4664        *
 4665        * @param str  the String to pad out, may be null
 4666        * @param size  the size to pad to
 4667        * @param padChar  the character to pad with
 4668        * @return right padded String or original String if no padding is necessary,
 4669        *  <code>null</code> if null String input
 4670        * @since 2.0
 4671        */
 4672       public static String rightPad(String str, int size, char padChar) {
 4673           if (str == null) {
 4674               return null;
 4675           }
 4676           int pads = size - str.length();
 4677           if (pads <= 0) {
 4678               return str; // returns original String when possible
 4679           }
 4680           if (pads > PAD_LIMIT) {
 4681               return rightPad(str, size, String.valueOf(padChar));
 4682           }
 4683           return str.concat(padding(pads, padChar));
 4684       }
 4685   
 4686       /**
 4687        * <p>Right pad a String with a specified String.</p>
 4688        *
 4689        * <p>The String is padded to the size of <code>size</code>.</p>
 4690        *
 4691        * <pre>
 4692        * StringUtils.rightPad(null, *, *)      = null
 4693        * StringUtils.rightPad("", 3, "z")      = "zzz"
 4694        * StringUtils.rightPad("bat", 3, "yz")  = "bat"
 4695        * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
 4696        * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
 4697        * StringUtils.rightPad("bat", 1, "yz")  = "bat"
 4698        * StringUtils.rightPad("bat", -1, "yz") = "bat"
 4699        * StringUtils.rightPad("bat", 5, null)  = "bat  "
 4700        * StringUtils.rightPad("bat", 5, "")    = "bat  "
 4701        * </pre>
 4702        *
 4703        * @param str  the String to pad out, may be null
 4704        * @param size  the size to pad to
 4705        * @param padStr  the String to pad with, null or empty treated as single space
 4706        * @return right padded String or original String if no padding is necessary,
 4707        *  <code>null</code> if null String input
 4708        */
 4709       public static String rightPad(String str, int size, String padStr) {
 4710           if (str == null) {
 4711               return null;
 4712           }
 4713           if (isEmpty(padStr)) {
 4714               padStr = " ";
 4715           }
 4716           int padLen = padStr.length();
 4717           int strLen = str.length();
 4718           int pads = size - strLen;
 4719           if (pads <= 0) {
 4720               return str; // returns original String when possible
 4721           }
 4722           if (padLen == 1 && pads <= PAD_LIMIT) {
 4723               return rightPad(str, size, padStr.charAt(0));
 4724           }
 4725   
 4726           if (pads == padLen) {
 4727               return str.concat(padStr);
 4728           } else if (pads < padLen) {
 4729               return str.concat(padStr.substring(0, pads));
 4730           } else {
 4731               char[] padding = new char[pads];
 4732               char[] padChars = padStr.toCharArray();
 4733               for (int i = 0; i < pads; i++) {
 4734                   padding[i] = padChars[i % padLen];
 4735               }
 4736               return str.concat(new String(padding));
 4737           }
 4738       }
 4739   
 4740       /**
 4741        * <p>Left pad a String with spaces (' ').</p>
 4742        *
 4743        * <p>The String is padded to the size of <code>size</code>.</p>
 4744        *
 4745        * <pre>
 4746        * StringUtils.leftPad(null, *)   = null
 4747        * StringUtils.leftPad("", 3)     = "   "
 4748        * StringUtils.leftPad("bat", 3)  = "bat"
 4749        * StringUtils.leftPad("bat", 5)  = "  bat"
 4750        * StringUtils.leftPad("bat", 1)  = "bat"
 4751        * StringUtils.leftPad("bat", -1) = "bat"
 4752        * </pre>
 4753        *
 4754        * @param str  the String to pad out, may be null
 4755        * @param size  the size to pad to
 4756        * @return left padded String or original String if no padding is necessary,
 4757        *  <code>null</code> if null String input
 4758        */
 4759       public static String leftPad(String str, int size) {
 4760           return leftPad(str, size, ' ');
 4761       }
 4762   
 4763       /**
 4764        * <p>Left pad a String with a specified character.</p>
 4765        *
 4766        * <p>Pad to a size of <code>size</code>.</p>
 4767        *
 4768        * <pre>
 4769        * StringUtils.leftPad(null, *, *)     = null
 4770        * StringUtils.leftPad("", 3, 'z')     = "zzz"
 4771        * StringUtils.leftPad("bat", 3, 'z')  = "bat"
 4772        * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"
 4773        * StringUtils.leftPad("bat", 1, 'z')  = "bat"
 4774        * StringUtils.leftPad("bat", -1, 'z') = "bat"
 4775        * </pre>
 4776        *
 4777        * @param str  the String to pad out, may be null
 4778        * @param size  the size to pad to
 4779        * @param padChar  the character to pad with
 4780        * @return left padded String or original String if no padding is necessary,
 4781        *  <code>null</code> if null String input
 4782        * @since 2.0
 4783        */
 4784       public static String leftPad(String str, int size, char padChar) {
 4785           if (str == null) {
 4786               return null;
 4787           }
 4788           int pads = size - str.length();
 4789           if (pads <= 0) {
 4790               return str; // returns original String when possible
 4791           }
 4792           if (pads > PAD_LIMIT) {
 4793               return leftPad(str, size, String.valueOf(padChar));
 4794           }
 4795           return padding(pads, padChar).concat(str);
 4796       }
 4797   
 4798       /**
 4799        * <p>Left pad a String with a specified String.</p>
 4800        *
 4801        * <p>Pad to a size of <code>size</code>.</p>
 4802        *
 4803        * <pre>
 4804        * StringUtils.leftPad(null, *, *)      = null
 4805        * StringUtils.leftPad("", 3, "z")      = "zzz"
 4806        * StringUtils.leftPad("bat", 3, "yz")  = "bat"
 4807        * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
 4808        * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
 4809        * StringUtils.leftPad("bat", 1, "yz")  = "bat"
 4810        * StringUtils.leftPad("bat", -1, "yz") = "bat"
 4811        * StringUtils.leftPad("bat", 5, null)  = "  bat"
 4812        * StringUtils.leftPad("bat", 5, "")    = "  bat"
 4813        * </pre>
 4814        *
 4815        * @param str  the String to pad out, may be null
 4816        * @param size  the size to pad to
 4817        * @param padStr  the String to pad with, null or empty treated as single space
 4818        * @return left padded String or original String if no padding is necessary,
 4819        *  <code>null</code> if null String input
 4820        */
 4821       public static String leftPad(String str, int size, String padStr) {
 4822           if (str == null) {
 4823               return null;
 4824           }
 4825           if (isEmpty(padStr)) {
 4826               padStr = " ";
 4827           }
 4828           int padLen = padStr.length();
 4829           int strLen = str.length();
 4830           int pads = size - strLen;
 4831           if (pads <= 0) {
 4832               return str; // returns original String when possible
 4833           }
 4834           if (padLen == 1 && pads <= PAD_LIMIT) {
 4835               return leftPad(str, size, padStr.charAt(0));
 4836           }
 4837   
 4838           if (pads == padLen) {
 4839               return padStr.concat(str);
 4840           } else if (pads < padLen) {
 4841               return padStr.substring(0, pads).concat(str);
 4842           } else {
 4843               char[] padding = new char[pads];
 4844               char[] padChars = padStr.toCharArray();
 4845               for (int i = 0; i < pads; i++) {
 4846                   padding[i] = padChars[i % padLen];
 4847               }
 4848               return new String(padding).concat(str);
 4849           }
 4850       }
 4851   
 4852       /**
 4853        * Gets a String's length or <code>0</code> if the String is <code>null</code>.
 4854        * 
 4855        * @param str
 4856        *            a String or <code>null</code>
 4857        * @return String length or <code>0</code> if the String is <code>null</code>.
 4858        * @since 2.4
 4859        */
 4860       public static int length(String str) {
 4861           return str == null ? 0 : str.length();
 4862       }
 4863       
 4864       // Centering
 4865       //-----------------------------------------------------------------------
 4866       /**
 4867        * <p>Centers a String in a larger String of size <code>size</code>
 4868        * using the space character (' ').<p>
 4869        *
 4870        * <p>If the size is less than the String length, the String is returned.
 4871        * A <code>null</code> String returns <code>null</code>.
 4872        * A negative size is treated as zero.</p>
 4873        *
 4874        * <p>Equivalent to <code>center(str, size, " ")</code>.</p>
 4875        *
 4876        * <pre>
 4877        * StringUtils.center(null, *)   = null
 4878        * StringUtils.center("", 4)     = "    "
 4879        * StringUtils.center("ab", -1)  = "ab"
 4880        * StringUtils.center("ab", 4)   = " ab "
 4881        * StringUtils.center("abcd", 2) = "abcd"
 4882        * StringUtils.center("a", 4)    = " a  "
 4883        * </pre>
 4884        *
 4885        * @param str  the String to center, may be null
 4886        * @param size  the int size of new String, negative treated as zero
 4887        * @return centered String, <code>null</code> if null String input
 4888        */
 4889       public static String center(String str, int size) {
 4890           return center(str, size, ' ');
 4891       }
 4892   
 4893       /**
 4894        * <p>Centers a String in a larger String of size <code>size</code>.
 4895        * Uses a supplied character as the value to pad the String with.</p>
 4896        *
 4897        * <p>If the size is less than the String length, the String is returned.
 4898        * A <code>null</code> String returns <code>null</code>.
 4899        * A negative size is treated as zero.</p>
 4900        *
 4901        * <pre>
 4902        * StringUtils.center(null, *, *)     = null
 4903        * StringUtils.center("", 4, ' ')     = "    "
 4904        * StringUtils.center("ab", -1, ' ')  = "ab"
 4905        * StringUtils.center("ab", 4, ' ')   = " ab"
 4906        * StringUtils.center("abcd", 2, ' ') = "abcd"
 4907        * StringUtils.center("a", 4, ' ')    = " a  "
 4908        * StringUtils.center("a", 4, 'y')    = "yayy"
 4909        * </pre>
 4910        *
 4911        * @param str  the String to center, may be null
 4912        * @param size  the int size of new String, negative treated as zero
 4913        * @param padChar  the character to pad the new String with
 4914        * @return centered String, <code>null</code> if null String input
 4915        * @since 2.0
 4916        */
 4917       public static String center(String str, int size, char padChar) {
 4918           if (str == null || size <= 0) {
 4919               return str;
 4920           }
 4921           int strLen = str.length();
 4922           int pads = size - strLen;
 4923           if (pads <= 0) {
 4924               return str;
 4925           }
 4926           str = leftPad(str, strLen + pads / 2, padChar);
 4927           str = rightPad(str, size, padChar);
 4928           return str;
 4929       }
 4930   
 4931       /**
 4932        * <p>Centers a String in a larger String of size <code>size</code>.
 4933        * Uses a supplied String as the value to pad the String with.</p>
 4934        *
 4935        * <p>If the size is less than the String length, the String is returned.
 4936        * A <code>null</code> String returns <code>null</code>.
 4937        * A negative size is treated as zero.</p>
 4938        *
 4939        * <pre>
 4940        * StringUtils.center(null, *, *)     = null
 4941        * StringUtils.center("", 4, " ")     = "    "
 4942        * StringUtils.center("ab", -1, " ")  = "ab"
 4943        * StringUtils.center("ab", 4, " ")   = " ab"
 4944        * StringUtils.center("abcd", 2, " ") = "abcd"
 4945        * StringUtils.center("a", 4, " ")    = " a  "
 4946        * StringUtils.center("a", 4, "yz")   = "yayz"
 4947        * StringUtils.center("abc", 7, null) = "  abc  "
 4948        * StringUtils.center("abc", 7, "")   = "  abc  "
 4949        * </pre>
 4950        *
 4951        * @param str  the String to center, may be null
 4952        * @param size  the int size of new String, negative treated as zero
 4953        * @param padStr  the String to pad the new String with, must not be null or empty
 4954        * @return centered String, <code>null</code> if null String input
 4955        * @throws IllegalArgumentException if padStr is <code>null</code> or empty
 4956        */
 4957       public static String center(String str, int size, String padStr) {
 4958           if (str == null || size <= 0) {
 4959               return str;
 4960           }
 4961           if (isEmpty(padStr)) {
 4962               padStr = " ";
 4963           }
 4964           int strLen = str.length();
 4965           int pads = size - strLen;
 4966           if (pads <= 0) {
 4967               return str;
 4968           }
 4969           str = leftPad(str, strLen + pads / 2, padStr);
 4970           str = rightPad(str, size, padStr);
 4971           return str;
 4972       }
 4973   
 4974       // Case conversion
 4975       //-----------------------------------------------------------------------
 4976       /**
 4977        * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p>
 4978        *
 4979        * <p>A <code>null</code> input String returns <code>null</code>.</p>
 4980        *
 4981        * <pre>
 4982        * StringUtils.upperCase(null)  = null
 4983        * StringUtils.upperCase("")    = ""
 4984        * StringUtils.upperCase("aBc") = "ABC"
 4985        * </pre>
 4986        *
 4987        * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()},
 4988        * the result of this method is affected by the current locale.
 4989        * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
 4990        * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
 4991        *
 4992        * @param str  the String to upper case, may be null
 4993        * @return the upper cased String, <code>null</code> if null String input
 4994        */
 4995       public static String upperCase(String str) {
 4996           if (str == null) {
 4997               return null;
 4998           }
 4999           return str.toUpperCase();
 5000       }
 5001   
 5002       /**
 5003        * <p>Converts a String to upper case as per {@link String#toUpperCase(Locale)}.</p>
 5004        *
 5005        * <p>A <code>null</code> input String returns <code>null</code>.</p>
 5006        *
 5007        * <pre>
 5008        * StringUtils.upperCase(null, Locale.ENGLISH)  = null
 5009        * StringUtils.upperCase("", Locale.ENGLISH)    = ""
 5010        * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
 5011        * </pre>
 5012        *
 5013        * @param str  the String to upper case, may be null
 5014        * @param locale  the locale that defines the case transformation rules, must not be null
 5015        * @return the upper cased String, <code>null</code> if null String input
 5016        * @since 2.5
 5017        */
 5018       public static String upperCase(String str, Locale locale) {
 5019           if (str == null) {
 5020               return null;
 5021           }
 5022           return str.toUpperCase(locale);
 5023       }
 5024   
 5025       /**
 5026        * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p>
 5027        *
 5028        * <p>A <code>null</code> input String returns <code>null</code>.</p>
 5029        *
 5030        * <pre>
 5031        * StringUtils.lowerCase(null)  = null
 5032        * StringUtils.lowerCase("")    = ""
 5033        * StringUtils.lowerCase("aBc") = "abc"
 5034        * </pre>
 5035        *
 5036        * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()},
 5037        * the result of this method is affected by the current locale.
 5038        * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
 5039        * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
 5040        *
 5041        * @param str  the String to lower case, may be null
 5042        * @return the lower cased String, <code>null</code> if null String input
 5043        */
 5044       public static String lowerCase(String str) {
 5045           if (str == null) {
 5046               return null;
 5047           }
 5048           return str.toLowerCase();
 5049       }
 5050   
 5051       /**
 5052        * <p>Converts a String to lower case as per {@link String#toLowerCase(Locale)}.</p>
 5053        *
 5054        * <p>A <code>null</code> input String returns <code>null</code>.</p>
 5055        *
 5056        * <pre>
 5057        * StringUtils.lowerCase(null, Locale.ENGLISH)  = null
 5058        * StringUtils.lowerCase("", Locale.ENGLISH)    = ""
 5059        * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
 5060        * </pre>
 5061        *
 5062        * @param str  the String to lower case, may be null
 5063        * @param locale  the locale that defines the case transformation rules, must not be null
 5064        * @return the lower cased String, <code>null</code> if null String input
 5065        * @since 2.5
 5066        */
 5067       public static String lowerCase(String str, Locale locale) {
 5068           if (str == null) {
 5069               return null;
 5070           }
 5071           return str.toLowerCase(locale);
 5072       }
 5073   
 5074       /**
 5075        * <p>Capitalizes a String changing the first letter to title case as
 5076        * per {@link Character#toTitleCase(char)}. No other letters are changed.</p>
 5077        *
 5078        * <p>For a word based algorithm, see {@link WordUtils#capitalize(String)}.
 5079        * A <code>null</code> input String returns <code>null</code>.</p>
 5080        *
 5081        * <pre>
 5082        * StringUtils.capitalize(null)  = null
 5083        * StringUtils.capitalize("")    = ""
 5084        * StringUtils.capitalize("cat") = "Cat"
 5085        * StringUtils.capitalize("cAt") = "CAt"
 5086        * </pre>
 5087        *
 5088        * @param str  the String to capitalize, may be null
 5089        * @return the capitalized String, <code>null</code> if null String input
 5090        * @see WordUtils#capitalize(String)
 5091        * @see #uncapitalize(String)
 5092        * @since 2.0
 5093        */
 5094       public static String capitalize(String str) {
 5095           int strLen;
 5096           if (str == null || (strLen = str.length()) == 0) {
 5097               return str;
 5098           }
 5099           return new StringBuffer(strLen)
 5100               .append(Character.toTitleCase(str.charAt(0)))
 5101               .append(str.substring(1))
 5102               .toString();
 5103       }
 5104   
 5105       /**
 5106        * <p>Capitalizes a String changing the first letter to title case as
 5107        * per {@link Character#toTitleCase(char)}. No other letters are changed.</p>
 5108        *
 5109        * @param str  the String to capitalize, may be null
 5110        * @return the capitalized String, <code>null</code> if null String input
 5111        * @deprecated Use the standardly named {@link #capitalize(String)}.
 5112        *             Method will be removed in Commons Lang 3.0.
 5113        */
 5114       public static String capitalise(String str) {
 5115           return capitalize(str);
 5116       }
 5117   
 5118       /**
 5119        * <p>Uncapitalizes a String changing the first letter to title case as
 5120        * per {@link Character#toLowerCase(char)}. No other letters are changed.</p>
 5121        *
 5122        * <p>For a word based algorithm, see {@link WordUtils#uncapitalize(String)}.
 5123        * A <code>null</code> input String returns <code>null</code>.</p>
 5124        *
 5125        * <pre>
 5126        * StringUtils.uncapitalize(null)  = null
 5127        * StringUtils.uncapitalize("")    = ""
 5128        * StringUtils.uncapitalize("Cat") = "cat"
 5129        * StringUtils.uncapitalize("CAT") = "cAT"
 5130        * </pre>
 5131        *
 5132        * @param str  the String to uncapitalize, may be null
 5133        * @return the uncapitalized String, <code>null</code> if null String input
 5134        * @see WordUtils#uncapitalize(String)
 5135        * @see #capitalize(String)
 5136        * @since 2.0
 5137        */
 5138       public static String uncapitalize(String str) {
 5139           int strLen;
 5140           if (str == null || (strLen = str.length()) == 0) {
 5141               return str;
 5142           }
 5143           return new StringBuffer(strLen)
 5144               .append(Character.toLowerCase(str.charAt(0)))
 5145               .append(str.substring(1))
 5146               .toString();
 5147       }
 5148   
 5149       /**
 5150        * <p>Uncapitalizes a String changing the first letter to title case as
 5151        * per {@link Character#toLowerCase(char)}. No other letters are changed.</p>
 5152        *
 5153        * @param str  the String to uncapitalize, may be null
 5154        * @return the uncapitalized String, <code>null</code> if null String input
 5155        * @deprecated Use the standardly named {@link #uncapitalize(String)}.
 5156        *             Method will be removed in Commons Lang 3.0.
 5157        */
 5158       public static String uncapitalise(String str) {
 5159           return uncapitalize(str);
 5160       }
 5161   
 5162       /**
 5163        * <p>Swaps the case of a String changing upper and title case to
 5164        * lower case, and lower case to upper case.</p>
 5165        *
 5166        * <ul>
 5167        *  <li>Upper case character converts to Lower case</li>
 5168        *  <li>Title case character converts to Lower case</li>
 5169        *  <li>Lower case character converts to Upper case</li>
 5170        * </ul>
 5171        *
 5172        * <p>For a word based algorithm, see {@link WordUtils#swapCase(String)}.
 5173        * A <code>null</code> input String returns <code>null</code>.</p>
 5174        *
 5175        * <pre>
 5176        * StringUtils.swapCase(null)                 = null
 5177        * StringUtils.swapCase("")                   = ""
 5178        * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
 5179        * </pre>
 5180        *
 5181        * <p>NOTE: This method changed in Lang version 2.0.
 5182        * It no longer performs a word based algorithm.
 5183        * If you only use ASCII, you will notice no change.
 5184        * That functionality is available in WordUtils.</p>
 5185        *
 5186        * @param str  the String to swap case, may be null
 5187        * @return the changed String, <code>null</code> if null String input
 5188        */
 5189       public static String swapCase(String str) {
 5190           int strLen;
 5191           if (str == null || (strLen = str.length()) == 0) {
 5192               return str;
 5193           }
 5194           StringBuffer buffer = new StringBuffer(strLen);
 5195   
 5196           char ch = 0;
 5197           for (int i = 0; i < strLen; i++) {
 5198               ch = str.charAt(i);
 5199               if (Character.isUpperCase(ch)) {
 5200                   ch = Character.toLowerCase(ch);
 5201               } else if (Character.isTitleCase(ch)) {
 5202                   ch = Character.toLowerCase(ch);
 5203               } else if (Character.isLowerCase(ch)) {
 5204                   ch = Character.toUpperCase(ch);
 5205               }
 5206               buffer.append(ch);
 5207           }
 5208           return buffer.toString();
 5209       }
 5210   
 5211       /**
 5212        * <p>Capitalizes all the whitespace separated words in a String.
 5213        * Only the first letter of each word is changed.</p>
 5214        *
 5215        * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
 5216        * A <code>null</code> input String returns <code>null</code>.</p>
 5217        *
 5218        * @param str  the String to capitalize, may be null
 5219        * @return capitalized String, <code>null</code> if null String input
 5220        * @deprecated Use the relocated {@link WordUtils#capitalize(String)}.
 5221        *             Method will be removed in Commons Lang 3.0.
 5222        */
 5223       public static String capitaliseAllWords(String str) {
 5224           return WordUtils.capitalize(str);
 5225       }
 5226   
 5227       // Count matches
 5228       //-----------------------------------------------------------------------
 5229       /**
 5230        * <p>Counts how many times the substring appears in the larger String.</p>
 5231        *
 5232        * <p>A <code>null</code> or empty ("") String input returns <code>0</code>.</p>
 5233        *
 5234        * <pre>
 5235        * StringUtils.countMatches(null, *)       = 0
 5236        * StringUtils.countMatches("", *)         = 0
 5237        * StringUtils.countMatches("abba", null)  = 0
 5238        * StringUtils.countMatches("abba", "")    = 0
 5239        * StringUtils.countMatches("abba", "a")   = 2
 5240        * StringUtils.countMatches("abba", "ab")  = 1
 5241        * StringUtils.countMatches("abba", "xxx") = 0
 5242        * </pre>
 5243        *
 5244        * @param str  the String to check, may be null
 5245        * @param sub  the substring to count, may be null
 5246        * @return the number of occurrences, 0 if either String is <code>null</code>
 5247        */
 5248       public static int countMatches(String str, String sub) {
 5249           if (isEmpty(str) || isEmpty(sub)) {
 5250               return 0;
 5251           }
 5252           int count = 0;
 5253           int idx = 0;
 5254           while ((idx = str.indexOf(sub, idx)) != -1) {
 5255               count++;
 5256               idx += sub.length();
 5257           }
 5258           return count;
 5259       }
 5260   
 5261       // Character Tests
 5262       //-----------------------------------------------------------------------
 5263       /**
 5264        * <p>Checks if the String contains only unicode letters.</p>
 5265        *
 5266        * <p><code>null</code> will return <code>false</code>.
 5267        * An empty String ("") will return <code>true</code>.</p>
 5268        *
 5269        * <pre>
 5270        * StringUtils.isAlpha(null)   = false
 5271        * StringUtils.isAlpha("")     = true
 5272        * StringUtils.isAlpha("  ")   = false
 5273        * StringUtils.isAlpha("abc")  = true
 5274        * StringUtils.isAlpha("ab2c") = false
 5275        * StringUtils.isAlpha("ab-c") = false
 5276        * </pre>
 5277        *
 5278        * @param str  the String to check, may be null
 5279        * @return <code>true</code> if only contains letters, and is non-null
 5280        */
 5281       public static boolean isAlpha(String str) {
 5282           if (str == null) {
 5283               return false;
 5284           }
 5285           int sz = str.length();
 5286           for (int i = 0; i < sz; i++) {
 5287               if (Character.isLetter(str.charAt(i)) == false) {
 5288                   return false;
 5289               }
 5290           }
 5291           return true;
 5292       }
 5293   
 5294       /**
 5295        * <p>Checks if the String contains only unicode letters and
 5296        * space (' ').</p>
 5297        *
 5298        * <p><code>null</code> will return <code>false</code>
 5299        * An empty String ("") will return <code>true</code>.</p>
 5300        *
 5301        * <pre>
 5302        * StringUtils.isAlphaSpace(null)   = false
 5303        * StringUtils.isAlphaSpace("")     = true
 5304        * StringUtils.isAlphaSpace("  ")   = true
 5305        * StringUtils.isAlphaSpace("abc")  = true
 5306        * StringUtils.isAlphaSpace("ab c") = true
 5307        * StringUtils.isAlphaSpace("ab2c") = false
 5308        * StringUtils.isAlphaSpace("ab-c") = false
 5309        * </pre>
 5310        *
 5311        * @param str  the String to check, may be null
 5312        * @return <code>true</code> if only contains letters and space,
 5313        *  and is non-null
 5314        */
 5315       public static boolean isAlphaSpace(String str) {
 5316           if (str == null) {
 5317               return false;
 5318           }
 5319           int sz = str.length();
 5320           for (int i = 0; i < sz; i++) {
 5321               if ((Character.isLetter(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
 5322                   return false;
 5323               }
 5324           }
 5325           return true;
 5326       }
 5327   
 5328       /**
 5329        * <p>Checks if the String contains only unicode letters or digits.</p>
 5330        *
 5331        * <p><code>null</code> will return <code>false</code>.
 5332        * An empty String ("") will return <code>true</code>.</p>
 5333        *
 5334        * <pre>
 5335        * StringUtils.isAlphanumeric(null)   = false
 5336        * StringUtils.isAlphanumeric("")     = true
 5337        * StringUtils.isAlphanumeric("  ")   = false
 5338        * StringUtils.isAlphanumeric("abc")  = true
 5339        * StringUtils.isAlphanumeric("ab c") = false
 5340        * StringUtils.isAlphanumeric("ab2c") = true
 5341        * StringUtils.isAlphanumeric("ab-c") = false
 5342        * </pre>
 5343        *
 5344        * @param str  the String to check, may be null
 5345        * @return <code>true</code> if only contains letters or digits,
 5346        *  and is non-null
 5347        */
 5348       public static boolean isAlphanumeric(String str) {
 5349           if (str == null) {
 5350               return false;
 5351           }
 5352           int sz = str.length();
 5353           for (int i = 0; i < sz; i++) {
 5354               if (Character.isLetterOrDigit(str.charAt(i)) == false) {
 5355                   return false;
 5356               }
 5357           }
 5358           return true;
 5359       }
 5360   
 5361       /**
 5362        * <p>Checks if the String contains only unicode letters, digits
 5363        * or space (<code>' '</code>).</p>
 5364        *
 5365        * <p><code>null</code> will return <code>false</code>.
 5366        * An empty String ("") will return <code>true</code>.</p>
 5367        *
 5368        * <pre>
 5369        * StringUtils.isAlphanumeric(null)   = false
 5370        * StringUtils.isAlphanumeric("")     = true
 5371        * StringUtils.isAlphanumeric("  ")   = true
 5372        * StringUtils.isAlphanumeric("abc")  = true
 5373        * StringUtils.isAlphanumeric("ab c") = true
 5374        * StringUtils.isAlphanumeric("ab2c") = true
 5375        * StringUtils.isAlphanumeric("ab-c") = false
 5376        * </pre>
 5377        *
 5378        * @param str  the String to check, may be null
 5379        * @return <code>true</code> if only contains letters, digits or space,
 5380        *  and is non-null
 5381        */
 5382       public static boolean isAlphanumericSpace(String str) {
 5383           if (str == null) {
 5384               return false;
 5385           }
 5386           int sz = str.length();
 5387           for (int i = 0; i < sz; i++) {
 5388               if ((Character.isLetterOrDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
 5389                   return false;
 5390               }
 5391           }
 5392           return true;
 5393       }
 5394   
 5395       /**
 5396        * <p>Checks if the string contains only ASCII printable characters.</p>
 5397        * 
 5398        * <p><code>null</code> will return <code>false</code>.
 5399        * An empty String ("") will return <code>true</code>.</p>
 5400        * 
 5401        * <pre>
 5402        * StringUtils.isAsciiPrintable(null)     = false
 5403        * StringUtils.isAsciiPrintable("")       = true
 5404        * StringUtils.isAsciiPrintable(" ")      = true
 5405        * StringUtils.isAsciiPrintable("Ceki")   = true
 5406        * StringUtils.isAsciiPrintable("ab2c")   = true
 5407        * StringUtils.isAsciiPrintable("!ab-c~") = true
 5408        * StringUtils.isAsciiPrintable("\u0020") = true
 5409        * StringUtils.isAsciiPrintable("\u0021") = true
 5410        * StringUtils.isAsciiPrintable("\u007e") = true
 5411        * StringUtils.isAsciiPrintable("\u007f") = false
 5412        * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
 5413        * </pre>
 5414        *
 5415        * @param str the string to check, may be null
 5416        * @return <code>true</code> if every character is in the range
 5417        *  32 thru 126
 5418        * @since 2.1
 5419        */
 5420       public static boolean isAsciiPrintable(String str) {
 5421           if (str == null) {
 5422               return false;
 5423           }
 5424           int sz = str.length();
 5425           for (int i = 0; i < sz; i++) {
 5426               if (CharUtils.isAsciiPrintable(str.charAt(i)) == false) {
 5427                   return false;
 5428               }
 5429           }
 5430           return true;
 5431       }
 5432   
 5433       /**
 5434        * <p>Checks if the String contains only unicode digits.
 5435        * A decimal point is not a unicode digit and returns false.</p>
 5436        *
 5437        * <p><code>null</code> will return <code>false</code>.
 5438        * An empty String ("") will return <code>true</code>.</p>
 5439        *
 5440        * <pre>
 5441        * StringUtils.isNumeric(null)   = false
 5442        * StringUtils.isNumeric("")     = true
 5443        * StringUtils.isNumeric("  ")   = false
 5444        * StringUtils.isNumeric("123")  = true
 5445        * StringUtils.isNumeric("12 3") = false
 5446        * StringUtils.isNumeric("ab2c") = false
 5447        * StringUtils.isNumeric("12-3") = false
 5448        * StringUtils.isNumeric("12.3") = false
 5449        * </pre>
 5450        *
 5451        * @param str  the String to check, may be null
 5452        * @return <code>true</code> if only contains digits, and is non-null
 5453        */
 5454       public static boolean isNumeric(String str) {
 5455           if (str == null) {
 5456               return false;
 5457           }
 5458           int sz = str.length();
 5459           for (int i = 0; i < sz; i++) {
 5460               if (Character.isDigit(str.charAt(i)) == false) {
 5461                   return false;
 5462               }
 5463           }
 5464           return true;
 5465       }
 5466   
 5467       /**
 5468        * <p>Checks if the String contains only unicode digits or space
 5469        * (<code>' '</code>).
 5470        * A decimal point is not a unicode digit and returns false.</p>
 5471        *
 5472        * <p><code>null</code> will return <code>false</code>.
 5473        * An empty String ("") will return <code>true</code>.</p>
 5474        *
 5475        * <pre>
 5476        * StringUtils.isNumeric(null)   = false
 5477        * StringUtils.isNumeric("")     = true
 5478        * StringUtils.isNumeric("  ")   = true
 5479        * StringUtils.isNumeric("123")  = true
 5480        * StringUtils.isNumeric("12 3") = true
 5481        * StringUtils.isNumeric("ab2c") = false
 5482        * StringUtils.isNumeric("12-3") = false
 5483        * StringUtils.isNumeric("12.3") = false
 5484        * </pre>
 5485        *
 5486        * @param str  the String to check, may be null
 5487        * @return <code>true</code> if only contains digits or space,
 5488        *  and is non-null
 5489        */
 5490       public static boolean isNumericSpace(String str) {
 5491           if (str == null) {
 5492               return false;
 5493           }
 5494           int sz = str.length();
 5495           for (int i = 0; i < sz; i++) {
 5496               if ((Character.isDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
 5497                   return false;
 5498               }
 5499           }
 5500           return true;
 5501       }
 5502   
 5503       /**
 5504        * <p>Checks if the String contains only whitespace.</p>
 5505        *
 5506        * <p><code>null</code> will return <code>false</code>.
 5507        * An empty String ("") will return <code>true</code>.</p>
 5508        *
 5509        * <pre>
 5510        * StringUtils.isWhitespace(null)   = false
 5511        * StringUtils.isWhitespace("")     = true
 5512        * StringUtils.isWhitespace("  ")   = true
 5513        * StringUtils.isWhitespace("abc")  = false
 5514        * StringUtils.isWhitespace("ab2c") = false
 5515        * StringUtils.isWhitespace("ab-c") = false
 5516        * </pre>
 5517        *
 5518        * @param str  the String to check, may be null
 5519        * @return <code>true</code> if only contains whitespace, and is non-null
 5520        * @since 2.0
 5521        */
 5522       public static boolean isWhitespace(String str) {
 5523           if (str == null) {
 5524               return false;
 5525           }
 5526           int sz = str.length();
 5527           for (int i = 0; i < sz; i++) {
 5528               if ((Character.isWhitespace(str.charAt(i)) == false)) {
 5529                   return false;
 5530               }
 5531           }
 5532           return true;
 5533       }
 5534   
 5535       /**
 5536        * <p>Checks if the String contains only lowercase characters.</p>
 5537        *
 5538        * <p><code>null</code> will return <code>false</code>.
 5539        * An empty String ("") will return <code>false</code>.</p>
 5540        *
 5541        * <pre>
 5542        * StringUtils.isAllLowerCase(null)   = false
 5543        * StringUtils.isAllLowerCase("")     = false
 5544        * StringUtils.isAllLowerCase("  ")   = false
 5545        * StringUtils.isAllLowerCase("abc")  = true
 5546        * StringUtils.isAllLowerCase("abC") = false
 5547        * </pre>
 5548        *
 5549        * @param str  the String to check, may be null
 5550        * @return <code>true</code> if only contains lowercase characters, and is non-null
 5551        * @since 2.5
 5552        */
 5553       public static boolean isAllLowerCase(String str) {
 5554           if (str == null || isEmpty(str)) {
 5555               return false;
 5556           }
 5557           int sz = str.length();
 5558           for (int i = 0; i < sz; i++) {
 5559               if (Character.isLowerCase(str.charAt(i)) == false) {
 5560                   return false;
 5561               }
 5562           }
 5563           return true;
 5564       }
 5565   
 5566       /**
 5567        * <p>Checks if the String contains only uppercase characters.</p>
 5568        *
 5569        * <p><code>null</code> will return <code>false</code>.
 5570        * An empty String ("") will return <code>false</code>.</p>
 5571        *
 5572        * <pre>
 5573        * StringUtils.isAllUpperCase(null)   = false
 5574        * StringUtils.isAllUpperCase("")     = false
 5575        * StringUtils.isAllUpperCase("  ")   = false
 5576        * StringUtils.isAllUpperCase("ABC")  = true
 5577        * StringUtils.isAllUpperCase("aBC") = false
 5578        * </pre>
 5579        *
 5580        * @param str  the String to check, may be null
 5581        * @return <code>true</code> if only contains uppercase characters, and is non-null
 5582        * @since 2.5
 5583        */
 5584       public static boolean isAllUpperCase(String str) {
 5585           if (str == null || isEmpty(str)) {
 5586               return false;
 5587           }
 5588           int sz = str.length();
 5589           for (int i = 0; i < sz; i++) {
 5590               if (Character.isUpperCase(str.charAt(i)) == false) {
 5591                   return false;
 5592               }
 5593           }
 5594           return true;
 5595       }
 5596   
 5597       // Defaults
 5598       //-----------------------------------------------------------------------
 5599       /**
 5600        * <p>Returns either the passed in String,
 5601        * or if the String is <code>null</code>, an empty String ("").</p>
 5602        *
 5603        * <pre>
 5604        * StringUtils.defaultString(null)  = ""
 5605        * StringUtils.defaultString("")    = ""
 5606        * StringUtils.defaultString("bat") = "bat"
 5607        * </pre>
 5608        *
 5609        * @see ObjectUtils#toString(Object)
 5610        * @see String#valueOf(Object)
 5611        * @param str  the String to check, may be null
 5612        * @return the passed in String, or the empty String if it
 5613        *  was <code>null</code>
 5614        */
 5615       public static String defaultString(String str) {
 5616           return str == null ? EMPTY : str;
 5617       }
 5618   
 5619       /**
 5620        * <p>Returns either the passed in String, or if the String is
 5621        * <code>null</code>, the value of <code>defaultStr</code>.</p>
 5622        *
 5623        * <pre>
 5624        * StringUtils.defaultString(null, "NULL")  = "NULL"
 5625        * StringUtils.defaultString("", "NULL")    = ""
 5626        * StringUtils.defaultString("bat", "NULL") = "bat"
 5627        * </pre>
 5628        *
 5629        * @see ObjectUtils#toString(Object,String)
 5630        * @see String#valueOf(Object)
 5631        * @param str  the String to check, may be null
 5632        * @param defaultStr  the default String to return
 5633        *  if the input is <code>null</code>, may be null
 5634        * @return the passed in String, or the default if it was <code>null</code>
 5635        */
 5636       public static String defaultString(String str, String defaultStr) {
 5637           return str == null ? defaultStr : str;
 5638       }
 5639   
 5640       /**
 5641        * <p>Returns either the passed in String, or if the String is
 5642        * empty or <code>null</code>, the value of <code>defaultStr</code>.</p>
 5643        *
 5644        * <pre>
 5645        * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
 5646        * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
 5647        * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
 5648        * StringUtils.defaultIfEmpty("", null)      = null
 5649        * </pre>
 5650        *
 5651        * @see StringUtils#defaultString(String, String)
 5652        * @param str  the String to check, may be null
 5653        * @param defaultStr  the default String to return
 5654        *  if the input is empty ("") or <code>null</code>, may be null
 5655        * @return the passed in String, or the default
 5656        */
 5657       public static String defaultIfEmpty(String str, String defaultStr) {
 5658           return StringUtils.isEmpty(str) ? defaultStr : str;
 5659       }
 5660   
 5661       // Reversing
 5662       //-----------------------------------------------------------------------
 5663       /**
 5664        * <p>Reverses a String as per {@link StringBuffer#reverse()}.</p>
 5665        *
 5666        * <p>A <code>null</code> String returns <code>null</code>.</p>
 5667        *
 5668        * <pre>
 5669        * StringUtils.reverse(null)  = null
 5670        * StringUtils.reverse("")    = ""
 5671        * StringUtils.reverse("bat") = "tab"
 5672        * </pre>
 5673        *
 5674        * @param str  the String to reverse, may be null
 5675        * @return the reversed String, <code>null</code> if null String input
 5676        */
 5677       public static String reverse(String str) {
 5678           if (str == null) {
 5679               return null;
 5680           }
 5681           return new StringBuffer(str).reverse().toString();
 5682       }
 5683   
 5684       /**
 5685        * <p>Reverses a String that is delimited by a specific character.</p>
 5686        *
 5687        * <p>The Strings between the delimiters are not reversed.
 5688        * Thus java.lang.String becomes String.lang.java (if the delimiter
 5689        * is <code>'.'</code>).</p>
 5690        *
 5691        * <pre>
 5692        * StringUtils.reverseDelimited(null, *)      = null
 5693        * StringUtils.reverseDelimited("", *)        = ""
 5694        * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
 5695        * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
 5696        * </pre>
 5697        *
 5698        * @param str  the String to reverse, may be null
 5699        * @param separatorChar  the separator character to use
 5700        * @return the reversed String, <code>null</code> if null String input
 5701        * @since 2.0
 5702        */
 5703       public static String reverseDelimited(String str, char separatorChar) {
 5704           if (str == null) {
 5705               return null;
 5706           }
 5707           // could implement manually, but simple way is to reuse other,
 5708           // probably slower, methods.
 5709           String[] strs = split(str, separatorChar);
 5710           ArrayUtils.reverse(strs);
 5711           return join(strs, separatorChar);
 5712       }
 5713   
 5714       /**
 5715        * <p>Reverses a String that is delimited by a specific character.</p>
 5716        *
 5717        * <p>The Strings between the delimiters are not reversed.
 5718        * Thus java.lang.String becomes String.lang.java (if the delimiter
 5719        * is <code>"."</code>).</p>
 5720        *
 5721        * <pre>
 5722        * StringUtils.reverseDelimitedString(null, *)       = null
 5723        * StringUtils.reverseDelimitedString("",*)          = ""
 5724        * StringUtils.reverseDelimitedString("a.b.c", null) = "a.b.c"
 5725        * StringUtils.reverseDelimitedString("a.b.c", ".")  = "c.b.a"
 5726        * </pre>
 5727        *
 5728        * @param str  the String to reverse, may be null
 5729        * @param separatorChars  the separator characters to use, null treated as whitespace
 5730        * @return the reversed String, <code>null</code> if null String input
 5731        * @deprecated Use {@link #reverseDelimited(String, char)} instead.
 5732        *      This method is broken as the join doesn't know which char to use.
 5733        *      Method will be removed in Commons Lang 3.0.
 5734        *
 5735        */
 5736       public static String reverseDelimitedString(String str, String separatorChars) {
 5737           if (str == null) {
 5738               return null;
 5739           }
 5740           // could implement manually, but simple way is to reuse other,
 5741           // probably slower, methods.
 5742           String[] strs = split(str, separatorChars);
 5743           ArrayUtils.reverse(strs);
 5744           if (separatorChars == null) {
 5745               return join(strs, ' ');
 5746           }
 5747           return join(strs, separatorChars);
 5748       }
 5749   
 5750       // Abbreviating
 5751       //-----------------------------------------------------------------------
 5752       /**
 5753        * <p>Abbreviates a String using ellipses. This will turn
 5754        * "Now is the time for all good men" into "Now is the time for..."</p>
 5755        *
 5756        * <p>Specifically:
 5757        * <ul>
 5758        *   <li>If <code>str</code> is less than <code>maxWidth</code> characters
 5759        *       long, return it.</li>
 5760        *   <li>Else abbreviate it to <code>(substring(str, 0, max-3) + "...")</code>.</li>
 5761        *   <li>If <code>maxWidth</code> is less than <code>4</code>, throw an
 5762        *       <code>IllegalArgumentException</code>.</li>
 5763        *   <li>In no case will it return a String of length greater than
 5764        *       <code>maxWidth</code>.</li>
 5765        * </ul>
 5766        * </p>
 5767        *
 5768        * <pre>
 5769        * StringUtils.abbreviate(null, *)      = null
 5770        * StringUtils.abbreviate("", 4)        = ""
 5771        * StringUtils.abbreviate("abcdefg", 6) = "abc..."
 5772        * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
 5773        * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
 5774        * StringUtils.abbreviate("abcdefg", 4) = "a..."
 5775        * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
 5776        * </pre>
 5777        *
 5778        * @param str  the String to check, may be null
 5779        * @param maxWidth  maximum length of result String, must be at least 4
 5780        * @return abbreviated String, <code>null</code> if null String input
 5781        * @throws IllegalArgumentException if the width is too small
 5782        * @since 2.0
 5783        */
 5784       public static String abbreviate(String str, int maxWidth) {
 5785           return abbreviate(str, 0, maxWidth);
 5786       }
 5787   
 5788       /**
 5789        * <p>Abbreviates a String using ellipses. This will turn
 5790        * "Now is the time for all good men" into "...is the time for..."</p>
 5791        *
 5792        * <p>Works like <code>abbreviate(String, int)</code>, but allows you to specify
 5793        * a "left edge" offset.  Note that this left edge is not necessarily going to
 5794        * be the leftmost character in the result, or the first character following the
 5795        * ellipses, but it will appear somewhere in the result.
 5796        *
 5797        * <p>In no case will it return a String of length greater than
 5798        * <code>maxWidth</code>.</p>
 5799        *
 5800        * <pre>
 5801        * StringUtils.abbreviate(null, *, *)                = null
 5802        * StringUtils.abbreviate("", 0, 4)                  = ""
 5803        * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
 5804        * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
 5805        * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
 5806        * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
 5807        * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
 5808        * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
 5809        * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
 5810        * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
 5811        * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
 5812        * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
 5813        * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
 5814        * </pre>
 5815        *
 5816        * @param str  the String to check, may be null
 5817        * @param offset  left edge of source String
 5818        * @param maxWidth  maximum length of result String, must be at least 4
 5819        * @return abbreviated String, <code>null</code> if null String input
 5820        * @throws IllegalArgumentException if the width is too small
 5821        * @since 2.0
 5822        */
 5823       public static String abbreviate(String str, int offset, int maxWidth) {
 5824           if (str == null) {
 5825               return null;
 5826           }
 5827           if (maxWidth < 4) {
 5828               throw new IllegalArgumentException("Minimum abbreviation width is 4");
 5829           }
 5830           if (str.length() <= maxWidth) {
 5831               return str;
 5832           }
 5833           if (offset > str.length()) {
 5834               offset = str.length();
 5835           }
 5836           if ((str.length() - offset) < (maxWidth - 3)) {
 5837               offset = str.length() - (maxWidth - 3);
 5838           }
 5839           if (offset <= 4) {
 5840               return str.substring(0, maxWidth - 3) + "...";
 5841           }
 5842           if (maxWidth < 7) {
 5843               throw new IllegalArgumentException("Minimum abbreviation width with offset is 7");
 5844           }
 5845           if ((offset + (maxWidth - 3)) < str.length()) {
 5846               return "..." + abbreviate(str.substring(offset), maxWidth - 3);
 5847           }
 5848           return "..." + str.substring(str.length() - (maxWidth - 3));
 5849       }
 5850       
 5851       /**
 5852        * <p>Abbreviates a String to the length passed, replacing the middle characters with the supplied
 5853        * replacement String.</p>
 5854        *
 5855        * <p>This abbreviation only occurs if the following criteria is met:
 5856        * <ul>
 5857        * <li>Neither the String for abbreviation nor the replacement String are null or empty </li>
 5858        * <li>The length to truncate to is less than the length of the supplied String</li>
 5859        * <li>The length to truncate to is greater than 0</li>
 5860        * <li>The abbreviated String will have enough room for the length supplied replacement String
 5861        * and the first and last characters of the supplied String for abbreviation</li>
 5862        * </ul>
 5863        * Otherwise, the returned String will be the same as the supplied String for abbreviation.
 5864        * </p>
 5865        *
 5866        * <pre>
 5867        * StringUtils.abbreviateMiddle(null, null, 0)      = null
 5868        * StringUtils.abbreviateMiddle("abc", null, 0)      = "abc"
 5869        * StringUtils.abbreviateMiddle("abc", ".", 0)      = "abc"
 5870        * StringUtils.abbreviateMiddle("abc", ".", 3)      = "abc"
 5871        * StringUtils.abbreviateMiddle("abcdef", ".", 4)     = "ab.f"
 5872        * </pre>
 5873        *
 5874        * @param str  the String to abbreviate, may be null
 5875        * @param middle the String to replace the middle characters with, may be null
 5876        * @param length the length to abbreviate <code>str</code> to.
 5877        * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
 5878        * @since 2.5
 5879        */
 5880       public static String abbreviateMiddle(String str, String middle, int length) {
 5881           if (isEmpty(str) || isEmpty(middle)) {
 5882               return str;
 5883           }
 5884         
 5885           if (length >= str.length() || length < (middle.length()+2)) {
 5886               return str;
 5887           }
 5888   
 5889           int targetSting = length-middle.length();
 5890           int startOffset = targetSting/2+targetSting%2;
 5891           int endOffset = str.length()-targetSting/2;
 5892           
 5893           StringBuffer builder = new StringBuffer(length);
 5894           builder.append(str.substring(0,startOffset));
 5895           builder.append(middle);
 5896           builder.append(str.substring(endOffset));
 5897           
 5898           return builder.toString();
 5899       }
 5900   
 5901       // Difference
 5902       //-----------------------------------------------------------------------
 5903       /**
 5904        * <p>Compares two Strings, and returns the portion where they differ.
 5905        * (More precisely, return the remainder of the second String,
 5906        * starting from where it's different from the first.)</p>
 5907        *
 5908        * <p>For example,
 5909        * <code>difference("i am a machine", "i am a robot") -> "robot"</code>.</p>
 5910        *
 5911        * <pre>
 5912        * StringUtils.difference(null, null) = null
 5913        * StringUtils.difference("", "") = ""
 5914        * StringUtils.difference("", "abc") = "abc"
 5915        * StringUtils.difference("abc", "") = ""
 5916        * StringUtils.difference("abc", "abc") = ""
 5917        * StringUtils.difference("ab", "abxyz") = "xyz"
 5918        * StringUtils.difference("abcde", "abxyz") = "xyz"
 5919        * StringUtils.difference("abcde", "xyz") = "xyz"
 5920        * </pre>
 5921        *
 5922        * @param str1  the first String, may be null
 5923        * @param str2  the second String, may be null
 5924        * @return the portion of str2 where it differs from str1; returns the
 5925        * empty String if they are equal
 5926        * @since 2.0
 5927        */
 5928       public static String difference(String str1, String str2) {
 5929           if (str1 == null) {
 5930               return str2;
 5931           }
 5932           if (str2 == null) {
 5933               return str1;
 5934           }
 5935           int at = indexOfDifference(str1, str2);
 5936           if (at == -1) {
 5937               return EMPTY;
 5938           }
 5939           return str2.substring(at);
 5940       }
 5941   
 5942       /**
 5943        * <p>Compares two Strings, and returns the index at which the
 5944        * Strings begin to differ.</p>
 5945        *
 5946        * <p>For example,
 5947        * <code>indexOfDifference("i am a machine", "i am a robot") -> 7</code></p>
 5948        *
 5949        * <pre>
 5950        * StringUtils.indexOfDifference(null, null) = -1
 5951        * StringUtils.indexOfDifference("", "") = -1
 5952        * StringUtils.indexOfDifference("", "abc") = 0
 5953        * StringUtils.indexOfDifference("abc", "") = 0
 5954        * StringUtils.indexOfDifference("abc", "abc") = -1
 5955        * StringUtils.indexOfDifference("ab", "abxyz") = 2
 5956        * StringUtils.indexOfDifference("abcde", "abxyz") = 2
 5957        * StringUtils.indexOfDifference("abcde", "xyz") = 0
 5958        * </pre>
 5959        *
 5960        * @param str1  the first String, may be null
 5961        * @param str2  the second String, may be null
 5962        * @return the index where str2 and str1 begin to differ; -1 if they are equal
 5963        * @since 2.0
 5964        */
 5965       public static int indexOfDifference(String str1, String str2) {
 5966           if (str1 == str2) {
 5967               return -1;
 5968           }
 5969           if (str1 == null || str2 == null) {
 5970               return 0;
 5971           }
 5972           int i;
 5973           for (i = 0; i < str1.length() && i < str2.length(); ++i) {
 5974               if (str1.charAt(i) != str2.charAt(i)) {
 5975                   break;
 5976               }
 5977           }
 5978           if (i < str2.length() || i < str1.length()) {
 5979               return i;
 5980           }
 5981           return -1;
 5982       }
 5983   
 5984       /**
 5985        * <p>Compares all Strings in an array and returns the index at which the
 5986        * Strings begin to differ.</p>
 5987        *
 5988        * <p>For example,
 5989        * <code>indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7</code></p>
 5990        *
 5991        * <pre>
 5992        * StringUtils.indexOfDifference(null) = -1
 5993        * StringUtils.indexOfDifference(new String[] {}) = -1
 5994        * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
 5995        * StringUtils.indexOfDifference(new String[] {null, null}) = -1
 5996        * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
 5997        * StringUtils.indexOfDifference(new String[] {"", null}) = 0
 5998        * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
 5999        * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
 6000        * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
 6001        * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
 6002        * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
 6003        * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
 6004        * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
 6005        * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
 6006        * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
 6007        * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
 6008        * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
 6009        * </pre>
 6010        *
 6011        * @param strs  array of strings, entries may be null
 6012        * @return the index where the strings begin to differ; -1 if they are all equal
 6013        * @since 2.4
 6014        */
 6015       public static int indexOfDifference(String[] strs) {
 6016           if (strs == null || strs.length <= 1) {
 6017               return -1;
 6018           }
 6019           boolean anyStringNull = false;
 6020           boolean allStringsNull = true;
 6021           int arrayLen = strs.length;
 6022           int shortestStrLen = Integer.MAX_VALUE;
 6023           int longestStrLen = 0;
 6024   
 6025           // find the min and max string lengths; this avoids checking to make
 6026           // sure we are not exceeding the length of the string each time through
 6027           // the bottom loop.
 6028           for (int i = 0; i < arrayLen; i++) {
 6029               if (strs[i] == null) {
 6030                   anyStringNull = true;
 6031                   shortestStrLen = 0;
 6032               } else {
 6033                   allStringsNull = false;
 6034                   shortestStrLen = Math.min(strs[i].length(), shortestStrLen);
 6035                   longestStrLen = Math.max(strs[i].length(), longestStrLen);
 6036               }
 6037           }
 6038   
 6039           // handle lists containing all nulls or all empty strings
 6040           if (allStringsNull || (longestStrLen == 0 && !anyStringNull)) {
 6041               return -1;
 6042           }
 6043   
 6044           // handle lists containing some nulls or some empty strings
 6045           if (shortestStrLen == 0) {
 6046               return 0;
 6047           }
 6048   
 6049           // find the position with the first difference across all strings
 6050           int firstDiff = -1;
 6051           for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
 6052               char comparisonChar = strs[0].charAt(stringPos);
 6053               for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
 6054                   if (strs[arrayPos].charAt(stringPos) != comparisonChar) {
 6055                       firstDiff = stringPos;
 6056                       break;
 6057                   }
 6058               }
 6059               if (firstDiff != -1) {
 6060                   break;
 6061               }
 6062           }
 6063   
 6064           if (firstDiff == -1 && shortestStrLen != longestStrLen) {
 6065               // we compared all of the characters up to the length of the
 6066               // shortest string and didn't find a match, but the string lengths
 6067               // vary, so return the length of the shortest string.
 6068               return shortestStrLen;
 6069           }
 6070           return firstDiff;
 6071       }
 6072       
 6073       /**
 6074        * <p>Compares all Strings in an array and returns the initial sequence of 
 6075        * characters that is common to all of them.</p>
 6076        *
 6077        * <p>For example,
 6078        * <code>getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "</code></p>
 6079        *
 6080        * <pre>
 6081        * StringUtils.getCommonPrefix(null) = ""
 6082        * StringUtils.getCommonPrefix(new String[] {}) = ""
 6083        * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc"
 6084        * StringUtils.getCommonPrefix(new String[] {null, null}) = ""
 6085        * StringUtils.getCommonPrefix(new String[] {"", ""}) = ""
 6086        * StringUtils.getCommonPrefix(new String[] {"", null}) = ""
 6087        * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
 6088        * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
 6089        * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = ""
 6090        * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = ""
 6091        * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc"
 6092        * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a"
 6093        * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab"
 6094        * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"
 6095        * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = ""
 6096        * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = ""
 6097        * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
 6098        * </pre>
 6099        *
 6100        * @param strs  array of String objects, entries may be null
 6101        * @return the initial sequence of characters that are common to all Strings
 6102        * in the array; empty String if the array is null, the elements are all null 
 6103        * or if there is no common prefix. 
 6104        * @since 2.4
 6105        */
 6106       public static String getCommonPrefix(String[] strs) {
 6107           if (strs == null || strs.length == 0) {
 6108               return EMPTY;
 6109           }
 6110           int smallestIndexOfDiff = indexOfDifference(strs);
 6111           if (smallestIndexOfDiff == -1) {
 6112               // all strings were identical
 6113               if (strs[0] == null) {
 6114                   return EMPTY;
 6115               }
 6116               return strs[0];
 6117           } else if (smallestIndexOfDiff == 0) {
 6118               // there were no common initial characters
 6119               return EMPTY;
 6120           } else {
 6121               // we found a common initial character sequence
 6122               return strs[0].substring(0, smallestIndexOfDiff);
 6123           }
 6124       }  
 6125       
 6126       // Misc
 6127       //-----------------------------------------------------------------------
 6128       /**
 6129        * <p>Find the Levenshtein distance between two Strings.</p>
 6130        *
 6131        * <p>This is the number of changes needed to change one String into
 6132        * another, where each change is a single character modification (deletion,
 6133        * insertion or substitution).</p>
 6134        *
 6135        * <p>The previous implementation of the Levenshtein distance algorithm
 6136        * was from <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
 6137        *
 6138        * <p>Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError
 6139        * which can occur when my Java implementation is used with very large strings.<br>
 6140        * This implementation of the Levenshtein distance algorithm
 6141        * is from <a href="http://www.merriampark.com/ldjava.htm">http://www.merriampark.com/ldjava.htm</a></p>
 6142        *
 6143        * <pre>
 6144        * StringUtils.getLevenshteinDistance(null, *)             = IllegalArgumentException
 6145        * StringUtils.getLevenshteinDistance(*, null)             = IllegalArgumentException
 6146        * StringUtils.getLevenshteinDistance("","")               = 0
 6147        * StringUtils.getLevenshteinDistance("","a")              = 1
 6148        * StringUtils.getLevenshteinDistance("aaapppp", "")       = 7
 6149        * StringUtils.getLevenshteinDistance("frog", "fog")       = 1
 6150        * StringUtils.getLevenshteinDistance("fly", "ant")        = 3
 6151        * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
 6152        * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
 6153        * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
 6154        * StringUtils.getLevenshteinDistance("hello", "hallo")    = 1
 6155        * </pre>
 6156        *
 6157        * @param s  the first String, must not be null
 6158        * @param t  the second String, must not be null
 6159        * @return result distance
 6160        * @throws IllegalArgumentException if either String input <code>null</code>
 6161        */
 6162       public static int getLevenshteinDistance(String s, String t) {
 6163           if (s == null || t == null) {
 6164               throw new IllegalArgumentException("Strings must not be null");
 6165           }
 6166   
 6167           /*
 6168              The difference between this impl. and the previous is that, rather 
 6169              than creating and retaining a matrix of size s.length()+1 by t.length()+1, 
 6170              we maintain two single-dimensional arrays of length s.length()+1.  The first, d,
 6171              is the 'current working' distance array that maintains the newest distance cost
 6172              counts as we iterate through the characters of String s.  Each time we increment
 6173              the index of String t we are comparing, d is copied to p, the second int[].  Doing so
 6174              allows us to retain the previous cost counts as required by the algorithm (taking 
 6175              the minimum of the cost count to the left, up one, and diagonally up and to the left
 6176              of the current cost count being calculated).  (Note that the arrays aren't really 
 6177              copied anymore, just switched...this is clearly much better than cloning an array 
 6178              or doing a System.arraycopy() each time  through the outer loop.)
 6179   
 6180              Effectively, the difference between the two implementations is this one does not 
 6181              cause an out of memory condition when calculating the LD over two very large strings.
 6182            */
 6183   
 6184           int n = s.length(); // length of s
 6185           int m = t.length(); // length of t
 6186   
 6187           if (n == 0) {
 6188               return m;
 6189           } else if (m == 0) {
 6190               return n;
 6191           }
 6192   
 6193           if (n > m) {
 6194               // swap the input strings to consume less memory
 6195               String tmp = s;
 6196               s = t;
 6197               t = tmp;
 6198               n = m;
 6199               m = t.length();
 6200           }
 6201   
 6202           int p[] = new int[n+1]; //'previous' cost array, horizontally
 6203           int d[] = new int[n+1]; // cost array, horizontally
 6204           int _d[]; //placeholder to assist in swapping p and d
 6205   
 6206           // indexes into strings s and t
 6207           int i; // iterates through s
 6208           int j; // iterates through t
 6209   
 6210           char t_j; // jth character of t
 6211   
 6212           int cost; // cost
 6213   
 6214           for (i = 0; i<=n; i++) {
 6215               p[i] = i;
 6216           }
 6217   
 6218           for (j = 1; j<=m; j++) {
 6219               t_j = t.charAt(j-1);
 6220               d[0] = j;
 6221   
 6222               for (i=1; i<=n; i++) {
 6223                   cost = s.charAt(i-1)==t_j ? 0 : 1;
 6224                   // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
 6225                   d[i] = Math.min(Math.min(d[i-1]+1, p[i]+1),  p[i-1]+cost);
 6226               }
 6227   
 6228               // copy current distance counts to 'previous row' distance counts
 6229               _d = p;
 6230               p = d;
 6231               d = _d;
 6232           }
 6233   
 6234           // our last action in the above loop was to switch d and p, so p now 
 6235           // actually has the most recent cost counts
 6236           return p[n];
 6237       }
 6238   
 6239       /**
 6240        * <p>Gets the minimum of three <code>int</code> values.</p>
 6241        *
 6242        * @param a  value 1
 6243        * @param b  value 2
 6244        * @param c  value 3
 6245        * @return  the smallest of the values
 6246        */
 6247   /*
 6248       private static int min(int a, int b, int c) {
 6249           // Method copied from NumberUtils to avoid dependency on subpackage
 6250           if (b < a) {
 6251               a = b;
 6252           }
 6253           if (c < a) {
 6254               a = c;
 6255           }
 6256           return a;
 6257       }
 6258   */
 6259   
 6260       // startsWith
 6261       //-----------------------------------------------------------------------
 6262   
 6263       /**
 6264        * <p>Check if a String starts with a specified prefix.</p>
 6265        *
 6266        * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
 6267        * references are considered to be equal. The comparison is case sensitive.</p>
 6268        *
 6269        * <pre>
 6270        * StringUtils.startsWith(null, null)      = true
 6271        * StringUtils.startsWith(null, "abc")     = false
 6272        * StringUtils.startsWith("abcdef", null)  = false
 6273        * StringUtils.startsWith("abcdef", "abc") = true
 6274        * StringUtils.startsWith("ABCDEF", "abc") = false
 6275        * </pre>
 6276        *
 6277        * @see java.lang.String#startsWith(String)
 6278        * @param str  the String to check, may be null
 6279        * @param prefix the prefix to find, may be null
 6280        * @return <code>true</code> if the String starts with the prefix, case sensitive, or
 6281        *  both <code>null</code>
 6282        * @since 2.4
 6283        */
 6284       public static boolean startsWith(String str, String prefix) {
 6285           return startsWith(str, prefix, false);
 6286       }
 6287   
 6288       /**
 6289        * <p>Case insensitive check if a String starts with a specified prefix.</p>
 6290        *
 6291        * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
 6292        * references are considered to be equal. The comparison is case insensitive.</p>
 6293        *
 6294        * <pre>
 6295        * StringUtils.startsWithIgnoreCase(null, null)      = true
 6296        * StringUtils.startsWithIgnoreCase(null, "abc")     = false
 6297        * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
 6298        * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
 6299        * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
 6300        * </pre>
 6301        *
 6302        * @see java.lang.String#startsWith(String)
 6303        * @param str  the String to check, may be null
 6304        * @param prefix the prefix to find, may be null
 6305        * @return <code>true</code> if the String starts with the prefix, case insensitive, or
 6306        *  both <code>null</code>
 6307        * @since 2.4
 6308        */
 6309       public static boolean startsWithIgnoreCase(String str, String prefix) {
 6310           return startsWith(str, prefix, true);
 6311       }
 6312   
 6313       /**
 6314        * <p>Check if a String starts with a specified prefix (optionally case insensitive).</p>
 6315        *
 6316        * @see java.lang.String#startsWith(String)
 6317        * @param str  the String to check, may be null
 6318        * @param prefix the prefix to find, may be null
 6319        * @param ignoreCase inidicates whether the compare should ignore case
 6320        *  (case insensitive) or not.
 6321        * @return <code>true</code> if the String starts with the prefix or
 6322        *  both <code>null</code>
 6323        */
 6324       private static boolean startsWith(String str, String prefix, boolean ignoreCase) {
 6325           if (str == null || prefix == null) {
 6326               return (str == null && prefix == null);
 6327           }
 6328           if (prefix.length() > str.length()) {
 6329               return false;
 6330           }
 6331           return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
 6332       }
 6333       
 6334       /**
 6335        * <p>Check if a String starts with any of an array of specified strings.</p>
 6336        * 
 6337        * <pre>
 6338        * StringUtils.startsWithAny(null, null)      = false
 6339        * StringUtils.startsWithAny(null, new String[] {"abc"})  = false
 6340        * StringUtils.startsWithAny("abcxyz", null)     = false
 6341        * StringUtils.startsWithAny("abcxyz", new String[] {""}) = false
 6342        * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
 6343        * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
 6344        * </pre>
 6345        *
 6346        * @see #startsWith(String, String)
 6347        * @param string  the String to check, may be null
 6348        * @param searchStrings the Strings to find, may be null or empty
 6349        * @return <code>true</code> if the String starts with any of the the prefixes, case insensitive, or
 6350        *  both <code>null</code>
 6351        * @since 2.5
 6352        */
 6353       public static boolean startsWithAny(String string, String[] searchStrings) {
 6354           if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) {
 6355               return false;
 6356           }
 6357           for (int i = 0; i < searchStrings.length; i++) {
 6358               String searchString = searchStrings[i];
 6359               if (StringUtils.startsWith(string, searchString)) {
 6360                   return true;
 6361               }
 6362           }
 6363           return false;
 6364       }
 6365   
 6366       // endsWith
 6367       //-----------------------------------------------------------------------
 6368   
 6369       /**
 6370        * <p>Check if a String ends with a specified suffix.</p>
 6371        *
 6372        * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
 6373        * references are considered to be equal. The comparison is case sensitive.</p>
 6374        *
 6375        * <pre>
 6376        * StringUtils.endsWith(null, null)      = true
 6377        * StringUtils.endsWith(null, "def")     = false
 6378        * StringUtils.endsWith("abcdef", null)  = false
 6379        * StringUtils.endsWith("abcdef", "def") = true
 6380        * StringUtils.endsWith("ABCDEF", "def") = false
 6381        * StringUtils.endsWith("ABCDEF", "cde") = false
 6382        * </pre>
 6383        *
 6384        * @see java.lang.String#endsWith(String)
 6385        * @param str  the String to check, may be null
 6386        * @param suffix the suffix to find, may be null
 6387        * @return <code>true</code> if the String ends with the suffix, case sensitive, or
 6388        *  both <code>null</code>
 6389        * @since 2.4
 6390        */
 6391       public static boolean endsWith(String str, String suffix) {
 6392           return endsWith(str, suffix, false);
 6393       }
 6394   
 6395       /**
 6396        * <p>Case insensitive check if a String ends with a specified suffix.</p>
 6397        *
 6398        * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
 6399        * references are considered to be equal. The comparison is case insensitive.</p>
 6400        *
 6401        * <pre>
 6402        * StringUtils.endsWithIgnoreCase(null, null)      = true
 6403        * StringUtils.endsWithIgnoreCase(null, "def")     = false
 6404        * StringUtils.endsWithIgnoreCase("abcdef", null)  = false
 6405        * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
 6406        * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
 6407        * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
 6408        * </pre>
 6409        *
 6410        * @see java.lang.String#endsWith(String)
 6411        * @param str  the String to check, may be null
 6412        * @param suffix the suffix to find, may be null
 6413        * @return <code>true</code> if the String ends with the suffix, case insensitive, or
 6414        *  both <code>null</code>
 6415        * @since 2.4
 6416        */
 6417       public static boolean endsWithIgnoreCase(String str, String suffix) {
 6418           return endsWith(str, suffix, true);
 6419       }
 6420   
 6421       /**
 6422        * <p>Check if a String ends with a specified suffix (optionally case insensitive).</p>
 6423        *
 6424        * @see java.lang.String#endsWith(String)
 6425        * @param str  the String to check, may be null
 6426        * @param suffix the suffix to find, may be null
 6427        * @param ignoreCase inidicates whether the compare should ignore case
 6428        *  (case insensitive) or not.
 6429        * @return <code>true</code> if the String starts with the prefix or
 6430        *  both <code>null</code>
 6431        */
 6432       private static boolean endsWith(String str, String suffix, boolean ignoreCase) {
 6433           if (str == null || suffix == null) {
 6434               return (str == null && suffix == null);
 6435           }
 6436           if (suffix.length() > str.length()) {
 6437               return false;
 6438           }
 6439           int strOffset = str.length() - suffix.length();
 6440           return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length());
 6441       }
 6442   }

Save This Page
Home » commons-lang-2.5-src » org.apache.commons » lang » [javadoc | source]