StringUtils.java

  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.  *      https://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.lang3;

  18. import java.io.UnsupportedEncodingException;
  19. import java.nio.CharBuffer;
  20. import java.nio.charset.Charset;
  21. import java.text.Normalizer;
  22. import java.util.ArrayList;
  23. import java.util.Arrays;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Locale;
  27. import java.util.Objects;
  28. import java.util.Set;
  29. import java.util.function.Supplier;
  30. import java.util.regex.Pattern;
  31. import java.util.stream.Collectors;

  32. import org.apache.commons.lang3.function.Suppliers;
  33. import org.apache.commons.lang3.stream.LangCollectors;
  34. import org.apache.commons.lang3.stream.Streams;

  35. /**
  36.  * Operations on {@link String} that are
  37.  * {@code null} safe.
  38.  *
  39.  * <ul>
  40.  *  <li><strong>IsEmpty/IsBlank</strong>
  41.  *      - checks if a String contains text</li>
  42.  *  <li><strong>Trim/Strip</strong>
  43.  *      - removes leading and trailing whitespace</li>
  44.  *  <li><strong>Equals/Compare</strong>
  45.  *      - compares two strings in a null-safe manner</li>
  46.  *  <li><strong>startsWith</strong>
  47.  *      - check if a String starts with a prefix in a null-safe manner</li>
  48.  *  <li><strong>endsWith</strong>
  49.  *      - check if a String ends with a suffix in a null-safe manner</li>
  50.  *  <li><strong>IndexOf/LastIndexOf/Contains</strong>
  51.  *      - null-safe index-of checks
  52.  *  <li><strong>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</strong>
  53.  *      - index-of any of a set of Strings</li>
  54.  *  <li><strong>ContainsOnly/ContainsNone/ContainsAny</strong>
  55.  *      - checks if String contains only/none/any of these characters</li>
  56.  *  <li><strong>Substring/Left/Right/Mid</strong>
  57.  *      - null-safe substring extractions</li>
  58.  *  <li><strong>SubstringBefore/SubstringAfter/SubstringBetween</strong>
  59.  *      - substring extraction relative to other strings</li>
  60.  *  <li><strong>Split/Join</strong>
  61.  *      - splits a String into an array of substrings and vice versa</li>
  62.  *  <li><strong>Remove/Delete</strong>
  63.  *      - removes part of a String</li>
  64.  *  <li><strong>Replace/Overlay</strong>
  65.  *      - Searches a String and replaces one String with another</li>
  66.  *  <li><strong>Chomp/Chop</strong>
  67.  *      - removes the last part of a String</li>
  68.  *  <li><strong>AppendIfMissing</strong>
  69.  *      - appends a suffix to the end of the String if not present</li>
  70.  *  <li><strong>PrependIfMissing</strong>
  71.  *      - prepends a prefix to the start of the String if not present</li>
  72.  *  <li><strong>LeftPad/RightPad/Center/Repeat</strong>
  73.  *      - pads a String</li>
  74.  *  <li><strong>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</strong>
  75.  *      - changes the case of a String</li>
  76.  *  <li><strong>CountMatches</strong>
  77.  *      - counts the number of occurrences of one String in another</li>
  78.  *  <li><strong>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</strong>
  79.  *      - checks the characters in a String</li>
  80.  *  <li><strong>DefaultString</strong>
  81.  *      - protects against a null input String</li>
  82.  *  <li><strong>Rotate</strong>
  83.  *      - rotate (circular shift) a String</li>
  84.  *  <li><strong>Reverse/ReverseDelimited</strong>
  85.  *      - reverses a String</li>
  86.  *  <li><strong>Abbreviate</strong>
  87.  *      - abbreviates a string using ellipses or another given String</li>
  88.  *  <li><strong>Difference</strong>
  89.  *      - compares Strings and reports on their differences</li>
  90.  *  <li><strong>LevenshteinDistance</strong>
  91.  *      - the number of changes needed to change one String into another</li>
  92.  * </ul>
  93.  *
  94.  * <p>The {@link StringUtils} class defines certain words related to
  95.  * String handling.</p>
  96.  *
  97.  * <ul>
  98.  *  <li>null - {@code null}</li>
  99.  *  <li>empty - a zero-length string ({@code ""})</li>
  100.  *  <li>space - the space character ({@code ' '}, char 32)</li>
  101.  *  <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
  102.  *  <li>trim - the characters &lt;= 32 as in {@link String#trim()}</li>
  103.  * </ul>
  104.  *
  105.  * <p>{@link StringUtils} handles {@code null} input Strings quietly.
  106.  * That is to say that a {@code null} input will return {@code null}.
  107.  * Where a {@code boolean} or {@code int} is being returned
  108.  * details vary by method.</p>
  109.  *
  110.  * <p>A side effect of the {@code null} handling is that a
  111.  * {@link NullPointerException} should be considered a bug in
  112.  * {@link StringUtils}.</p>
  113.  *
  114.  * <p>Methods in this class include sample code in their Javadoc comments to explain their operation.
  115.  * The symbol {@code *} is used to indicate any input including {@code null}.</p>
  116.  *
  117.  * <p>#ThreadSafe#</p>
  118.  * @see String
  119.  * @since 1.0
  120.  */
  121. //@Immutable
  122. public class StringUtils {

  123.     // Performance testing notes (JDK 1.4, Jul03, scolebourne)
  124.     // Whitespace:
  125.     // Character.isWhitespace() is faster than WHITESPACE.indexOf()
  126.     // where WHITESPACE is a string of all whitespace characters
  127.     //
  128.     // Character access:
  129.     // String.charAt(n) versus toCharArray(), then array[n]
  130.     // String.charAt(n) is about 15% worse for a 10K string
  131.     // They are about equal for a length 50 string
  132.     // String.charAt(n) is about 4 times better for a length 3 string
  133.     // String.charAt(n) is best bet overall
  134.     //
  135.     // Append:
  136.     // String.concat about twice as fast as StringBuffer.append
  137.     // (not sure who tested this)

  138.     /**
  139.      * This is a 3 character version of an ellipsis. There is a Unicode character for a HORIZONTAL ELLIPSIS, U+2026 … this isn't it.
  140.      */
  141.     private static final String ELLIPSIS3 = "...";

  142.     /**
  143.      * A String for a space character.
  144.      *
  145.      * @since 3.2
  146.      */
  147.     public static final String SPACE = " ";

  148.     /**
  149.      * The empty String {@code ""}.
  150.      * @since 2.0
  151.      */
  152.     public static final String EMPTY = "";

  153.     /**
  154.      * The null String {@code null}. Package-private only.
  155.      */
  156.     static final String NULL = null;

  157.     /**
  158.      * A String for linefeed LF ("\n").
  159.      *
  160.      * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
  161.      *      for Character and String Literals</a>
  162.      * @since 3.2
  163.      */
  164.     public static final String LF = "\n";

  165.     /**
  166.      * A String for carriage return CR ("\r").
  167.      *
  168.      * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
  169.      *      for Character and String Literals</a>
  170.      * @since 3.2
  171.      */
  172.     public static final String CR = "\r";

  173.     /**
  174.      * Represents a failed index search.
  175.      * @since 2.1
  176.      */
  177.     public static final int INDEX_NOT_FOUND = -1;

  178.     /**
  179.      * The maximum size to which the padding constant(s) can expand.
  180.      */
  181.     private static final int PAD_LIMIT = 8192;

  182.     /**
  183.      * The default maximum depth at which recursive replacement will continue until no further search replacements are possible.
  184.      */
  185.     private static final int DEFAULT_TTL = 5;

  186.     /**
  187.      * Pattern used in {@link #stripAccents(String)}.
  188.      */
  189.     private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$

  190.     /**
  191.      * Abbreviates a String using ellipses. This will turn
  192.      * "Now is the time for all good men" into "Now is the time for..."
  193.      *
  194.      * <p>Specifically:</p>
  195.      * <ul>
  196.      *   <li>If the number of characters in {@code str} is less than or equal to
  197.      *       {@code maxWidth}, return {@code str}.</li>
  198.      *   <li>Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.</li>
  199.      *   <li>If {@code maxWidth} is less than {@code 4}, throw an
  200.      *       {@link IllegalArgumentException}.</li>
  201.      *   <li>In no case will it return a String of length greater than
  202.      *       {@code maxWidth}.</li>
  203.      * </ul>
  204.      *
  205.      * <pre>
  206.      * StringUtils.abbreviate(null, *)      = null
  207.      * StringUtils.abbreviate("", 4)        = ""
  208.      * StringUtils.abbreviate("abcdefg", 6) = "abc..."
  209.      * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
  210.      * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
  211.      * StringUtils.abbreviate("abcdefg", 4) = "a..."
  212.      * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
  213.      * </pre>
  214.      *
  215.      * @param str  the String to check, may be null
  216.      * @param maxWidth  maximum length of result String, must be at least 4
  217.      * @return abbreviated String, {@code null} if null String input
  218.      * @throws IllegalArgumentException if the width is too small
  219.      * @since 2.0
  220.      */
  221.     public static String abbreviate(final String str, final int maxWidth) {
  222.         return abbreviate(str, ELLIPSIS3, 0, maxWidth);
  223.     }

  224.     /**
  225.      * Abbreviates a String using ellipses. This will turn
  226.      * "Now is the time for all good men" into "...is the time for..."
  227.      *
  228.      * <p>Works like {@code abbreviate(String, int)}, but allows you to specify
  229.      * a "left edge" offset.  Note that this left edge is not necessarily going to
  230.      * be the leftmost character in the result, or the first character following the
  231.      * ellipses, but it will appear somewhere in the result.
  232.      *
  233.      * <p>In no case will it return a String of length greater than
  234.      * {@code maxWidth}.</p>
  235.      *
  236.      * <pre>
  237.      * StringUtils.abbreviate(null, *, *)                = null
  238.      * StringUtils.abbreviate("", 0, 4)                  = ""
  239.      * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
  240.      * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
  241.      * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
  242.      * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
  243.      * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
  244.      * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
  245.      * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
  246.      * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
  247.      * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
  248.      * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
  249.      * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
  250.      * </pre>
  251.      *
  252.      * @param str  the String to check, may be null
  253.      * @param offset  left edge of source String
  254.      * @param maxWidth  maximum length of result String, must be at least 4
  255.      * @return abbreviated String, {@code null} if null String input
  256.      * @throws IllegalArgumentException if the width is too small
  257.      * @since 2.0
  258.      */
  259.     public static String abbreviate(final String str, final int offset, final int maxWidth) {
  260.         return abbreviate(str, ELLIPSIS3, offset, maxWidth);
  261.     }

  262.     /**
  263.      * Abbreviates a String using another given String as replacement marker. This will turn
  264.      * "Now is the time for all good men" into "Now is the time for..." if "..." was defined
  265.      * as the replacement marker.
  266.      *
  267.      * <p>Specifically:</p>
  268.      * <ul>
  269.      *   <li>If the number of characters in {@code str} is less than or equal to
  270.      *       {@code maxWidth}, return {@code str}.</li>
  271.      *   <li>Else abbreviate it to {@code (substring(str, 0, max-abbrevMarker.length) + abbrevMarker)}.</li>
  272.      *   <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an
  273.      *       {@link IllegalArgumentException}.</li>
  274.      *   <li>In no case will it return a String of length greater than
  275.      *       {@code maxWidth}.</li>
  276.      * </ul>
  277.      *
  278.      * <pre>
  279.      * StringUtils.abbreviate(null, "...", *)      = null
  280.      * StringUtils.abbreviate("abcdefg", null, *)  = "abcdefg"
  281.      * StringUtils.abbreviate("", "...", 4)        = ""
  282.      * StringUtils.abbreviate("abcdefg", ".", 5)   = "abcd."
  283.      * StringUtils.abbreviate("abcdefg", ".", 7)   = "abcdefg"
  284.      * StringUtils.abbreviate("abcdefg", ".", 8)   = "abcdefg"
  285.      * StringUtils.abbreviate("abcdefg", "..", 4)  = "ab.."
  286.      * StringUtils.abbreviate("abcdefg", "..", 3)  = "a.."
  287.      * StringUtils.abbreviate("abcdefg", "..", 2)  = IllegalArgumentException
  288.      * StringUtils.abbreviate("abcdefg", "...", 3) = IllegalArgumentException
  289.      * </pre>
  290.      *
  291.      * @param str  the String to check, may be null
  292.      * @param abbrevMarker  the String used as replacement marker
  293.      * @param maxWidth  maximum length of result String, must be at least {@code abbrevMarker.length + 1}
  294.      * @return abbreviated String, {@code null} if null String input
  295.      * @throws IllegalArgumentException if the width is too small
  296.      * @since 3.6
  297.      */
  298.     public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) {
  299.         return abbreviate(str, abbrevMarker, 0, maxWidth);
  300.     }
  301.     /**
  302.      * Abbreviates a String using a given replacement marker. This will turn
  303.      * "Now is the time for all good men" into "...is the time for..." if "..." was defined
  304.      * as the replacement marker.
  305.      *
  306.      * <p>Works like {@code abbreviate(String, String, int)}, but allows you to specify
  307.      * a "left edge" offset.  Note that this left edge is not necessarily going to
  308.      * be the leftmost character in the result, or the first character following the
  309.      * replacement marker, but it will appear somewhere in the result.
  310.      *
  311.      * <p>In no case will it return a String of length greater than {@code maxWidth}.</p>
  312.      *
  313.      * <pre>
  314.      * StringUtils.abbreviate(null, null, *, *)                 = null
  315.      * StringUtils.abbreviate("abcdefghijklmno", null, *, *)    = "abcdefghijklmno"
  316.      * StringUtils.abbreviate("", "...", 0, 4)                  = ""
  317.      * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---"
  318.      * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10)    = "abcdefghi,"
  319.      * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10)    = "abcdefghi,"
  320.      * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10)    = "abcdefghi,"
  321.      * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10)   = "::efghij::"
  322.      * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10)  = "...ghij..."
  323.      * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10)    = "*ghijklmno"
  324.      * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10)   = "'ghijklmno"
  325.      * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10)   = "!ghijklmno"
  326.      * StringUtils.abbreviate("abcdefghij", "abra", 0, 4)       = IllegalArgumentException
  327.      * StringUtils.abbreviate("abcdefghij", "...", 5, 6)        = IllegalArgumentException
  328.      * </pre>
  329.      *
  330.      * @param str  the String to check, may be null
  331.      * @param abbrevMarker  the String used as replacement marker
  332.      * @param offset  left edge of source String
  333.      * @param maxWidth  maximum length of result String, must be at least 4
  334.      * @return abbreviated String, {@code null} if null String input
  335.      * @throws IllegalArgumentException if the width is too small
  336.      * @since 3.6
  337.      */
  338.     public static String abbreviate(final String str, final String abbrevMarker, int offset, final int maxWidth) {
  339.         if (isNotEmpty(str) && EMPTY.equals(abbrevMarker) && maxWidth > 0) {
  340.             return substring(str, 0, maxWidth);
  341.         }
  342.         if (isAnyEmpty(str, abbrevMarker)) {
  343.             return str;
  344.         }
  345.         final int abbrevMarkerLength = abbrevMarker.length();
  346.         final int minAbbrevWidth = abbrevMarkerLength + 1;
  347.         final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1;

  348.         if (maxWidth < minAbbrevWidth) {
  349.             throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth));
  350.         }
  351.         final int strLen = str.length();
  352.         if (strLen <= maxWidth) {
  353.             return str;
  354.         }
  355.         if (offset > strLen) {
  356.             offset = strLen;
  357.         }
  358.         if (strLen - offset < maxWidth - abbrevMarkerLength) {
  359.             offset = strLen - (maxWidth - abbrevMarkerLength);
  360.         }
  361.         if (offset <= abbrevMarkerLength + 1) {
  362.             return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker;
  363.         }
  364.         if (maxWidth < minAbbrevWidthOffset) {
  365.             throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset));
  366.         }
  367.         if (offset + maxWidth - abbrevMarkerLength < strLen) {
  368.             return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength);
  369.         }
  370.         return abbrevMarker + str.substring(strLen - (maxWidth - abbrevMarkerLength));
  371.     }

  372.     /**
  373.      * Abbreviates a String to the length passed, replacing the middle characters with the supplied
  374.      * replacement String.
  375.      *
  376.      * <p>This abbreviation only occurs if the following criteria is met:</p>
  377.      * <ul>
  378.      * <li>Neither the String for abbreviation nor the replacement String are null or empty </li>
  379.      * <li>The length to truncate to is less than the length of the supplied String</li>
  380.      * <li>The length to truncate to is greater than 0</li>
  381.      * <li>The abbreviated String will have enough room for the length supplied replacement String
  382.      * and the first and last characters of the supplied String for abbreviation</li>
  383.      * </ul>
  384.      * <p>Otherwise, the returned String will be the same as the supplied String for abbreviation.
  385.      * </p>
  386.      *
  387.      * <pre>
  388.      * StringUtils.abbreviateMiddle(null, null, 0)    = null
  389.      * StringUtils.abbreviateMiddle("abc", null, 0)   = "abc"
  390.      * StringUtils.abbreviateMiddle("abc", ".", 0)    = "abc"
  391.      * StringUtils.abbreviateMiddle("abc", ".", 3)    = "abc"
  392.      * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f"
  393.      * </pre>
  394.      *
  395.      * @param str  the String to abbreviate, may be null
  396.      * @param middle the String to replace the middle characters with, may be null
  397.      * @param length the length to abbreviate {@code str} to.
  398.      * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
  399.      * @since 2.5
  400.      */
  401.     public static String abbreviateMiddle(final String str, final String middle, final int length) {
  402.         if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length() + 2) {
  403.             return str;
  404.         }
  405.         final int targetSting = length - middle.length();
  406.         final int startOffset = targetSting / 2 + targetSting % 2;
  407.         final int endOffset = str.length() - targetSting / 2;
  408.         return str.substring(0, startOffset) + middle + str.substring(endOffset);
  409.     }

  410.     /**
  411.      * Appends the suffix to the end of the string if the string does not already end with any of the suffixes.
  412.      *
  413.      * <pre>
  414.      * StringUtils.appendIfMissing(null, null)      = null
  415.      * StringUtils.appendIfMissing("abc", null)     = "abc"
  416.      * StringUtils.appendIfMissing("", "xyz"        = "xyz"
  417.      * StringUtils.appendIfMissing("abc", "xyz")    = "abcxyz"
  418.      * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz"
  419.      * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz"
  420.      * </pre>
  421.      * <p>
  422.      * With additional suffixes,
  423.      * </p>
  424.      *
  425.      * <pre>
  426.      * StringUtils.appendIfMissing(null, null, null)       = null
  427.      * StringUtils.appendIfMissing("abc", null, null)      = "abc"
  428.      * StringUtils.appendIfMissing("", "xyz", null)        = "xyz"
  429.      * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
  430.      * StringUtils.appendIfMissing("abc", "xyz", "")       = "abc"
  431.      * StringUtils.appendIfMissing("abc", "xyz", "mno")    = "abcxyz"
  432.      * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz"
  433.      * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno"
  434.      * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz"
  435.      * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz"
  436.      * </pre>
  437.      *
  438.      * @param str      The string.
  439.      * @param suffix   The suffix to append to the end of the string.
  440.      * @param suffixes Additional suffixes that are valid terminators.
  441.      * @return A new String if suffix was appended, the same string otherwise.
  442.      * @since 3.2
  443.      * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CS.appendIfMissing(String, CharSequence, CharSequence...)}
  444.      */
  445.     @Deprecated
  446.     public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) {
  447.         return Strings.CS.appendIfMissing(str, suffix, suffixes);
  448.     }

  449.     /**
  450.      * Appends the suffix to the end of the string if the string does not
  451.      * already end, case-insensitive, with any of the suffixes.
  452.      *
  453.      * <pre>
  454.      * StringUtils.appendIfMissingIgnoreCase(null, null)      = null
  455.      * StringUtils.appendIfMissingIgnoreCase("abc", null)     = "abc"
  456.      * StringUtils.appendIfMissingIgnoreCase("", "xyz")       = "xyz"
  457.      * StringUtils.appendIfMissingIgnoreCase("abc", "xyz")    = "abcxyz"
  458.      * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz"
  459.      * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ"
  460.      * </pre>
  461.      * <p>With additional suffixes,</p>
  462.      * <pre>
  463.      * StringUtils.appendIfMissingIgnoreCase(null, null, null)       = null
  464.      * StringUtils.appendIfMissingIgnoreCase("abc", null, null)      = "abc"
  465.      * StringUtils.appendIfMissingIgnoreCase("", "xyz", null)        = "xyz"
  466.      * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
  467.      * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "")       = "abc"
  468.      * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno")    = "abcxyz"
  469.      * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz"
  470.      * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno"
  471.      * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ"
  472.      * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO"
  473.      * </pre>
  474.      *
  475.      * @param str The string.
  476.      * @param suffix The suffix to append to the end of the string.
  477.      * @param suffixes Additional suffixes that are valid terminators.
  478.      * @return A new String if suffix was appended, the same string otherwise.
  479.      * @since 3.2
  480.      * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CI.appendIfMissing(String, CharSequence, CharSequence...)}
  481.      */
  482.     @Deprecated
  483.     public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) {
  484.         return Strings.CI.appendIfMissing(str, suffix, suffixes);
  485.     }

  486.     /**
  487.      * Capitalizes a String changing the first character to title case as
  488.      * per {@link Character#toTitleCase(int)}. No other characters are changed.
  489.      *
  490.      * <p>For a word based algorithm, see {@link org.apache.commons.text.WordUtils#capitalize(String)}.
  491.      * A {@code null} input String returns {@code null}.</p>
  492.      *
  493.      * <pre>
  494.      * StringUtils.capitalize(null)    = null
  495.      * StringUtils.capitalize("")      = ""
  496.      * StringUtils.capitalize("cat")   = "Cat"
  497.      * StringUtils.capitalize("cAt")   = "CAt"
  498.      * StringUtils.capitalize("'cat'") = "'cat'"
  499.      * </pre>
  500.      *
  501.      * @param str the String to capitalize, may be null
  502.      * @return the capitalized String, {@code null} if null String input
  503.      * @see org.apache.commons.text.WordUtils#capitalize(String)
  504.      * @see #uncapitalize(String)
  505.      * @since 2.0
  506.      */
  507.     public static String capitalize(final String str) {
  508.         if (isEmpty(str)) {
  509.             return str;
  510.         }
  511.         final int firstCodepoint = str.codePointAt(0);
  512.         final int newCodePoint = Character.toTitleCase(firstCodepoint);
  513.         if (firstCodepoint == newCodePoint) {
  514.             // already capitalized
  515.             return str;
  516.         }
  517.         final int[] newCodePoints = str.codePoints().toArray();
  518.         newCodePoints[0] = newCodePoint; // copy the first code point
  519.         return new String(newCodePoints, 0, newCodePoints.length);
  520.     }

  521.     /**
  522.      * Centers a String in a larger String of size {@code size}
  523.      * using the space character (' ').
  524.      *
  525.      * <p>If the size is less than the String length, the original String is returned.
  526.      * A {@code null} String returns {@code null}.
  527.      * A negative size is treated as zero.</p>
  528.      *
  529.      * <p>Equivalent to {@code center(str, size, " ")}.</p>
  530.      *
  531.      * <pre>
  532.      * StringUtils.center(null, *)   = null
  533.      * StringUtils.center("", 4)     = "    "
  534.      * StringUtils.center("ab", -1)  = "ab"
  535.      * StringUtils.center("ab", 4)   = " ab "
  536.      * StringUtils.center("abcd", 2) = "abcd"
  537.      * StringUtils.center("a", 4)    = " a  "
  538.      * </pre>
  539.      *
  540.      * @param str  the String to center, may be null
  541.      * @param size  the int size of new String, negative treated as zero
  542.      * @return centered String, {@code null} if null String input
  543.      */
  544.     public static String center(final String str, final int size) {
  545.         return center(str, size, ' ');
  546.     }

  547.     /**
  548.      * Centers a String in a larger String of size {@code size}.
  549.      * Uses a supplied character as the value to pad the String with.
  550.      *
  551.      * <p>If the size is less than the String length, the String is returned.
  552.      * A {@code null} String returns {@code null}.
  553.      * A negative size is treated as zero.</p>
  554.      *
  555.      * <pre>
  556.      * StringUtils.center(null, *, *)     = null
  557.      * StringUtils.center("", 4, ' ')     = "    "
  558.      * StringUtils.center("ab", -1, ' ')  = "ab"
  559.      * StringUtils.center("ab", 4, ' ')   = " ab "
  560.      * StringUtils.center("abcd", 2, ' ') = "abcd"
  561.      * StringUtils.center("a", 4, ' ')    = " a  "
  562.      * StringUtils.center("a", 4, 'y')    = "yayy"
  563.      * </pre>
  564.      *
  565.      * @param str  the String to center, may be null
  566.      * @param size  the int size of new String, negative treated as zero
  567.      * @param padChar  the character to pad the new String with
  568.      * @return centered String, {@code null} if null String input
  569.      * @since 2.0
  570.      */
  571.     public static String center(String str, final int size, final char padChar) {
  572.         if (str == null || size <= 0) {
  573.             return str;
  574.         }
  575.         final int strLen = str.length();
  576.         final int pads = size - strLen;
  577.         if (pads <= 0) {
  578.             return str;
  579.         }
  580.         str = leftPad(str, strLen + pads / 2, padChar);
  581.         return rightPad(str, size, padChar);
  582.     }

  583.     /**
  584.      * Centers a String in a larger String of size {@code size}.
  585.      * Uses a supplied String as the value to pad the String with.
  586.      *
  587.      * <p>If the size is less than the String length, the String is returned.
  588.      * A {@code null} String returns {@code null}.
  589.      * A negative size is treated as zero.</p>
  590.      *
  591.      * <pre>
  592.      * StringUtils.center(null, *, *)     = null
  593.      * StringUtils.center("", 4, " ")     = "    "
  594.      * StringUtils.center("ab", -1, " ")  = "ab"
  595.      * StringUtils.center("ab", 4, " ")   = " ab "
  596.      * StringUtils.center("abcd", 2, " ") = "abcd"
  597.      * StringUtils.center("a", 4, " ")    = " a  "
  598.      * StringUtils.center("a", 4, "yz")   = "yayz"
  599.      * StringUtils.center("abc", 7, null) = "  abc  "
  600.      * StringUtils.center("abc", 7, "")   = "  abc  "
  601.      * </pre>
  602.      *
  603.      * @param str  the String to center, may be null
  604.      * @param size  the int size of new String, negative treated as zero
  605.      * @param padStr  the String to pad the new String with, must not be null or empty
  606.      * @return centered String, {@code null} if null String input
  607.      * @throws IllegalArgumentException if padStr is {@code null} or empty
  608.      */
  609.     public static String center(String str, final int size, String padStr) {
  610.         if (str == null || size <= 0) {
  611.             return str;
  612.         }
  613.         if (isEmpty(padStr)) {
  614.             padStr = SPACE;
  615.         }
  616.         final int strLen = str.length();
  617.         final int pads = size - strLen;
  618.         if (pads <= 0) {
  619.             return str;
  620.         }
  621.         str = leftPad(str, strLen + pads / 2, padStr);
  622.         return rightPad(str, size, padStr);
  623.     }

  624.     /**
  625.      * Removes one newline from end of a String if it's there,
  626.      * otherwise leave it alone.  A newline is &quot;{@code \n}&quot;,
  627.      * &quot;{@code \r}&quot;, or &quot;{@code \r\n}&quot;.
  628.      *
  629.      * <p>NOTE: This method changed in 2.0.
  630.      * It now more closely matches Perl chomp.</p>
  631.      *
  632.      * <pre>
  633.      * StringUtils.chomp(null)          = null
  634.      * StringUtils.chomp("")            = ""
  635.      * StringUtils.chomp("abc \r")      = "abc "
  636.      * StringUtils.chomp("abc\n")       = "abc"
  637.      * StringUtils.chomp("abc\r\n")     = "abc"
  638.      * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
  639.      * StringUtils.chomp("abc\n\r")     = "abc\n"
  640.      * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
  641.      * StringUtils.chomp("\r")          = ""
  642.      * StringUtils.chomp("\n")          = ""
  643.      * StringUtils.chomp("\r\n")        = ""
  644.      * </pre>
  645.      *
  646.      * @param str  the String to chomp a newline from, may be null
  647.      * @return String without newline, {@code null} if null String input
  648.      */
  649.     public static String chomp(final String str) {
  650.         if (isEmpty(str)) {
  651.             return str;
  652.         }

  653.         if (str.length() == 1) {
  654.             final char ch = str.charAt(0);
  655.             if (ch == CharUtils.CR || ch == CharUtils.LF) {
  656.                 return EMPTY;
  657.             }
  658.             return str;
  659.         }

  660.         int lastIdx = str.length() - 1;
  661.         final char last = str.charAt(lastIdx);

  662.         if (last == CharUtils.LF) {
  663.             if (str.charAt(lastIdx - 1) == CharUtils.CR) {
  664.                 lastIdx--;
  665.             }
  666.         } else if (last != CharUtils.CR) {
  667.             lastIdx++;
  668.         }
  669.         return str.substring(0, lastIdx);
  670.     }

  671.     /**
  672.      * Removes {@code separator} from the end of
  673.      * {@code str} if it's there, otherwise leave it alone.
  674.      *
  675.      * <p>NOTE: This method changed in version 2.0.
  676.      * It now more closely matches Perl chomp.
  677.      * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
  678.      * This method uses {@link String#endsWith(String)}.</p>
  679.      *
  680.      * <pre>
  681.      * StringUtils.chomp(null, *)         = null
  682.      * StringUtils.chomp("", *)           = ""
  683.      * StringUtils.chomp("foobar", "bar") = "foo"
  684.      * StringUtils.chomp("foobar", "baz") = "foobar"
  685.      * StringUtils.chomp("foo", "foo")    = ""
  686.      * StringUtils.chomp("foo ", "foo")   = "foo "
  687.      * StringUtils.chomp(" foo", "foo")   = " "
  688.      * StringUtils.chomp("foo", "foooo")  = "foo"
  689.      * StringUtils.chomp("foo", "")       = "foo"
  690.      * StringUtils.chomp("foo", null)     = "foo"
  691.      * </pre>
  692.      *
  693.      * @param str  the String to chomp from, may be null
  694.      * @param separator  separator String, may be null
  695.      * @return String without trailing separator, {@code null} if null String input
  696.      * @deprecated This feature will be removed in Lang 4, use {@link StringUtils#removeEnd(String, String)} instead
  697.      */
  698.     @Deprecated
  699.     public static String chomp(final String str, final String separator) {
  700.         return Strings.CS.removeEnd(str, separator);
  701.     }

  702.     /**
  703.      * Remove the last character from a String.
  704.      *
  705.      * <p>If the String ends in {@code \r\n}, then remove both
  706.      * of them.</p>
  707.      *
  708.      * <pre>
  709.      * StringUtils.chop(null)          = null
  710.      * StringUtils.chop("")            = ""
  711.      * StringUtils.chop("abc \r")      = "abc "
  712.      * StringUtils.chop("abc\n")       = "abc"
  713.      * StringUtils.chop("abc\r\n")     = "abc"
  714.      * StringUtils.chop("abc")         = "ab"
  715.      * StringUtils.chop("abc\nabc")    = "abc\nab"
  716.      * StringUtils.chop("a")           = ""
  717.      * StringUtils.chop("\r")          = ""
  718.      * StringUtils.chop("\n")          = ""
  719.      * StringUtils.chop("\r\n")        = ""
  720.      * </pre>
  721.      *
  722.      * @param str  the String to chop last character from, may be null
  723.      * @return String without last character, {@code null} if null String input
  724.      */
  725.     public static String chop(final String str) {
  726.         if (str == null) {
  727.             return null;
  728.         }
  729.         final int strLen = str.length();
  730.         if (strLen < 2) {
  731.             return EMPTY;
  732.         }
  733.         final int lastIdx = strLen - 1;
  734.         final String ret = str.substring(0, lastIdx);
  735.         final char last = str.charAt(lastIdx);
  736.         if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
  737.             return ret.substring(0, lastIdx - 1);
  738.         }
  739.         return ret;
  740.     }

  741.     /**
  742.      * Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
  743.      * <ul>
  744.      *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
  745.      *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
  746.      *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
  747.      * </ul>
  748.      *
  749.      * <p>This is a {@code null} safe version of :</p>
  750.      * <blockquote><pre>str1.compareTo(str2)</pre></blockquote>
  751.      *
  752.      * <p>{@code null} value is considered less than non-{@code null} value.
  753.      * Two {@code null} references are considered equal.</p>
  754.      *
  755.      * <pre>{@code
  756.      * StringUtils.compare(null, null)   = 0
  757.      * StringUtils.compare(null , "a")   < 0
  758.      * StringUtils.compare("a", null)   > 0
  759.      * StringUtils.compare("abc", "abc") = 0
  760.      * StringUtils.compare("a", "b")     < 0
  761.      * StringUtils.compare("b", "a")     > 0
  762.      * StringUtils.compare("a", "B")     > 0
  763.      * StringUtils.compare("ab", "abc")  < 0
  764.      * }</pre>
  765.      *
  766.      * @see #compare(String, String, boolean)
  767.      * @see String#compareTo(String)
  768.      * @param str1  the String to compare from
  769.      * @param str2  the String to compare to
  770.      * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal or greater than {@code str2}
  771.      * @since 3.5
  772.      * @deprecated Use {@link Strings#compare(String, String) Strings.CS.compare(String, String)}
  773.      */
  774.     @Deprecated
  775.     public static int compare(final String str1, final String str2) {
  776.         return Strings.CS.compare(str1, str2);
  777.     }

  778.     /**
  779.      * Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
  780.      * <ul>
  781.      *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
  782.      *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
  783.      *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
  784.      * </ul>
  785.      *
  786.      * <p>This is a {@code null} safe version of :</p>
  787.      * <blockquote><pre>str1.compareTo(str2)</pre></blockquote>
  788.      *
  789.      * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter.
  790.      * Two {@code null} references are considered equal.</p>
  791.      *
  792.      * <pre>{@code
  793.      * StringUtils.compare(null, null, *)     = 0
  794.      * StringUtils.compare(null , "a", true)  < 0
  795.      * StringUtils.compare(null , "a", false) > 0
  796.      * StringUtils.compare("a", null, true)   > 0
  797.      * StringUtils.compare("a", null, false)  < 0
  798.      * StringUtils.compare("abc", "abc", *)   = 0
  799.      * StringUtils.compare("a", "b", *)       < 0
  800.      * StringUtils.compare("b", "a", *)       > 0
  801.      * StringUtils.compare("a", "B", *)       > 0
  802.      * StringUtils.compare("ab", "abc", *)    < 0
  803.      * }</pre>
  804.      *
  805.      * @see String#compareTo(String)
  806.      * @param str1  the String to compare from
  807.      * @param str2  the String to compare to
  808.      * @param nullIsLess  whether consider {@code null} value less than non-{@code null} value
  809.      * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2}
  810.      * @since 3.5
  811.      */
  812.     public static int compare(final String str1, final String str2, final boolean nullIsLess) {
  813.         if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null
  814.             return 0;
  815.         }
  816.         if (str1 == null) {
  817.             return nullIsLess ? -1 : 1;
  818.         }
  819.         if (str2 == null) {
  820.             return nullIsLess ? 1 : - 1;
  821.         }
  822.         return str1.compareTo(str2);
  823.     }

  824.     /**
  825.      * Compare two Strings lexicographically, ignoring case differences,
  826.      * as per {@link String#compareToIgnoreCase(String)}, returning :
  827.      * <ul>
  828.      *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
  829.      *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
  830.      *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
  831.      * </ul>
  832.      *
  833.      * <p>This is a {@code null} safe version of :</p>
  834.      * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote>
  835.      *
  836.      * <p>{@code null} value is considered less than non-{@code null} value.
  837.      * Two {@code null} references are considered equal.
  838.      * Comparison is case insensitive.</p>
  839.      *
  840.      * <pre>{@code
  841.      * StringUtils.compareIgnoreCase(null, null)   = 0
  842.      * StringUtils.compareIgnoreCase(null , "a")   < 0
  843.      * StringUtils.compareIgnoreCase("a", null)    > 0
  844.      * StringUtils.compareIgnoreCase("abc", "abc") = 0
  845.      * StringUtils.compareIgnoreCase("abc", "ABC") = 0
  846.      * StringUtils.compareIgnoreCase("a", "b")     < 0
  847.      * StringUtils.compareIgnoreCase("b", "a")     > 0
  848.      * StringUtils.compareIgnoreCase("a", "B")     < 0
  849.      * StringUtils.compareIgnoreCase("A", "b")     < 0
  850.      * StringUtils.compareIgnoreCase("ab", "ABC")  < 0
  851.      * }</pre>
  852.      *
  853.      * @see #compareIgnoreCase(String, String, boolean)
  854.      * @see String#compareToIgnoreCase(String)
  855.      * @param str1  the String to compare from
  856.      * @param str2  the String to compare to
  857.      * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
  858.      *          ignoring case differences.
  859.      * @since 3.5
  860.      * @deprecated Use {@link Strings#compare(String, String) Strings.CI.compare(String, String)}
  861.      */
  862.     @Deprecated
  863.     public static int compareIgnoreCase(final String str1, final String str2) {
  864.         return Strings.CI.compare(str1, str2);
  865.     }

  866.     /**
  867.      * Compare two Strings lexicographically, ignoring case differences,
  868.      * as per {@link String#compareToIgnoreCase(String)}, returning :
  869.      * <ul>
  870.      *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
  871.      *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
  872.      *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
  873.      * </ul>
  874.      *
  875.      * <p>This is a {@code null} safe version of :</p>
  876.      * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote>
  877.      *
  878.      * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter.
  879.      * Two {@code null} references are considered equal.
  880.      * Comparison is case insensitive.</p>
  881.      *
  882.      * <pre>{@code
  883.      * StringUtils.compareIgnoreCase(null, null, *)     = 0
  884.      * StringUtils.compareIgnoreCase(null , "a", true)  < 0
  885.      * StringUtils.compareIgnoreCase(null , "a", false) > 0
  886.      * StringUtils.compareIgnoreCase("a", null, true)   > 0
  887.      * StringUtils.compareIgnoreCase("a", null, false)  < 0
  888.      * StringUtils.compareIgnoreCase("abc", "abc", *)   = 0
  889.      * StringUtils.compareIgnoreCase("abc", "ABC", *)   = 0
  890.      * StringUtils.compareIgnoreCase("a", "b", *)       < 0
  891.      * StringUtils.compareIgnoreCase("b", "a", *)       > 0
  892.      * StringUtils.compareIgnoreCase("a", "B", *)       < 0
  893.      * StringUtils.compareIgnoreCase("A", "b", *)       < 0
  894.      * StringUtils.compareIgnoreCase("ab", "abc", *)    < 0
  895.      * }</pre>
  896.      *
  897.      * @see String#compareToIgnoreCase(String)
  898.      * @param str1  the String to compare from
  899.      * @param str2  the String to compare to
  900.      * @param nullIsLess  whether consider {@code null} value less than non-{@code null} value
  901.      * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
  902.      *          ignoring case differences.
  903.      * @since 3.5
  904.      */
  905.     public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) {
  906.         if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null
  907.             return 0;
  908.         }
  909.         if (str1 == null) {
  910.             return nullIsLess ? -1 : 1;
  911.         }
  912.         if (str2 == null) {
  913.             return nullIsLess ? 1 : - 1;
  914.         }
  915.         return str1.compareToIgnoreCase(str2);
  916.     }

  917.     /**
  918.      * Tests if CharSequence contains a search CharSequence, handling {@code null}.
  919.      * This method uses {@link String#indexOf(String)} if possible.
  920.      *
  921.      * <p>A {@code null} CharSequence will return {@code false}.</p>
  922.      *
  923.      * <pre>
  924.      * StringUtils.contains(null, *)     = false
  925.      * StringUtils.contains(*, null)     = false
  926.      * StringUtils.contains("", "")      = true
  927.      * StringUtils.contains("abc", "")   = true
  928.      * StringUtils.contains("abc", "a")  = true
  929.      * StringUtils.contains("abc", "z")  = false
  930.      * </pre>
  931.      *
  932.      * @param seq  the CharSequence to check, may be null
  933.      * @param searchSeq  the CharSequence to find, may be null
  934.      * @return true if the CharSequence contains the search CharSequence,
  935.      *  false if not or {@code null} string input
  936.      * @since 2.0
  937.      * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence)
  938.      * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CS.contains(CharSequence, CharSequence)}
  939.      */
  940.     @Deprecated
  941.     public static boolean contains(final CharSequence seq, final CharSequence searchSeq) {
  942.         return Strings.CS.contains(seq, searchSeq);
  943.     }

  944.     /**
  945.      * Tests if CharSequence contains a search character, handling {@code null}.
  946.      * This method uses {@link String#indexOf(int)} if possible.
  947.      *
  948.      * <p>A {@code null} or empty ("") CharSequence will return {@code false}.</p>
  949.      *
  950.      * <pre>
  951.      * StringUtils.contains(null, *)    = false
  952.      * StringUtils.contains("", *)      = false
  953.      * StringUtils.contains("abc", 'a') = true
  954.      * StringUtils.contains("abc", 'z') = false
  955.      * </pre>
  956.      *
  957.      * @param seq  the CharSequence to check, may be null
  958.      * @param searchChar  the character to find
  959.      * @return true if the CharSequence contains the search character,
  960.      *  false if not or {@code null} string input
  961.      * @since 2.0
  962.      * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int)
  963.      */
  964.     public static boolean contains(final CharSequence seq, final int searchChar) {
  965.         if (isEmpty(seq)) {
  966.             return false;
  967.         }
  968.         return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0;
  969.     }

  970.     /**
  971.      * Tests if the CharSequence contains any character in the given
  972.      * set of characters.
  973.      *
  974.      * <p>A {@code null} CharSequence will return {@code false}.
  975.      * A {@code null} or zero length search array will return {@code false}.</p>
  976.      *
  977.      * <pre>
  978.      * StringUtils.containsAny(null, *)                  = false
  979.      * StringUtils.containsAny("", *)                    = false
  980.      * StringUtils.containsAny(*, null)                  = false
  981.      * StringUtils.containsAny(*, [])                    = false
  982.      * StringUtils.containsAny("zzabyycdxx", ['z', 'a']) = true
  983.      * StringUtils.containsAny("zzabyycdxx", ['b', 'y']) = true
  984.      * StringUtils.containsAny("zzabyycdxx", ['z', 'y']) = true
  985.      * StringUtils.containsAny("aba", ['z'])             = false
  986.      * </pre>
  987.      *
  988.      * @param cs  the CharSequence to check, may be null
  989.      * @param searchChars  the chars to search for, may be null
  990.      * @return the {@code true} if any of the chars are found,
  991.      * {@code false} if no match or null input
  992.      * @since 2.4
  993.      * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...)
  994.      */
  995.     public static boolean containsAny(final CharSequence cs, final char... searchChars) {
  996.         if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
  997.             return false;
  998.         }
  999.         final int csLength = cs.length();
  1000.         final int searchLength = searchChars.length;
  1001.         final int csLast = csLength - 1;
  1002.         final int searchLast = searchLength - 1;
  1003.         for (int i = 0; i < csLength; i++) {
  1004.             final char ch = cs.charAt(i);
  1005.             for (int j = 0; j < searchLength; j++) {
  1006.                 if (searchChars[j] == ch) {
  1007.                     if (!Character.isHighSurrogate(ch) || j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
  1008.                         return true;
  1009.                     }
  1010.                 }
  1011.             }
  1012.         }
  1013.         return false;
  1014.     }

  1015.     /**
  1016.      * Tests if the CharSequence contains any character in the given set of characters.
  1017.      *
  1018.      * <p>
  1019.      * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return
  1020.      * {@code false}.
  1021.      * </p>
  1022.      *
  1023.      * <pre>
  1024.      * StringUtils.containsAny(null, *)               = false
  1025.      * StringUtils.containsAny("", *)                 = false
  1026.      * StringUtils.containsAny(*, null)               = false
  1027.      * StringUtils.containsAny(*, "")                 = false
  1028.      * StringUtils.containsAny("zzabyycdxx", "za")    = true
  1029.      * StringUtils.containsAny("zzabyycdxx", "by")    = true
  1030.      * StringUtils.containsAny("zzabyycdxx", "zy")    = true
  1031.      * StringUtils.containsAny("zzabyycdxx", "\tx")   = true
  1032.      * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true
  1033.      * StringUtils.containsAny("aba", "z")            = false
  1034.      * </pre>
  1035.      *
  1036.      * @param cs
  1037.      *            the CharSequence to check, may be null
  1038.      * @param searchChars
  1039.      *            the chars to search for, may be null
  1040.      * @return the {@code true} if any of the chars are found, {@code false} if no match or null input
  1041.      * @since 2.4
  1042.      * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence)
  1043.      */
  1044.     public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) {
  1045.         if (searchChars == null) {
  1046.             return false;
  1047.         }
  1048.         return containsAny(cs, CharSequenceUtils.toCharArray(searchChars));
  1049.     }

  1050.     /**
  1051.      * Tests if the CharSequence contains any of the CharSequences in the given array.
  1052.      *
  1053.      * <p>
  1054.      * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will
  1055.      * return {@code false}.
  1056.      * </p>
  1057.      *
  1058.      * <pre>
  1059.      * StringUtils.containsAny(null, *)            = false
  1060.      * StringUtils.containsAny("", *)              = false
  1061.      * StringUtils.containsAny(*, null)            = false
  1062.      * StringUtils.containsAny(*, [])              = false
  1063.      * StringUtils.containsAny("abcd", "ab", null) = true
  1064.      * StringUtils.containsAny("abcd", "ab", "cd") = true
  1065.      * StringUtils.containsAny("abc", "d", "abc")  = true
  1066.      * </pre>
  1067.      *
  1068.      * @param cs The CharSequence to check, may be null
  1069.      * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be
  1070.      *        null as well.
  1071.      * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
  1072.      * @since 3.4
  1073.      * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CS.containsAny(CharSequence, CharSequence...)}
  1074.      */
  1075.     @Deprecated
  1076.     public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) {
  1077.         return Strings.CS.containsAny(cs, searchCharSequences);
  1078.     }

  1079.     /**
  1080.      * Tests if the CharSequence contains any of the CharSequences in the given array, ignoring case.
  1081.      *
  1082.      * <p>
  1083.      * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will
  1084.      * return {@code false}.
  1085.      * </p>
  1086.      *
  1087.      * <pre>
  1088.      * StringUtils.containsAny(null, *)            = false
  1089.      * StringUtils.containsAny("", *)              = false
  1090.      * StringUtils.containsAny(*, null)            = false
  1091.      * StringUtils.containsAny(*, [])              = false
  1092.      * StringUtils.containsAny("abcd", "ab", null) = true
  1093.      * StringUtils.containsAny("abcd", "ab", "cd") = true
  1094.      * StringUtils.containsAny("abc", "d", "abc")  = true
  1095.      * StringUtils.containsAny("abc", "D", "ABC")  = true
  1096.      * StringUtils.containsAny("ABC", "d", "abc")  = true
  1097.      * </pre>
  1098.      *
  1099.      * @param cs The CharSequence to check, may be null
  1100.      * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be
  1101.      *        null as well.
  1102.      * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
  1103.      * @since 3.12.0
  1104.      * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CI.containsAny(CharSequence, CharSequence...)}
  1105.      */
  1106.     @Deprecated
  1107.     public static boolean containsAnyIgnoreCase(final CharSequence cs, final CharSequence... searchCharSequences) {
  1108.         return Strings.CI.containsAny(cs, searchCharSequences);
  1109.     }

  1110.     /**
  1111.      * Tests if CharSequence contains a search CharSequence irrespective of case,
  1112.      * handling {@code null}. Case-insensitivity is defined as by
  1113.      * {@link String#equalsIgnoreCase(String)}.
  1114.      *
  1115.      * <p>A {@code null} CharSequence will return {@code false}.
  1116.      *
  1117.      * <pre>
  1118.      * StringUtils.containsIgnoreCase(null, *)    = false
  1119.      * StringUtils.containsIgnoreCase(*, null)    = false
  1120.      * StringUtils.containsIgnoreCase("", "")     = true
  1121.      * StringUtils.containsIgnoreCase("abc", "")  = true
  1122.      * StringUtils.containsIgnoreCase("abc", "a") = true
  1123.      * StringUtils.containsIgnoreCase("abc", "z") = false
  1124.      * StringUtils.containsIgnoreCase("abc", "A") = true
  1125.      * StringUtils.containsIgnoreCase("abc", "Z") = false
  1126.      * </pre>
  1127.      *
  1128.      * @param str  the CharSequence to check, may be null
  1129.      * @param searchStr  the CharSequence to find, may be null
  1130.      * @return true if the CharSequence contains the search CharSequence irrespective of
  1131.      * case or false if not or {@code null} string input
  1132.      * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence)
  1133.      * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CI.contains(CharSequence, CharSequence)}
  1134.      */
  1135.     @Deprecated
  1136.     public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {
  1137.         return Strings.CI.contains(str, searchStr);
  1138.     }

  1139.     /**
  1140.      * Tests that the CharSequence does not contain certain characters.
  1141.      *
  1142.      * <p>A {@code null} CharSequence will return {@code true}.
  1143.      * A {@code null} invalid character array will return {@code true}.
  1144.      * An empty CharSequence (length()=0) always returns true.</p>
  1145.      *
  1146.      * <pre>
  1147.      * StringUtils.containsNone(null, *)       = true
  1148.      * StringUtils.containsNone(*, null)       = true
  1149.      * StringUtils.containsNone("", *)         = true
  1150.      * StringUtils.containsNone("ab", '')      = true
  1151.      * StringUtils.containsNone("abab", 'xyz') = true
  1152.      * StringUtils.containsNone("ab1", 'xyz')  = true
  1153.      * StringUtils.containsNone("abz", 'xyz')  = false
  1154.      * </pre>
  1155.      *
  1156.      * @param cs  the CharSequence to check, may be null
  1157.      * @param searchChars  an array of invalid chars, may be null
  1158.      * @return true if it contains none of the invalid chars, or is null
  1159.      * @since 2.0
  1160.      * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...)
  1161.      */
  1162.     public static boolean containsNone(final CharSequence cs, final char... searchChars) {
  1163.         if (cs == null || searchChars == null) {
  1164.             return true;
  1165.         }
  1166.         final int csLen = cs.length();
  1167.         final int csLast = csLen - 1;
  1168.         final int searchLen = searchChars.length;
  1169.         final int searchLast = searchLen - 1;
  1170.         for (int i = 0; i < csLen; i++) {
  1171.             final char ch = cs.charAt(i);
  1172.             for (int j = 0; j < searchLen; j++) {
  1173.                 if (searchChars[j] == ch) {
  1174.                     if (!Character.isHighSurrogate(ch) || j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
  1175.                         return false;
  1176.                     }
  1177.                 }
  1178.             }
  1179.         }
  1180.         return true;
  1181.     }

  1182.     /**
  1183.      * Tests that the CharSequence does not contain certain characters.
  1184.      *
  1185.      * <p>A {@code null} CharSequence will return {@code true}.
  1186.      * A {@code null} invalid character array will return {@code true}.
  1187.      * An empty String ("") always returns true.</p>
  1188.      *
  1189.      * <pre>
  1190.      * StringUtils.containsNone(null, *)       = true
  1191.      * StringUtils.containsNone(*, null)       = true
  1192.      * StringUtils.containsNone("", *)         = true
  1193.      * StringUtils.containsNone("ab", "")      = true
  1194.      * StringUtils.containsNone("abab", "xyz") = true
  1195.      * StringUtils.containsNone("ab1", "xyz")  = true
  1196.      * StringUtils.containsNone("abz", "xyz")  = false
  1197.      * </pre>
  1198.      *
  1199.      * @param cs  the CharSequence to check, may be null
  1200.      * @param invalidChars  a String of invalid chars, may be null
  1201.      * @return true if it contains none of the invalid chars, or is null
  1202.      * @since 2.0
  1203.      * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String)
  1204.      */
  1205.     public static boolean containsNone(final CharSequence cs, final String invalidChars) {
  1206.         if (invalidChars == null) {
  1207.             return true;
  1208.         }
  1209.         return containsNone(cs, invalidChars.toCharArray());
  1210.     }

  1211.     /**
  1212.      * Tests if the CharSequence contains only certain characters.
  1213.      *
  1214.      * <p>A {@code null} CharSequence will return {@code false}.
  1215.      * A {@code null} valid character array will return {@code false}.
  1216.      * An empty CharSequence (length()=0) always returns {@code true}.</p>
  1217.      *
  1218.      * <pre>
  1219.      * StringUtils.containsOnly(null, *)       = false
  1220.      * StringUtils.containsOnly(*, null)       = false
  1221.      * StringUtils.containsOnly("", *)         = true
  1222.      * StringUtils.containsOnly("ab", '')      = false
  1223.      * StringUtils.containsOnly("abab", 'abc') = true
  1224.      * StringUtils.containsOnly("ab1", 'abc')  = false
  1225.      * StringUtils.containsOnly("abz", 'abc')  = false
  1226.      * </pre>
  1227.      *
  1228.      * @param cs  the String to check, may be null
  1229.      * @param valid  an array of valid chars, may be null
  1230.      * @return true if it only contains valid chars and is non-null
  1231.      * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...)
  1232.      */
  1233.     public static boolean containsOnly(final CharSequence cs, final char... valid) {
  1234.         // All these pre-checks are to maintain API with an older version
  1235.         if (valid == null || cs == null) {
  1236.             return false;
  1237.         }
  1238.         if (cs.length() == 0) {
  1239.             return true;
  1240.         }
  1241.         if (valid.length == 0) {
  1242.             return false;
  1243.         }
  1244.         return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND;
  1245.     }

  1246.     /**
  1247.      * Tests if the CharSequence contains only certain characters.
  1248.      *
  1249.      * <p>A {@code null} CharSequence will return {@code false}.
  1250.      * A {@code null} valid character String will return {@code false}.
  1251.      * An empty String (length()=0) always returns {@code true}.</p>
  1252.      *
  1253.      * <pre>
  1254.      * StringUtils.containsOnly(null, *)       = false
  1255.      * StringUtils.containsOnly(*, null)       = false
  1256.      * StringUtils.containsOnly("", *)         = true
  1257.      * StringUtils.containsOnly("ab", "")      = false
  1258.      * StringUtils.containsOnly("abab", "abc") = true
  1259.      * StringUtils.containsOnly("ab1", "abc")  = false
  1260.      * StringUtils.containsOnly("abz", "abc")  = false
  1261.      * </pre>
  1262.      *
  1263.      * @param cs  the CharSequence to check, may be null
  1264.      * @param validChars  a String of valid chars, may be null
  1265.      * @return true if it only contains valid chars and is non-null
  1266.      * @since 2.0
  1267.      * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String)
  1268.      */
  1269.     public static boolean containsOnly(final CharSequence cs, final String validChars) {
  1270.         if (cs == null || validChars == null) {
  1271.             return false;
  1272.         }
  1273.         return containsOnly(cs, validChars.toCharArray());
  1274.     }

  1275.     /**
  1276.      * Tests whether the given CharSequence contains any whitespace characters.
  1277.      *
  1278.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  1279.      *
  1280.      * <pre>
  1281.      * StringUtils.containsWhitespace(null)       = false
  1282.      * StringUtils.containsWhitespace("")         = false
  1283.      * StringUtils.containsWhitespace("ab")       = false
  1284.      * StringUtils.containsWhitespace(" ab")      = true
  1285.      * StringUtils.containsWhitespace("a b")      = true
  1286.      * StringUtils.containsWhitespace("ab ")      = true
  1287.      * </pre>
  1288.      *
  1289.      * @param seq the CharSequence to check (may be {@code null})
  1290.      * @return {@code true} if the CharSequence is not empty and
  1291.      * contains at least 1 (breaking) whitespace character
  1292.      * @since 3.0
  1293.      */
  1294.     // From org.springframework.util.StringUtils, under Apache License 2.0
  1295.     public static boolean containsWhitespace(final CharSequence seq) {
  1296.         if (isEmpty(seq)) {
  1297.             return false;
  1298.         }
  1299.         final int strLen = seq.length();
  1300.         for (int i = 0; i < strLen; i++) {
  1301.             if (Character.isWhitespace(seq.charAt(i))) {
  1302.                 return true;
  1303.             }
  1304.         }
  1305.         return false;
  1306.     }

  1307.     private static void convertRemainingAccentCharacters(final StringBuilder decomposed) {
  1308.         for (int i = 0; i < decomposed.length(); i++) {
  1309.             final char charAt = decomposed.charAt(i);
  1310.             switch (charAt) {
  1311.             case '\u0141':
  1312.                 decomposed.setCharAt(i, 'L');
  1313.                 break;
  1314.             case '\u0142':
  1315.                 decomposed.setCharAt(i, 'l');
  1316.                 break;
  1317.             // D with stroke
  1318.             case '\u0110':
  1319.                 // LATIN CAPITAL LETTER D WITH STROKE
  1320.                 decomposed.setCharAt(i, 'D');
  1321.                 break;
  1322.             case '\u0111':
  1323.                 // LATIN SMALL LETTER D WITH STROKE
  1324.                 decomposed.setCharAt(i, 'd');
  1325.                 break;
  1326.             // I with bar
  1327.             case '\u0197':
  1328.                 decomposed.setCharAt(i, 'I');
  1329.                 break;
  1330.             case '\u0268':
  1331.                 decomposed.setCharAt(i, 'i');
  1332.                 break;
  1333.             case '\u1D7B':
  1334.                 decomposed.setCharAt(i, 'I');
  1335.                 break;
  1336.             case '\u1DA4':
  1337.                 decomposed.setCharAt(i, 'i');
  1338.                 break;
  1339.             case '\u1DA7':
  1340.                 decomposed.setCharAt(i, 'I');
  1341.                 break;
  1342.             // U with bar
  1343.             case '\u0244':
  1344.                 // LATIN CAPITAL LETTER U BAR
  1345.                 decomposed.setCharAt(i, 'U');
  1346.                 break;
  1347.             case '\u0289':
  1348.                 // LATIN SMALL LETTER U BAR
  1349.                 decomposed.setCharAt(i, 'u');
  1350.                 break;
  1351.             case '\u1D7E':
  1352.                 // LATIN SMALL CAPITAL LETTER U WITH STROKE
  1353.                 decomposed.setCharAt(i, 'U');
  1354.                 break;
  1355.             case '\u1DB6':
  1356.                 // MODIFIER LETTER SMALL U BAR
  1357.                 decomposed.setCharAt(i, 'u');
  1358.                 break;
  1359.             // T with stroke
  1360.             case '\u0166':
  1361.                 // LATIN CAPITAL LETTER T WITH STROKE
  1362.                 decomposed.setCharAt(i, 'T');
  1363.                 break;
  1364.             case '\u0167':
  1365.                 // LATIN SMALL LETTER T WITH STROKE
  1366.                 decomposed.setCharAt(i, 't');
  1367.                 break;
  1368.             default:
  1369.                 break;
  1370.             }
  1371.         }
  1372.     }

  1373.     /**
  1374.      * Counts how many times the char appears in the given string.
  1375.      *
  1376.      * <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
  1377.      *
  1378.      * <pre>
  1379.      * StringUtils.countMatches(null, *)     = 0
  1380.      * StringUtils.countMatches("", *)       = 0
  1381.      * StringUtils.countMatches("abba", 0)   = 0
  1382.      * StringUtils.countMatches("abba", 'a') = 2
  1383.      * StringUtils.countMatches("abba", 'b') = 2
  1384.      * StringUtils.countMatches("abba", 'x') = 0
  1385.      * </pre>
  1386.      *
  1387.      * @param str  the CharSequence to check, may be null
  1388.      * @param ch  the char to count
  1389.      * @return the number of occurrences, 0 if the CharSequence is {@code null}
  1390.      * @since 3.4
  1391.      */
  1392.     public static int countMatches(final CharSequence str, final char ch) {
  1393.         if (isEmpty(str)) {
  1394.             return 0;
  1395.         }
  1396.         int count = 0;
  1397.         // We could also call str.toCharArray() for faster lookups but that would generate more garbage.
  1398.         for (int i = 0; i < str.length(); i++) {
  1399.             if (ch == str.charAt(i)) {
  1400.                 count++;
  1401.             }
  1402.         }
  1403.         return count;
  1404.     }

  1405.     /**
  1406.      * Counts how many times the substring appears in the larger string.
  1407.      * Note that the code only counts non-overlapping matches.
  1408.      *
  1409.      * <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
  1410.      *
  1411.      * <pre>
  1412.      * StringUtils.countMatches(null, *)        = 0
  1413.      * StringUtils.countMatches("", *)          = 0
  1414.      * StringUtils.countMatches("abba", null)   = 0
  1415.      * StringUtils.countMatches("abba", "")     = 0
  1416.      * StringUtils.countMatches("abba", "a")    = 2
  1417.      * StringUtils.countMatches("abba", "ab")   = 1
  1418.      * StringUtils.countMatches("abba", "xxx")  = 0
  1419.      * StringUtils.countMatches("ababa", "aba") = 1
  1420.      * </pre>
  1421.      *
  1422.      * @param str  the CharSequence to check, may be null
  1423.      * @param sub  the substring to count, may be null
  1424.      * @return the number of occurrences, 0 if either CharSequence is {@code null}
  1425.      * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence)
  1426.      */
  1427.     public static int countMatches(final CharSequence str, final CharSequence sub) {
  1428.         if (isEmpty(str) || isEmpty(sub)) {
  1429.             return 0;
  1430.         }
  1431.         int count = 0;
  1432.         int idx = 0;
  1433.         while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) {
  1434.             count++;
  1435.             idx += sub.length();
  1436.         }
  1437.         return count;
  1438.     }

  1439.     /**
  1440.      * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or
  1441.      * {@code null}), the value of {@code defaultStr}.
  1442.      *
  1443.      * <p>
  1444.      * Whitespace is defined by {@link Character#isWhitespace(char)}.
  1445.      * </p>
  1446.      *
  1447.      * <pre>
  1448.      * StringUtils.defaultIfBlank(null, "NULL")  = "NULL"
  1449.      * StringUtils.defaultIfBlank("", "NULL")    = "NULL"
  1450.      * StringUtils.defaultIfBlank(" ", "NULL")   = "NULL"
  1451.      * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
  1452.      * StringUtils.defaultIfBlank("", null)      = null
  1453.      * </pre>
  1454.      *
  1455.      * @param <T>        the specific kind of CharSequence
  1456.      * @param str        the CharSequence to check, may be null
  1457.      * @param defaultStr the default CharSequence to return if {@code str} is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code""}) or
  1458.      *                   {@code null}); may be null
  1459.      * @return the passed in CharSequence, or the default
  1460.      * @see StringUtils#defaultString(String, String)
  1461.      * @see #isBlank(CharSequence)
  1462.      */
  1463.     public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) {
  1464.         return isBlank(str) ? defaultStr : str;
  1465.     }

  1466.     /**
  1467.      * Returns either the passed in CharSequence, or if the CharSequence is
  1468.      * empty or {@code null}, the value of {@code defaultStr}.
  1469.      *
  1470.      * <pre>
  1471.      * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
  1472.      * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
  1473.      * StringUtils.defaultIfEmpty(" ", "NULL")   = " "
  1474.      * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
  1475.      * StringUtils.defaultIfEmpty("", null)      = null
  1476.      * </pre>
  1477.      * @param <T> the specific kind of CharSequence
  1478.      * @param str  the CharSequence to check, may be null
  1479.      * @param defaultStr  the default CharSequence to return
  1480.      *  if the input is empty ("") or {@code null}, may be null
  1481.      * @return the passed in CharSequence, or the default
  1482.      * @see StringUtils#defaultString(String, String)
  1483.      */
  1484.     public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) {
  1485.         return isEmpty(str) ? defaultStr : str;
  1486.     }

  1487.     /**
  1488.      * Returns either the passed in String,
  1489.      * or if the String is {@code null}, an empty String ("").
  1490.      *
  1491.      * <pre>
  1492.      * StringUtils.defaultString(null)  = ""
  1493.      * StringUtils.defaultString("")    = ""
  1494.      * StringUtils.defaultString("bat") = "bat"
  1495.      * </pre>
  1496.      *
  1497.      * @see Objects#toString(Object, String)
  1498.      * @see String#valueOf(Object)
  1499.      * @param str  the String to check, may be null
  1500.      * @return the passed in String, or the empty String if it
  1501.      *  was {@code null}
  1502.      */
  1503.     public static String defaultString(final String str) {
  1504.         return Objects.toString(str, EMPTY);
  1505.     }

  1506.     /**
  1507.      * Returns either the given String, or if the String is
  1508.      * {@code null}, {@code nullDefault}.
  1509.      *
  1510.      * <pre>
  1511.      * StringUtils.defaultString(null, "NULL")  = "NULL"
  1512.      * StringUtils.defaultString("", "NULL")    = ""
  1513.      * StringUtils.defaultString("bat", "NULL") = "bat"
  1514.      * </pre>
  1515.      * <p>
  1516.      * Since this is now provided by Java, instead call {@link Objects#toString(Object, String)}:
  1517.      * </p>
  1518.      * <pre>
  1519.      * Objects.toString(null, "NULL")  = "NULL"
  1520.      * Objects.toString("", "NULL")    = ""
  1521.      * Objects.toString("bat", "NULL") = "bat"
  1522.      * </pre>
  1523.      *
  1524.      * @see Objects#toString(Object, String)
  1525.      * @see String#valueOf(Object)
  1526.      * @param str  the String to check, may be null
  1527.      * @param nullDefault  the default String to return
  1528.      *  if the input is {@code null}, may be null
  1529.      * @return the passed in String, or the default if it was {@code null}
  1530.      * @deprecated Use {@link Objects#toString(Object, String)}
  1531.      */
  1532.     @Deprecated
  1533.     public static String defaultString(final String str, final String nullDefault) {
  1534.         return Objects.toString(str, nullDefault);
  1535.     }

  1536.     /**
  1537.      * Deletes all whitespaces from a String as defined by
  1538.      * {@link Character#isWhitespace(char)}.
  1539.      *
  1540.      * <pre>
  1541.      * StringUtils.deleteWhitespace(null)         = null
  1542.      * StringUtils.deleteWhitespace("")           = ""
  1543.      * StringUtils.deleteWhitespace("abc")        = "abc"
  1544.      * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
  1545.      * </pre>
  1546.      *
  1547.      * @param str  the String to delete whitespace from, may be null
  1548.      * @return the String without whitespaces, {@code null} if null String input
  1549.      */
  1550.     public static String deleteWhitespace(final String str) {
  1551.         if (isEmpty(str)) {
  1552.             return str;
  1553.         }
  1554.         final int sz = str.length();
  1555.         final char[] chs = new char[sz];
  1556.         int count = 0;
  1557.         for (int i = 0; i < sz; i++) {
  1558.             if (!Character.isWhitespace(str.charAt(i))) {
  1559.                 chs[count++] = str.charAt(i);
  1560.             }
  1561.         }
  1562.         if (count == sz) {
  1563.             return str;
  1564.         }
  1565.         if (count == 0) {
  1566.             return EMPTY;
  1567.         }
  1568.         return new String(chs, 0, count);
  1569.     }

  1570.     /**
  1571.      * Compares two Strings, and returns the portion where they differ.
  1572.      * More precisely, return the remainder of the second String,
  1573.      * starting from where it's different from the first. This means that
  1574.      * the difference between "abc" and "ab" is the empty String and not "c".
  1575.      *
  1576.      * <p>For example,
  1577.      * {@code difference("i am a machine", "i am a robot") -> "robot"}.</p>
  1578.      *
  1579.      * <pre>
  1580.      * StringUtils.difference(null, null)       = null
  1581.      * StringUtils.difference("", "")           = ""
  1582.      * StringUtils.difference("", "abc")        = "abc"
  1583.      * StringUtils.difference("abc", "")        = ""
  1584.      * StringUtils.difference("abc", "abc")     = ""
  1585.      * StringUtils.difference("abc", "ab")      = ""
  1586.      * StringUtils.difference("ab", "abxyz")    = "xyz"
  1587.      * StringUtils.difference("abcde", "abxyz") = "xyz"
  1588.      * StringUtils.difference("abcde", "xyz")   = "xyz"
  1589.      * </pre>
  1590.      *
  1591.      * @param str1  the first String, may be null
  1592.      * @param str2  the second String, may be null
  1593.      * @return the portion of str2 where it differs from str1; returns the
  1594.      * empty String if they are equal
  1595.      * @see #indexOfDifference(CharSequence,CharSequence)
  1596.      * @since 2.0
  1597.      */
  1598.     public static String difference(final String str1, final String str2) {
  1599.         if (str1 == null) {
  1600.             return str2;
  1601.         }
  1602.         if (str2 == null) {
  1603.             return str1;
  1604.         }
  1605.         final int at = indexOfDifference(str1, str2);
  1606.         if (at == INDEX_NOT_FOUND) {
  1607.             return EMPTY;
  1608.         }
  1609.         return str2.substring(at);
  1610.     }

  1611.     /**
  1612.      * Tests if a CharSequence ends with a specified suffix.
  1613.      *
  1614.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  1615.      * references are considered to be equal. The comparison is case-sensitive.</p>
  1616.      *
  1617.      * <pre>
  1618.      * StringUtils.endsWith(null, null)      = true
  1619.      * StringUtils.endsWith(null, "def")     = false
  1620.      * StringUtils.endsWith("abcdef", null)  = false
  1621.      * StringUtils.endsWith("abcdef", "def") = true
  1622.      * StringUtils.endsWith("ABCDEF", "def") = false
  1623.      * StringUtils.endsWith("ABCDEF", "cde") = false
  1624.      * StringUtils.endsWith("ABCDEF", "")    = true
  1625.      * </pre>
  1626.      *
  1627.      * @see String#endsWith(String)
  1628.      * @param str  the CharSequence to check, may be null
  1629.      * @param suffix the suffix to find, may be null
  1630.      * @return {@code true} if the CharSequence ends with the suffix, case-sensitive, or
  1631.      *  both {@code null}
  1632.      * @since 2.4
  1633.      * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence)
  1634.      * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CS.endsWith(CharSequence, CharSequence)}
  1635.      */
  1636.     @Deprecated
  1637.     public static boolean endsWith(final CharSequence str, final CharSequence suffix) {
  1638.         return Strings.CS.endsWith(str, suffix);
  1639.     }

  1640.     /**
  1641.      * Tests if a CharSequence ends with any of the provided case-sensitive suffixes.
  1642.      *
  1643.      * <pre>
  1644.      * StringUtils.endsWithAny(null, null)                  = false
  1645.      * StringUtils.endsWithAny(null, new String[] {"abc"})  = false
  1646.      * StringUtils.endsWithAny("abcxyz", null)              = false
  1647.      * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
  1648.      * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
  1649.      * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
  1650.      * StringUtils.endsWithAny("abcXYZ", "def", "XYZ")      = true
  1651.      * StringUtils.endsWithAny("abcXYZ", "def", "xyz")      = false
  1652.      * </pre>
  1653.      *
  1654.      * @param sequence  the CharSequence to check, may be null
  1655.      * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null}
  1656.      * @see StringUtils#endsWith(CharSequence, CharSequence)
  1657.      * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
  1658.      *   the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}.
  1659.      * @since 3.0
  1660.      * @deprecated Use {@link Strings#endsWithAny(CharSequence, CharSequence...) Strings.CS.endsWithAny(CharSequence, CharSequence...)}
  1661.      */
  1662.     @Deprecated
  1663.     public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
  1664.         return Strings.CS.endsWithAny(sequence, searchStrings);
  1665.     }

  1666.     /**
  1667.      * Case-insensitive check if a CharSequence ends with a specified suffix.
  1668.      *
  1669.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  1670.      * references are considered to be equal. The comparison is case insensitive.</p>
  1671.      *
  1672.      * <pre>
  1673.      * StringUtils.endsWithIgnoreCase(null, null)      = true
  1674.      * StringUtils.endsWithIgnoreCase(null, "def")     = false
  1675.      * StringUtils.endsWithIgnoreCase("abcdef", null)  = false
  1676.      * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
  1677.      * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
  1678.      * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
  1679.      * </pre>
  1680.      *
  1681.      * @see String#endsWith(String)
  1682.      * @param str  the CharSequence to check, may be null
  1683.      * @param suffix the suffix to find, may be null
  1684.      * @return {@code true} if the CharSequence ends with the suffix, case-insensitive, or
  1685.      *  both {@code null}
  1686.      * @since 2.4
  1687.      * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence)
  1688.      * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CS.endsWith(CharSequence, CharSequence)}
  1689.      */
  1690.     @Deprecated
  1691.     public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) {
  1692.         return Strings.CI.endsWith(str, suffix);
  1693.     }

  1694.     /**
  1695.      * Compares two CharSequences, returning {@code true} if they represent
  1696.      * equal sequences of characters.
  1697.      *
  1698.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  1699.      * references are considered to be equal. The comparison is <strong>case-sensitive</strong>.</p>
  1700.      *
  1701.      * <pre>
  1702.      * StringUtils.equals(null, null)   = true
  1703.      * StringUtils.equals(null, "abc")  = false
  1704.      * StringUtils.equals("abc", null)  = false
  1705.      * StringUtils.equals("abc", "abc") = true
  1706.      * StringUtils.equals("abc", "ABC") = false
  1707.      * </pre>
  1708.      *
  1709.      * @param cs1  the first CharSequence, may be {@code null}
  1710.      * @param cs2  the second CharSequence, may be {@code null}
  1711.      * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
  1712.      * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
  1713.      * @see Object#equals(Object)
  1714.      * @see #equalsIgnoreCase(CharSequence, CharSequence)
  1715.      * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CS.equals(CharSequence, CharSequence)}
  1716.      */
  1717.     @Deprecated
  1718.     public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
  1719.         return Strings.CS.equals(cs1, cs2);
  1720.     }

  1721.     /**
  1722.      * Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
  1723.      * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}.
  1724.      *
  1725.      * <pre>
  1726.      * StringUtils.equalsAny(null, (CharSequence[]) null) = false
  1727.      * StringUtils.equalsAny(null, null, null)    = true
  1728.      * StringUtils.equalsAny(null, "abc", "def")  = false
  1729.      * StringUtils.equalsAny("abc", null, "def")  = false
  1730.      * StringUtils.equalsAny("abc", "abc", "def") = true
  1731.      * StringUtils.equalsAny("abc", "ABC", "DEF") = false
  1732.      * </pre>
  1733.      *
  1734.      * @param string to compare, may be {@code null}.
  1735.      * @param searchStrings a vararg of strings, may be {@code null}.
  1736.      * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings};
  1737.      * {@code false} if {@code searchStrings} is null or contains no matches.
  1738.      * @since 3.5
  1739.      * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CS.equalsAny(CharSequence, CharSequence...)}
  1740.      */
  1741.     @Deprecated
  1742.     public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) {
  1743.         return Strings.CS.equalsAny(string, searchStrings);
  1744.     }

  1745.     /**
  1746.      * Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
  1747.      * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case.
  1748.      *
  1749.      * <pre>
  1750.      * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
  1751.      * StringUtils.equalsAnyIgnoreCase(null, null, null)    = true
  1752.      * StringUtils.equalsAnyIgnoreCase(null, "abc", "def")  = false
  1753.      * StringUtils.equalsAnyIgnoreCase("abc", null, "def")  = false
  1754.      * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
  1755.      * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true
  1756.      * </pre>
  1757.      *
  1758.      * @param string to compare, may be {@code null}.
  1759.      * @param searchStrings a vararg of strings, may be {@code null}.
  1760.      * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings};
  1761.      * {@code false} if {@code searchStrings} is null or contains no matches.
  1762.      * @since 3.5
  1763.      * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CI-.equalsAny(CharSequence, CharSequence...)}
  1764.      */
  1765.     @Deprecated
  1766.     public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence... searchStrings) {
  1767.         return Strings.CI.equalsAny(string, searchStrings);
  1768.     }

  1769.     /**
  1770.      * Compares two CharSequences, returning {@code true} if they represent
  1771.      * equal sequences of characters, ignoring case.
  1772.      *
  1773.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  1774.      * references are considered equal. The comparison is <strong>case insensitive</strong>.</p>
  1775.      *
  1776.      * <pre>
  1777.      * StringUtils.equalsIgnoreCase(null, null)   = true
  1778.      * StringUtils.equalsIgnoreCase(null, "abc")  = false
  1779.      * StringUtils.equalsIgnoreCase("abc", null)  = false
  1780.      * StringUtils.equalsIgnoreCase("abc", "abc") = true
  1781.      * StringUtils.equalsIgnoreCase("abc", "ABC") = true
  1782.      * </pre>
  1783.      *
  1784.      * @param cs1  the first CharSequence, may be {@code null}
  1785.      * @param cs2  the second CharSequence, may be {@code null}
  1786.      * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}
  1787.      * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence)
  1788.      * @see #equals(CharSequence, CharSequence)
  1789.      * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CI.equals(CharSequence, CharSequence)}
  1790.      */
  1791.     @Deprecated
  1792.     public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) {
  1793.         return Strings.CI.equals(cs1, cs2);
  1794.     }

  1795.     /**
  1796.      * Returns the first value in the array which is not empty (""),
  1797.      * {@code null} or whitespace only.
  1798.      *
  1799.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  1800.      *
  1801.      * <p>If all values are blank or the array is {@code null}
  1802.      * or empty then {@code null} is returned.</p>
  1803.      *
  1804.      * <pre>
  1805.      * StringUtils.firstNonBlank(null, null, null)     = null
  1806.      * StringUtils.firstNonBlank(null, "", " ")        = null
  1807.      * StringUtils.firstNonBlank("abc")                = "abc"
  1808.      * StringUtils.firstNonBlank(null, "xyz")          = "xyz"
  1809.      * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz"
  1810.      * StringUtils.firstNonBlank(null, "xyz", "abc")   = "xyz"
  1811.      * StringUtils.firstNonBlank()                     = null
  1812.      * </pre>
  1813.      *
  1814.      * @param <T> the specific kind of CharSequence
  1815.      * @param values  the values to test, may be {@code null} or empty
  1816.      * @return the first value from {@code values} which is not blank,
  1817.      *  or {@code null} if there are no non-blank values
  1818.      * @since 3.8
  1819.      */
  1820.     @SafeVarargs
  1821.     public static <T extends CharSequence> T firstNonBlank(final T... values) {
  1822.         if (values != null) {
  1823.             for (final T val : values) {
  1824.                 if (isNotBlank(val)) {
  1825.                     return val;
  1826.                 }
  1827.             }
  1828.         }
  1829.         return null;
  1830.     }

  1831.     /**
  1832.      * Returns the first value in the array which is not empty.
  1833.      *
  1834.      * <p>If all values are empty or the array is {@code null}
  1835.      * or empty then {@code null} is returned.</p>
  1836.      *
  1837.      * <pre>
  1838.      * StringUtils.firstNonEmpty(null, null, null)   = null
  1839.      * StringUtils.firstNonEmpty(null, null, "")     = null
  1840.      * StringUtils.firstNonEmpty(null, "", " ")      = " "
  1841.      * StringUtils.firstNonEmpty("abc")              = "abc"
  1842.      * StringUtils.firstNonEmpty(null, "xyz")        = "xyz"
  1843.      * StringUtils.firstNonEmpty("", "xyz")          = "xyz"
  1844.      * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz"
  1845.      * StringUtils.firstNonEmpty()                   = null
  1846.      * </pre>
  1847.      *
  1848.      * @param <T> the specific kind of CharSequence
  1849.      * @param values  the values to test, may be {@code null} or empty
  1850.      * @return the first value from {@code values} which is not empty,
  1851.      *  or {@code null} if there are no non-empty values
  1852.      * @since 3.8
  1853.      */
  1854.     @SafeVarargs
  1855.     public static <T extends CharSequence> T firstNonEmpty(final T... values) {
  1856.         if (values != null) {
  1857.             for (final T val : values) {
  1858.                 if (isNotEmpty(val)) {
  1859.                     return val;
  1860.                 }
  1861.             }
  1862.         }
  1863.         return null;
  1864.     }

  1865.     /**
  1866.      * Calls {@link String#getBytes(Charset)} in a null-safe manner.
  1867.      *
  1868.      * @param string input string
  1869.      * @param charset The {@link Charset} to encode the {@link String}. If null, then use the default Charset.
  1870.      * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise.
  1871.      * @see String#getBytes(Charset)
  1872.      * @since 3.10
  1873.      */
  1874.     public static byte[] getBytes(final String string, final Charset charset) {
  1875.         return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset));
  1876.     }

  1877.     /**
  1878.      * Calls {@link String#getBytes(String)} in a null-safe manner.
  1879.      *
  1880.      * @param string input string
  1881.      * @param charset The {@link Charset} name to encode the {@link String}. If null, then use the default Charset.
  1882.      * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise.
  1883.      * @throws UnsupportedEncodingException Thrown when the named charset is not supported.
  1884.      * @see String#getBytes(String)
  1885.      * @since 3.10
  1886.      */
  1887.     public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException {
  1888.         return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset));
  1889.     }

  1890.     /**
  1891.      * Compares all Strings in an array and returns the initial sequence of
  1892.      * characters that is common to all of them.
  1893.      *
  1894.      * <p>For example,
  1895.      * {@code getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -&gt; "i am a "}</p>
  1896.      *
  1897.      * <pre>
  1898.      * StringUtils.getCommonPrefix(null)                             = ""
  1899.      * StringUtils.getCommonPrefix(new String[] {})                  = ""
  1900.      * StringUtils.getCommonPrefix(new String[] {"abc"})             = "abc"
  1901.      * StringUtils.getCommonPrefix(new String[] {null, null})        = ""
  1902.      * StringUtils.getCommonPrefix(new String[] {"", ""})            = ""
  1903.      * StringUtils.getCommonPrefix(new String[] {"", null})          = ""
  1904.      * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
  1905.      * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
  1906.      * StringUtils.getCommonPrefix(new String[] {"", "abc"})         = ""
  1907.      * StringUtils.getCommonPrefix(new String[] {"abc", ""})         = ""
  1908.      * StringUtils.getCommonPrefix(new String[] {"abc", "abc"})      = "abc"
  1909.      * StringUtils.getCommonPrefix(new String[] {"abc", "a"})        = "a"
  1910.      * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"})     = "ab"
  1911.      * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"})  = "ab"
  1912.      * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"})    = ""
  1913.      * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"})    = ""
  1914.      * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
  1915.      * </pre>
  1916.      *
  1917.      * @param strs  array of String objects, entries may be null
  1918.      * @return the initial sequence of characters that are common to all Strings
  1919.      * in the array; empty String if the array is null, the elements are all null
  1920.      * or if there is no common prefix.
  1921.      * @since 2.4
  1922.      */
  1923.     public static String getCommonPrefix(final String... strs) {
  1924.         if (ArrayUtils.isEmpty(strs)) {
  1925.             return EMPTY;
  1926.         }
  1927.         final int smallestIndexOfDiff = indexOfDifference(strs);
  1928.         if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
  1929.             // all strings were identical
  1930.             if (strs[0] == null) {
  1931.                 return EMPTY;
  1932.             }
  1933.             return strs[0];
  1934.         }
  1935.         if (smallestIndexOfDiff == 0) {
  1936.             // there were no common initial characters
  1937.             return EMPTY;
  1938.         }
  1939.         // we found a common initial character sequence
  1940.         return strs[0].substring(0, smallestIndexOfDiff);
  1941.     }

  1942.     /**
  1943.      * Checks if a String {@code str} contains Unicode digits,
  1944.      * if yes then concatenate all the digits in {@code str} and return it as a String.
  1945.      *
  1946.      * <p>An empty ("") String will be returned if no digits found in {@code str}.</p>
  1947.      *
  1948.      * <pre>
  1949.      * StringUtils.getDigits(null)                 = null
  1950.      * StringUtils.getDigits("")                   = ""
  1951.      * StringUtils.getDigits("abc")                = ""
  1952.      * StringUtils.getDigits("1000$")              = "1000"
  1953.      * StringUtils.getDigits("1123~45")            = "112345"
  1954.      * StringUtils.getDigits("(541) 754-3010")     = "5417543010"
  1955.      * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969"
  1956.      * </pre>
  1957.      *
  1958.      * @param str the String to extract digits from, may be null
  1959.      * @return String with only digits,
  1960.      *           or an empty ("") String if no digits found,
  1961.      *           or {@code null} String if {@code str} is null
  1962.      * @since 3.6
  1963.      */
  1964.     public static String getDigits(final String str) {
  1965.         if (isEmpty(str)) {
  1966.             return str;
  1967.         }
  1968.         final int sz = str.length();
  1969.         final StringBuilder strDigits = new StringBuilder(sz);
  1970.         for (int i = 0; i < sz; i++) {
  1971.             final char tempChar = str.charAt(i);
  1972.             if (Character.isDigit(tempChar)) {
  1973.                 strDigits.append(tempChar);
  1974.             }
  1975.         }
  1976.         return strDigits.toString();
  1977.     }

  1978.     /**
  1979.      * Find the Fuzzy Distance which indicates the similarity score between two Strings.
  1980.      *
  1981.      * <p>This string matching algorithm is similar to the algorithms of editors such as Sublime Text,
  1982.      * TextMate, Atom and others. One point is given for every matched character. Subsequent
  1983.      * matches yield two bonus points. A higher score indicates a higher similarity.</p>
  1984.      *
  1985.      * <pre>
  1986.      * StringUtils.getFuzzyDistance(null, null, null)                                    = IllegalArgumentException
  1987.      * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH)                              = 0
  1988.      * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH)                     = 0
  1989.      * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH)                         = 1
  1990.      * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH)                     = 1
  1991.      * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH)                    = 2
  1992.      * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH)                    = 4
  1993.      * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3
  1994.      * </pre>
  1995.      *
  1996.      * @param term a full term that should be matched against, must not be null
  1997.      * @param query the query that will be matched against a term, must not be null
  1998.      * @param locale This string matching logic is case-insensitive. A locale is necessary to normalize
  1999.      *  both Strings to lower case.
  2000.      * @return result score
  2001.      * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null}
  2002.      * @since 3.4
  2003.      * @deprecated As of 3.6, use Apache Commons Text
  2004.      * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html">
  2005.      * FuzzyScore</a> instead
  2006.      */
  2007.     @Deprecated
  2008.     public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) {
  2009.         if (term == null || query == null) {
  2010.             throw new IllegalArgumentException("Strings must not be null");
  2011.         }
  2012.         if (locale == null) {
  2013.             throw new IllegalArgumentException("Locale must not be null");
  2014.         }

  2015.         // fuzzy logic is case-insensitive. We normalize the Strings to lower
  2016.         // case right from the start. Turning characters to lower case
  2017.         // via Character.toLowerCase(char) is unfortunately insufficient
  2018.         // as it does not accept a locale.
  2019.         final String termLowerCase = term.toString().toLowerCase(locale);
  2020.         final String queryLowerCase = query.toString().toLowerCase(locale);

  2021.         // the resulting score
  2022.         int score = 0;

  2023.         // the position in the term which will be scanned next for potential
  2024.         // query character matches
  2025.         int termIndex = 0;

  2026.         // index of the previously matched character in the term
  2027.         int previousMatchingCharacterIndex = Integer.MIN_VALUE;

  2028.         for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) {
  2029.             final char queryChar = queryLowerCase.charAt(queryIndex);

  2030.             boolean termCharacterMatchFound = false;
  2031.             for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) {
  2032.                 final char termChar = termLowerCase.charAt(termIndex);

  2033.                 if (queryChar == termChar) {
  2034.                     // simple character matches result in one point
  2035.                     score++;

  2036.                     // subsequent character matches further improve
  2037.                     // the score.
  2038.                     if (previousMatchingCharacterIndex + 1 == termIndex) {
  2039.                         score += 2;
  2040.                     }

  2041.                     previousMatchingCharacterIndex = termIndex;

  2042.                     // we can leave the nested loop. Every character in the
  2043.                     // query can match at most one character in the term.
  2044.                     termCharacterMatchFound = true;
  2045.                 }
  2046.             }
  2047.         }

  2048.         return score;
  2049.     }

  2050.     /**
  2051.      * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or
  2052.      * {@code null}), the value supplied by {@code defaultStrSupplier}.
  2053.      *
  2054.      * <p>
  2055.      * Whitespace is defined by {@link Character#isWhitespace(char)}.
  2056.      * </p>
  2057.      *
  2058.      * <p>
  2059.      * Caller responsible for thread-safety and exception handling of default value supplier
  2060.      * </p>
  2061.      *
  2062.      * <pre>
  2063.      * {@code
  2064.      * StringUtils.getIfBlank(null, () -> "NULL")   = "NULL"
  2065.      * StringUtils.getIfBlank("", () -> "NULL")     = "NULL"
  2066.      * StringUtils.getIfBlank(" ", () -> "NULL")    = "NULL"
  2067.      * StringUtils.getIfBlank("bat", () -> "NULL")  = "bat"
  2068.      * StringUtils.getIfBlank("", () -> null)       = null
  2069.      * StringUtils.getIfBlank("", null)             = null
  2070.      * }</pre>
  2071.      *
  2072.      * @param <T>             the specific kind of CharSequence
  2073.      * @param str             the CharSequence to check, may be null
  2074.      * @param defaultSupplier the supplier of default CharSequence to return if the input is {@link #isBlank(CharSequence) blank} (whitespaces, empty
  2075.      *                        ({@code ""}) or {@code null}); may be null
  2076.      * @return the passed in CharSequence, or the default
  2077.      * @see StringUtils#defaultString(String, String)
  2078.      * @see #isBlank(CharSequence)
  2079.      * @since 3.10
  2080.      */
  2081.     public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) {
  2082.         return isBlank(str) ? Suppliers.get(defaultSupplier) : str;
  2083.     }

  2084.     /**
  2085.      * Returns either the passed in CharSequence, or if the CharSequence is
  2086.      * empty or {@code null}, the value supplied by {@code defaultStrSupplier}.
  2087.      *
  2088.      * <p>Caller responsible for thread-safety and exception handling of default value supplier</p>
  2089.      *
  2090.      * <pre>
  2091.      * {@code
  2092.      * StringUtils.getIfEmpty(null, () -> "NULL")    = "NULL"
  2093.      * StringUtils.getIfEmpty("", () -> "NULL")      = "NULL"
  2094.      * StringUtils.getIfEmpty(" ", () -> "NULL")     = " "
  2095.      * StringUtils.getIfEmpty("bat", () -> "NULL")   = "bat"
  2096.      * StringUtils.getIfEmpty("", () -> null)        = null
  2097.      * StringUtils.getIfEmpty("", null)              = null
  2098.      * }
  2099.      * </pre>
  2100.      * @param <T> the specific kind of CharSequence
  2101.      * @param str  the CharSequence to check, may be null
  2102.      * @param defaultSupplier  the supplier of default CharSequence to return
  2103.      *  if the input is empty ("") or {@code null}, may be null
  2104.      * @return the passed in CharSequence, or the default
  2105.      * @see StringUtils#defaultString(String, String)
  2106.      * @since 3.10
  2107.      */
  2108.     public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) {
  2109.         return isEmpty(str) ? Suppliers.get(defaultSupplier) : str;
  2110.     }

  2111.     /**
  2112.      * Find the Jaro Winkler Distance which indicates the similarity score between two Strings.
  2113.      *
  2114.      * <p>The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters.
  2115.      * Winkler increased this measure for matching initial characters.</p>
  2116.      *
  2117.      * <p>This implementation is based on the Jaro Winkler similarity algorithm
  2118.      * from <a href="https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>.</p>
  2119.      *
  2120.      * <pre>
  2121.      * StringUtils.getJaroWinklerDistance(null, null)          = IllegalArgumentException
  2122.      * StringUtils.getJaroWinklerDistance("", "")              = 0.0
  2123.      * StringUtils.getJaroWinklerDistance("", "a")             = 0.0
  2124.      * StringUtils.getJaroWinklerDistance("aaapppp", "")       = 0.0
  2125.      * StringUtils.getJaroWinklerDistance("frog", "fog")       = 0.93
  2126.      * StringUtils.getJaroWinklerDistance("fly", "ant")        = 0.0
  2127.      * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44
  2128.      * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44
  2129.      * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0
  2130.      * StringUtils.getJaroWinklerDistance("hello", "hallo")    = 0.88
  2131.      * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93
  2132.      * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D &amp; H Enterprises, Inc.") = 0.95
  2133.      * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92
  2134.      * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88
  2135.      * </pre>
  2136.      *
  2137.      * @param first the first String, must not be null
  2138.      * @param second the second String, must not be null
  2139.      * @return result distance
  2140.      * @throws IllegalArgumentException if either String input {@code null}
  2141.      * @since 3.3
  2142.      * @deprecated As of 3.6, use Apache Commons Text
  2143.      * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html">
  2144.      * JaroWinklerDistance</a> instead
  2145.      */
  2146.     @Deprecated
  2147.     public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) {
  2148.         final double DEFAULT_SCALING_FACTOR = 0.1;

  2149.         if (first == null || second == null) {
  2150.             throw new IllegalArgumentException("Strings must not be null");
  2151.         }

  2152.         final int[] mtp = matches(first, second);
  2153.         final double m = mtp[0];
  2154.         if (m == 0) {
  2155.             return 0D;
  2156.         }
  2157.         final double j = (m / first.length() + m / second.length() + (m - mtp[1]) / m) / 3;
  2158.         final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j);
  2159.         return Math.round(jw * 100.0D) / 100.0D;
  2160.     }

  2161.     /**
  2162.      * Find the Levenshtein distance between two Strings.
  2163.      *
  2164.      * <p>This is the number of changes needed to change one String into
  2165.      * another, where each change is a single character modification (deletion,
  2166.      * insertion or substitution).</p>
  2167.      *
  2168.      * <p>The implementation uses a single-dimensional array of length s.length() + 1. See
  2169.      * <a href="https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html">
  2170.      * https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details.</p>
  2171.      *
  2172.      * <pre>
  2173.      * StringUtils.getLevenshteinDistance(null, *)             = IllegalArgumentException
  2174.      * StringUtils.getLevenshteinDistance(*, null)             = IllegalArgumentException
  2175.      * StringUtils.getLevenshteinDistance("", "")              = 0
  2176.      * StringUtils.getLevenshteinDistance("", "a")             = 1
  2177.      * StringUtils.getLevenshteinDistance("aaapppp", "")       = 7
  2178.      * StringUtils.getLevenshteinDistance("frog", "fog")       = 1
  2179.      * StringUtils.getLevenshteinDistance("fly", "ant")        = 3
  2180.      * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
  2181.      * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
  2182.      * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
  2183.      * StringUtils.getLevenshteinDistance("hello", "hallo")    = 1
  2184.      * </pre>
  2185.      *
  2186.      * @param s  the first String, must not be null
  2187.      * @param t  the second String, must not be null
  2188.      * @return result distance
  2189.      * @throws IllegalArgumentException if either String input {@code null}
  2190.      * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to
  2191.      * getLevenshteinDistance(CharSequence, CharSequence)
  2192.      * @deprecated As of 3.6, use Apache Commons Text
  2193.      * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
  2194.      * LevenshteinDistance</a> instead
  2195.      */
  2196.     @Deprecated
  2197.     public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
  2198.         if (s == null || t == null) {
  2199.             throw new IllegalArgumentException("Strings must not be null");
  2200.         }

  2201.         int n = s.length();
  2202.         int m = t.length();

  2203.         if (n == 0) {
  2204.             return m;
  2205.         }
  2206.         if (m == 0) {
  2207.             return n;
  2208.         }

  2209.         if (n > m) {
  2210.             // swap the input strings to consume less memory
  2211.             final CharSequence tmp = s;
  2212.             s = t;
  2213.             t = tmp;
  2214.             n = m;
  2215.             m = t.length();
  2216.         }

  2217.         final int[] p = new int[n + 1];
  2218.         // indexes into strings s and t
  2219.         int i; // iterates through s
  2220.         int j; // iterates through t
  2221.         int upperleft;
  2222.         int upper;

  2223.         char jOfT; // jth character of t
  2224.         int cost;

  2225.         for (i = 0; i <= n; i++) {
  2226.             p[i] = i;
  2227.         }

  2228.         for (j = 1; j <= m; j++) {
  2229.             upperleft = p[0];
  2230.             jOfT = t.charAt(j - 1);
  2231.             p[0] = j;

  2232.             for (i = 1; i <= n; i++) {
  2233.                 upper = p[i];
  2234.                 cost = s.charAt(i - 1) == jOfT ? 0 : 1;
  2235.                 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
  2236.                 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upperleft + cost);
  2237.                 upperleft = upper;
  2238.             }
  2239.         }

  2240.         return p[n];
  2241.     }

  2242.     /**
  2243.      * Find the Levenshtein distance between two Strings if it's less than or equal to a given
  2244.      * threshold.
  2245.      *
  2246.      * <p>This is the number of changes needed to change one String into
  2247.      * another, where each change is a single character modification (deletion,
  2248.      * insertion or substitution).</p>
  2249.      *
  2250.      * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield
  2251.      * and Chas Emerick's implementation of the Levenshtein distance algorithm from
  2252.      * <a href="https://web.archive.org/web/20120212021906/http%3A//www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
  2253.      *
  2254.      * <pre>
  2255.      * StringUtils.getLevenshteinDistance(null, *, *)             = IllegalArgumentException
  2256.      * StringUtils.getLevenshteinDistance(*, null, *)             = IllegalArgumentException
  2257.      * StringUtils.getLevenshteinDistance(*, *, -1)               = IllegalArgumentException
  2258.      * StringUtils.getLevenshteinDistance("", "", 0)              = 0
  2259.      * StringUtils.getLevenshteinDistance("aaapppp", "", 8)       = 7
  2260.      * StringUtils.getLevenshteinDistance("aaapppp", "", 7)       = 7
  2261.      * StringUtils.getLevenshteinDistance("aaapppp", "", 6))      = -1
  2262.      * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7
  2263.      * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1
  2264.      * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7
  2265.      * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1
  2266.      * </pre>
  2267.      *
  2268.      * @param s  the first String, must not be null
  2269.      * @param t  the second String, must not be null
  2270.      * @param threshold the target threshold, must not be negative
  2271.      * @return result distance, or {@code -1} if the distance would be greater than the threshold
  2272.      * @throws IllegalArgumentException if either String input {@code null} or negative threshold
  2273.      * @deprecated As of 3.6, use Apache Commons Text
  2274.      * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
  2275.      * LevenshteinDistance</a> instead
  2276.      */
  2277.     @Deprecated
  2278.     public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) {
  2279.         if (s == null || t == null) {
  2280.             throw new IllegalArgumentException("Strings must not be null");
  2281.         }
  2282.         if (threshold < 0) {
  2283.             throw new IllegalArgumentException("Threshold must not be negative");
  2284.         }

  2285.         /*
  2286.         This implementation only computes the distance if it's less than or equal to the
  2287.         threshold value, returning -1 if it's greater.  The advantage is performance: unbounded
  2288.         distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only
  2289.         computing a diagonal stripe of width 2k + 1 of the cost table.
  2290.         It is also possible to use this to compute the unbounded Levenshtein distance by starting
  2291.         the threshold at 1 and doubling each time until the distance is found; this is O(dm), where
  2292.         d is the distance.

  2293.         One subtlety comes from needing to ignore entries on the border of our stripe
  2294.         eg.
  2295.         p[] = |#|#|#|*
  2296.         d[] =  *|#|#|#|
  2297.         We must ignore the entry to the left of the leftmost member
  2298.         We must ignore the entry above the rightmost member

  2299.         Another subtlety comes from our stripe running off the matrix if the strings aren't
  2300.         of the same size.  Since string s is always swapped to be the shorter of the two,
  2301.         the stripe will always run off to the upper right instead of the lower left of the matrix.

  2302.         As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1.
  2303.         In this case we're going to walk a stripe of length 3.  The matrix would look like so:

  2304.            1 2 3 4 5
  2305.         1 |#|#| | | |
  2306.         2 |#|#|#| | |
  2307.         3 | |#|#|#| |
  2308.         4 | | |#|#|#|
  2309.         5 | | | |#|#|
  2310.         6 | | | | |#|
  2311.         7 | | | | | |

  2312.         Note how the stripe leads off the table as there is no possible way to turn a string of length 5
  2313.         into one of length 7 in edit distance of 1.

  2314.         Additionally, this implementation decreases memory usage by using two
  2315.         single-dimensional arrays and swapping them back and forth instead of allocating
  2316.         an entire n by m matrix.  This requires a few minor changes, such as immediately returning
  2317.         when it's detected that the stripe has run off the matrix and initially filling the arrays with
  2318.         large values so that entries we don't compute are ignored.

  2319.         See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion.
  2320.          */

  2321.         int n = s.length(); // length of s
  2322.         int m = t.length(); // length of t

  2323.         // if one string is empty, the edit distance is necessarily the length of the other
  2324.         if (n == 0) {
  2325.             return m <= threshold ? m : -1;
  2326.         }
  2327.         if (m == 0) {
  2328.             return n <= threshold ? n : -1;
  2329.         }
  2330.         if (Math.abs(n - m) > threshold) {
  2331.             // no need to calculate the distance if the length difference is greater than the threshold
  2332.             return -1;
  2333.         }

  2334.         if (n > m) {
  2335.             // swap the two strings to consume less memory
  2336.             final CharSequence tmp = s;
  2337.             s = t;
  2338.             t = tmp;
  2339.             n = m;
  2340.             m = t.length();
  2341.         }

  2342.         int[] p = new int[n + 1]; // 'previous' cost array, horizontally
  2343.         int[] d = new int[n + 1]; // cost array, horizontally
  2344.         int[] tmp; // placeholder to assist in swapping p and d

  2345.         // fill in starting table values
  2346.         final int boundary = Math.min(n, threshold) + 1;
  2347.         for (int i = 0; i < boundary; i++) {
  2348.             p[i] = i;
  2349.         }
  2350.         // these fills ensure that the value above the rightmost entry of our
  2351.         // stripe will be ignored in following loop iterations
  2352.         Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE);
  2353.         Arrays.fill(d, Integer.MAX_VALUE);

  2354.         // iterates through t
  2355.         for (int j = 1; j <= m; j++) {
  2356.             final char jOfT = t.charAt(j - 1); // jth character of t
  2357.             d[0] = j;

  2358.             // compute stripe indices, constrain to array size
  2359.             final int min = Math.max(1, j - threshold);
  2360.             final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold);

  2361.             // the stripe may lead off of the table if s and t are of different sizes
  2362.             if (min > max) {
  2363.                 return -1;
  2364.             }

  2365.             // ignore entry left of leftmost
  2366.             if (min > 1) {
  2367.                 d[min - 1] = Integer.MAX_VALUE;
  2368.             }

  2369.             // iterates through [min, max] in s
  2370.             for (int i = min; i <= max; i++) {
  2371.                 if (s.charAt(i - 1) == jOfT) {
  2372.                     // diagonally left and up
  2373.                     d[i] = p[i - 1];
  2374.                 } else {
  2375.                     // 1 + minimum of cell to the left, to the top, diagonally left and up
  2376.                     d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);
  2377.                 }
  2378.             }

  2379.             // copy current distance counts to 'previous row' distance counts
  2380.             tmp = p;
  2381.             p = d;
  2382.             d = tmp;
  2383.         }

  2384.         // if p[n] is greater than the threshold, there's no guarantee on it being the correct
  2385.         // distance
  2386.         if (p[n] <= threshold) {
  2387.             return p[n];
  2388.         }
  2389.         return -1;
  2390.     }

  2391.     /**
  2392.      * Finds the first index within a CharSequence, handling {@code null}.
  2393.      * This method uses {@link String#indexOf(String, int)} if possible.
  2394.      *
  2395.      * <p>A {@code null} CharSequence will return {@code -1}.</p>
  2396.      *
  2397.      * <pre>
  2398.      * StringUtils.indexOf(null, *)          = -1
  2399.      * StringUtils.indexOf(*, null)          = -1
  2400.      * StringUtils.indexOf("", "")           = 0
  2401.      * StringUtils.indexOf("", *)            = -1 (except when * = "")
  2402.      * StringUtils.indexOf("aabaabaa", "a")  = 0
  2403.      * StringUtils.indexOf("aabaabaa", "b")  = 2
  2404.      * StringUtils.indexOf("aabaabaa", "ab") = 1
  2405.      * StringUtils.indexOf("aabaabaa", "")   = 0
  2406.      * </pre>
  2407.      *
  2408.      * @param seq  the CharSequence to check, may be null
  2409.      * @param searchSeq  the CharSequence to find, may be null
  2410.      * @return the first index of the search CharSequence,
  2411.      *  -1 if no match or {@code null} string input
  2412.      * @since 2.0
  2413.      * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence)
  2414.      * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CS.indexOf(CharSequence, CharSequence)}
  2415.      */
  2416.     @Deprecated
  2417.     public static int indexOf(final CharSequence seq, final CharSequence searchSeq) {
  2418.         return Strings.CS.indexOf(seq, searchSeq);
  2419.     }

  2420.     /**
  2421.      * Finds the first index within a CharSequence, handling {@code null}.
  2422.      * This method uses {@link String#indexOf(String, int)} if possible.
  2423.      *
  2424.      * <p>A {@code null} CharSequence will return {@code -1}.
  2425.      * A negative start position is treated as zero.
  2426.      * An empty ("") search CharSequence always matches.
  2427.      * A start position greater than the string length only matches
  2428.      * an empty search CharSequence.</p>
  2429.      *
  2430.      * <pre>
  2431.      * StringUtils.indexOf(null, *, *)          = -1
  2432.      * StringUtils.indexOf(*, null, *)          = -1
  2433.      * StringUtils.indexOf("", "", 0)           = 0
  2434.      * StringUtils.indexOf("", *, 0)            = -1 (except when * = "")
  2435.      * StringUtils.indexOf("aabaabaa", "a", 0)  = 0
  2436.      * StringUtils.indexOf("aabaabaa", "b", 0)  = 2
  2437.      * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
  2438.      * StringUtils.indexOf("aabaabaa", "b", 3)  = 5
  2439.      * StringUtils.indexOf("aabaabaa", "b", 9)  = -1
  2440.      * StringUtils.indexOf("aabaabaa", "b", -1) = 2
  2441.      * StringUtils.indexOf("aabaabaa", "", 2)   = 2
  2442.      * StringUtils.indexOf("abc", "", 9)        = 3
  2443.      * </pre>
  2444.      *
  2445.      * @param seq  the CharSequence to check, may be null
  2446.      * @param searchSeq  the CharSequence to find, may be null
  2447.      * @param startPos  the start position, negative treated as zero
  2448.      * @return the first index of the search CharSequence (always &ge; startPos),
  2449.      *  -1 if no match or {@code null} string input
  2450.      * @since 2.0
  2451.      * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int)
  2452.      * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CS.indexOf(CharSequence, CharSequence, int)}
  2453.      */
  2454.     @Deprecated
  2455.     public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
  2456.         return Strings.CS.indexOf(seq, searchSeq, startPos);
  2457.     }

  2458.     /**
  2459.      * Returns the index within {@code seq} of the first occurrence of
  2460.      * the specified character. If a character with value
  2461.      * {@code searchChar} occurs in the character sequence represented by
  2462.      * {@code seq} {@link CharSequence} object, then the index (in Unicode
  2463.      * code units) of the first such occurrence is returned. For
  2464.      * values of {@code searchChar} in the range from 0 to 0xFFFF
  2465.      * (inclusive), this is the smallest value <em>k</em> such that:
  2466.      * <blockquote><pre>
  2467.      * this.charAt(<em>k</em>) == searchChar
  2468.      * </pre></blockquote>
  2469.      * is true. For other values of {@code searchChar}, it is the
  2470.      * smallest value <em>k</em> such that:
  2471.      * <blockquote><pre>
  2472.      * this.codePointAt(<em>k</em>) == searchChar
  2473.      * </pre></blockquote>
  2474.      * is true. In either case, if no such character occurs in {@code seq},
  2475.      * then {@code INDEX_NOT_FOUND (-1)} is returned.
  2476.      *
  2477.      * <p>Furthermore, a {@code null} or empty ("") CharSequence will
  2478.      * return {@code INDEX_NOT_FOUND (-1)}.</p>
  2479.      *
  2480.      * <pre>
  2481.      * StringUtils.indexOf(null, *)         = -1
  2482.      * StringUtils.indexOf("", *)           = -1
  2483.      * StringUtils.indexOf("aabaabaa", 'a') = 0
  2484.      * StringUtils.indexOf("aabaabaa", 'b') = 2
  2485.      * StringUtils.indexOf("aaaaaaaa", 'Z') = -1
  2486.      * </pre>
  2487.      *
  2488.      * @param seq  the CharSequence to check, may be null
  2489.      * @param searchChar  the character to find
  2490.      * @return the first index of the search character,
  2491.      *  -1 if no match or {@code null} string input
  2492.      * @since 2.0
  2493.      * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int)
  2494.      * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
  2495.      */
  2496.     public static int indexOf(final CharSequence seq, final int searchChar) {
  2497.         if (isEmpty(seq)) {
  2498.             return INDEX_NOT_FOUND;
  2499.         }
  2500.         return CharSequenceUtils.indexOf(seq, searchChar, 0);
  2501.     }

  2502.     /**
  2503.      * Returns the index within {@code seq} of the first occurrence of the
  2504.      * specified character, starting the search at the specified index.
  2505.      * <p>
  2506.      * If a character with value {@code searchChar} occurs in the
  2507.      * character sequence represented by the {@code seq} {@link CharSequence}
  2508.      * object at an index no smaller than {@code startPos}, then
  2509.      * the index of the first such occurrence is returned. For values
  2510.      * of {@code searchChar} in the range from 0 to 0xFFFF (inclusive),
  2511.      * this is the smallest value <em>k</em> such that:
  2512.      * <blockquote><pre>
  2513.      * (this.charAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &gt;= startPos)
  2514.      * </pre></blockquote>
  2515.      * is true. For other values of {@code searchChar}, it is the
  2516.      * smallest value <em>k</em> such that:
  2517.      * <blockquote><pre>
  2518.      * (this.codePointAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &gt;= startPos)
  2519.      * </pre></blockquote>
  2520.      * is true. In either case, if no such character occurs in {@code seq}
  2521.      * at or after position {@code startPos}, then
  2522.      * {@code -1} is returned.
  2523.      *
  2524.      * <p>
  2525.      * There is no restriction on the value of {@code startPos}. If it
  2526.      * is negative, it has the same effect as if it were zero: this entire
  2527.      * string may be searched. If it is greater than the length of this
  2528.      * string, it has the same effect as if it were equal to the length of
  2529.      * this string: {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a
  2530.      * {@code null} or empty ("") CharSequence will
  2531.      * return {@code (INDEX_NOT_FOUND) -1}.
  2532.      *
  2533.      * <p>All indices are specified in {@code char} values
  2534.      * (Unicode code units).
  2535.      *
  2536.      * <pre>
  2537.      * StringUtils.indexOf(null, *, *)          = -1
  2538.      * StringUtils.indexOf("", *, *)            = -1
  2539.      * StringUtils.indexOf("aabaabaa", 'b', 0)  = 2
  2540.      * StringUtils.indexOf("aabaabaa", 'b', 3)  = 5
  2541.      * StringUtils.indexOf("aabaabaa", 'b', 9)  = -1
  2542.      * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
  2543.      * </pre>
  2544.      *
  2545.      * @param seq  the CharSequence to check, may be null
  2546.      * @param searchChar  the character to find
  2547.      * @param startPos  the start position, negative treated as zero
  2548.      * @return the first index of the search character (always &ge; startPos),
  2549.      *  -1 if no match or {@code null} string input
  2550.      * @since 2.0
  2551.      * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int)
  2552.      * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
  2553.      */
  2554.     public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) {
  2555.         if (isEmpty(seq)) {
  2556.             return INDEX_NOT_FOUND;
  2557.         }
  2558.         return CharSequenceUtils.indexOf(seq, searchChar, startPos);
  2559.     }

  2560.     /**
  2561.      * Search a CharSequence to find the first index of any
  2562.      * character in the given set of characters.
  2563.      *
  2564.      * <p>A {@code null} String will return {@code -1}.
  2565.      * A {@code null} or zero length search array will return {@code -1}.</p>
  2566.      *
  2567.      * <pre>
  2568.      * StringUtils.indexOfAny(null, *)                  = -1
  2569.      * StringUtils.indexOfAny("", *)                    = -1
  2570.      * StringUtils.indexOfAny(*, null)                  = -1
  2571.      * StringUtils.indexOfAny(*, [])                    = -1
  2572.      * StringUtils.indexOfAny("zzabyycdxx", ['z', 'a']) = 0
  2573.      * StringUtils.indexOfAny("zzabyycdxx", ['b', 'y']) = 3
  2574.      * StringUtils.indexOfAny("aba", ['z'])             = -1
  2575.      * </pre>
  2576.      *
  2577.      * @param cs  the CharSequence to check, may be null
  2578.      * @param searchChars  the chars to search for, may be null
  2579.      * @return the index of any of the chars, -1 if no match or null input
  2580.      * @since 2.0
  2581.      * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)
  2582.      */
  2583.     public static int indexOfAny(final CharSequence cs, final char... searchChars) {
  2584.         if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
  2585.             return INDEX_NOT_FOUND;
  2586.         }
  2587.         final int csLen = cs.length();
  2588.         final int csLast = csLen - 1;
  2589.         final int searchLen = searchChars.length;
  2590.         final int searchLast = searchLen - 1;
  2591.         for (int i = 0; i < csLen; i++) {
  2592.             final char ch = cs.charAt(i);
  2593.             for (int j = 0; j < searchLen; j++) {
  2594.                 if (searchChars[j] == ch) {
  2595.                     // ch is a supplementary character
  2596.                     if (i >= csLast || j >= searchLast || !Character.isHighSurrogate(ch) || searchChars[j + 1] == cs.charAt(i + 1)) {
  2597.                         return i;
  2598.                     }
  2599.                 }
  2600.             }
  2601.         }
  2602.         return INDEX_NOT_FOUND;
  2603.     }

  2604.     /**
  2605.      * Find the first index of any of a set of potential substrings.
  2606.      *
  2607.      * <p>A {@code null} CharSequence will return {@code -1}.
  2608.      * A {@code null} or zero length search array will return {@code -1}.
  2609.      * A {@code null} search array entry will be ignored, but a search
  2610.      * array containing "" will return {@code 0} if {@code str} is not
  2611.      * null. This method uses {@link String#indexOf(String)} if possible.</p>
  2612.      *
  2613.      * <pre>
  2614.      * StringUtils.indexOfAny(null, *)                      = -1
  2615.      * StringUtils.indexOfAny(*, null)                      = -1
  2616.      * StringUtils.indexOfAny(*, [])                        = -1
  2617.      * StringUtils.indexOfAny("zzabyycdxx", ["ab", "cd"])   = 2
  2618.      * StringUtils.indexOfAny("zzabyycdxx", ["cd", "ab"])   = 2
  2619.      * StringUtils.indexOfAny("zzabyycdxx", ["mn", "op"])   = -1
  2620.      * StringUtils.indexOfAny("zzabyycdxx", ["zab", "aby"]) = 1
  2621.      * StringUtils.indexOfAny("zzabyycdxx", [""])           = 0
  2622.      * StringUtils.indexOfAny("", [""])                     = 0
  2623.      * StringUtils.indexOfAny("", ["a"])                    = -1
  2624.      * </pre>
  2625.      *
  2626.      * @param str  the CharSequence to check, may be null
  2627.      * @param searchStrs  the CharSequences to search for, may be null
  2628.      * @return the first index of any of the searchStrs in str, -1 if no match
  2629.      * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...)
  2630.      */
  2631.     public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) {
  2632.         if (str == null || searchStrs == null) {
  2633.             return INDEX_NOT_FOUND;
  2634.         }

  2635.         // String's can't have a MAX_VALUEth index.
  2636.         int ret = Integer.MAX_VALUE;

  2637.         int tmp;
  2638.         for (final CharSequence search : searchStrs) {
  2639.             if (search == null) {
  2640.                 continue;
  2641.             }
  2642.             tmp = CharSequenceUtils.indexOf(str, search, 0);
  2643.             if (tmp == INDEX_NOT_FOUND) {
  2644.                 continue;
  2645.             }

  2646.             if (tmp < ret) {
  2647.                 ret = tmp;
  2648.             }
  2649.         }

  2650.         return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret;
  2651.     }

  2652.     /**
  2653.      * Search a CharSequence to find the first index of any
  2654.      * character in the given set of characters.
  2655.      *
  2656.      * <p>A {@code null} String will return {@code -1}.
  2657.      * A {@code null} search string will return {@code -1}.</p>
  2658.      *
  2659.      * <pre>
  2660.      * StringUtils.indexOfAny(null, *)            = -1
  2661.      * StringUtils.indexOfAny("", *)              = -1
  2662.      * StringUtils.indexOfAny(*, null)            = -1
  2663.      * StringUtils.indexOfAny(*, "")              = -1
  2664.      * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
  2665.      * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
  2666.      * StringUtils.indexOfAny("aba", "z")         = -1
  2667.      * </pre>
  2668.      *
  2669.      * @param cs  the CharSequence to check, may be null
  2670.      * @param searchChars  the chars to search for, may be null
  2671.      * @return the index of any of the chars, -1 if no match or null input
  2672.      * @since 2.0
  2673.      * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String)
  2674.      */
  2675.     public static int indexOfAny(final CharSequence cs, final String searchChars) {
  2676.         if (isEmpty(cs) || isEmpty(searchChars)) {
  2677.             return INDEX_NOT_FOUND;
  2678.         }
  2679.         return indexOfAny(cs, searchChars.toCharArray());
  2680.     }

  2681.     /**
  2682.      * Searches a CharSequence to find the first index of any
  2683.      * character not in the given set of characters, i.e.,
  2684.      * find index i of first char in cs such that (cs.codePointAt(i) ∉ { x ∈ codepoints(searchChars) })
  2685.      *
  2686.      * <p>A {@code null} CharSequence will return {@code -1}.
  2687.      * A {@code null} or zero length search array will return {@code -1}.</p>
  2688.      *
  2689.      * <pre>
  2690.      * StringUtils.indexOfAnyBut(null, *)                              = -1
  2691.      * StringUtils.indexOfAnyBut("", *)                                = -1
  2692.      * StringUtils.indexOfAnyBut(*, null)                              = -1
  2693.      * StringUtils.indexOfAnyBut(*, [])                                = -1
  2694.      * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
  2695.      * StringUtils.indexOfAnyBut("aba", new char[] {'z'} )             = 0
  2696.      * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} )        = -1

  2697.      * </pre>
  2698.      *
  2699.      * @param cs  the CharSequence to check, may be null
  2700.      * @param searchChars  the chars to search for, may be null
  2701.      * @return the index of any of the chars, -1 if no match or null input
  2702.      * @since 2.0
  2703.      * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...)
  2704.      */
  2705.     public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) {
  2706.         if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
  2707.             return INDEX_NOT_FOUND;
  2708.         }
  2709.         return indexOfAnyBut(cs, CharBuffer.wrap(searchChars));
  2710.     }

  2711.     /**
  2712.      * Search a CharSequence to find the first index of any
  2713.      * character not in the given set of characters, i.e.,
  2714.      * find index i of first char in seq such that (seq.codePointAt(i) ∉ { x ∈ codepoints(searchChars) })
  2715.      *
  2716.      * <p>A {@code null} CharSequence will return {@code -1}.
  2717.      * A {@code null} or empty search string will return {@code -1}.</p>
  2718.      *
  2719.      * <pre>
  2720.      * StringUtils.indexOfAnyBut(null, *)            = -1
  2721.      * StringUtils.indexOfAnyBut("", *)              = -1
  2722.      * StringUtils.indexOfAnyBut(*, null)            = -1
  2723.      * StringUtils.indexOfAnyBut(*, "")              = -1
  2724.      * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
  2725.      * StringUtils.indexOfAnyBut("zzabyycdxx", "")   = -1
  2726.      * StringUtils.indexOfAnyBut("aba", "ab")        = -1
  2727.      * </pre>
  2728.      *
  2729.      * @param seq  the CharSequence to check, may be null
  2730.      * @param searchChars  the chars to search for, may be null
  2731.      * @return the index of any of the chars, -1 if no match or null input
  2732.      * @since 2.0
  2733.      * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence)
  2734.      */
  2735.     public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) {
  2736.         if (isEmpty(seq) || isEmpty(searchChars)) {
  2737.             return INDEX_NOT_FOUND;
  2738.         }
  2739.         final Set<Integer> searchSetCodePoints = searchChars.codePoints()
  2740.                 .boxed().collect(Collectors.toSet());
  2741.         // advance character index from one interpreted codepoint to the next
  2742.         for (int curSeqCharIdx = 0; curSeqCharIdx < seq.length();) {
  2743.             final int curSeqCodePoint = Character.codePointAt(seq, curSeqCharIdx);
  2744.             if (!searchSetCodePoints.contains(curSeqCodePoint)) {
  2745.                 return curSeqCharIdx;
  2746.             }
  2747.             curSeqCharIdx += Character.charCount(curSeqCodePoint); // skip indices to paired low-surrogates
  2748.         }
  2749.         return INDEX_NOT_FOUND;
  2750.     }

  2751.     /**
  2752.      * Compares all CharSequences in an array and returns the index at which the
  2753.      * CharSequences begin to differ.
  2754.      *
  2755.      * <p>For example,
  2756.      * {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7}</p>
  2757.      *
  2758.      * <pre>
  2759.      * StringUtils.indexOfDifference(null)                             = -1
  2760.      * StringUtils.indexOfDifference(new String[] {})                  = -1
  2761.      * StringUtils.indexOfDifference(new String[] {"abc"})             = -1
  2762.      * StringUtils.indexOfDifference(new String[] {null, null})        = -1
  2763.      * StringUtils.indexOfDifference(new String[] {"", ""})            = -1
  2764.      * StringUtils.indexOfDifference(new String[] {"", null})          = 0
  2765.      * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
  2766.      * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
  2767.      * StringUtils.indexOfDifference(new String[] {"", "abc"})         = 0
  2768.      * StringUtils.indexOfDifference(new String[] {"abc", ""})         = 0
  2769.      * StringUtils.indexOfDifference(new String[] {"abc", "abc"})      = -1
  2770.      * StringUtils.indexOfDifference(new String[] {"abc", "a"})        = 1
  2771.      * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"})     = 2
  2772.      * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"})  = 2
  2773.      * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"})    = 0
  2774.      * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"})    = 0
  2775.      * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
  2776.      * </pre>
  2777.      *
  2778.      * @param css  array of CharSequences, entries may be null
  2779.      * @return the index where the strings begin to differ; -1 if they are all equal
  2780.      * @since 2.4
  2781.      * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...)
  2782.      */
  2783.     public static int indexOfDifference(final CharSequence... css) {
  2784.         if (ArrayUtils.getLength(css) <= 1) {
  2785.             return INDEX_NOT_FOUND;
  2786.         }
  2787.         boolean anyStringNull = false;
  2788.         boolean allStringsNull = true;
  2789.         final int arrayLen = css.length;
  2790.         int shortestStrLen = Integer.MAX_VALUE;
  2791.         int longestStrLen = 0;

  2792.         // find the min and max string lengths; this avoids checking to make
  2793.         // sure we are not exceeding the length of the string each time through
  2794.         // the bottom loop.
  2795.         for (final CharSequence cs : css) {
  2796.             if (cs == null) {
  2797.                 anyStringNull = true;
  2798.                 shortestStrLen = 0;
  2799.             } else {
  2800.                 allStringsNull = false;
  2801.                 shortestStrLen = Math.min(cs.length(), shortestStrLen);
  2802.                 longestStrLen = Math.max(cs.length(), longestStrLen);
  2803.             }
  2804.         }

  2805.         // handle lists containing all nulls or all empty strings
  2806.         if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
  2807.             return INDEX_NOT_FOUND;
  2808.         }

  2809.         // handle lists containing some nulls or some empty strings
  2810.         if (shortestStrLen == 0) {
  2811.             return 0;
  2812.         }

  2813.         // find the position with the first difference across all strings
  2814.         int firstDiff = -1;
  2815.         for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
  2816.             final char comparisonChar = css[0].charAt(stringPos);
  2817.             for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
  2818.                 if (css[arrayPos].charAt(stringPos) != comparisonChar) {
  2819.                     firstDiff = stringPos;
  2820.                     break;
  2821.                 }
  2822.             }
  2823.             if (firstDiff != -1) {
  2824.                 break;
  2825.             }
  2826.         }

  2827.         if (firstDiff == -1 && shortestStrLen != longestStrLen) {
  2828.             // we compared all of the characters up to the length of the
  2829.             // shortest string and didn't find a match, but the string lengths
  2830.             // vary, so return the length of the shortest string.
  2831.             return shortestStrLen;
  2832.         }
  2833.         return firstDiff;
  2834.     }

  2835.     /**
  2836.      * Compares two CharSequences, and returns the index at which the
  2837.      * CharSequences begin to differ.
  2838.      *
  2839.      * <p>For example,
  2840.      * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}</p>
  2841.      *
  2842.      * <pre>
  2843.      * StringUtils.indexOfDifference(null, null)       = -1
  2844.      * StringUtils.indexOfDifference("", "")           = -1
  2845.      * StringUtils.indexOfDifference("", "abc")        = 0
  2846.      * StringUtils.indexOfDifference("abc", "")        = 0
  2847.      * StringUtils.indexOfDifference("abc", "abc")     = -1
  2848.      * StringUtils.indexOfDifference("ab", "abxyz")    = 2
  2849.      * StringUtils.indexOfDifference("abcde", "abxyz") = 2
  2850.      * StringUtils.indexOfDifference("abcde", "xyz")   = 0
  2851.      * </pre>
  2852.      *
  2853.      * @param cs1  the first CharSequence, may be null
  2854.      * @param cs2  the second CharSequence, may be null
  2855.      * @return the index where cs1 and cs2 begin to differ; -1 if they are equal
  2856.      * @since 2.0
  2857.      * @since 3.0 Changed signature from indexOfDifference(String, String) to
  2858.      * indexOfDifference(CharSequence, CharSequence)
  2859.      */
  2860.     public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) {
  2861.         if (cs1 == cs2) {
  2862.             return INDEX_NOT_FOUND;
  2863.         }
  2864.         if (cs1 == null || cs2 == null) {
  2865.             return 0;
  2866.         }
  2867.         int i;
  2868.         for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {
  2869.             if (cs1.charAt(i) != cs2.charAt(i)) {
  2870.                 break;
  2871.             }
  2872.         }
  2873.         if (i < cs2.length() || i < cs1.length()) {
  2874.             return i;
  2875.         }
  2876.         return INDEX_NOT_FOUND;
  2877.     }

  2878.     /**
  2879.      * Case in-sensitive find of the first index within a CharSequence.
  2880.      *
  2881.      * <p>A {@code null} CharSequence will return {@code -1}.
  2882.      * A negative start position is treated as zero.
  2883.      * An empty ("") search CharSequence always matches.
  2884.      * A start position greater than the string length only matches
  2885.      * an empty search CharSequence.</p>
  2886.      *
  2887.      * <pre>
  2888.      * StringUtils.indexOfIgnoreCase(null, *)          = -1
  2889.      * StringUtils.indexOfIgnoreCase(*, null)          = -1
  2890.      * StringUtils.indexOfIgnoreCase("", "")           = 0
  2891.      * StringUtils.indexOfIgnoreCase(" ", " ")         = 0
  2892.      * StringUtils.indexOfIgnoreCase("aabaabaa", "a")  = 0
  2893.      * StringUtils.indexOfIgnoreCase("aabaabaa", "b")  = 2
  2894.      * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
  2895.      * </pre>
  2896.      *
  2897.      * @param str  the CharSequence to check, may be null
  2898.      * @param searchStr  the CharSequence to find, may be null
  2899.      * @return the first index of the search CharSequence,
  2900.      *  -1 if no match or {@code null} string input
  2901.      * @since 2.5
  2902.      * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence)
  2903.      * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CI.indexOf(CharSequence, CharSequence)}
  2904.      */
  2905.     @Deprecated
  2906.     public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
  2907.         return Strings.CI.indexOf(str, searchStr);
  2908.     }

  2909.     /**
  2910.      * Case in-sensitive find of the first index within a CharSequence
  2911.      * from the specified position.
  2912.      *
  2913.      * <p>A {@code null} CharSequence will return {@code -1}.
  2914.      * A negative start position is treated as zero.
  2915.      * An empty ("") search CharSequence always matches.
  2916.      * A start position greater than the string length only matches
  2917.      * an empty search CharSequence.</p>
  2918.      *
  2919.      * <pre>
  2920.      * StringUtils.indexOfIgnoreCase(null, *, *)          = -1
  2921.      * StringUtils.indexOfIgnoreCase(*, null, *)          = -1
  2922.      * StringUtils.indexOfIgnoreCase("", "", 0)           = 0
  2923.      * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
  2924.      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
  2925.      * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
  2926.      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
  2927.      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
  2928.      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
  2929.      * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
  2930.      * StringUtils.indexOfIgnoreCase("abc", "", 9)        = -1
  2931.      * </pre>
  2932.      *
  2933.      * @param str  the CharSequence to check, may be null
  2934.      * @param searchStr  the CharSequence to find, may be null
  2935.      * @param startPos  the start position, negative treated as zero
  2936.      * @return the first index of the search CharSequence (always &ge; startPos),
  2937.      *  -1 if no match or {@code null} string input
  2938.      * @since 2.5
  2939.      * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int)
  2940.      * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CI.indexOf(CharSequence, CharSequence, int)}
  2941.      */
  2942.     @Deprecated
  2943.     public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) {
  2944.         return Strings.CI.indexOf(str, searchStr, startPos);
  2945.     }

  2946.     /**
  2947.      * Tests if all of the CharSequences are empty (""), null or whitespace only.
  2948.      *
  2949.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  2950.      *
  2951.      * <pre>
  2952.      * StringUtils.isAllBlank(null)             = true
  2953.      * StringUtils.isAllBlank(null, "foo")      = false
  2954.      * StringUtils.isAllBlank(null, null)       = true
  2955.      * StringUtils.isAllBlank("", "bar")        = false
  2956.      * StringUtils.isAllBlank("bob", "")        = false
  2957.      * StringUtils.isAllBlank("  bob  ", null)  = false
  2958.      * StringUtils.isAllBlank(" ", "bar")       = false
  2959.      * StringUtils.isAllBlank("foo", "bar")     = false
  2960.      * StringUtils.isAllBlank(new String[] {})  = true
  2961.      * </pre>
  2962.      *
  2963.      * @param css  the CharSequences to check, may be null or empty
  2964.      * @return {@code true} if all of the CharSequences are empty or null or whitespace only
  2965.      * @since 3.6
  2966.      */
  2967.     public static boolean isAllBlank(final CharSequence... css) {
  2968.         if (ArrayUtils.isEmpty(css)) {
  2969.             return true;
  2970.         }
  2971.         for (final CharSequence cs : css) {
  2972.             if (isNotBlank(cs)) {
  2973.                return false;
  2974.             }
  2975.         }
  2976.         return true;
  2977.     }

  2978.     /**
  2979.      * Tests if all of the CharSequences are empty ("") or null.
  2980.      *
  2981.      * <pre>
  2982.      * StringUtils.isAllEmpty(null)             = true
  2983.      * StringUtils.isAllEmpty(null, "")         = true
  2984.      * StringUtils.isAllEmpty(new String[] {})  = true
  2985.      * StringUtils.isAllEmpty(null, "foo")      = false
  2986.      * StringUtils.isAllEmpty("", "bar")        = false
  2987.      * StringUtils.isAllEmpty("bob", "")        = false
  2988.      * StringUtils.isAllEmpty("  bob  ", null)  = false
  2989.      * StringUtils.isAllEmpty(" ", "bar")       = false
  2990.      * StringUtils.isAllEmpty("foo", "bar")     = false
  2991.      * </pre>
  2992.      *
  2993.      * @param css  the CharSequences to check, may be null or empty
  2994.      * @return {@code true} if all of the CharSequences are empty or null
  2995.      * @since 3.6
  2996.      */
  2997.     public static boolean isAllEmpty(final CharSequence... css) {
  2998.         if (ArrayUtils.isEmpty(css)) {
  2999.             return true;
  3000.         }
  3001.         for (final CharSequence cs : css) {
  3002.             if (isNotEmpty(cs)) {
  3003.                 return false;
  3004.             }
  3005.         }
  3006.         return true;
  3007.     }

  3008.     /**
  3009.      * Tests if the CharSequence contains only lowercase characters.
  3010.      *
  3011.      * <p>{@code null} will return {@code false}.
  3012.      * An empty CharSequence (length()=0) will return {@code false}.</p>
  3013.      *
  3014.      * <pre>
  3015.      * StringUtils.isAllLowerCase(null)   = false
  3016.      * StringUtils.isAllLowerCase("")     = false
  3017.      * StringUtils.isAllLowerCase("  ")   = false
  3018.      * StringUtils.isAllLowerCase("abc")  = true
  3019.      * StringUtils.isAllLowerCase("abC")  = false
  3020.      * StringUtils.isAllLowerCase("ab c") = false
  3021.      * StringUtils.isAllLowerCase("ab1c") = false
  3022.      * StringUtils.isAllLowerCase("ab/c") = false
  3023.      * </pre>
  3024.      *
  3025.      * @param cs  the CharSequence to check, may be null
  3026.      * @return {@code true} if only contains lowercase characters, and is non-null
  3027.      * @since 2.5
  3028.      * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence)
  3029.      */
  3030.     public static boolean isAllLowerCase(final CharSequence cs) {
  3031.         if (isEmpty(cs)) {
  3032.             return false;
  3033.         }
  3034.         final int sz = cs.length();
  3035.         for (int i = 0; i < sz; i++) {
  3036.             if (!Character.isLowerCase(cs.charAt(i))) {
  3037.                 return false;
  3038.             }
  3039.         }
  3040.         return true;
  3041.     }

  3042.     /**
  3043.      * Tests if the CharSequence contains only uppercase characters.
  3044.      *
  3045.      * <p>{@code null} will return {@code false}.
  3046.      * An empty String (length()=0) will return {@code false}.</p>
  3047.      *
  3048.      * <pre>
  3049.      * StringUtils.isAllUpperCase(null)   = false
  3050.      * StringUtils.isAllUpperCase("")     = false
  3051.      * StringUtils.isAllUpperCase("  ")   = false
  3052.      * StringUtils.isAllUpperCase("ABC")  = true
  3053.      * StringUtils.isAllUpperCase("aBC")  = false
  3054.      * StringUtils.isAllUpperCase("A C")  = false
  3055.      * StringUtils.isAllUpperCase("A1C")  = false
  3056.      * StringUtils.isAllUpperCase("A/C")  = false
  3057.      * </pre>
  3058.      *
  3059.      * @param cs the CharSequence to check, may be null
  3060.      * @return {@code true} if only contains uppercase characters, and is non-null
  3061.      * @since 2.5
  3062.      * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence)
  3063.      */
  3064.     public static boolean isAllUpperCase(final CharSequence cs) {
  3065.         if (isEmpty(cs)) {
  3066.             return false;
  3067.         }
  3068.         final int sz = cs.length();
  3069.         for (int i = 0; i < sz; i++) {
  3070.             if (!Character.isUpperCase(cs.charAt(i))) {
  3071.                 return false;
  3072.             }
  3073.         }
  3074.         return true;
  3075.     }

  3076.     /**
  3077.      * Tests if the CharSequence contains only Unicode letters.
  3078.      *
  3079.      * <p>{@code null} will return {@code false}.
  3080.      * An empty CharSequence (length()=0) will return {@code false}.</p>
  3081.      *
  3082.      * <pre>
  3083.      * StringUtils.isAlpha(null)   = false
  3084.      * StringUtils.isAlpha("")     = false
  3085.      * StringUtils.isAlpha("  ")   = false
  3086.      * StringUtils.isAlpha("abc")  = true
  3087.      * StringUtils.isAlpha("ab2c") = false
  3088.      * StringUtils.isAlpha("ab-c") = false
  3089.      * </pre>
  3090.      *
  3091.      * @param cs  the CharSequence to check, may be null
  3092.      * @return {@code true} if only contains letters, and is non-null
  3093.      * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence)
  3094.      * @since 3.0 Changed "" to return false and not true
  3095.      */
  3096.     public static boolean isAlpha(final CharSequence cs) {
  3097.         if (isEmpty(cs)) {
  3098.             return false;
  3099.         }
  3100.         final int sz = cs.length();
  3101.         for (int i = 0; i < sz; i++) {
  3102.             if (!Character.isLetter(cs.charAt(i))) {
  3103.                 return false;
  3104.             }
  3105.         }
  3106.         return true;
  3107.     }

  3108.     /**
  3109.      * Tests if the CharSequence contains only Unicode letters or digits.
  3110.      *
  3111.      * <p>{@code null} will return {@code false}.
  3112.      * An empty CharSequence (length()=0) will return {@code false}.</p>
  3113.      *
  3114.      * <pre>
  3115.      * StringUtils.isAlphanumeric(null)   = false
  3116.      * StringUtils.isAlphanumeric("")     = false
  3117.      * StringUtils.isAlphanumeric("  ")   = false
  3118.      * StringUtils.isAlphanumeric("abc")  = true
  3119.      * StringUtils.isAlphanumeric("ab c") = false
  3120.      * StringUtils.isAlphanumeric("ab2c") = true
  3121.      * StringUtils.isAlphanumeric("ab-c") = false
  3122.      * </pre>
  3123.      *
  3124.      * @param cs  the CharSequence to check, may be null
  3125.      * @return {@code true} if only contains letters or digits,
  3126.      *  and is non-null
  3127.      * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence)
  3128.      * @since 3.0 Changed "" to return false and not true
  3129.      */
  3130.     public static boolean isAlphanumeric(final CharSequence cs) {
  3131.         if (isEmpty(cs)) {
  3132.             return false;
  3133.         }
  3134.         final int sz = cs.length();
  3135.         for (int i = 0; i < sz; i++) {
  3136.             if (!Character.isLetterOrDigit(cs.charAt(i))) {
  3137.                 return false;
  3138.             }
  3139.         }
  3140.         return true;
  3141.     }

  3142.     /**
  3143.      * Tests if the CharSequence contains only Unicode letters, digits
  3144.      * or space ({@code ' '}).
  3145.      *
  3146.      * <p>{@code null} will return {@code false}.
  3147.      * An empty CharSequence (length()=0) will return {@code true}.</p>
  3148.      *
  3149.      * <pre>
  3150.      * StringUtils.isAlphanumericSpace(null)   = false
  3151.      * StringUtils.isAlphanumericSpace("")     = true
  3152.      * StringUtils.isAlphanumericSpace("  ")   = true
  3153.      * StringUtils.isAlphanumericSpace("abc")  = true
  3154.      * StringUtils.isAlphanumericSpace("ab c") = true
  3155.      * StringUtils.isAlphanumericSpace("ab2c") = true
  3156.      * StringUtils.isAlphanumericSpace("ab-c") = false
  3157.      * </pre>
  3158.      *
  3159.      * @param cs  the CharSequence to check, may be null
  3160.      * @return {@code true} if only contains letters, digits or space,
  3161.      *  and is non-null
  3162.      * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence)
  3163.      */
  3164.     public static boolean isAlphanumericSpace(final CharSequence cs) {
  3165.         if (cs == null) {
  3166.             return false;
  3167.         }
  3168.         final int sz = cs.length();
  3169.         for (int i = 0; i < sz; i++) {
  3170.             final char nowChar = cs.charAt(i);
  3171.             if (nowChar != ' ' && !Character.isLetterOrDigit(nowChar)) {
  3172.                 return false;
  3173.             }
  3174.         }
  3175.         return true;
  3176.     }

  3177.     /**
  3178.      * Tests if the CharSequence contains only Unicode letters and
  3179.      * space (' ').
  3180.      *
  3181.      * <p>{@code null} will return {@code false}
  3182.      * An empty CharSequence (length()=0) will return {@code true}.</p>
  3183.      *
  3184.      * <pre>
  3185.      * StringUtils.isAlphaSpace(null)   = false
  3186.      * StringUtils.isAlphaSpace("")     = true
  3187.      * StringUtils.isAlphaSpace("  ")   = true
  3188.      * StringUtils.isAlphaSpace("abc")  = true
  3189.      * StringUtils.isAlphaSpace("ab c") = true
  3190.      * StringUtils.isAlphaSpace("ab2c") = false
  3191.      * StringUtils.isAlphaSpace("ab-c") = false
  3192.      * </pre>
  3193.      *
  3194.      * @param cs  the CharSequence to check, may be null
  3195.      * @return {@code true} if only contains letters and space,
  3196.      *  and is non-null
  3197.      * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence)
  3198.      */
  3199.     public static boolean isAlphaSpace(final CharSequence cs) {
  3200.         if (cs == null) {
  3201.             return false;
  3202.         }
  3203.         final int sz = cs.length();
  3204.         for (int i = 0; i < sz; i++) {
  3205.             final char nowChar = cs.charAt(i);
  3206.             if (nowChar != ' ' && !Character.isLetter(nowChar)) {
  3207.                 return false;
  3208.             }
  3209.         }
  3210.         return true;
  3211.     }

  3212.     /**
  3213.      * Tests if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or {@code null}).
  3214.      *
  3215.      * <p>
  3216.      * Whitespace is defined by {@link Character#isWhitespace(char)}.
  3217.      * </p>
  3218.      *
  3219.      * <pre>
  3220.      * StringUtils.isAnyBlank((String) null)    = true
  3221.      * StringUtils.isAnyBlank((String[]) null)  = false
  3222.      * StringUtils.isAnyBlank(null, "foo")      = true
  3223.      * StringUtils.isAnyBlank(null, null)       = true
  3224.      * StringUtils.isAnyBlank("", "bar")        = true
  3225.      * StringUtils.isAnyBlank("bob", "")        = true
  3226.      * StringUtils.isAnyBlank("  bob  ", null)  = true
  3227.      * StringUtils.isAnyBlank(" ", "bar")       = true
  3228.      * StringUtils.isAnyBlank(new String[] {})  = false
  3229.      * StringUtils.isAnyBlank(new String[]{""}) = true
  3230.      * StringUtils.isAnyBlank("foo", "bar")     = false
  3231.      * </pre>
  3232.      *
  3233.      * @param css the CharSequences to check, may be null or empty
  3234.      * @return {@code true} if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or {@code null})
  3235.      * @see #isBlank(CharSequence)
  3236.      * @since 3.2
  3237.      */
  3238.     public static boolean isAnyBlank(final CharSequence... css) {
  3239.         if (ArrayUtils.isEmpty(css)) {
  3240.             return false;
  3241.         }
  3242.         for (final CharSequence cs : css) {
  3243.             if (isBlank(cs)) {
  3244.                 return true;
  3245.             }
  3246.         }
  3247.         return false;
  3248.     }

  3249.     /**
  3250.      * Tests if any of the CharSequences are empty ("") or null.
  3251.      *
  3252.      * <pre>
  3253.      * StringUtils.isAnyEmpty((String) null)    = true
  3254.      * StringUtils.isAnyEmpty((String[]) null)  = false
  3255.      * StringUtils.isAnyEmpty(null, "foo")      = true
  3256.      * StringUtils.isAnyEmpty("", "bar")        = true
  3257.      * StringUtils.isAnyEmpty("bob", "")        = true
  3258.      * StringUtils.isAnyEmpty("  bob  ", null)  = true
  3259.      * StringUtils.isAnyEmpty(" ", "bar")       = false
  3260.      * StringUtils.isAnyEmpty("foo", "bar")     = false
  3261.      * StringUtils.isAnyEmpty(new String[]{})   = false
  3262.      * StringUtils.isAnyEmpty(new String[]{""}) = true
  3263.      * </pre>
  3264.      *
  3265.      * @param css  the CharSequences to check, may be null or empty
  3266.      * @return {@code true} if any of the CharSequences are empty or null
  3267.      * @since 3.2
  3268.      */
  3269.     public static boolean isAnyEmpty(final CharSequence... css) {
  3270.         if (ArrayUtils.isEmpty(css)) {
  3271.             return false;
  3272.         }
  3273.         for (final CharSequence cs : css) {
  3274.             if (isEmpty(cs)) {
  3275.                 return true;
  3276.             }
  3277.         }
  3278.         return false;
  3279.     }

  3280.     /**
  3281.      * Tests if the CharSequence contains only ASCII printable characters.
  3282.      *
  3283.      * <p>{@code null} will return {@code false}.
  3284.      * An empty CharSequence (length()=0) will return {@code true}.</p>
  3285.      *
  3286.      * <pre>
  3287.      * StringUtils.isAsciiPrintable(null)     = false
  3288.      * StringUtils.isAsciiPrintable("")       = true
  3289.      * StringUtils.isAsciiPrintable(" ")      = true
  3290.      * StringUtils.isAsciiPrintable("Ceki")   = true
  3291.      * StringUtils.isAsciiPrintable("ab2c")   = true
  3292.      * StringUtils.isAsciiPrintable("!ab-c~") = true
  3293.      * StringUtils.isAsciiPrintable("\u0020") = true
  3294.      * StringUtils.isAsciiPrintable("\u0021") = true
  3295.      * StringUtils.isAsciiPrintable("\u007e") = true
  3296.      * StringUtils.isAsciiPrintable("\u007f") = false
  3297.      * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
  3298.      * </pre>
  3299.      *
  3300.      * @param cs the CharSequence to check, may be null
  3301.      * @return {@code true} if every character is in the range
  3302.      *  32 through 126
  3303.      * @since 2.1
  3304.      * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence)
  3305.      */
  3306.     public static boolean isAsciiPrintable(final CharSequence cs) {
  3307.         if (cs == null) {
  3308.             return false;
  3309.         }
  3310.         final int sz = cs.length();
  3311.         for (int i = 0; i < sz; i++) {
  3312.             if (!CharUtils.isAsciiPrintable(cs.charAt(i))) {
  3313.                 return false;
  3314.             }
  3315.         }
  3316.         return true;
  3317.     }

  3318.     /**
  3319.      * Tests if a CharSequence is empty ({@code "")}, null, or contains only whitespace as defined by {@link Character#isWhitespace(char)}.
  3320.      *
  3321.      * <pre>
  3322.      * StringUtils.isBlank(null)      = true
  3323.      * StringUtils.isBlank("")        = true
  3324.      * StringUtils.isBlank(" ")       = true
  3325.      * StringUtils.isBlank("bob")     = false
  3326.      * StringUtils.isBlank("  bob  ") = false
  3327.      * </pre>
  3328.      *
  3329.      * @param cs the CharSequence to check, may be null
  3330.      * @return {@code true} if the CharSequence is null, empty or whitespace only
  3331.      * @since 2.0
  3332.      * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
  3333.      */
  3334.     public static boolean isBlank(final CharSequence cs) {
  3335.         final int strLen = length(cs);
  3336.         if (strLen == 0) {
  3337.             return true;
  3338.         }
  3339.         for (int i = 0; i < strLen; i++) {
  3340.             if (!Character.isWhitespace(cs.charAt(i))) {
  3341.                 return false;
  3342.             }
  3343.         }
  3344.         return true;
  3345.     }

  3346.     /**
  3347.      * Tests if a CharSequence is empty ("") or null.
  3348.      *
  3349.      * <pre>
  3350.      * StringUtils.isEmpty(null)      = true
  3351.      * StringUtils.isEmpty("")        = true
  3352.      * StringUtils.isEmpty(" ")       = false
  3353.      * StringUtils.isEmpty("bob")     = false
  3354.      * StringUtils.isEmpty("  bob  ") = false
  3355.      * </pre>
  3356.      *
  3357.      * <p>NOTE: This method changed in Lang version 2.0.
  3358.      * It no longer trims the CharSequence.
  3359.      * That functionality is available in isBlank().</p>
  3360.      *
  3361.      * @param cs  the CharSequence to check, may be null
  3362.      * @return {@code true} if the CharSequence is empty or null
  3363.      * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
  3364.      */
  3365.     public static boolean isEmpty(final CharSequence cs) {
  3366.         return cs == null || cs.length() == 0;
  3367.     }

  3368.     /**
  3369.      * Tests if the CharSequence contains mixed casing of both uppercase and lowercase characters.
  3370.      *
  3371.      * <p>{@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return
  3372.      * {@code false}.</p>
  3373.      *
  3374.      * <pre>
  3375.      * StringUtils.isMixedCase(null)    = false
  3376.      * StringUtils.isMixedCase("")      = false
  3377.      * StringUtils.isMixedCase(" ")     = false
  3378.      * StringUtils.isMixedCase("ABC")   = false
  3379.      * StringUtils.isMixedCase("abc")   = false
  3380.      * StringUtils.isMixedCase("aBc")   = true
  3381.      * StringUtils.isMixedCase("A c")   = true
  3382.      * StringUtils.isMixedCase("A1c")   = true
  3383.      * StringUtils.isMixedCase("a/C")   = true
  3384.      * StringUtils.isMixedCase("aC\t")  = true
  3385.      * </pre>
  3386.      *
  3387.      * @param cs the CharSequence to check, may be null
  3388.      * @return {@code true} if the CharSequence contains both uppercase and lowercase characters
  3389.      * @since 3.5
  3390.      */
  3391.     public static boolean isMixedCase(final CharSequence cs) {
  3392.         if (isEmpty(cs) || cs.length() == 1) {
  3393.             return false;
  3394.         }
  3395.         boolean containsUppercase = false;
  3396.         boolean containsLowercase = false;
  3397.         final int sz = cs.length();
  3398.         for (int i = 0; i < sz; i++) {
  3399.             final char nowChar = cs.charAt(i);
  3400.             if (Character.isUpperCase(nowChar)) {
  3401.                 containsUppercase = true;
  3402.             } else if (Character.isLowerCase(nowChar)) {
  3403.                 containsLowercase = true;
  3404.             }
  3405.             if (containsUppercase && containsLowercase) {
  3406.                 return true;
  3407.             }
  3408.         }
  3409.         return false;
  3410.     }

  3411.     /**
  3412.      * Tests if none of the CharSequences are empty (""), null or whitespace only.
  3413.      *
  3414.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  3415.      *
  3416.      * <pre>
  3417.      * StringUtils.isNoneBlank((String) null)    = false
  3418.      * StringUtils.isNoneBlank((String[]) null)  = true
  3419.      * StringUtils.isNoneBlank(null, "foo")      = false
  3420.      * StringUtils.isNoneBlank(null, null)       = false
  3421.      * StringUtils.isNoneBlank("", "bar")        = false
  3422.      * StringUtils.isNoneBlank("bob", "")        = false
  3423.      * StringUtils.isNoneBlank("  bob  ", null)  = false
  3424.      * StringUtils.isNoneBlank(" ", "bar")       = false
  3425.      * StringUtils.isNoneBlank(new String[] {})  = true
  3426.      * StringUtils.isNoneBlank(new String[]{""}) = false
  3427.      * StringUtils.isNoneBlank("foo", "bar")     = true
  3428.      * </pre>
  3429.      *
  3430.      * @param css  the CharSequences to check, may be null or empty
  3431.      * @return {@code true} if none of the CharSequences are empty or null or whitespace only
  3432.      * @since 3.2
  3433.      */
  3434.     public static boolean isNoneBlank(final CharSequence... css) {
  3435.       return !isAnyBlank(css);
  3436.     }

  3437.     /**
  3438.      * Tests if none of the CharSequences are empty ("") or null.
  3439.      *
  3440.      * <pre>
  3441.      * StringUtils.isNoneEmpty((String) null)    = false
  3442.      * StringUtils.isNoneEmpty((String[]) null)  = true
  3443.      * StringUtils.isNoneEmpty(null, "foo")      = false
  3444.      * StringUtils.isNoneEmpty("", "bar")        = false
  3445.      * StringUtils.isNoneEmpty("bob", "")        = false
  3446.      * StringUtils.isNoneEmpty("  bob  ", null)  = false
  3447.      * StringUtils.isNoneEmpty(new String[] {})  = true
  3448.      * StringUtils.isNoneEmpty(new String[]{""}) = false
  3449.      * StringUtils.isNoneEmpty(" ", "bar")       = true
  3450.      * StringUtils.isNoneEmpty("foo", "bar")     = true
  3451.      * </pre>
  3452.      *
  3453.      * @param css  the CharSequences to check, may be null or empty
  3454.      * @return {@code true} if none of the CharSequences are empty or null
  3455.      * @since 3.2
  3456.      */
  3457.     public static boolean isNoneEmpty(final CharSequence... css) {
  3458.       return !isAnyEmpty(css);
  3459.     }

  3460.     /**
  3461.      * Tests if a CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or {@code null}).
  3462.      *
  3463.      * <p>
  3464.      * Whitespace is defined by {@link Character#isWhitespace(char)}.
  3465.      * </p>
  3466.      *
  3467.      * <pre>
  3468.      * StringUtils.isNotBlank(null)      = false
  3469.      * StringUtils.isNotBlank("")        = false
  3470.      * StringUtils.isNotBlank(" ")       = false
  3471.      * StringUtils.isNotBlank("bob")     = true
  3472.      * StringUtils.isNotBlank("  bob  ") = true
  3473.      * </pre>
  3474.      *
  3475.      * @param cs the CharSequence to check, may be null
  3476.      * @return {@code true} if the CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or {@code null})
  3477.      * @see #isBlank(CharSequence)
  3478.      * @since 2.0
  3479.      * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
  3480.      */
  3481.     public static boolean isNotBlank(final CharSequence cs) {
  3482.         return !isBlank(cs);
  3483.     }

  3484.     /**
  3485.      * Tests if a CharSequence is not empty ("") and not null.
  3486.      *
  3487.      * <pre>
  3488.      * StringUtils.isNotEmpty(null)      = false
  3489.      * StringUtils.isNotEmpty("")        = false
  3490.      * StringUtils.isNotEmpty(" ")       = true
  3491.      * StringUtils.isNotEmpty("bob")     = true
  3492.      * StringUtils.isNotEmpty("  bob  ") = true
  3493.      * </pre>
  3494.      *
  3495.      * @param cs  the CharSequence to check, may be null
  3496.      * @return {@code true} if the CharSequence is not empty and not null
  3497.      * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
  3498.      */
  3499.     public static boolean isNotEmpty(final CharSequence cs) {
  3500.         return !isEmpty(cs);
  3501.     }

  3502.     /**
  3503.      * Tests if the CharSequence contains only Unicode digits.
  3504.      * A decimal point is not a Unicode digit and returns false.
  3505.      *
  3506.      * <p>{@code null} will return {@code false}.
  3507.      * An empty CharSequence (length()=0) will return {@code false}.</p>
  3508.      *
  3509.      * <p>Note that the method does not allow for a leading sign, either positive or negative.
  3510.      * Also, if a String passes the numeric test, it may still generate a NumberFormatException
  3511.      * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range
  3512.      * for int or long respectively.</p>
  3513.      *
  3514.      * <pre>
  3515.      * StringUtils.isNumeric(null)   = false
  3516.      * StringUtils.isNumeric("")     = false
  3517.      * StringUtils.isNumeric("  ")   = false
  3518.      * StringUtils.isNumeric("123")  = true
  3519.      * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
  3520.      * StringUtils.isNumeric("12 3") = false
  3521.      * StringUtils.isNumeric("ab2c") = false
  3522.      * StringUtils.isNumeric("12-3") = false
  3523.      * StringUtils.isNumeric("12.3") = false
  3524.      * StringUtils.isNumeric("-123") = false
  3525.      * StringUtils.isNumeric("+123") = false
  3526.      * </pre>
  3527.      *
  3528.      * @param cs  the CharSequence to check, may be null
  3529.      * @return {@code true} if only contains digits, and is non-null
  3530.      * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
  3531.      * @since 3.0 Changed "" to return false and not true
  3532.      */
  3533.     public static boolean isNumeric(final CharSequence cs) {
  3534.         if (isEmpty(cs)) {
  3535.             return false;
  3536.         }
  3537.         final int sz = cs.length();
  3538.         for (int i = 0; i < sz; i++) {
  3539.             if (!Character.isDigit(cs.charAt(i))) {
  3540.                 return false;
  3541.             }
  3542.         }
  3543.         return true;
  3544.     }

  3545.     /**
  3546.      * Tests if the CharSequence contains only Unicode digits or space
  3547.      * ({@code ' '}).
  3548.      * A decimal point is not a Unicode digit and returns false.
  3549.      *
  3550.      * <p>{@code null} will return {@code false}.
  3551.      * An empty CharSequence (length()=0) will return {@code true}.</p>
  3552.      *
  3553.      * <pre>
  3554.      * StringUtils.isNumericSpace(null)   = false
  3555.      * StringUtils.isNumericSpace("")     = true
  3556.      * StringUtils.isNumericSpace("  ")   = true
  3557.      * StringUtils.isNumericSpace("123")  = true
  3558.      * StringUtils.isNumericSpace("12 3") = true
  3559.      * StringUtils.isNumericSpace("\u0967\u0968\u0969")   = true
  3560.      * StringUtils.isNumericSpace("\u0967\u0968 \u0969")  = true
  3561.      * StringUtils.isNumericSpace("ab2c") = false
  3562.      * StringUtils.isNumericSpace("12-3") = false
  3563.      * StringUtils.isNumericSpace("12.3") = false
  3564.      * </pre>
  3565.      *
  3566.      * @param cs  the CharSequence to check, may be null
  3567.      * @return {@code true} if only contains digits or space,
  3568.      *  and is non-null
  3569.      * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence)
  3570.      */
  3571.     public static boolean isNumericSpace(final CharSequence cs) {
  3572.         if (cs == null) {
  3573.             return false;
  3574.         }
  3575.         final int sz = cs.length();
  3576.         for (int i = 0; i < sz; i++) {
  3577.             final char nowChar = cs.charAt(i);
  3578.             if (nowChar != ' ' && !Character.isDigit(nowChar)) {
  3579.                 return false;
  3580.             }
  3581.         }
  3582.         return true;
  3583.     }

  3584.     /**
  3585.      * Tests if the CharSequence contains only whitespace.
  3586.      *
  3587.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  3588.      *
  3589.      * <p>{@code null} will return {@code false}.
  3590.      * An empty CharSequence (length()=0) will return {@code true}.</p>
  3591.      *
  3592.      * <pre>
  3593.      * StringUtils.isWhitespace(null)   = false
  3594.      * StringUtils.isWhitespace("")     = true
  3595.      * StringUtils.isWhitespace("  ")   = true
  3596.      * StringUtils.isWhitespace("abc")  = false
  3597.      * StringUtils.isWhitespace("ab2c") = false
  3598.      * StringUtils.isWhitespace("ab-c") = false
  3599.      * </pre>
  3600.      *
  3601.      * @param cs  the CharSequence to check, may be null
  3602.      * @return {@code true} if only contains whitespace, and is non-null
  3603.      * @since 2.0
  3604.      * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence)
  3605.      */
  3606.     public static boolean isWhitespace(final CharSequence cs) {
  3607.         if (cs == null) {
  3608.             return false;
  3609.         }
  3610.         final int sz = cs.length();
  3611.         for (int i = 0; i < sz; i++) {
  3612.             if (!Character.isWhitespace(cs.charAt(i))) {
  3613.                 return false;
  3614.             }
  3615.         }
  3616.         return true;
  3617.     }

  3618.     /**
  3619.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3620.      *
  3621.      * <p>
  3622.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3623.      * by empty strings.
  3624.      * </p>
  3625.      *
  3626.      * <pre>
  3627.      * StringUtils.join(null, *)             = null
  3628.      * StringUtils.join([], *)               = ""
  3629.      * StringUtils.join([null], *)           = ""
  3630.      * StringUtils.join([false, false], ';') = "false;false"
  3631.      * </pre>
  3632.      *
  3633.      * @param array
  3634.      *            the array of values to join together, may be null
  3635.      * @param delimiter
  3636.      *            the separator character to use
  3637.      * @return the joined String, {@code null} if null array input
  3638.      * @since 3.12.0
  3639.      */
  3640.     public static String join(final boolean[] array, final char delimiter) {
  3641.         if (array == null) {
  3642.             return null;
  3643.         }
  3644.         return join(array, delimiter, 0, array.length);
  3645.     }

  3646.     /**
  3647.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3648.      *
  3649.      * <p>
  3650.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3651.      * by empty strings.
  3652.      * </p>
  3653.      *
  3654.      * <pre>
  3655.      * StringUtils.join(null, *)                  = null
  3656.      * StringUtils.join([], *)                    = ""
  3657.      * StringUtils.join([null], *)                = ""
  3658.      * StringUtils.join([true, false, true], ';') = "true;false;true"
  3659.      * </pre>
  3660.      *
  3661.      * @param array
  3662.      *            the array of values to join together, may be null
  3663.      * @param delimiter
  3664.      *            the separator character to use
  3665.      * @param startIndex
  3666.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  3667.      *            array
  3668.      * @param endIndex
  3669.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  3670.      *            the array
  3671.      * @return the joined String, {@code null} if null array input
  3672.      * @since 3.12.0
  3673.      */
  3674.     public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) {
  3675.         if (array == null) {
  3676.             return null;
  3677.         }
  3678.         if (endIndex - startIndex <= 0) {
  3679.             return EMPTY;
  3680.         }
  3681.         final StringBuilder stringBuilder = new StringBuilder(array.length * 5 + array.length - 1);
  3682.         for (int i = startIndex; i < endIndex; i++) {
  3683.             stringBuilder
  3684.                     .append(array[i])
  3685.                     .append(delimiter);
  3686.         }
  3687.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  3688.     }

  3689.     /**
  3690.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3691.      *
  3692.      * <p>
  3693.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3694.      * by empty strings.
  3695.      * </p>
  3696.      *
  3697.      * <pre>
  3698.      * StringUtils.join(null, *)         = null
  3699.      * StringUtils.join([], *)           = ""
  3700.      * StringUtils.join([null], *)       = ""
  3701.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3702.      * StringUtils.join([1, 2, 3], null) = "123"
  3703.      * </pre>
  3704.      *
  3705.      * @param array
  3706.      *            the array of values to join together, may be null
  3707.      * @param delimiter
  3708.      *            the separator character to use
  3709.      * @return the joined String, {@code null} if null array input
  3710.      * @since 3.2
  3711.      */
  3712.     public static String join(final byte[] array, final char delimiter) {
  3713.         if (array == null) {
  3714.             return null;
  3715.         }
  3716.         return join(array, delimiter, 0, array.length);
  3717.     }

  3718.     /**
  3719.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3720.      *
  3721.      * <p>
  3722.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3723.      * by empty strings.
  3724.      * </p>
  3725.      *
  3726.      * <pre>
  3727.      * StringUtils.join(null, *)         = null
  3728.      * StringUtils.join([], *)           = ""
  3729.      * StringUtils.join([null], *)       = ""
  3730.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3731.      * StringUtils.join([1, 2, 3], null) = "123"
  3732.      * </pre>
  3733.      *
  3734.      * @param array
  3735.      *            the array of values to join together, may be null
  3736.      * @param delimiter
  3737.      *            the separator character to use
  3738.      * @param startIndex
  3739.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  3740.      *            array
  3741.      * @param endIndex
  3742.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  3743.      *            the array
  3744.      * @return the joined String, {@code null} if null array input
  3745.      * @since 3.2
  3746.      */
  3747.     public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) {
  3748.         if (array == null) {
  3749.             return null;
  3750.         }
  3751.         if (endIndex - startIndex <= 0) {
  3752.             return EMPTY;
  3753.         }
  3754.         final StringBuilder stringBuilder = new StringBuilder();
  3755.         for (int i = startIndex; i < endIndex; i++) {
  3756.             stringBuilder
  3757.                     .append(array[i])
  3758.                     .append(delimiter);
  3759.         }
  3760.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  3761.     }

  3762.     /**
  3763.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3764.      *
  3765.      * <p>
  3766.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3767.      * by empty strings.
  3768.      * </p>
  3769.      *
  3770.      * <pre>
  3771.      * StringUtils.join(null, *)         = null
  3772.      * StringUtils.join([], *)           = ""
  3773.      * StringUtils.join([null], *)       = ""
  3774.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3775.      * StringUtils.join([1, 2, 3], null) = "123"
  3776.      * </pre>
  3777.      *
  3778.      * @param array
  3779.      *            the array of values to join together, may be null
  3780.      * @param delimiter
  3781.      *            the separator character to use
  3782.      * @return the joined String, {@code null} if null array input
  3783.      * @since 3.2
  3784.      */
  3785.     public static String join(final char[] array, final char delimiter) {
  3786.         if (array == null) {
  3787.             return null;
  3788.         }
  3789.         return join(array, delimiter, 0, array.length);
  3790.     }

  3791.     /**
  3792.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3793.      *
  3794.      * <p>
  3795.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3796.      * by empty strings.
  3797.      * </p>
  3798.      *
  3799.      * <pre>
  3800.      * StringUtils.join(null, *)         = null
  3801.      * StringUtils.join([], *)           = ""
  3802.      * StringUtils.join([null], *)       = ""
  3803.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3804.      * StringUtils.join([1, 2, 3], null) = "123"
  3805.      * </pre>
  3806.      *
  3807.      * @param array
  3808.      *            the array of values to join together, may be null
  3809.      * @param delimiter
  3810.      *            the separator character to use
  3811.      * @param startIndex
  3812.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  3813.      *            array
  3814.      * @param endIndex
  3815.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  3816.      *            the array
  3817.      * @return the joined String, {@code null} if null array input
  3818.      * @since 3.2
  3819.      */
  3820.     public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) {
  3821.         if (array == null) {
  3822.             return null;
  3823.         }
  3824.         if (endIndex - startIndex <= 0) {
  3825.             return EMPTY;
  3826.         }
  3827.         final StringBuilder stringBuilder = new StringBuilder(array.length * 2 - 1);
  3828.         for (int i = startIndex; i < endIndex; i++) {
  3829.             stringBuilder
  3830.                     .append(array[i])
  3831.                     .append(delimiter);
  3832.         }
  3833.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  3834.     }

  3835.     /**
  3836.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3837.      *
  3838.      * <p>
  3839.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3840.      * by empty strings.
  3841.      * </p>
  3842.      *
  3843.      * <pre>
  3844.      * StringUtils.join(null, *)               = null
  3845.      * StringUtils.join([], *)                 = ""
  3846.      * StringUtils.join([null], *)             = ""
  3847.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3848.      * StringUtils.join([1, 2, 3], null) = "123"
  3849.      * </pre>
  3850.      *
  3851.      * @param array
  3852.      *            the array of values to join together, may be null
  3853.      * @param delimiter
  3854.      *            the separator character to use
  3855.      * @return the joined String, {@code null} if null array input
  3856.      * @since 3.2
  3857.      */
  3858.     public static String join(final double[] array, final char delimiter) {
  3859.         if (array == null) {
  3860.             return null;
  3861.         }
  3862.         return join(array, delimiter, 0, array.length);
  3863.     }

  3864.     /**
  3865.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3866.      *
  3867.      * <p>
  3868.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3869.      * by empty strings.
  3870.      * </p>
  3871.      *
  3872.      * <pre>
  3873.      * StringUtils.join(null, *)               = null
  3874.      * StringUtils.join([], *)                 = ""
  3875.      * StringUtils.join([null], *)             = ""
  3876.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3877.      * StringUtils.join([1, 2, 3], null) = "123"
  3878.      * </pre>
  3879.      *
  3880.      * @param array
  3881.      *            the array of values to join together, may be null
  3882.      * @param delimiter
  3883.      *            the separator character to use
  3884.      * @param startIndex
  3885.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  3886.      *            array
  3887.      * @param endIndex
  3888.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  3889.      *            the array
  3890.      * @return the joined String, {@code null} if null array input
  3891.      * @since 3.2
  3892.      */
  3893.     public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) {
  3894.         if (array == null) {
  3895.             return null;
  3896.         }
  3897.         if (endIndex - startIndex <= 0) {
  3898.             return EMPTY;
  3899.         }
  3900.         final StringBuilder stringBuilder = new StringBuilder();
  3901.         for (int i = startIndex; i < endIndex; i++) {
  3902.             stringBuilder
  3903.                     .append(array[i])
  3904.                     .append(delimiter);
  3905.         }
  3906.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  3907.     }

  3908.     /**
  3909.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3910.      *
  3911.      * <p>
  3912.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3913.      * by empty strings.
  3914.      * </p>
  3915.      *
  3916.      * <pre>
  3917.      * StringUtils.join(null, *)               = null
  3918.      * StringUtils.join([], *)                 = ""
  3919.      * StringUtils.join([null], *)             = ""
  3920.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3921.      * StringUtils.join([1, 2, 3], null) = "123"
  3922.      * </pre>
  3923.      *
  3924.      * @param array
  3925.      *            the array of values to join together, may be null
  3926.      * @param delimiter
  3927.      *            the separator character to use
  3928.      * @return the joined String, {@code null} if null array input
  3929.      * @since 3.2
  3930.      */
  3931.     public static String join(final float[] array, final char delimiter) {
  3932.         if (array == null) {
  3933.             return null;
  3934.         }
  3935.         return join(array, delimiter, 0, array.length);
  3936.     }

  3937.     /**
  3938.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3939.      *
  3940.      * <p>
  3941.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3942.      * by empty strings.
  3943.      * </p>
  3944.      *
  3945.      * <pre>
  3946.      * StringUtils.join(null, *)               = null
  3947.      * StringUtils.join([], *)                 = ""
  3948.      * StringUtils.join([null], *)             = ""
  3949.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3950.      * StringUtils.join([1, 2, 3], null) = "123"
  3951.      * </pre>
  3952.      *
  3953.      * @param array
  3954.      *            the array of values to join together, may be null
  3955.      * @param delimiter
  3956.      *            the separator character to use
  3957.      * @param startIndex
  3958.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  3959.      *            array
  3960.      * @param endIndex
  3961.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  3962.      *            the array
  3963.      * @return the joined String, {@code null} if null array input
  3964.      * @since 3.2
  3965.      */
  3966.     public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) {
  3967.         if (array == null) {
  3968.             return null;
  3969.         }
  3970.         if (endIndex - startIndex <= 0) {
  3971.             return EMPTY;
  3972.         }
  3973.         final StringBuilder stringBuilder = new StringBuilder();
  3974.         for (int i = startIndex; i < endIndex; i++) {
  3975.             stringBuilder
  3976.                     .append(array[i])
  3977.                     .append(delimiter);
  3978.         }
  3979.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  3980.     }

  3981.     /**
  3982.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3983.      *
  3984.      * <p>
  3985.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3986.      * by empty strings.
  3987.      * </p>
  3988.      *
  3989.      * <pre>
  3990.      * StringUtils.join(null, *)               = null
  3991.      * StringUtils.join([], *)                 = ""
  3992.      * StringUtils.join([null], *)             = ""
  3993.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3994.      * StringUtils.join([1, 2, 3], null) = "123"
  3995.      * </pre>
  3996.      *
  3997.      * @param array
  3998.      *            the array of values to join together, may be null
  3999.      * @param separator
  4000.      *            the separator character to use
  4001.      * @return the joined String, {@code null} if null array input
  4002.      * @since 3.2
  4003.      */
  4004.     public static String join(final int[] array, final char separator) {
  4005.         if (array == null) {
  4006.             return null;
  4007.         }
  4008.         return join(array, separator, 0, array.length);
  4009.     }

  4010.     /**
  4011.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4012.      *
  4013.      * <p>
  4014.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4015.      * by empty strings.
  4016.      * </p>
  4017.      *
  4018.      * <pre>
  4019.      * StringUtils.join(null, *)               = null
  4020.      * StringUtils.join([], *)                 = ""
  4021.      * StringUtils.join([null], *)             = ""
  4022.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4023.      * StringUtils.join([1, 2, 3], null) = "123"
  4024.      * </pre>
  4025.      *
  4026.      * @param array
  4027.      *            the array of values to join together, may be null
  4028.      * @param delimiter
  4029.      *            the separator character to use
  4030.      * @param startIndex
  4031.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  4032.      *            array
  4033.      * @param endIndex
  4034.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  4035.      *            the array
  4036.      * @return the joined String, {@code null} if null array input
  4037.      * @since 3.2
  4038.      */
  4039.     public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) {
  4040.         if (array == null) {
  4041.             return null;
  4042.         }
  4043.         if (endIndex - startIndex <= 0) {
  4044.             return EMPTY;
  4045.         }
  4046.         final StringBuilder stringBuilder = new StringBuilder();
  4047.         for (int i = startIndex; i < endIndex; i++) {
  4048.             stringBuilder
  4049.                     .append(array[i])
  4050.                     .append(delimiter);
  4051.         }
  4052.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  4053.     }

  4054.     /**
  4055.      * Joins the elements of the provided {@link Iterable} into
  4056.      * a single String containing the provided elements.
  4057.      *
  4058.      * <p>No delimiter is added before or after the list. Null objects or empty
  4059.      * strings within the iteration are represented by empty strings.</p>
  4060.      *
  4061.      * <p>See the examples here: {@link #join(Object[],char)}.</p>
  4062.      *
  4063.      * @param iterable  the {@link Iterable} providing the values to join together, may be null
  4064.      * @param separator  the separator character to use
  4065.      * @return the joined String, {@code null} if null iterator input
  4066.      * @since 2.3
  4067.      */
  4068.     public static String join(final Iterable<?> iterable, final char separator) {
  4069.         return iterable != null ? join(iterable.iterator(), separator) : null;
  4070.     }

  4071.     /**
  4072.      * Joins the elements of the provided {@link Iterable} into
  4073.      * a single String containing the provided elements.
  4074.      *
  4075.      * <p>No delimiter is added before or after the list.
  4076.      * A {@code null} separator is the same as an empty String ("").</p>
  4077.      *
  4078.      * <p>See the examples here: {@link #join(Object[],String)}.</p>
  4079.      *
  4080.      * @param iterable  the {@link Iterable} providing the values to join together, may be null
  4081.      * @param separator  the separator character to use, null treated as ""
  4082.      * @return the joined String, {@code null} if null iterator input
  4083.      * @since 2.3
  4084.      */
  4085.     public static String join(final Iterable<?> iterable, final String separator) {
  4086.         return iterable != null ? join(iterable.iterator(), separator) : null;
  4087.     }

  4088.     /**
  4089.      * Joins the elements of the provided {@link Iterator} into
  4090.      * a single String containing the provided elements.
  4091.      *
  4092.      * <p>No delimiter is added before or after the list. Null objects or empty
  4093.      * strings within the iteration are represented by empty strings.</p>
  4094.      *
  4095.      * <p>See the examples here: {@link #join(Object[],char)}.</p>
  4096.      *
  4097.      * @param iterator  the {@link Iterator} of values to join together, may be null
  4098.      * @param separator  the separator character to use
  4099.      * @return the joined String, {@code null} if null iterator input
  4100.      * @since 2.0
  4101.      */
  4102.     public static String join(final Iterator<?> iterator, final char separator) {
  4103.         // handle null, zero and one elements before building a buffer
  4104.         if (iterator == null) {
  4105.             return null;
  4106.         }
  4107.         if (!iterator.hasNext()) {
  4108.             return EMPTY;
  4109.         }
  4110.         return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(String.valueOf(separator)), EMPTY, EMPTY, ObjectUtils::toString));
  4111.     }

  4112.     /**
  4113.      * Joins the elements of the provided {@link Iterator} into
  4114.      * a single String containing the provided elements.
  4115.      *
  4116.      * <p>No delimiter is added before or after the list.
  4117.      * A {@code null} separator is the same as an empty String ("").</p>
  4118.      *
  4119.      * <p>See the examples here: {@link #join(Object[],String)}.</p>
  4120.      *
  4121.      * @param iterator  the {@link Iterator} of values to join together, may be null
  4122.      * @param separator  the separator character to use, null treated as ""
  4123.      * @return the joined String, {@code null} if null iterator input
  4124.      */
  4125.     public static String join(final Iterator<?> iterator, final String separator) {
  4126.         // handle null, zero and one elements before building a buffer
  4127.         if (iterator == null) {
  4128.             return null;
  4129.         }
  4130.         if (!iterator.hasNext()) {
  4131.             return EMPTY;
  4132.         }
  4133.         return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(separator), EMPTY, EMPTY, ObjectUtils::toString));
  4134.     }

  4135.     /**
  4136.      * Joins the elements of the provided {@link List} into a single String
  4137.      * containing the provided list of elements.
  4138.      *
  4139.      * <p>No delimiter is added before or after the list.
  4140.      * Null objects or empty strings within the array are represented by
  4141.      * empty strings.</p>
  4142.      *
  4143.      * <pre>
  4144.      * StringUtils.join(null, *)               = null
  4145.      * StringUtils.join([], *)                 = ""
  4146.      * StringUtils.join([null], *)             = ""
  4147.      * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
  4148.      * StringUtils.join(["a", "b", "c"], null) = "abc"
  4149.      * StringUtils.join([null, "", "a"], ';')  = ";;a"
  4150.      * </pre>
  4151.      *
  4152.      * @param list  the {@link List} of values to join together, may be null
  4153.      * @param separator  the separator character to use
  4154.      * @param startIndex the first index to start joining from.  It is
  4155.      * an error to pass in a start index past the end of the list
  4156.      * @param endIndex the index to stop joining from (exclusive). It is
  4157.      * an error to pass in an end index past the end of the list
  4158.      * @return the joined String, {@code null} if null list input
  4159.      * @since 3.8
  4160.      */
  4161.     public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) {
  4162.         if (list == null) {
  4163.             return null;
  4164.         }
  4165.         final int noOfItems = endIndex - startIndex;
  4166.         if (noOfItems <= 0) {
  4167.             return EMPTY;
  4168.         }
  4169.         final List<?> subList = list.subList(startIndex, endIndex);
  4170.         return join(subList.iterator(), separator);
  4171.     }

  4172.     /**
  4173.      * Joins the elements of the provided {@link List} into a single String
  4174.      * containing the provided list of elements.
  4175.      *
  4176.      * <p>No delimiter is added before or after the list.
  4177.      * Null objects or empty strings within the array are represented by
  4178.      * empty strings.</p>
  4179.      *
  4180.      * <pre>
  4181.      * StringUtils.join(null, *)               = null
  4182.      * StringUtils.join([], *)                 = ""
  4183.      * StringUtils.join([null], *)             = ""
  4184.      * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
  4185.      * StringUtils.join(["a", "b", "c"], null) = "abc"
  4186.      * StringUtils.join([null, "", "a"], ';')  = ";;a"
  4187.      * </pre>
  4188.      *
  4189.      * @param list  the {@link List} of values to join together, may be null
  4190.      * @param separator  the separator character to use
  4191.      * @param startIndex the first index to start joining from.  It is
  4192.      * an error to pass in a start index past the end of the list
  4193.      * @param endIndex the index to stop joining from (exclusive). It is
  4194.      * an error to pass in an end index past the end of the list
  4195.      * @return the joined String, {@code null} if null list input
  4196.      * @since 3.8
  4197.      */
  4198.     public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) {
  4199.         if (list == null) {
  4200.             return null;
  4201.         }
  4202.         final int noOfItems = endIndex - startIndex;
  4203.         if (noOfItems <= 0) {
  4204.             return EMPTY;
  4205.         }
  4206.         final List<?> subList = list.subList(startIndex, endIndex);
  4207.         return join(subList.iterator(), separator);
  4208.     }

  4209.     /**
  4210.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4211.      *
  4212.      * <p>
  4213.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4214.      * by empty strings.
  4215.      * </p>
  4216.      *
  4217.      * <pre>
  4218.      * StringUtils.join(null, *)               = null
  4219.      * StringUtils.join([], *)                 = ""
  4220.      * StringUtils.join([null], *)             = ""
  4221.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4222.      * StringUtils.join([1, 2, 3], null) = "123"
  4223.      * </pre>
  4224.      *
  4225.      * @param array
  4226.      *            the array of values to join together, may be null
  4227.      * @param separator
  4228.      *            the separator character to use
  4229.      * @return the joined String, {@code null} if null array input
  4230.      * @since 3.2
  4231.      */
  4232.     public static String join(final long[] array, final char separator) {
  4233.         if (array == null) {
  4234.             return null;
  4235.         }
  4236.         return join(array, separator, 0, array.length);
  4237.     }

  4238.     /**
  4239.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4240.      *
  4241.      * <p>
  4242.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4243.      * by empty strings.
  4244.      * </p>
  4245.      *
  4246.      * <pre>
  4247.      * StringUtils.join(null, *)               = null
  4248.      * StringUtils.join([], *)                 = ""
  4249.      * StringUtils.join([null], *)             = ""
  4250.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4251.      * StringUtils.join([1, 2, 3], null) = "123"
  4252.      * </pre>
  4253.      *
  4254.      * @param array
  4255.      *            the array of values to join together, may be null
  4256.      * @param delimiter
  4257.      *            the separator character to use
  4258.      * @param startIndex
  4259.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  4260.      *            array
  4261.      * @param endIndex
  4262.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  4263.      *            the array
  4264.      * @return the joined String, {@code null} if null array input
  4265.      * @since 3.2
  4266.      */
  4267.     public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) {
  4268.         if (array == null) {
  4269.             return null;
  4270.         }
  4271.         if (endIndex - startIndex <= 0) {
  4272.             return EMPTY;
  4273.         }
  4274.         final StringBuilder stringBuilder = new StringBuilder();
  4275.         for (int i = startIndex; i < endIndex; i++) {
  4276.             stringBuilder
  4277.                     .append(array[i])
  4278.                     .append(delimiter);
  4279.         }
  4280.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  4281.     }

  4282.     /**
  4283.      * Joins the elements of the provided array into a single String
  4284.      * containing the provided list of elements.
  4285.      *
  4286.      * <p>No delimiter is added before or after the list.
  4287.      * Null objects or empty strings within the array are represented by
  4288.      * empty strings.</p>
  4289.      *
  4290.      * <pre>
  4291.      * StringUtils.join(null, *)               = null
  4292.      * StringUtils.join([], *)                 = ""
  4293.      * StringUtils.join([null], *)             = ""
  4294.      * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
  4295.      * StringUtils.join(["a", "b", "c"], null) = "abc"
  4296.      * StringUtils.join([null, "", "a"], ';')  = ";;a"
  4297.      * </pre>
  4298.      *
  4299.      * @param array  the array of values to join together, may be null
  4300.      * @param delimiter  the separator character to use
  4301.      * @return the joined String, {@code null} if null array input
  4302.      * @since 2.0
  4303.      */
  4304.     public static String join(final Object[] array, final char delimiter) {
  4305.         if (array == null) {
  4306.             return null;
  4307.         }
  4308.         return join(array, delimiter, 0, array.length);
  4309.     }

  4310.     /**
  4311.      * Joins the elements of the provided array into a single String
  4312.      * containing the provided list of elements.
  4313.      *
  4314.      * <p>No delimiter is added before or after the list.
  4315.      * Null objects or empty strings within the array are represented by
  4316.      * empty strings.</p>
  4317.      *
  4318.      * <pre>
  4319.      * StringUtils.join(null, *)               = null
  4320.      * StringUtils.join([], *)                 = ""
  4321.      * StringUtils.join([null], *)             = ""
  4322.      * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
  4323.      * StringUtils.join(["a", "b", "c"], null) = "abc"
  4324.      * StringUtils.join([null, "", "a"], ';')  = ";;a"
  4325.      * </pre>
  4326.      *
  4327.      * @param array  the array of values to join together, may be null
  4328.      * @param delimiter  the separator character to use
  4329.      * @param startIndex the first index to start joining from.  It is
  4330.      * an error to pass in a start index past the end of the array
  4331.      * @param endIndex the index to stop joining from (exclusive). It is
  4332.      * an error to pass in an end index past the end of the array
  4333.      * @return the joined String, {@code null} if null array input
  4334.      * @since 2.0
  4335.      */
  4336.     public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) {
  4337.         return join(array, String.valueOf(delimiter), startIndex, endIndex);
  4338.     }

  4339.     /**
  4340.      * Joins the elements of the provided array into a single String
  4341.      * containing the provided list of elements.
  4342.      *
  4343.      * <p>No delimiter is added before or after the list.
  4344.      * A {@code null} separator is the same as an empty String ("").
  4345.      * Null objects or empty strings within the array are represented by
  4346.      * empty strings.</p>
  4347.      *
  4348.      * <pre>
  4349.      * StringUtils.join(null, *)                = null
  4350.      * StringUtils.join([], *)                  = ""
  4351.      * StringUtils.join([null], *)              = ""
  4352.      * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
  4353.      * StringUtils.join(["a", "b", "c"], null)  = "abc"
  4354.      * StringUtils.join(["a", "b", "c"], "")    = "abc"
  4355.      * StringUtils.join([null, "", "a"], ',')   = ",,a"
  4356.      * </pre>
  4357.      *
  4358.      * @param array  the array of values to join together, may be null
  4359.      * @param delimiter  the separator character to use, null treated as ""
  4360.      * @return the joined String, {@code null} if null array input
  4361.      */
  4362.     public static String join(final Object[] array, final String delimiter) {
  4363.         return array != null ? join(array, ObjectUtils.toString(delimiter), 0, array.length) : null;
  4364.     }

  4365.     /**
  4366.      * Joins the elements of the provided array into a single String
  4367.      * containing the provided list of elements.
  4368.      *
  4369.      * <p>No delimiter is added before or after the list.
  4370.      * A {@code null} separator is the same as an empty String ("").
  4371.      * Null objects or empty strings within the array are represented by
  4372.      * empty strings.</p>
  4373.      *
  4374.      * <pre>
  4375.      * StringUtils.join(null, *, *, *)                = null
  4376.      * StringUtils.join([], *, *, *)                  = ""
  4377.      * StringUtils.join([null], *, *, *)              = ""
  4378.      * StringUtils.join(["a", "b", "c"], "--", 0, 3)  = "a--b--c"
  4379.      * StringUtils.join(["a", "b", "c"], "--", 1, 3)  = "b--c"
  4380.      * StringUtils.join(["a", "b", "c"], "--", 2, 3)  = "c"
  4381.      * StringUtils.join(["a", "b", "c"], "--", 2, 2)  = ""
  4382.      * StringUtils.join(["a", "b", "c"], null, 0, 3)  = "abc"
  4383.      * StringUtils.join(["a", "b", "c"], "", 0, 3)    = "abc"
  4384.      * StringUtils.join([null, "", "a"], ',', 0, 3)   = ",,a"
  4385.      * </pre>
  4386.      *
  4387.      * @param array  the array of values to join together, may be null
  4388.      * @param delimiter  the separator character to use, null treated as ""
  4389.      * @param startIndex the first index to start joining from.
  4390.      * @param endIndex the index to stop joining from (exclusive).
  4391.      * @return the joined String, {@code null} if null array input; or the empty string
  4392.      * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by
  4393.      * {@code endIndex - startIndex}
  4394.      * @throws ArrayIndexOutOfBoundsException ife<br>
  4395.      * {@code startIndex < 0} or <br>
  4396.      * {@code startIndex >= array.length()} or <br>
  4397.      * {@code endIndex < 0} or <br>
  4398.      * {@code endIndex > array.length()}
  4399.      */
  4400.     public static String join(final Object[] array, final String delimiter, final int startIndex, final int endIndex) {
  4401.         return array != null ? Streams.of(array).skip(startIndex).limit(Math.max(0, endIndex - startIndex))
  4402.             .collect(LangCollectors.joining(delimiter, EMPTY, EMPTY, ObjectUtils::toString)) : null;
  4403.     }

  4404.     /**
  4405.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4406.      *
  4407.      * <p>
  4408.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4409.      * by empty strings.
  4410.      * </p>
  4411.      *
  4412.      * <pre>
  4413.      * StringUtils.join(null, *)               = null
  4414.      * StringUtils.join([], *)                 = ""
  4415.      * StringUtils.join([null], *)             = ""
  4416.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4417.      * StringUtils.join([1, 2, 3], null) = "123"
  4418.      * </pre>
  4419.      *
  4420.      * @param array
  4421.      *            the array of values to join together, may be null
  4422.      * @param delimiter
  4423.      *            the separator character to use
  4424.      * @return the joined String, {@code null} if null array input
  4425.      * @since 3.2
  4426.      */
  4427.     public static String join(final short[] array, final char delimiter) {
  4428.         if (array == null) {
  4429.             return null;
  4430.         }
  4431.         return join(array, delimiter, 0, array.length);
  4432.     }

  4433.     /**
  4434.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4435.      *
  4436.      * <p>
  4437.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4438.      * by empty strings.
  4439.      * </p>
  4440.      *
  4441.      * <pre>
  4442.      * StringUtils.join(null, *)               = null
  4443.      * StringUtils.join([], *)                 = ""
  4444.      * StringUtils.join([null], *)             = ""
  4445.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4446.      * StringUtils.join([1, 2, 3], null) = "123"
  4447.      * </pre>
  4448.      *
  4449.      * @param array
  4450.      *            the array of values to join together, may be null
  4451.      * @param delimiter
  4452.      *            the separator character to use
  4453.      * @param startIndex
  4454.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  4455.      *            array
  4456.      * @param endIndex
  4457.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  4458.      *            the array
  4459.      * @return the joined String, {@code null} if null array input
  4460.      * @since 3.2
  4461.      */
  4462.     public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) {
  4463.         if (array == null) {
  4464.             return null;
  4465.         }
  4466.         if (endIndex - startIndex <= 0) {
  4467.             return EMPTY;
  4468.         }
  4469.         final StringBuilder stringBuilder = new StringBuilder();
  4470.         for (int i = startIndex; i < endIndex; i++) {
  4471.             stringBuilder
  4472.                     .append(array[i])
  4473.                     .append(delimiter);
  4474.         }
  4475.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  4476.     }

  4477.     /**
  4478.      * Joins the elements of the provided array into a single String
  4479.      * containing the provided list of elements.
  4480.      *
  4481.      * <p>No separator is added to the joined String.
  4482.      * Null objects or empty strings within the array are represented by
  4483.      * empty strings.</p>
  4484.      *
  4485.      * <pre>
  4486.      * StringUtils.join(null)            = null
  4487.      * StringUtils.join([])              = ""
  4488.      * StringUtils.join([null])          = ""
  4489.      * StringUtils.join(["a", "b", "c"]) = "abc"
  4490.      * StringUtils.join([null, "", "a"]) = "a"
  4491.      * </pre>
  4492.      *
  4493.      * @param <T> the specific type of values to join together
  4494.      * @param elements  the values to join together, may be null
  4495.      * @return the joined String, {@code null} if null array input
  4496.      * @since 2.0
  4497.      * @since 3.0 Changed signature to use varargs
  4498.      */
  4499.     @SafeVarargs
  4500.     public static <T> String join(final T... elements) {
  4501.         return join(elements, null);
  4502.     }

  4503.     /**
  4504.      * Joins the elements of the provided varargs into a
  4505.      * single String containing the provided elements.
  4506.      *
  4507.      * <p>No delimiter is added before or after the list.
  4508.      * {@code null} elements and separator are treated as empty Strings ("").</p>
  4509.      *
  4510.      * <pre>
  4511.      * StringUtils.joinWith(",", {"a", "b"})        = "a,b"
  4512.      * StringUtils.joinWith(",", {"a", "b",""})     = "a,b,"
  4513.      * StringUtils.joinWith(",", {"a", null, "b"})  = "a,,b"
  4514.      * StringUtils.joinWith(null, {"a", "b"})       = "ab"
  4515.      * </pre>
  4516.      *
  4517.      * @param delimiter the separator character to use, null treated as ""
  4518.      * @param array the varargs providing the values to join together. {@code null} elements are treated as ""
  4519.      * @return the joined String.
  4520.      * @throws IllegalArgumentException if a null varargs is provided
  4521.      * @since 3.5
  4522.      */
  4523.     public static String joinWith(final String delimiter, final Object... array) {
  4524.         if (array == null) {
  4525.             throw new IllegalArgumentException("Object varargs must not be null");
  4526.         }
  4527.         return join(array, delimiter);
  4528.     }

  4529.     /**
  4530.      * Finds the last index within a CharSequence, handling {@code null}.
  4531.      * This method uses {@link String#lastIndexOf(String)} if possible.
  4532.      *
  4533.      * <p>A {@code null} CharSequence will return {@code -1}.</p>
  4534.      *
  4535.      * <pre>
  4536.      * StringUtils.lastIndexOf(null, *)          = -1
  4537.      * StringUtils.lastIndexOf(*, null)          = -1
  4538.      * StringUtils.lastIndexOf("", "")           = 0
  4539.      * StringUtils.lastIndexOf("aabaabaa", "a")  = 7
  4540.      * StringUtils.lastIndexOf("aabaabaa", "b")  = 5
  4541.      * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
  4542.      * StringUtils.lastIndexOf("aabaabaa", "")   = 8
  4543.      * </pre>
  4544.      *
  4545.      * @param seq  the CharSequence to check, may be null
  4546.      * @param searchSeq  the CharSequence to find, may be null
  4547.      * @return the last index of the search String,
  4548.      *  -1 if no match or {@code null} string input
  4549.      * @since 2.0
  4550.      * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence)
  4551.      * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CS.lastIndexOf(CharSequence, CharSequence)}
  4552.      */
  4553.     @Deprecated
  4554.     public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) {
  4555.         return Strings.CS.lastIndexOf(seq, searchSeq);
  4556.     }

  4557.     /**
  4558.      * Finds the last index within a CharSequence, handling {@code null}.
  4559.      * This method uses {@link String#lastIndexOf(String, int)} if possible.
  4560.      *
  4561.      * <p>A {@code null} CharSequence will return {@code -1}.
  4562.      * A negative start position returns {@code -1}.
  4563.      * An empty ("") search CharSequence always matches unless the start position is negative.
  4564.      * A start position greater than the string length searches the whole string.
  4565.      * The search starts at the startPos and works backwards; matches starting after the start
  4566.      * position are ignored.
  4567.      * </p>
  4568.      *
  4569.      * <pre>
  4570.      * StringUtils.lastIndexOf(null, *, *)          = -1
  4571.      * StringUtils.lastIndexOf(*, null, *)          = -1
  4572.      * StringUtils.lastIndexOf("aabaabaa", "a", 8)  = 7
  4573.      * StringUtils.lastIndexOf("aabaabaa", "b", 8)  = 5
  4574.      * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
  4575.      * StringUtils.lastIndexOf("aabaabaa", "b", 9)  = 5
  4576.      * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
  4577.      * StringUtils.lastIndexOf("aabaabaa", "a", 0)  = 0
  4578.      * StringUtils.lastIndexOf("aabaabaa", "b", 0)  = -1
  4579.      * StringUtils.lastIndexOf("aabaabaa", "b", 1)  = -1
  4580.      * StringUtils.lastIndexOf("aabaabaa", "b", 2)  = 2
  4581.      * StringUtils.lastIndexOf("aabaabaa", "ba", 2)  = 2
  4582.      * </pre>
  4583.      *
  4584.      * @param seq  the CharSequence to check, may be null
  4585.      * @param searchSeq  the CharSequence to find, may be null
  4586.      * @param startPos  the start position, negative treated as zero
  4587.      * @return the last index of the search CharSequence (always &le; startPos),
  4588.      *  -1 if no match or {@code null} string input
  4589.      * @since 2.0
  4590.      * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int)
  4591.      * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CS.lastIndexOf(CharSequence, CharSequence, int)}
  4592.      */
  4593.     @Deprecated
  4594.     public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
  4595.         return Strings.CS.lastIndexOf(seq, searchSeq, startPos);
  4596.     }

  4597.     /**
  4598.      * Returns the index within {@code seq} of the last occurrence of
  4599.      * the specified character. For values of {@code searchChar} in the
  4600.      * range from 0 to 0xFFFF (inclusive), the index (in Unicode code
  4601.      * units) returned is the largest value <em>k</em> such that:
  4602.      * <blockquote><pre>
  4603.      * this.charAt(<em>k</em>) == searchChar
  4604.      * </pre></blockquote>
  4605.      * is true. For other values of {@code searchChar}, it is the
  4606.      * largest value <em>k</em> such that:
  4607.      * <blockquote><pre>
  4608.      * this.codePointAt(<em>k</em>) == searchChar
  4609.      * </pre></blockquote>
  4610.      * is true.  In either case, if no such character occurs in this
  4611.      * string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("")
  4612.      * {@link CharSequence} will return {@code -1}. The
  4613.      * {@code seq} {@link CharSequence} object is searched backwards
  4614.      * starting at the last character.
  4615.      *
  4616.      * <pre>
  4617.      * StringUtils.lastIndexOf(null, *)         = -1
  4618.      * StringUtils.lastIndexOf("", *)           = -1
  4619.      * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
  4620.      * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
  4621.      * </pre>
  4622.      *
  4623.      * @param seq  the {@link CharSequence} to check, may be null
  4624.      * @param searchChar  the character to find
  4625.      * @return the last index of the search character,
  4626.      *  -1 if no match or {@code null} string input
  4627.      * @since 2.0
  4628.      * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int)
  4629.      * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
  4630.      */
  4631.     public static int lastIndexOf(final CharSequence seq, final int searchChar) {
  4632.         if (isEmpty(seq)) {
  4633.             return INDEX_NOT_FOUND;
  4634.         }
  4635.         return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length());
  4636.     }

  4637.     /**
  4638.      * Returns the index within {@code seq} of the last occurrence of
  4639.      * the specified character, searching backward starting at the
  4640.      * specified index. For values of {@code searchChar} in the range
  4641.      * from 0 to 0xFFFF (inclusive), the index returned is the largest
  4642.      * value <em>k</em> such that:
  4643.      * <blockquote><pre>
  4644.      * (this.charAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &lt;= startPos)
  4645.      * </pre></blockquote>
  4646.      * is true. For other values of {@code searchChar}, it is the
  4647.      * largest value <em>k</em> such that:
  4648.      * <blockquote><pre>
  4649.      * (this.codePointAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &lt;= startPos)
  4650.      * </pre></blockquote>
  4651.      * is true. In either case, if no such character occurs in {@code seq}
  4652.      * at or before position {@code startPos}, then
  4653.      * {@code -1} is returned. Furthermore, a {@code null} or empty ("")
  4654.      * {@link CharSequence} will return {@code -1}. A start position greater
  4655.      * than the string length searches the whole string.
  4656.      * The search starts at the {@code startPos} and works backwards;
  4657.      * matches starting after the start position are ignored.
  4658.      *
  4659.      * <p>All indices are specified in {@code char} values
  4660.      * (Unicode code units).
  4661.      *
  4662.      * <pre>
  4663.      * StringUtils.lastIndexOf(null, *, *)          = -1
  4664.      * StringUtils.lastIndexOf("", *,  *)           = -1
  4665.      * StringUtils.lastIndexOf("aabaabaa", 'b', 8)  = 5
  4666.      * StringUtils.lastIndexOf("aabaabaa", 'b', 4)  = 2
  4667.      * StringUtils.lastIndexOf("aabaabaa", 'b', 0)  = -1
  4668.      * StringUtils.lastIndexOf("aabaabaa", 'b', 9)  = 5
  4669.      * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
  4670.      * StringUtils.lastIndexOf("aabaabaa", 'a', 0)  = 0
  4671.      * </pre>
  4672.      *
  4673.      * @param seq  the CharSequence to check, may be null
  4674.      * @param searchChar  the character to find
  4675.      * @param startPos  the start position
  4676.      * @return the last index of the search character (always &le; startPos),
  4677.      *  -1 if no match or {@code null} string input
  4678.      * @since 2.0
  4679.      * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int)
  4680.      */
  4681.     public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) {
  4682.         if (isEmpty(seq)) {
  4683.             return INDEX_NOT_FOUND;
  4684.         }
  4685.         return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos);
  4686.     }

  4687.     /**
  4688.      * Find the latest index of any substring in a set of potential substrings.
  4689.      *
  4690.      * <p>A {@code null} CharSequence will return {@code -1}.
  4691.      * A {@code null} search array will return {@code -1}.
  4692.      * A {@code null} or zero length search array entry will be ignored,
  4693.      * but a search array containing "" will return the length of {@code str}
  4694.      * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible</p>
  4695.      *
  4696.      * <pre>
  4697.      * StringUtils.lastIndexOfAny(null, *)                    = -1
  4698.      * StringUtils.lastIndexOfAny(*, null)                    = -1
  4699.      * StringUtils.lastIndexOfAny(*, [])                      = -1
  4700.      * StringUtils.lastIndexOfAny(*, [null])                  = -1
  4701.      * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6
  4702.      * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6
  4703.      * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
  4704.      * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
  4705.      * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""])   = 10
  4706.      * </pre>
  4707.      *
  4708.      * @param str  the CharSequence to check, may be null
  4709.      * @param searchStrs  the CharSequences to search for, may be null
  4710.      * @return the last index of any of the CharSequences, -1 if no match
  4711.      * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence)
  4712.      */
  4713.     public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) {
  4714.         if (str == null || searchStrs == null) {
  4715.             return INDEX_NOT_FOUND;
  4716.         }
  4717.         int ret = INDEX_NOT_FOUND;
  4718.         int tmp;
  4719.         for (final CharSequence search : searchStrs) {
  4720.             if (search == null) {
  4721.                 continue;
  4722.             }
  4723.             tmp = CharSequenceUtils.lastIndexOf(str, search, str.length());
  4724.             if (tmp > ret) {
  4725.                 ret = tmp;
  4726.             }
  4727.         }
  4728.         return ret;
  4729.     }

  4730.     /**
  4731.      * Case in-sensitive find of the last index within a CharSequence.
  4732.      *
  4733.      * <p>A {@code null} CharSequence will return {@code -1}.
  4734.      * A negative start position returns {@code -1}.
  4735.      * An empty ("") search CharSequence always matches unless the start position is negative.
  4736.      * A start position greater than the string length searches the whole string.</p>
  4737.      *
  4738.      * <pre>
  4739.      * StringUtils.lastIndexOfIgnoreCase(null, *)          = -1
  4740.      * StringUtils.lastIndexOfIgnoreCase(*, null)          = -1
  4741.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A")  = 7
  4742.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B")  = 5
  4743.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
  4744.      * </pre>
  4745.      *
  4746.      * @param str  the CharSequence to check, may be null
  4747.      * @param searchStr  the CharSequence to find, may be null
  4748.      * @return the first index of the search CharSequence,
  4749.      *  -1 if no match or {@code null} string input
  4750.      * @since 2.5
  4751.      * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence)
  4752.      * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CI.lastIndexOf(CharSequence, CharSequence)}
  4753.      */
  4754.     @Deprecated
  4755.     public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
  4756.         return Strings.CI.lastIndexOf(str, searchStr);
  4757.     }

  4758.     /**
  4759.      * Case in-sensitive find of the last index within a CharSequence
  4760.      * from the specified position.
  4761.      *
  4762.      * <p>A {@code null} CharSequence will return {@code -1}.
  4763.      * A negative start position returns {@code -1}.
  4764.      * An empty ("") search CharSequence always matches unless the start position is negative.
  4765.      * A start position greater than the string length searches the whole string.
  4766.      * The search starts at the startPos and works backwards; matches starting after the start
  4767.      * position are ignored.
  4768.      * </p>
  4769.      *
  4770.      * <pre>
  4771.      * StringUtils.lastIndexOfIgnoreCase(null, *, *)          = -1
  4772.      * StringUtils.lastIndexOfIgnoreCase(*, null, *)          = -1
  4773.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8)  = 7
  4774.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8)  = 5
  4775.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
  4776.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9)  = 5
  4777.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
  4778.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0)  = 0
  4779.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0)  = -1
  4780.      * </pre>
  4781.      *
  4782.      * @param str  the CharSequence to check, may be null
  4783.      * @param searchStr  the CharSequence to find, may be null
  4784.      * @param startPos  the start position
  4785.      * @return the last index of the search CharSequence (always &le; startPos),
  4786.      *  -1 if no match or {@code null} input
  4787.      * @since 2.5
  4788.      * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int)
  4789.      * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CI.lastIndexOf(CharSequence, CharSequence, int)}
  4790.      */
  4791.     @Deprecated
  4792.     public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) {
  4793.         return Strings.CI.lastIndexOf(str, searchStr, startPos);
  4794.     }

  4795.     /**
  4796.      * Finds the n-th last index within a String, handling {@code null}.
  4797.      * This method uses {@link String#lastIndexOf(String)}.
  4798.      *
  4799.      * <p>A {@code null} String will return {@code -1}.</p>
  4800.      *
  4801.      * <pre>
  4802.      * StringUtils.lastOrdinalIndexOf(null, *, *)          = -1
  4803.      * StringUtils.lastOrdinalIndexOf(*, null, *)          = -1
  4804.      * StringUtils.lastOrdinalIndexOf("", "", *)           = 0
  4805.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1)  = 7
  4806.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2)  = 6
  4807.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1)  = 5
  4808.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2)  = 2
  4809.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
  4810.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
  4811.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1)   = 8
  4812.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2)   = 8
  4813.      * </pre>
  4814.      *
  4815.      * <p>Note that 'tail(CharSequence str, int n)' may be implemented as: </p>
  4816.      *
  4817.      * <pre>
  4818.      *   str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
  4819.      * </pre>
  4820.      *
  4821.      * @param str  the CharSequence to check, may be null
  4822.      * @param searchStr  the CharSequence to find, may be null
  4823.      * @param ordinal  the n-th last {@code searchStr} to find
  4824.      * @return the n-th last index of the search CharSequence,
  4825.      *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
  4826.      * @since 2.5
  4827.      * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int)
  4828.      */
  4829.     public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
  4830.         return ordinalIndexOf(str, searchStr, ordinal, true);
  4831.     }

  4832.     /**
  4833.      * Gets the leftmost {@code len} characters of a String.
  4834.      *
  4835.      * <p>If {@code len} characters are not available, or the
  4836.      * String is {@code null}, the String will be returned without
  4837.      * an exception. An empty String is returned if len is negative.</p>
  4838.      *
  4839.      * <pre>
  4840.      * StringUtils.left(null, *)    = null
  4841.      * StringUtils.left(*, -ve)     = ""
  4842.      * StringUtils.left("", *)      = ""
  4843.      * StringUtils.left("abc", 0)   = ""
  4844.      * StringUtils.left("abc", 2)   = "ab"
  4845.      * StringUtils.left("abc", 4)   = "abc"
  4846.      * </pre>
  4847.      *
  4848.      * @param str  the String to get the leftmost characters from, may be null
  4849.      * @param len  the length of the required String
  4850.      * @return the leftmost characters, {@code null} if null String input
  4851.      */
  4852.     public static String left(final String str, final int len) {
  4853.         if (str == null) {
  4854.             return null;
  4855.         }
  4856.         if (len < 0) {
  4857.             return EMPTY;
  4858.         }
  4859.         if (str.length() <= len) {
  4860.             return str;
  4861.         }
  4862.         return str.substring(0, len);
  4863.     }

  4864.     /**
  4865.      * Left pad a String with spaces (' ').
  4866.      *
  4867.      * <p>The String is padded to the size of {@code size}.</p>
  4868.      *
  4869.      * <pre>
  4870.      * StringUtils.leftPad(null, *)   = null
  4871.      * StringUtils.leftPad("", 3)     = "   "
  4872.      * StringUtils.leftPad("bat", 3)  = "bat"
  4873.      * StringUtils.leftPad("bat", 5)  = "  bat"
  4874.      * StringUtils.leftPad("bat", 1)  = "bat"
  4875.      * StringUtils.leftPad("bat", -1) = "bat"
  4876.      * </pre>
  4877.      *
  4878.      * @param str  the String to pad out, may be null
  4879.      * @param size  the size to pad to
  4880.      * @return left padded String or original String if no padding is necessary,
  4881.      *  {@code null} if null String input
  4882.      */
  4883.     public static String leftPad(final String str, final int size) {
  4884.         return leftPad(str, size, ' ');
  4885.     }

  4886.     /**
  4887.      * Left pad a String with a specified character.
  4888.      *
  4889.      * <p>Pad to a size of {@code size}.</p>
  4890.      *
  4891.      * <pre>
  4892.      * StringUtils.leftPad(null, *, *)     = null
  4893.      * StringUtils.leftPad("", 3, 'z')     = "zzz"
  4894.      * StringUtils.leftPad("bat", 3, 'z')  = "bat"
  4895.      * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"
  4896.      * StringUtils.leftPad("bat", 1, 'z')  = "bat"
  4897.      * StringUtils.leftPad("bat", -1, 'z') = "bat"
  4898.      * </pre>
  4899.      *
  4900.      * @param str  the String to pad out, may be null
  4901.      * @param size  the size to pad to
  4902.      * @param padChar  the character to pad with
  4903.      * @return left padded String or original String if no padding is necessary,
  4904.      *  {@code null} if null String input
  4905.      * @since 2.0
  4906.      */
  4907.     public static String leftPad(final String str, final int size, final char padChar) {
  4908.         if (str == null) {
  4909.             return null;
  4910.         }
  4911.         final int pads = size - str.length();
  4912.         if (pads <= 0) {
  4913.             return str; // returns original String when possible
  4914.         }
  4915.         if (pads > PAD_LIMIT) {
  4916.             return leftPad(str, size, String.valueOf(padChar));
  4917.         }
  4918.         return repeat(padChar, pads).concat(str);
  4919.     }

  4920.     /**
  4921.      * Left pad a String with a specified String.
  4922.      *
  4923.      * <p>Pad to a size of {@code size}.</p>
  4924.      *
  4925.      * <pre>
  4926.      * StringUtils.leftPad(null, *, *)      = null
  4927.      * StringUtils.leftPad("", 3, "z")      = "zzz"
  4928.      * StringUtils.leftPad("bat", 3, "yz")  = "bat"
  4929.      * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
  4930.      * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
  4931.      * StringUtils.leftPad("bat", 1, "yz")  = "bat"
  4932.      * StringUtils.leftPad("bat", -1, "yz") = "bat"
  4933.      * StringUtils.leftPad("bat", 5, null)  = "  bat"
  4934.      * StringUtils.leftPad("bat", 5, "")    = "  bat"
  4935.      * </pre>
  4936.      *
  4937.      * @param str  the String to pad out, may be null
  4938.      * @param size  the size to pad to
  4939.      * @param padStr  the String to pad with, null or empty treated as single space
  4940.      * @return left padded String or original String if no padding is necessary,
  4941.      *  {@code null} if null String input
  4942.      */
  4943.     public static String leftPad(final String str, final int size, String padStr) {
  4944.         if (str == null) {
  4945.             return null;
  4946.         }
  4947.         if (isEmpty(padStr)) {
  4948.             padStr = SPACE;
  4949.         }
  4950.         final int padLen = padStr.length();
  4951.         final int strLen = str.length();
  4952.         final int pads = size - strLen;
  4953.         if (pads <= 0) {
  4954.             return str; // returns original String when possible
  4955.         }
  4956.         if (padLen == 1 && pads <= PAD_LIMIT) {
  4957.             return leftPad(str, size, padStr.charAt(0));
  4958.         }

  4959.         if (pads == padLen) {
  4960.             return padStr.concat(str);
  4961.         }
  4962.         if (pads < padLen) {
  4963.             return padStr.substring(0, pads).concat(str);
  4964.         }
  4965.         final char[] padding = new char[pads];
  4966.         final char[] padChars = padStr.toCharArray();
  4967.         for (int i = 0; i < pads; i++) {
  4968.             padding[i] = padChars[i % padLen];
  4969.         }
  4970.         return new String(padding).concat(str);
  4971.     }

  4972.     /**
  4973.      * Gets a CharSequence length or {@code 0} if the CharSequence is
  4974.      * {@code null}.
  4975.      *
  4976.      * @param cs
  4977.      *            a CharSequence or {@code null}
  4978.      * @return CharSequence length or {@code 0} if the CharSequence is
  4979.      *         {@code null}.
  4980.      * @since 2.4
  4981.      * @since 3.0 Changed signature from length(String) to length(CharSequence)
  4982.      */
  4983.     public static int length(final CharSequence cs) {
  4984.         return cs == null ? 0 : cs.length();
  4985.     }

  4986.     /**
  4987.      * Converts a String to lower case as per {@link String#toLowerCase()}.
  4988.      *
  4989.      * <p>A {@code null} input String returns {@code null}.</p>
  4990.      *
  4991.      * <pre>
  4992.      * StringUtils.lowerCase(null)  = null
  4993.      * StringUtils.lowerCase("")    = ""
  4994.      * StringUtils.lowerCase("aBc") = "abc"
  4995.      * </pre>
  4996.      *
  4997.      * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()},
  4998.      * the result of this method is affected by the current locale.
  4999.      * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
  5000.      * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
  5001.      *
  5002.      * @param str  the String to lower case, may be null
  5003.      * @return the lower cased String, {@code null} if null String input
  5004.      */
  5005.     public static String lowerCase(final String str) {
  5006.         if (str == null) {
  5007.             return null;
  5008.         }
  5009.         return str.toLowerCase();
  5010.     }

  5011.     /**
  5012.      * Converts a String to lower case as per {@link String#toLowerCase(Locale)}.
  5013.      *
  5014.      * <p>A {@code null} input String returns {@code null}.</p>
  5015.      *
  5016.      * <pre>
  5017.      * StringUtils.lowerCase(null, Locale.ENGLISH)  = null
  5018.      * StringUtils.lowerCase("", Locale.ENGLISH)    = ""
  5019.      * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
  5020.      * </pre>
  5021.      *
  5022.      * @param str  the String to lower case, may be null
  5023.      * @param locale  the locale that defines the case transformation rules, must not be null
  5024.      * @return the lower cased String, {@code null} if null String input
  5025.      * @since 2.5
  5026.      */
  5027.     public static String lowerCase(final String str, final Locale locale) {
  5028.         if (str == null) {
  5029.             return null;
  5030.         }
  5031.         return str.toLowerCase(LocaleUtils.toLocale(locale));
  5032.     }

  5033.     private static int[] matches(final CharSequence first, final CharSequence second) {
  5034.         final CharSequence max;
  5035.         final CharSequence min;
  5036.         if (first.length() > second.length()) {
  5037.             max = first;
  5038.             min = second;
  5039.         } else {
  5040.             max = second;
  5041.             min = first;
  5042.         }
  5043.         final int range = Math.max(max.length() / 2 - 1, 0);
  5044.         final int[] matchIndexes = ArrayFill.fill(new int[min.length()], -1);
  5045.         final boolean[] matchFlags = new boolean[max.length()];
  5046.         int matches = 0;
  5047.         for (int mi = 0; mi < min.length(); mi++) {
  5048.             final char c1 = min.charAt(mi);
  5049.             for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) {
  5050.                 if (!matchFlags[xi] && c1 == max.charAt(xi)) {
  5051.                     matchIndexes[mi] = xi;
  5052.                     matchFlags[xi] = true;
  5053.                     matches++;
  5054.                     break;
  5055.                 }
  5056.             }
  5057.         }
  5058.         final char[] ms1 = new char[matches];
  5059.         final char[] ms2 = new char[matches];
  5060.         for (int i = 0, si = 0; i < min.length(); i++) {
  5061.             if (matchIndexes[i] != -1) {
  5062.                 ms1[si] = min.charAt(i);
  5063.                 si++;
  5064.             }
  5065.         }
  5066.         for (int i = 0, si = 0; i < max.length(); i++) {
  5067.             if (matchFlags[i]) {
  5068.                 ms2[si] = max.charAt(i);
  5069.                 si++;
  5070.             }
  5071.         }
  5072.         int transpositions = 0;
  5073.         for (int mi = 0; mi < ms1.length; mi++) {
  5074.             if (ms1[mi] != ms2[mi]) {
  5075.                 transpositions++;
  5076.             }
  5077.         }
  5078.         int prefix = 0;
  5079.         for (int mi = 0; mi < min.length(); mi++) {
  5080.             if (first.charAt(mi) != second.charAt(mi)) {
  5081.                 break;
  5082.             }
  5083.             prefix++;
  5084.         }
  5085.         return new int[] { matches, transpositions / 2, prefix, max.length() };
  5086.     }

  5087.     /**
  5088.      * Gets {@code len} characters from the middle of a String.
  5089.      *
  5090.      * <p>If {@code len} characters are not available, the remainder
  5091.      * of the String will be returned without an exception. If the
  5092.      * String is {@code null}, {@code null} will be returned.
  5093.      * An empty String is returned if len is negative or exceeds the
  5094.      * length of {@code str}.</p>
  5095.      *
  5096.      * <pre>
  5097.      * StringUtils.mid(null, *, *)    = null
  5098.      * StringUtils.mid(*, *, -ve)     = ""
  5099.      * StringUtils.mid("", 0, *)      = ""
  5100.      * StringUtils.mid("abc", 0, 2)   = "ab"
  5101.      * StringUtils.mid("abc", 0, 4)   = "abc"
  5102.      * StringUtils.mid("abc", 2, 4)   = "c"
  5103.      * StringUtils.mid("abc", 4, 2)   = ""
  5104.      * StringUtils.mid("abc", -2, 2)  = "ab"
  5105.      * </pre>
  5106.      *
  5107.      * @param str  the String to get the characters from, may be null
  5108.      * @param pos  the position to start from, negative treated as zero
  5109.      * @param len  the length of the required String
  5110.      * @return the middle characters, {@code null} if null String input
  5111.      */
  5112.     public static String mid(final String str, int pos, final int len) {
  5113.         if (str == null) {
  5114.             return null;
  5115.         }
  5116.         if (len < 0 || pos > str.length()) {
  5117.             return EMPTY;
  5118.         }
  5119.         if (pos < 0) {
  5120.             pos = 0;
  5121.         }
  5122.         if (str.length() <= pos + len) {
  5123.             return str.substring(pos);
  5124.         }
  5125.         return str.substring(pos, pos + len);
  5126.     }

  5127.     /**
  5128.      * Similar to <a
  5129.      * href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize
  5130.      * -space</a>
  5131.      *
  5132.      * <p>
  5133.      * The function returns the argument string with whitespace normalized by using
  5134.      * {@code {@link #trim(String)}} to remove leading and trailing whitespace
  5135.      * and then replacing sequences of whitespace characters by a single space.
  5136.      * </p>
  5137.      * In XML Whitespace characters are the same as those allowed by the <a
  5138.      * href="https://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+
  5139.      * <p>
  5140.      * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r]
  5141.      *
  5142.      * <p>For reference:</p>
  5143.      * <ul>
  5144.      * <li>\x0B = vertical tab</li>
  5145.      * <li>\f = #xC = form feed</li>
  5146.      * <li>#x20 = space</li>
  5147.      * <li>#x9 = \t</li>
  5148.      * <li>#xA = \n</li>
  5149.      * <li>#xD = \r</li>
  5150.      * </ul>
  5151.      *
  5152.      * <p>
  5153.      * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also
  5154.      * normalize. Additionally {@code {@link #trim(String)}} removes control characters (char &lt;= 32) from both
  5155.      * ends of this String.
  5156.      * </p>
  5157.      *
  5158.      * @see Pattern
  5159.      * @see #trim(String)
  5160.      * @see <a
  5161.      *      href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize-space</a>
  5162.      * @param str the source String to normalize whitespaces from, may be null
  5163.      * @return the modified string with whitespace normalized, {@code null} if null String input
  5164.      * @since 3.0
  5165.      */
  5166.     public static String normalizeSpace(final String str) {
  5167.         // LANG-1020: Improved performance significantly by normalizing manually instead of using regex
  5168.         // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test
  5169.         if (isEmpty(str)) {
  5170.             return str;
  5171.         }
  5172.         final int size = str.length();
  5173.         final char[] newChars = new char[size];
  5174.         int count = 0;
  5175.         int whitespacesCount = 0;
  5176.         boolean startWhitespaces = true;
  5177.         for (int i = 0; i < size; i++) {
  5178.             final char actualChar = str.charAt(i);
  5179.             final boolean isWhitespace = Character.isWhitespace(actualChar);
  5180.             if (isWhitespace) {
  5181.                 if (whitespacesCount == 0 && !startWhitespaces) {
  5182.                     newChars[count++] = SPACE.charAt(0);
  5183.                 }
  5184.                 whitespacesCount++;
  5185.             } else {
  5186.                 startWhitespaces = false;
  5187.                 newChars[count++] = actualChar == 160 ? 32 : actualChar;
  5188.                 whitespacesCount = 0;
  5189.             }
  5190.         }
  5191.         if (startWhitespaces) {
  5192.             return EMPTY;
  5193.         }
  5194.         return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim();
  5195.     }

  5196.     /**
  5197.      * Finds the n-th index within a CharSequence, handling {@code null}.
  5198.      * This method uses {@link String#indexOf(String)} if possible.
  5199.      * <p><strong>Note:</strong> The code starts looking for a match at the start of the target,
  5200.      * incrementing the starting index by one after each successful match
  5201.      * (unless {@code searchStr} is an empty string in which case the position
  5202.      * is never incremented and {@code 0} is returned immediately).
  5203.      * This means that matches may overlap.</p>
  5204.      * <p>A {@code null} CharSequence will return {@code -1}.</p>
  5205.      *
  5206.      * <pre>
  5207.      * StringUtils.ordinalIndexOf(null, *, *)          = -1
  5208.      * StringUtils.ordinalIndexOf(*, null, *)          = -1
  5209.      * StringUtils.ordinalIndexOf("", "", *)           = 0
  5210.      * StringUtils.ordinalIndexOf("aabaabaa", "a", 1)  = 0
  5211.      * StringUtils.ordinalIndexOf("aabaabaa", "a", 2)  = 1
  5212.      * StringUtils.ordinalIndexOf("aabaabaa", "b", 1)  = 2
  5213.      * StringUtils.ordinalIndexOf("aabaabaa", "b", 2)  = 5
  5214.      * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
  5215.      * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
  5216.      * StringUtils.ordinalIndexOf("aabaabaa", "", 1)   = 0
  5217.      * StringUtils.ordinalIndexOf("aabaabaa", "", 2)   = 0
  5218.      * </pre>
  5219.      *
  5220.      * <p>Matches may overlap:</p>
  5221.      * <pre>
  5222.      * StringUtils.ordinalIndexOf("ababab", "aba", 1)   = 0
  5223.      * StringUtils.ordinalIndexOf("ababab", "aba", 2)   = 2
  5224.      * StringUtils.ordinalIndexOf("ababab", "aba", 3)   = -1
  5225.      *
  5226.      * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0
  5227.      * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2
  5228.      * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4
  5229.      * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1
  5230.      * </pre>
  5231.      *
  5232.      * <p>Note that 'head(CharSequence str, int n)' may be implemented as: </p>
  5233.      *
  5234.      * <pre>
  5235.      *   str.substring(0, lastOrdinalIndexOf(str, "\n", n))
  5236.      * </pre>
  5237.      *
  5238.      * @param str  the CharSequence to check, may be null
  5239.      * @param searchStr  the CharSequence to find, may be null
  5240.      * @param ordinal  the n-th {@code searchStr} to find
  5241.      * @return the n-th index of the search CharSequence,
  5242.      *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
  5243.      * @since 2.1
  5244.      * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int)
  5245.      */
  5246.     public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
  5247.         return ordinalIndexOf(str, searchStr, ordinal, false);
  5248.     }

  5249.     /**
  5250.      * Finds the n-th index within a String, handling {@code null}.
  5251.      * This method uses {@link String#indexOf(String)} if possible.
  5252.      * <p>Note that matches may overlap<p>
  5253.      *
  5254.      * <p>A {@code null} CharSequence will return {@code -1}.</p>
  5255.      *
  5256.      * @param str  the CharSequence to check, may be null
  5257.      * @param searchStr  the CharSequence to find, may be null
  5258.      * @param ordinal  the n-th {@code searchStr} to find, overlapping matches are allowed.
  5259.      * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
  5260.      * @return the n-th index of the search CharSequence,
  5261.      *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
  5262.      */
  5263.     // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int)
  5264.     private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) {
  5265.         if (str == null || searchStr == null || ordinal <= 0) {
  5266.             return INDEX_NOT_FOUND;
  5267.         }
  5268.         if (searchStr.length() == 0) {
  5269.             return lastIndex ? str.length() : 0;
  5270.         }
  5271.         int found = 0;
  5272.         // set the initial index beyond the end of the string
  5273.         // this is to allow for the initial index decrement/increment
  5274.         int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
  5275.         do {
  5276.             if (lastIndex) {
  5277.                 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards through string
  5278.             } else {
  5279.                 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string
  5280.             }
  5281.             if (index < 0) {
  5282.                 return index;
  5283.             }
  5284.             found++;
  5285.         } while (found < ordinal);
  5286.         return index;
  5287.     }

  5288.     /**
  5289.      * Overlays part of a String with another String.
  5290.      *
  5291.      * <p>A {@code null} string input returns {@code null}.
  5292.      * A negative index is treated as zero.
  5293.      * An index greater than the string length is treated as the string length.
  5294.      * The start index is always the smaller of the two indices.</p>
  5295.      *
  5296.      * <pre>
  5297.      * StringUtils.overlay(null, *, *, *)            = null
  5298.      * StringUtils.overlay("", "abc", 0, 0)          = "abc"
  5299.      * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
  5300.      * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
  5301.      * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
  5302.      * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
  5303.      * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
  5304.      * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
  5305.      * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
  5306.      * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
  5307.      * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
  5308.      * </pre>
  5309.      *
  5310.      * @param str  the String to do overlaying in, may be null
  5311.      * @param overlay  the String to overlay, may be null
  5312.      * @param start  the position to start overlaying at
  5313.      * @param end  the position to stop overlaying before
  5314.      * @return overlayed String, {@code null} if null String input
  5315.      * @since 2.0
  5316.      */
  5317.     public static String overlay(final String str, String overlay, int start, int end) {
  5318.         if (str == null) {
  5319.             return null;
  5320.         }
  5321.         if (overlay == null) {
  5322.             overlay = EMPTY;
  5323.         }
  5324.         final int len = str.length();
  5325.         if (start < 0) {
  5326.             start = 0;
  5327.         }
  5328.         if (start > len) {
  5329.             start = len;
  5330.         }
  5331.         if (end < 0) {
  5332.             end = 0;
  5333.         }
  5334.         if (end > len) {
  5335.             end = len;
  5336.         }
  5337.         if (start > end) {
  5338.             final int temp = start;
  5339.             start = end;
  5340.             end = temp;
  5341.         }
  5342.         return str.substring(0, start) +
  5343.             overlay +
  5344.             str.substring(end);
  5345.     }

  5346.     /**
  5347.      * Prepends the prefix to the start of the string if the string does not already start with any of the prefixes.
  5348.      *
  5349.      * <pre>
  5350.      * StringUtils.prependIfMissing(null, null) = null
  5351.      * StringUtils.prependIfMissing("abc", null) = "abc"
  5352.      * StringUtils.prependIfMissing("", "xyz") = "xyz"
  5353.      * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc"
  5354.      * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc"
  5355.      * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc"
  5356.      * </pre>
  5357.      * <p>
  5358.      * With additional prefixes,
  5359.      * </p>
  5360.      *
  5361.      * <pre>
  5362.      * StringUtils.prependIfMissing(null, null, null) = null
  5363.      * StringUtils.prependIfMissing("abc", null, null) = "abc"
  5364.      * StringUtils.prependIfMissing("", "xyz", null) = "xyz"
  5365.      * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
  5366.      * StringUtils.prependIfMissing("abc", "xyz", "") = "abc"
  5367.      * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc"
  5368.      * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc"
  5369.      * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc"
  5370.      * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc"
  5371.      * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc"
  5372.      * </pre>
  5373.      *
  5374.      * @param str      The string.
  5375.      * @param prefix   The prefix to prepend to the start of the string.
  5376.      * @param prefixes Additional prefixes that are valid.
  5377.      * @return A new String if prefix was prepended, the same string otherwise.
  5378.      * @since 3.2
  5379.      * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CS.prependIfMissing(String, CharSequence,
  5380.      *             CharSequence...)}
  5381.      */
  5382.     @Deprecated
  5383.     public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) {
  5384.         return Strings.CS.prependIfMissing(str, prefix, prefixes);
  5385.     }

  5386.     /**
  5387.      * Prepends the prefix to the start of the string if the string does not
  5388.      * already start, case-insensitive, with any of the prefixes.
  5389.      *
  5390.      * <pre>
  5391.      * StringUtils.prependIfMissingIgnoreCase(null, null) = null
  5392.      * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc"
  5393.      * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz"
  5394.      * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc"
  5395.      * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc"
  5396.      * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc"
  5397.      * </pre>
  5398.      * <p>With additional prefixes,</p>
  5399.      * <pre>
  5400.      * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null
  5401.      * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc"
  5402.      * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz"
  5403.      * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
  5404.      * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc"
  5405.      * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc"
  5406.      * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc"
  5407.      * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc"
  5408.      * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc"
  5409.      * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc"
  5410.      * </pre>
  5411.      *
  5412.      * @param str The string.
  5413.      * @param prefix The prefix to prepend to the start of the string.
  5414.      * @param prefixes Additional prefixes that are valid (optional).
  5415.      * @return A new String if prefix was prepended, the same string otherwise.
  5416.      * @since 3.2
  5417.      * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CI.prependIfMissing(String, CharSequence,
  5418.      *             CharSequence...)}
  5419.      */
  5420.     @Deprecated
  5421.     public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) {
  5422.         return Strings.CI.prependIfMissing(str, prefix, prefixes);
  5423.     }

  5424.     /**
  5425.      * Removes all occurrences of a character from within the source string.
  5426.      *
  5427.      * <p>A {@code null} source string will return {@code null}.
  5428.      * An empty ("") source string will return the empty string.</p>
  5429.      *
  5430.      * <pre>
  5431.      * StringUtils.remove(null, *)       = null
  5432.      * StringUtils.remove("", *)         = ""
  5433.      * StringUtils.remove("queued", 'u') = "qeed"
  5434.      * StringUtils.remove("queued", 'z') = "queued"
  5435.      * </pre>
  5436.      *
  5437.      * @param str  the source String to search, may be null
  5438.      * @param remove  the char to search for and remove, may be null
  5439.      * @return the substring with the char removed if found,
  5440.      *  {@code null} if null String input
  5441.      * @since 2.1
  5442.      */
  5443.     public static String remove(final String str, final char remove) {
  5444.         if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
  5445.             return str;
  5446.         }
  5447.         final char[] chars = str.toCharArray();
  5448.         int pos = 0;
  5449.         for (int i = 0; i < chars.length; i++) {
  5450.             if (chars[i] != remove) {
  5451.                 chars[pos++] = chars[i];
  5452.             }
  5453.         }
  5454.         return new String(chars, 0, pos);
  5455.     }

  5456.     /**
  5457.      * Removes all occurrences of a substring from within the source string.
  5458.      *
  5459.      * <p>A {@code null} source string will return {@code null}.
  5460.      * An empty ("") source string will return the empty string.
  5461.      * A {@code null} remove string will return the source string.
  5462.      * An empty ("") remove string will return the source string.</p>
  5463.      *
  5464.      * <pre>
  5465.      * StringUtils.remove(null, *)        = null
  5466.      * StringUtils.remove("", *)          = ""
  5467.      * StringUtils.remove(*, null)        = *
  5468.      * StringUtils.remove(*, "")          = *
  5469.      * StringUtils.remove("queued", "ue") = "qd"
  5470.      * StringUtils.remove("queued", "zz") = "queued"
  5471.      * </pre>
  5472.      *
  5473.      * @param str  the source String to search, may be null
  5474.      * @param remove  the String to search for and remove, may be null
  5475.      * @return the substring with the string removed if found,
  5476.      *  {@code null} if null String input
  5477.      * @since 2.1
  5478.      * @deprecated Use {@link Strings#remove(String, String) Strings.CS.remove(String, String)}
  5479.      */
  5480.     @Deprecated
  5481.     public static String remove(final String str, final String remove) {
  5482.         return Strings.CS.remove(str, remove);
  5483.     }

  5484.     /**
  5485.      * Removes each substring of the text String that matches the given regular expression.
  5486.      *
  5487.      * This method is a {@code null} safe equivalent to:
  5488.      * <ul>
  5489.      *  <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li>
  5490.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li>
  5491.      * </ul>
  5492.      *
  5493.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  5494.      *
  5495.      * <p>Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option
  5496.      * is NOT automatically added.
  5497.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  5498.      * DOTALL is also known as single-line mode in Perl.</p>
  5499.      *
  5500.      * <pre>{@code
  5501.      * StringUtils.removeAll(null, *)      = null
  5502.      * StringUtils.removeAll("any", (String) null)  = "any"
  5503.      * StringUtils.removeAll("any", "")    = "any"
  5504.      * StringUtils.removeAll("any", ".*")  = ""
  5505.      * StringUtils.removeAll("any", ".+")  = ""
  5506.      * StringUtils.removeAll("abc", ".?")  = ""
  5507.      * StringUtils.removeAll("A<__>\n<__>B", "<.*>")      = "A\nB"
  5508.      * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>")  = "AB"
  5509.      * StringUtils.removeAll("ABCabc123abc", "[a-z]")     = "ABC123"
  5510.      * }</pre>
  5511.      *
  5512.      * @param text  text to remove from, may be null
  5513.      * @param regex  the regular expression to which this string is to be matched
  5514.      * @return  the text with any removes processed,
  5515.      *              {@code null} if null String input
  5516.      *
  5517.      * @throws  java.util.regex.PatternSyntaxException
  5518.      *              if the regular expression's syntax is invalid
  5519.      *
  5520.      * @see #replaceAll(String, String, String)
  5521.      * @see #removePattern(String, String)
  5522.      * @see String#replaceAll(String, String)
  5523.      * @see java.util.regex.Pattern
  5524.      * @see java.util.regex.Pattern#DOTALL
  5525.      * @since 3.5
  5526.      * @deprecated Moved to RegExUtils.
  5527.      */
  5528.     @Deprecated
  5529.     public static String removeAll(final String text, final String regex) {
  5530.         return RegExUtils.removeAll(text, regex);
  5531.     }

  5532.     /**
  5533.      * Removes a substring only if it is at the end of a source string,
  5534.      * otherwise returns the source string.
  5535.      *
  5536.      * <p>A {@code null} source string will return {@code null}.
  5537.      * An empty ("") source string will return the empty string.
  5538.      * A {@code null} search string will return the source string.</p>
  5539.      *
  5540.      * <pre>
  5541.      * StringUtils.removeEnd(null, *)      = null
  5542.      * StringUtils.removeEnd("", *)        = ""
  5543.      * StringUtils.removeEnd(*, null)      = *
  5544.      * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
  5545.      * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
  5546.      * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
  5547.      * StringUtils.removeEnd("abc", "")    = "abc"
  5548.      * </pre>
  5549.      *
  5550.      * @param str  the source String to search, may be null
  5551.      * @param remove  the String to search for and remove, may be null
  5552.      * @return the substring with the string removed if found,
  5553.      *  {@code null} if null String input
  5554.      * @since 2.1
  5555.      * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CS.removeEnd(String, CharSequence)}
  5556.      */
  5557.     @Deprecated
  5558.     public static String removeEnd(final String str, final String remove) {
  5559.         return Strings.CS.removeEnd(str, remove);
  5560.     }

  5561.     /**
  5562.      * Case-insensitive removal of a substring if it is at the end of a source string,
  5563.      * otherwise returns the source string.
  5564.      *
  5565.      * <p>A {@code null} source string will return {@code null}.
  5566.      * An empty ("") source string will return the empty string.
  5567.      * A {@code null} search string will return the source string.</p>
  5568.      *
  5569.      * <pre>
  5570.      * StringUtils.removeEndIgnoreCase(null, *)      = null
  5571.      * StringUtils.removeEndIgnoreCase("", *)        = ""
  5572.      * StringUtils.removeEndIgnoreCase(*, null)      = *
  5573.      * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.")  = "www.domain.com"
  5574.      * StringUtils.removeEndIgnoreCase("www.domain.com", ".com")   = "www.domain"
  5575.      * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
  5576.      * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"
  5577.      * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
  5578.      * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
  5579.      * </pre>
  5580.      *
  5581.      * @param str  the source String to search, may be null
  5582.      * @param remove  the String to search for (case-insensitive) and remove, may be null
  5583.      * @return the substring with the string removed if found,
  5584.      *  {@code null} if null String input
  5585.      * @since 2.4
  5586.      * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CI.removeEnd(String, CharSequence)}
  5587.      */
  5588.     @Deprecated
  5589.     public static String removeEndIgnoreCase(final String str, final String remove) {
  5590.         return Strings.CI.removeEnd(str, remove);
  5591.     }

  5592.     /**
  5593.      * Removes the first substring of the text string that matches the given regular expression.
  5594.      *
  5595.      * This method is a {@code null} safe equivalent to:
  5596.      * <ul>
  5597.      *  <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li>
  5598.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li>
  5599.      * </ul>
  5600.      *
  5601.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  5602.      *
  5603.      * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
  5604.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  5605.      * DOTALL is also known as single-line mode in Perl.</p>
  5606.      *
  5607.      * <pre>{@code
  5608.      * StringUtils.removeFirst(null, *)      = null
  5609.      * StringUtils.removeFirst("any", (String) null)  = "any"
  5610.      * StringUtils.removeFirst("any", "")    = "any"
  5611.      * StringUtils.removeFirst("any", ".*")  = ""
  5612.      * StringUtils.removeFirst("any", ".+")  = ""
  5613.      * StringUtils.removeFirst("abc", ".?")  = "bc"
  5614.      * StringUtils.removeFirst("A<__>\n<__>B", "<.*>")      = "A\n<__>B"
  5615.      * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>")  = "AB"
  5616.      * StringUtils.removeFirst("ABCabc123", "[a-z]")          = "ABCbc123"
  5617.      * StringUtils.removeFirst("ABCabc123abc", "[a-z]+")      = "ABC123abc"
  5618.      * }</pre>
  5619.      *
  5620.      * @param text  text to remove from, may be null
  5621.      * @param regex  the regular expression to which this string is to be matched
  5622.      * @return  the text with the first replacement processed,
  5623.      *              {@code null} if null String input
  5624.      *
  5625.      * @throws  java.util.regex.PatternSyntaxException
  5626.      *              if the regular expression's syntax is invalid
  5627.      *
  5628.      * @see #replaceFirst(String, String, String)
  5629.      * @see String#replaceFirst(String, String)
  5630.      * @see java.util.regex.Pattern
  5631.      * @see java.util.regex.Pattern#DOTALL
  5632.      * @since 3.5
  5633.      * @deprecated Moved to RegExUtils.
  5634.      */
  5635.     @Deprecated
  5636.     public static String removeFirst(final String text, final String regex) {
  5637.         return replaceFirst(text, regex, EMPTY);
  5638.     }

  5639.     /**
  5640.      * Case-insensitive removal of all occurrences of a substring from within
  5641.      * the source string.
  5642.      *
  5643.      * <p>
  5644.      * A {@code null} source string will return {@code null}. An empty ("")
  5645.      * source string will return the empty string. A {@code null} remove string
  5646.      * will return the source string. An empty ("") remove string will return
  5647.      * the source string.
  5648.      * </p>
  5649.      *
  5650.      * <pre>
  5651.      * StringUtils.removeIgnoreCase(null, *)        = null
  5652.      * StringUtils.removeIgnoreCase("", *)          = ""
  5653.      * StringUtils.removeIgnoreCase(*, null)        = *
  5654.      * StringUtils.removeIgnoreCase(*, "")          = *
  5655.      * StringUtils.removeIgnoreCase("queued", "ue") = "qd"
  5656.      * StringUtils.removeIgnoreCase("queued", "zz") = "queued"
  5657.      * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd"
  5658.      * StringUtils.removeIgnoreCase("queued", "zZ") = "queued"
  5659.      * </pre>
  5660.      *
  5661.      * @param str
  5662.      *            the source String to search, may be null
  5663.      * @param remove
  5664.      *            the String to search for (case-insensitive) and remove, may be
  5665.      *            null
  5666.      * @return the substring with the string removed if found, {@code null} if
  5667.      *         null String input
  5668.      * @since 3.5
  5669.      * @deprecated Use {@link Strings#remove(String, String) Strings.CI.remove(String, String)}
  5670.      */
  5671.     @Deprecated
  5672.     public static String removeIgnoreCase(final String str, final String remove) {
  5673.         return Strings.CI.remove(str, remove);
  5674.     }

  5675.     /**
  5676.      * Removes each substring of the source String that matches the given regular expression using the DOTALL option.
  5677.      *
  5678.      * This call is a {@code null} safe equivalent to:
  5679.      * <ul>
  5680.      * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, StringUtils.EMPTY)}</li>
  5681.      * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li>
  5682.      * </ul>
  5683.      *
  5684.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  5685.      *
  5686.      * <pre>{@code
  5687.      * StringUtils.removePattern(null, *)       = null
  5688.      * StringUtils.removePattern("any", (String) null)   = "any"
  5689.      * StringUtils.removePattern("A<__>\n<__>B", "<.*>")  = "AB"
  5690.      * StringUtils.removePattern("ABCabc123", "[a-z]")    = "ABC123"
  5691.      * }</pre>
  5692.      *
  5693.      * @param source
  5694.      *            the source string
  5695.      * @param regex
  5696.      *            the regular expression to which this string is to be matched
  5697.      * @return The resulting {@link String}
  5698.      * @see #replacePattern(String, String, String)
  5699.      * @see String#replaceAll(String, String)
  5700.      * @see Pattern#DOTALL
  5701.      * @since 3.2
  5702.      * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
  5703.      * @deprecated Moved to RegExUtils.
  5704.      */
  5705.     @Deprecated
  5706.     public static String removePattern(final String source, final String regex) {
  5707.         return RegExUtils.removePattern(source, regex);
  5708.     }

  5709.     /**
  5710.      * Removes a char only if it is at the beginning of a source string,
  5711.      * otherwise returns the source string.
  5712.      *
  5713.      * <p>A {@code null} source string will return {@code null}.
  5714.      * An empty ("") source string will return the empty string.
  5715.      * A {@code null} search char will return the source string.</p>
  5716.      *
  5717.      * <pre>
  5718.      * StringUtils.removeStart(null, *)      = null
  5719.      * StringUtils.removeStart("", *)        = ""
  5720.      * StringUtils.removeStart(*, null)      = *
  5721.      * StringUtils.removeStart("/path", '/') = "path"
  5722.      * StringUtils.removeStart("path", '/')  = "path"
  5723.      * StringUtils.removeStart("path", 0)    = "path"
  5724.      * </pre>
  5725.      *
  5726.      * @param str  the source String to search, may be null.
  5727.      * @param remove  the char to search for and remove.
  5728.      * @return the substring with the char removed if found,
  5729.      *  {@code null} if null String input.
  5730.      * @since 3.13.0
  5731.      */
  5732.     public static String removeStart(final String str, final char remove) {
  5733.         if (isEmpty(str)) {
  5734.             return str;
  5735.         }
  5736.         return str.charAt(0) == remove ? str.substring(1) : str;
  5737.     }

  5738.     /**
  5739.      * Removes a substring only if it is at the beginning of a source string,
  5740.      * otherwise returns the source string.
  5741.      *
  5742.      * <p>A {@code null} source string will return {@code null}.
  5743.      * An empty ("") source string will return the empty string.
  5744.      * A {@code null} search string will return the source string.</p>
  5745.      *
  5746.      * <pre>
  5747.      * StringUtils.removeStart(null, *)      = null
  5748.      * StringUtils.removeStart("", *)        = ""
  5749.      * StringUtils.removeStart(*, null)      = *
  5750.      * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
  5751.      * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
  5752.      * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
  5753.      * StringUtils.removeStart("abc", "")    = "abc"
  5754.      * </pre>
  5755.      *
  5756.      * @param str  the source String to search, may be null
  5757.      * @param remove  the String to search for and remove, may be null
  5758.      * @return the substring with the string removed if found,
  5759.      *  {@code null} if null String input
  5760.      * @since 2.1
  5761.      * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CS.removeStart(String, CharSequence)}
  5762.      */
  5763.     @Deprecated
  5764.     public static String removeStart(final String str, final String remove) {
  5765.         return Strings.CS.removeStart(str, remove);
  5766.     }

  5767.     /**
  5768.      * Case-insensitive removal of a substring if it is at the beginning of a source string,
  5769.      * otherwise returns the source string.
  5770.      *
  5771.      * <p>A {@code null} source string will return {@code null}.
  5772.      * An empty ("") source string will return the empty string.
  5773.      * A {@code null} search string will return the source string.</p>
  5774.      *
  5775.      * <pre>
  5776.      * StringUtils.removeStartIgnoreCase(null, *)      = null
  5777.      * StringUtils.removeStartIgnoreCase("", *)        = ""
  5778.      * StringUtils.removeStartIgnoreCase(*, null)      = *
  5779.      * StringUtils.removeStartIgnoreCase("www.domain.com", "www.")   = "domain.com"
  5780.      * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.")   = "domain.com"
  5781.      * StringUtils.removeStartIgnoreCase("domain.com", "www.")       = "domain.com"
  5782.      * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
  5783.      * StringUtils.removeStartIgnoreCase("abc", "")    = "abc"
  5784.      * </pre>
  5785.      *
  5786.      * @param str  the source String to search, may be null
  5787.      * @param remove  the String to search for (case-insensitive) and remove, may be null
  5788.      * @return the substring with the string removed if found,
  5789.      *  {@code null} if null String input
  5790.      * @since 2.4
  5791.      * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CI.removeStart(String, CharSequence)}
  5792.      */
  5793.     @Deprecated
  5794.     public static String removeStartIgnoreCase(final String str, final String remove) {
  5795.         return Strings.CI.removeStart(str, remove);
  5796.     }

  5797.     /**
  5798.      * Returns padding using the specified delimiter repeated
  5799.      * to a given length.
  5800.      *
  5801.      * <pre>
  5802.      * StringUtils.repeat('e', 0)  = ""
  5803.      * StringUtils.repeat('e', 3)  = "eee"
  5804.      * StringUtils.repeat('e', -2) = ""
  5805.      * </pre>
  5806.      *
  5807.      * <p>Note: this method does not support padding with
  5808.      * <a href="https://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
  5809.      * as they require a pair of {@code char}s to be represented.
  5810.      * If you are needing to support full I18N of your applications
  5811.      * consider using {@link #repeat(String, int)} instead.
  5812.      * </p>
  5813.      *
  5814.      * @param repeat  character to repeat
  5815.      * @param count  number of times to repeat char, negative treated as zero
  5816.      * @return String with repeated character
  5817.      * @see #repeat(String, int)
  5818.      */
  5819.     public static String repeat(final char repeat, final int count) {
  5820.         if (count <= 0) {
  5821.             return EMPTY;
  5822.         }
  5823.         return new String(ArrayFill.fill(new char[count], repeat));
  5824.     }

  5825.     /**
  5826.      * Repeats a String {@code repeat} times to form a
  5827.      * new String.
  5828.      *
  5829.      * <pre>
  5830.      * StringUtils.repeat(null, 2) = null
  5831.      * StringUtils.repeat("", 0)   = ""
  5832.      * StringUtils.repeat("", 2)   = ""
  5833.      * StringUtils.repeat("a", 3)  = "aaa"
  5834.      * StringUtils.repeat("ab", 2) = "abab"
  5835.      * StringUtils.repeat("a", -2) = ""
  5836.      * </pre>
  5837.      *
  5838.      * @param repeat  the String to repeat, may be null
  5839.      * @param count  number of times to repeat str, negative treated as zero
  5840.      * @return a new String consisting of the original String repeated,
  5841.      *  {@code null} if null String input
  5842.      */
  5843.     public static String repeat(final String repeat, final int count) {
  5844.         // Performance tuned for 2.0 (JDK1.4)
  5845.         if (repeat == null) {
  5846.             return null;
  5847.         }
  5848.         if (count <= 0) {
  5849.             return EMPTY;
  5850.         }
  5851.         final int inputLength = repeat.length();
  5852.         if (count == 1 || inputLength == 0) {
  5853.             return repeat;
  5854.         }
  5855.         if (inputLength == 1 && count <= PAD_LIMIT) {
  5856.             return repeat(repeat.charAt(0), count);
  5857.         }

  5858.         final int outputLength = inputLength * count;
  5859.         switch (inputLength) {
  5860.             case 1 :
  5861.                 return repeat(repeat.charAt(0), count);
  5862.             case 2 :
  5863.                 final char ch0 = repeat.charAt(0);
  5864.                 final char ch1 = repeat.charAt(1);
  5865.                 final char[] output2 = new char[outputLength];
  5866.                 for (int i = count * 2 - 2; i >= 0; i--, i--) {
  5867.                     output2[i] = ch0;
  5868.                     output2[i + 1] = ch1;
  5869.                 }
  5870.                 return new String(output2);
  5871.             default :
  5872.                 final StringBuilder buf = new StringBuilder(outputLength);
  5873.                 for (int i = 0; i < count; i++) {
  5874.                     buf.append(repeat);
  5875.                 }
  5876.                 return buf.toString();
  5877.         }
  5878.     }

  5879.     /**
  5880.      * Repeats a String {@code repeat} times to form a
  5881.      * new String, with a String separator injected each time.
  5882.      *
  5883.      * <pre>
  5884.      * StringUtils.repeat(null, null, 2) = null
  5885.      * StringUtils.repeat(null, "x", 2)  = null
  5886.      * StringUtils.repeat("", null, 0)   = ""
  5887.      * StringUtils.repeat("", "", 2)     = ""
  5888.      * StringUtils.repeat("", "x", 3)    = "xx"
  5889.      * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
  5890.      * </pre>
  5891.      *
  5892.      * @param repeat        the String to repeat, may be null
  5893.      * @param separator  the String to inject, may be null
  5894.      * @param count     number of times to repeat str, negative treated as zero
  5895.      * @return a new String consisting of the original String repeated,
  5896.      *  {@code null} if null String input
  5897.      * @since 2.5
  5898.      */
  5899.     public static String repeat(final String repeat, final String separator, final int count) {
  5900.         if (repeat == null || separator == null) {
  5901.             return repeat(repeat, count);
  5902.         }
  5903.         // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
  5904.         final String result = repeat(repeat + separator, count);
  5905.         return Strings.CS.removeEnd(result, separator);
  5906.     }

  5907.     /**
  5908.      * Replaces all occurrences of a String within another String.
  5909.      *
  5910.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  5911.      *
  5912.      * <pre>
  5913.      * StringUtils.replace(null, *, *)        = null
  5914.      * StringUtils.replace("", *, *)          = ""
  5915.      * StringUtils.replace("any", null, *)    = "any"
  5916.      * StringUtils.replace("any", *, null)    = "any"
  5917.      * StringUtils.replace("any", "", *)      = "any"
  5918.      * StringUtils.replace("aba", "a", null)  = "aba"
  5919.      * StringUtils.replace("aba", "a", "")    = "b"
  5920.      * StringUtils.replace("aba", "a", "z")   = "zbz"
  5921.      * </pre>
  5922.      *
  5923.      * @see #replace(String text, String searchString, String replacement, int max)
  5924.      * @param text  text to search and replace in, may be null
  5925.      * @param searchString  the String to search for, may be null
  5926.      * @param replacement  the String to replace it with, may be null
  5927.      * @return the text with any replacements processed,
  5928.      *  {@code null} if null String input
  5929.      * @deprecated Use {@link Strings#replace(String, String, String) Strings.CS.replace(String, String, String)}
  5930.      */
  5931.     @Deprecated
  5932.     public static String replace(final String text, final String searchString, final String replacement) {
  5933.         return Strings.CS.replace(text, searchString, replacement);
  5934.     }

  5935.     /**
  5936.      * Replaces a String with another String inside a larger String,
  5937.      * for the first {@code max} values of the search String.
  5938.      *
  5939.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  5940.      *
  5941.      * <pre>
  5942.      * StringUtils.replace(null, *, *, *)         = null
  5943.      * StringUtils.replace("", *, *, *)           = ""
  5944.      * StringUtils.replace("any", null, *, *)     = "any"
  5945.      * StringUtils.replace("any", *, null, *)     = "any"
  5946.      * StringUtils.replace("any", "", *, *)       = "any"
  5947.      * StringUtils.replace("any", *, *, 0)        = "any"
  5948.      * StringUtils.replace("abaa", "a", null, -1) = "abaa"
  5949.      * StringUtils.replace("abaa", "a", "", -1)   = "b"
  5950.      * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
  5951.      * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
  5952.      * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
  5953.      * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
  5954.      * </pre>
  5955.      *
  5956.      * @param text  text to search and replace in, may be null
  5957.      * @param searchString  the String to search for, may be null
  5958.      * @param replacement  the String to replace it with, may be null
  5959.      * @param max  maximum number of values to replace, or {@code -1} if no maximum
  5960.      * @return the text with any replacements processed,
  5961.      *  {@code null} if null String input
  5962.      * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CS.replace(String, String, String, int)}
  5963.      */
  5964.     @Deprecated
  5965.     public static String replace(final String text, final String searchString, final String replacement, final int max) {
  5966.         return Strings.CS.replace(text, searchString, replacement, max);
  5967.     }

  5968.     /**
  5969.      * Replaces each substring of the text String that matches the given regular expression
  5970.      * with the given replacement.
  5971.      *
  5972.      * This method is a {@code null} safe equivalent to:
  5973.      * <ul>
  5974.      *  <li>{@code text.replaceAll(regex, replacement)}</li>
  5975.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li>
  5976.      * </ul>
  5977.      *
  5978.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  5979.      *
  5980.      * <p>Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option
  5981.      * is NOT automatically added.
  5982.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  5983.      * DOTALL is also known as single-line mode in Perl.</p>
  5984.      *
  5985.      * <pre>{@code
  5986.      * StringUtils.replaceAll(null, *, *)       = null
  5987.      * StringUtils.replaceAll("any", (String) null, *)   = "any"
  5988.      * StringUtils.replaceAll("any", *, null)   = "any"
  5989.      * StringUtils.replaceAll("", "", "zzz")    = "zzz"
  5990.      * StringUtils.replaceAll("", ".*", "zzz")  = "zzz"
  5991.      * StringUtils.replaceAll("", ".+", "zzz")  = ""
  5992.      * StringUtils.replaceAll("abc", "", "ZZ")  = "ZZaZZbZZcZZ"
  5993.      * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z")      = "z\nz"
  5994.      * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z")  = "z"
  5995.      * StringUtils.replaceAll("ABCabc123", "[a-z]", "_")       = "ABC___123"
  5996.      * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
  5997.      * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
  5998.      * StringUtils.replaceAll("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
  5999.      * }</pre>
  6000.      *
  6001.      * @param text  text to search and replace in, may be null
  6002.      * @param regex  the regular expression to which this string is to be matched
  6003.      * @param replacement  the string to be substituted for each match
  6004.      * @return  the text with any replacements processed,
  6005.      *              {@code null} if null String input
  6006.      *
  6007.      * @throws  java.util.regex.PatternSyntaxException
  6008.      *              if the regular expression's syntax is invalid
  6009.      *
  6010.      * @see #replacePattern(String, String, String)
  6011.      * @see String#replaceAll(String, String)
  6012.      * @see java.util.regex.Pattern
  6013.      * @see java.util.regex.Pattern#DOTALL
  6014.      * @since 3.5
  6015.      * @deprecated Moved to RegExUtils.
  6016.      */
  6017.     @Deprecated
  6018.     public static String replaceAll(final String text, final String regex, final String replacement) {
  6019.         return RegExUtils.replaceAll(text, regex, replacement);
  6020.     }

  6021.     /**
  6022.      * Replaces all occurrences of a character in a String with another.
  6023.      * This is a null-safe version of {@link String#replace(char, char)}.
  6024.      *
  6025.      * <p>A {@code null} string input returns {@code null}.
  6026.      * An empty ("") string input returns an empty string.</p>
  6027.      *
  6028.      * <pre>
  6029.      * StringUtils.replaceChars(null, *, *)        = null
  6030.      * StringUtils.replaceChars("", *, *)          = ""
  6031.      * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
  6032.      * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
  6033.      * </pre>
  6034.      *
  6035.      * @param str  String to replace characters in, may be null
  6036.      * @param searchChar  the character to search for, may be null
  6037.      * @param replaceChar  the character to replace, may be null
  6038.      * @return modified String, {@code null} if null string input
  6039.      * @since 2.0
  6040.      */
  6041.     public static String replaceChars(final String str, final char searchChar, final char replaceChar) {
  6042.         if (str == null) {
  6043.             return null;
  6044.         }
  6045.         return str.replace(searchChar, replaceChar);
  6046.     }

  6047.     /**
  6048.      * Replaces multiple characters in a String in one go.
  6049.      * This method can also be used to delete characters.
  6050.      *
  6051.      * <p>For example:<br>
  6052.      * {@code replaceChars(&quot;hello&quot;, &quot;ho&quot;, &quot;jy&quot;) = jelly}.</p>
  6053.      *
  6054.      * <p>A {@code null} string input returns {@code null}.
  6055.      * An empty ("") string input returns an empty string.
  6056.      * A null or empty set of search characters returns the input string.</p>
  6057.      *
  6058.      * <p>The length of the search characters should normally equal the length
  6059.      * of the replace characters.
  6060.      * If the search characters is longer, then the extra search characters
  6061.      * are deleted.
  6062.      * If the search characters is shorter, then the extra replace characters
  6063.      * are ignored.</p>
  6064.      *
  6065.      * <pre>
  6066.      * StringUtils.replaceChars(null, *, *)           = null
  6067.      * StringUtils.replaceChars("", *, *)             = ""
  6068.      * StringUtils.replaceChars("abc", null, *)       = "abc"
  6069.      * StringUtils.replaceChars("abc", "", *)         = "abc"
  6070.      * StringUtils.replaceChars("abc", "b", null)     = "ac"
  6071.      * StringUtils.replaceChars("abc", "b", "")       = "ac"
  6072.      * StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
  6073.      * StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
  6074.      * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
  6075.      * </pre>
  6076.      *
  6077.      * @param str  String to replace characters in, may be null
  6078.      * @param searchChars  a set of characters to search for, may be null
  6079.      * @param replaceChars  a set of characters to replace, may be null
  6080.      * @return modified String, {@code null} if null string input
  6081.      * @since 2.0
  6082.      */
  6083.     public static String replaceChars(final String str, final String searchChars, String replaceChars) {
  6084.         if (isEmpty(str) || isEmpty(searchChars)) {
  6085.             return str;
  6086.         }
  6087.         replaceChars = ObjectUtils.toString(replaceChars);
  6088.         boolean modified = false;
  6089.         final int replaceCharsLength = replaceChars.length();
  6090.         final int strLength = str.length();
  6091.         final StringBuilder buf = new StringBuilder(strLength);
  6092.         for (int i = 0; i < strLength; i++) {
  6093.             final char ch = str.charAt(i);
  6094.             final int index = searchChars.indexOf(ch);
  6095.             if (index >= 0) {
  6096.                 modified = true;
  6097.                 if (index < replaceCharsLength) {
  6098.                     buf.append(replaceChars.charAt(index));
  6099.                 }
  6100.             } else {
  6101.                 buf.append(ch);
  6102.             }
  6103.         }
  6104.         if (modified) {
  6105.             return buf.toString();
  6106.         }
  6107.         return str;
  6108.     }

  6109.     /**
  6110.      * Replaces all occurrences of Strings within another String.
  6111.      *
  6112.      * <p>
  6113.      * A {@code null} reference passed to this method is a no-op, or if
  6114.      * any "search string" or "string to replace" is null, that replace will be
  6115.      * ignored. This will not repeat. For repeating replaces, call the
  6116.      * overloaded method.
  6117.      * </p>
  6118.      *
  6119.      * <pre>
  6120.      *  StringUtils.replaceEach(null, *, *)        = null
  6121.      *  StringUtils.replaceEach("", *, *)          = ""
  6122.      *  StringUtils.replaceEach("aba", null, null) = "aba"
  6123.      *  StringUtils.replaceEach("aba", new String[0], null) = "aba"
  6124.      *  StringUtils.replaceEach("aba", null, new String[0]) = "aba"
  6125.      *  StringUtils.replaceEach("aba", new String[]{"a"}, null)  = "aba"
  6126.      *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""})  = "b"
  6127.      *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"})  = "aba"
  6128.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"})  = "wcte"
  6129.      *  (example of how it does not repeat)
  6130.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"})  = "dcte"
  6131.      * </pre>
  6132.      *
  6133.      * @param text
  6134.      *            text to search and replace in, no-op if null
  6135.      * @param searchList
  6136.      *            the Strings to search for, no-op if null
  6137.      * @param replacementList
  6138.      *            the Strings to replace them with, no-op if null
  6139.      * @return the text with any replacements processed, {@code null} if
  6140.      *         null String input
  6141.      * @throws IllegalArgumentException
  6142.      *             if the lengths of the arrays are not the same (null is ok,
  6143.      *             and/or size 0)
  6144.      * @since 2.4
  6145.      */
  6146.     public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) {
  6147.         return replaceEach(text, searchList, replacementList, false, 0);
  6148.     }

  6149.     /**
  6150.      * Replace all occurrences of Strings within another String.
  6151.      * This is a private recursive helper method for {@link #replaceEachRepeatedly(String, String[], String[])} and
  6152.      * {@link #replaceEach(String, String[], String[])}
  6153.      *
  6154.      * <p>
  6155.      * A {@code null} reference passed to this method is a no-op, or if
  6156.      * any "search string" or "string to replace" is null, that replace will be
  6157.      * ignored.
  6158.      * </p>
  6159.      *
  6160.      * <pre>
  6161.      *  StringUtils.replaceEach(null, *, *, *, *) = null
  6162.      *  StringUtils.replaceEach("", *, *, *, *) = ""
  6163.      *  StringUtils.replaceEach("aba", null, null, *, *) = "aba"
  6164.      *  StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba"
  6165.      *  StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba"
  6166.      *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba"
  6167.      *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b"
  6168.      *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba"
  6169.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte"
  6170.      *  (example of how it repeats)
  6171.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte"
  6172.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte"
  6173.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = IllegalStateException
  6174.      * </pre>
  6175.      *
  6176.      * @param text
  6177.      *            text to search and replace in, no-op if null
  6178.      * @param searchList
  6179.      *            the Strings to search for, no-op if null
  6180.      * @param replacementList
  6181.      *            the Strings to replace them with, no-op if null
  6182.      * @param repeat if true, then replace repeatedly
  6183.      *       until there are no more possible replacements or timeToLive < 0
  6184.      * @param timeToLive
  6185.      *            if less than 0 then there is a circular reference and endless
  6186.      *            loop
  6187.      * @return the text with any replacements processed, {@code null} if
  6188.      *         null String input
  6189.      * @throws IllegalStateException
  6190.      *             if the search is repeating and there is an endless loop due
  6191.      *             to outputs of one being inputs to another
  6192.      * @throws IllegalArgumentException
  6193.      *             if the lengths of the arrays are not the same (null is ok,
  6194.      *             and/or size 0)
  6195.      * @since 2.4
  6196.      */
  6197.     private static String replaceEach(
  6198.             final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) {

  6199.         // mchyzer Performance note: This creates very few new objects (one major goal)
  6200.         // let me know if there are performance requests, we can create a harness to measure
  6201.         if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList)) {
  6202.             return text;
  6203.         }

  6204.         // if recursing, this shouldn't be less than 0
  6205.         if (timeToLive < 0) {
  6206.             throw new IllegalStateException("Aborting to protect against StackOverflowError - " +
  6207.                 "output of one loop is the input of another");
  6208.         }

  6209.         final int searchLength = searchList.length;
  6210.         final int replacementLength = replacementList.length;

  6211.         // make sure lengths are ok, these need to be equal
  6212.         if (searchLength != replacementLength) {
  6213.             throw new IllegalArgumentException("Search and Replace array lengths don't match: "
  6214.                 + searchLength
  6215.                 + " vs "
  6216.                 + replacementLength);
  6217.         }

  6218.         // keep track of which still have matches
  6219.         final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];

  6220.         // index on index that the match was found
  6221.         int textIndex = -1;
  6222.         int replaceIndex = -1;
  6223.         int tempIndex;

  6224.         // index of replace array that will replace the search string found
  6225.         // NOTE: logic duplicated below START
  6226.         for (int i = 0; i < searchLength; i++) {
  6227.             if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) {
  6228.                 continue;
  6229.             }
  6230.             tempIndex = text.indexOf(searchList[i]);

  6231.             // see if we need to keep searching for this
  6232.             if (tempIndex == -1) {
  6233.                 noMoreMatchesForReplIndex[i] = true;
  6234.             } else if (textIndex == -1 || tempIndex < textIndex) {
  6235.                 textIndex = tempIndex;
  6236.                 replaceIndex = i;
  6237.             }
  6238.         }
  6239.         // NOTE: logic mostly below END

  6240.         // no search strings found, we are done
  6241.         if (textIndex == -1) {
  6242.             return text;
  6243.         }

  6244.         int start = 0;

  6245.         // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit
  6246.         int increase = 0;

  6247.         // count the replacement text elements that are larger than their corresponding text being replaced
  6248.         for (int i = 0; i < searchList.length; i++) {
  6249.             if (searchList[i] == null || replacementList[i] == null) {
  6250.                 continue;
  6251.             }
  6252.             final int greater = replacementList[i].length() - searchList[i].length();
  6253.             if (greater > 0) {
  6254.                 increase += 3 * greater; // assume 3 matches
  6255.             }
  6256.         }
  6257.         // have upper-bound at 20% increase, then let Java take over
  6258.         increase = Math.min(increase, text.length() / 5);

  6259.         final StringBuilder buf = new StringBuilder(text.length() + increase);

  6260.         while (textIndex != -1) {

  6261.             for (int i = start; i < textIndex; i++) {
  6262.                 buf.append(text.charAt(i));
  6263.             }
  6264.             buf.append(replacementList[replaceIndex]);

  6265.             start = textIndex + searchList[replaceIndex].length();

  6266.             textIndex = -1;
  6267.             replaceIndex = -1;
  6268.             // find the next earliest match
  6269.             // NOTE: logic mostly duplicated above START
  6270.             for (int i = 0; i < searchLength; i++) {
  6271.                 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) {
  6272.                     continue;
  6273.                 }
  6274.                 tempIndex = text.indexOf(searchList[i], start);

  6275.                 // see if we need to keep searching for this
  6276.                 if (tempIndex == -1) {
  6277.                     noMoreMatchesForReplIndex[i] = true;
  6278.                 } else if (textIndex == -1 || tempIndex < textIndex) {
  6279.                     textIndex = tempIndex;
  6280.                     replaceIndex = i;
  6281.                 }
  6282.             }
  6283.             // NOTE: logic duplicated above END

  6284.         }
  6285.         final int textLength = text.length();
  6286.         for (int i = start; i < textLength; i++) {
  6287.             buf.append(text.charAt(i));
  6288.         }
  6289.         final String result = buf.toString();
  6290.         if (!repeat) {
  6291.             return result;
  6292.         }

  6293.         return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
  6294.     }

  6295.     /**
  6296.      * Replaces all occurrences of Strings within another String.
  6297.      *
  6298.      * <p>
  6299.      * A {@code null} reference passed to this method is a no-op, or if
  6300.      * any "search string" or "string to replace" is null, that replace will be
  6301.      * ignored.
  6302.      * </p>
  6303.      *
  6304.      * <pre>
  6305.      *  StringUtils.replaceEachRepeatedly(null, *, *) = null
  6306.      *  StringUtils.replaceEachRepeatedly("", *, *) = ""
  6307.      *  StringUtils.replaceEachRepeatedly("aba", null, null) = "aba"
  6308.      *  StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba"
  6309.      *  StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba"
  6310.      *  StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba"
  6311.      *  StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b"
  6312.      *  StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba"
  6313.      *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
  6314.      *  (example of how it repeats)
  6315.      *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte"
  6316.      *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException
  6317.      * </pre>
  6318.      *
  6319.      * @param text
  6320.      *            text to search and replace in, no-op if null
  6321.      * @param searchList
  6322.      *            the Strings to search for, no-op if null
  6323.      * @param replacementList
  6324.      *            the Strings to replace them with, no-op if null
  6325.      * @return the text with any replacements processed, {@code null} if
  6326.      *         null String input
  6327.      * @throws IllegalStateException
  6328.      *             if the search is repeating and there is an endless loop due
  6329.      *             to outputs of one being inputs to another
  6330.      * @throws IllegalArgumentException
  6331.      *             if the lengths of the arrays are not the same (null is ok,
  6332.      *             and/or size 0)
  6333.      * @since 2.4
  6334.      */
  6335.     public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) {
  6336.         final int timeToLive = Math.max(ArrayUtils.getLength(searchList), DEFAULT_TTL);
  6337.         return replaceEach(text, searchList, replacementList, true, timeToLive);
  6338.     }

  6339.     /**
  6340.      * Replaces the first substring of the text string that matches the given regular expression
  6341.      * with the given replacement.
  6342.      *
  6343.      * This method is a {@code null} safe equivalent to:
  6344.      * <ul>
  6345.      *  <li>{@code text.replaceFirst(regex, replacement)}</li>
  6346.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li>
  6347.      * </ul>
  6348.      *
  6349.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6350.      *
  6351.      * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
  6352.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  6353.      * DOTALL is also known as single-line mode in Perl.</p>
  6354.      *
  6355.      * <pre>{@code
  6356.      * StringUtils.replaceFirst(null, *, *)       = null
  6357.      * StringUtils.replaceFirst("any", (String) null, *)   = "any"
  6358.      * StringUtils.replaceFirst("any", *, null)   = "any"
  6359.      * StringUtils.replaceFirst("", "", "zzz")    = "zzz"
  6360.      * StringUtils.replaceFirst("", ".*", "zzz")  = "zzz"
  6361.      * StringUtils.replaceFirst("", ".+", "zzz")  = ""
  6362.      * StringUtils.replaceFirst("abc", "", "ZZ")  = "ZZabc"
  6363.      * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z")      = "z\n<__>"
  6364.      * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z")  = "z"
  6365.      * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_")          = "ABC_bc123"
  6366.      * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_")  = "ABC_123abc"
  6367.      * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "")   = "ABC123abc"
  6368.      * StringUtils.replaceFirst("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum  dolor   sit"
  6369.      * }</pre>
  6370.      *
  6371.      * @param text  text to search and replace in, may be null
  6372.      * @param regex  the regular expression to which this string is to be matched
  6373.      * @param replacement  the string to be substituted for the first match
  6374.      * @return  the text with the first replacement processed,
  6375.      *              {@code null} if null String input
  6376.      *
  6377.      * @throws  java.util.regex.PatternSyntaxException
  6378.      *              if the regular expression's syntax is invalid
  6379.      *
  6380.      * @see String#replaceFirst(String, String)
  6381.      * @see java.util.regex.Pattern
  6382.      * @see java.util.regex.Pattern#DOTALL
  6383.      * @since 3.5
  6384.      * @deprecated Moved to RegExUtils.
  6385.      */
  6386.     @Deprecated
  6387.     public static String replaceFirst(final String text, final String regex, final String replacement) {
  6388.         return RegExUtils.replaceFirst(text, regex, replacement);
  6389.     }

  6390.     /**
  6391.      * Case insensitively replaces all occurrences of a String within another String.
  6392.      *
  6393.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6394.      *
  6395.      * <pre>
  6396.      * StringUtils.replaceIgnoreCase(null, *, *)        = null
  6397.      * StringUtils.replaceIgnoreCase("", *, *)          = ""
  6398.      * StringUtils.replaceIgnoreCase("any", null, *)    = "any"
  6399.      * StringUtils.replaceIgnoreCase("any", *, null)    = "any"
  6400.      * StringUtils.replaceIgnoreCase("any", "", *)      = "any"
  6401.      * StringUtils.replaceIgnoreCase("aba", "a", null)  = "aba"
  6402.      * StringUtils.replaceIgnoreCase("abA", "A", "")    = "b"
  6403.      * StringUtils.replaceIgnoreCase("aba", "A", "z")   = "zbz"
  6404.      * </pre>
  6405.      *
  6406.      * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
  6407.      * @param text  text to search and replace in, may be null
  6408.      * @param searchString  the String to search for (case-insensitive), may be null
  6409.      * @param replacement  the String to replace it with, may be null
  6410.      * @return the text with any replacements processed,
  6411.      *  {@code null} if null String input
  6412.      * @since 3.5
  6413.      * @deprecated Use {@link Strings#replace(String, String, String) Strings.CI.replace(String, String, String)}
  6414.      */
  6415.     @Deprecated
  6416.      public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) {
  6417.          return Strings.CI.replace(text, searchString, replacement);
  6418.      }

  6419.     /**
  6420.      * Case insensitively replaces a String with another String inside a larger String,
  6421.      * for the first {@code max} values of the search String.
  6422.      *
  6423.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6424.      *
  6425.      * <pre>
  6426.      * StringUtils.replaceIgnoreCase(null, *, *, *)         = null
  6427.      * StringUtils.replaceIgnoreCase("", *, *, *)           = ""
  6428.      * StringUtils.replaceIgnoreCase("any", null, *, *)     = "any"
  6429.      * StringUtils.replaceIgnoreCase("any", *, null, *)     = "any"
  6430.      * StringUtils.replaceIgnoreCase("any", "", *, *)       = "any"
  6431.      * StringUtils.replaceIgnoreCase("any", *, *, 0)        = "any"
  6432.      * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa"
  6433.      * StringUtils.replaceIgnoreCase("abaa", "a", "", -1)   = "b"
  6434.      * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0)   = "abaa"
  6435.      * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1)   = "zbaa"
  6436.      * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2)   = "zbza"
  6437.      * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1)  = "zbzz"
  6438.      * </pre>
  6439.      *
  6440.      * @param text  text to search and replace in, may be null
  6441.      * @param searchString  the String to search for (case-insensitive), may be null
  6442.      * @param replacement  the String to replace it with, may be null
  6443.      * @param max  maximum number of values to replace, or {@code -1} if no maximum
  6444.      * @return the text with any replacements processed,
  6445.      *  {@code null} if null String input
  6446.      * @since 3.5
  6447.      * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CI.replace(String, String, String, int)}
  6448.      */
  6449.     @Deprecated
  6450.     public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) {
  6451.         return Strings.CI.replace(text, searchString, replacement, max);
  6452.     }

  6453.     /**
  6454.      * Replaces a String with another String inside a larger String, once.
  6455.      *
  6456.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6457.      *
  6458.      * <pre>
  6459.      * StringUtils.replaceOnce(null, *, *)        = null
  6460.      * StringUtils.replaceOnce("", *, *)          = ""
  6461.      * StringUtils.replaceOnce("any", null, *)    = "any"
  6462.      * StringUtils.replaceOnce("any", *, null)    = "any"
  6463.      * StringUtils.replaceOnce("any", "", *)      = "any"
  6464.      * StringUtils.replaceOnce("aba", "a", null)  = "aba"
  6465.      * StringUtils.replaceOnce("aba", "a", "")    = "ba"
  6466.      * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
  6467.      * </pre>
  6468.      *
  6469.      * @see #replace(String text, String searchString, String replacement, int max)
  6470.      * @param text  text to search and replace in, may be null
  6471.      * @param searchString  the String to search for, may be null
  6472.      * @param replacement  the String to replace with, may be null
  6473.      * @return the text with any replacements processed,
  6474.      *  {@code null} if null String input
  6475.      * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CS.replaceOnce(String, String, String)}
  6476.      */
  6477.     @Deprecated
  6478.     public static String replaceOnce(final String text, final String searchString, final String replacement) {
  6479.         return Strings.CS.replaceOnce(text, searchString, replacement);
  6480.     }

  6481.     /**
  6482.      * Case insensitively replaces a String with another String inside a larger String, once.
  6483.      *
  6484.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6485.      *
  6486.      * <pre>
  6487.      * StringUtils.replaceOnceIgnoreCase(null, *, *)        = null
  6488.      * StringUtils.replaceOnceIgnoreCase("", *, *)          = ""
  6489.      * StringUtils.replaceOnceIgnoreCase("any", null, *)    = "any"
  6490.      * StringUtils.replaceOnceIgnoreCase("any", *, null)    = "any"
  6491.      * StringUtils.replaceOnceIgnoreCase("any", "", *)      = "any"
  6492.      * StringUtils.replaceOnceIgnoreCase("aba", "a", null)  = "aba"
  6493.      * StringUtils.replaceOnceIgnoreCase("aba", "a", "")    = "ba"
  6494.      * StringUtils.replaceOnceIgnoreCase("aba", "a", "z")   = "zba"
  6495.      * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo"
  6496.      * </pre>
  6497.      *
  6498.      * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
  6499.      * @param text  text to search and replace in, may be null
  6500.      * @param searchString  the String to search for (case-insensitive), may be null
  6501.      * @param replacement  the String to replace with, may be null
  6502.      * @return the text with any replacements processed,
  6503.      *  {@code null} if null String input
  6504.      * @since 3.5
  6505.      * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CI.replaceOnce(String, String, String)}
  6506.      */
  6507.     @Deprecated
  6508.     public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) {
  6509.         return Strings.CI.replaceOnce(text, searchString, replacement);
  6510.     }

  6511.     /**
  6512.      * Replaces each substring of the source String that matches the given regular expression with the given
  6513.      * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.
  6514.      *
  6515.      * This call is a {@code null} safe equivalent to:
  6516.      * <ul>
  6517.      * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, replacement)}</li>
  6518.      * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li>
  6519.      * </ul>
  6520.      *
  6521.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6522.      *
  6523.      * <pre>{@code
  6524.      * StringUtils.replacePattern(null, *, *)       = null
  6525.      * StringUtils.replacePattern("any", (String) null, *)   = "any"
  6526.      * StringUtils.replacePattern("any", *, null)   = "any"
  6527.      * StringUtils.replacePattern("", "", "zzz")    = "zzz"
  6528.      * StringUtils.replacePattern("", ".*", "zzz")  = "zzz"
  6529.      * StringUtils.replacePattern("", ".+", "zzz")  = ""
  6530.      * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z")       = "z"
  6531.      * StringUtils.replacePattern("ABCabc123", "[a-z]", "_")       = "ABC___123"
  6532.      * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
  6533.      * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
  6534.      * StringUtils.replacePattern("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
  6535.      * }</pre>
  6536.      *
  6537.      * @param source
  6538.      *            the source string
  6539.      * @param regex
  6540.      *            the regular expression to which this string is to be matched
  6541.      * @param replacement
  6542.      *            the string to be substituted for each match
  6543.      * @return The resulting {@link String}
  6544.      * @see #replaceAll(String, String, String)
  6545.      * @see String#replaceAll(String, String)
  6546.      * @see Pattern#DOTALL
  6547.      * @since 3.2
  6548.      * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
  6549.      * @deprecated Moved to RegExUtils.
  6550.      */
  6551.     @Deprecated
  6552.     public static String replacePattern(final String source, final String regex, final String replacement) {
  6553.         return RegExUtils.replacePattern(source, regex, replacement);
  6554.     }

  6555.     /**
  6556.      * Reverses a String as per {@link StringBuilder#reverse()}.
  6557.      *
  6558.      * <p>A {@code null} String returns {@code null}.</p>
  6559.      *
  6560.      * <pre>
  6561.      * StringUtils.reverse(null)  = null
  6562.      * StringUtils.reverse("")    = ""
  6563.      * StringUtils.reverse("bat") = "tab"
  6564.      * </pre>
  6565.      *
  6566.      * @param str  the String to reverse, may be null
  6567.      * @return the reversed String, {@code null} if null String input
  6568.      */
  6569.     public static String reverse(final String str) {
  6570.         if (str == null) {
  6571.             return null;
  6572.         }
  6573.         return new StringBuilder(str).reverse().toString();
  6574.     }

  6575.     /**
  6576.      * Reverses a String that is delimited by a specific character.
  6577.      *
  6578.      * <p>The Strings between the delimiters are not reversed.
  6579.      * Thus java.lang.String becomes String.lang.java (if the delimiter
  6580.      * is {@code '.'}).</p>
  6581.      *
  6582.      * <pre>
  6583.      * StringUtils.reverseDelimited(null, *)      = null
  6584.      * StringUtils.reverseDelimited("", *)        = ""
  6585.      * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
  6586.      * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
  6587.      * </pre>
  6588.      *
  6589.      * @param str  the String to reverse, may be null
  6590.      * @param separatorChar  the separator character to use
  6591.      * @return the reversed String, {@code null} if null String input
  6592.      * @since 2.0
  6593.      */
  6594.     public static String reverseDelimited(final String str, final char separatorChar) {
  6595.         final String[] strs = split(str, separatorChar);
  6596.         ArrayUtils.reverse(strs);
  6597.         return join(strs, separatorChar);
  6598.     }

  6599.     /**
  6600.      * Gets the rightmost {@code len} characters of a String.
  6601.      *
  6602.      * <p>If {@code len} characters are not available, or the String
  6603.      * is {@code null}, the String will be returned without an
  6604.      * an exception. An empty String is returned if len is negative.</p>
  6605.      *
  6606.      * <pre>
  6607.      * StringUtils.right(null, *)    = null
  6608.      * StringUtils.right(*, -ve)     = ""
  6609.      * StringUtils.right("", *)      = ""
  6610.      * StringUtils.right("abc", 0)   = ""
  6611.      * StringUtils.right("abc", 2)   = "bc"
  6612.      * StringUtils.right("abc", 4)   = "abc"
  6613.      * </pre>
  6614.      *
  6615.      * @param str  the String to get the rightmost characters from, may be null
  6616.      * @param len  the length of the required String
  6617.      * @return the rightmost characters, {@code null} if null String input
  6618.      */
  6619.     public static String right(final String str, final int len) {
  6620.         if (str == null) {
  6621.             return null;
  6622.         }
  6623.         if (len < 0) {
  6624.             return EMPTY;
  6625.         }
  6626.         if (str.length() <= len) {
  6627.             return str;
  6628.         }
  6629.         return str.substring(str.length() - len);
  6630.     }

  6631.     /**
  6632.      * Right pad a String with spaces (' ').
  6633.      *
  6634.      * <p>The String is padded to the size of {@code size}.</p>
  6635.      *
  6636.      * <pre>
  6637.      * StringUtils.rightPad(null, *)   = null
  6638.      * StringUtils.rightPad("", 3)     = "   "
  6639.      * StringUtils.rightPad("bat", 3)  = "bat"
  6640.      * StringUtils.rightPad("bat", 5)  = "bat  "
  6641.      * StringUtils.rightPad("bat", 1)  = "bat"
  6642.      * StringUtils.rightPad("bat", -1) = "bat"
  6643.      * </pre>
  6644.      *
  6645.      * @param str  the String to pad out, may be null
  6646.      * @param size  the size to pad to
  6647.      * @return right padded String or original String if no padding is necessary,
  6648.      *  {@code null} if null String input
  6649.      */
  6650.     public static String rightPad(final String str, final int size) {
  6651.         return rightPad(str, size, ' ');
  6652.     }

  6653.     /**
  6654.      * Right pad a String with a specified character.
  6655.      *
  6656.      * <p>The String is padded to the size of {@code size}.</p>
  6657.      *
  6658.      * <pre>
  6659.      * StringUtils.rightPad(null, *, *)     = null
  6660.      * StringUtils.rightPad("", 3, 'z')     = "zzz"
  6661.      * StringUtils.rightPad("bat", 3, 'z')  = "bat"
  6662.      * StringUtils.rightPad("bat", 5, 'z')  = "batzz"
  6663.      * StringUtils.rightPad("bat", 1, 'z')  = "bat"
  6664.      * StringUtils.rightPad("bat", -1, 'z') = "bat"
  6665.      * </pre>
  6666.      *
  6667.      * @param str  the String to pad out, may be null
  6668.      * @param size  the size to pad to
  6669.      * @param padChar  the character to pad with
  6670.      * @return right padded String or original String if no padding is necessary,
  6671.      *  {@code null} if null String input
  6672.      * @since 2.0
  6673.      */
  6674.     public static String rightPad(final String str, final int size, final char padChar) {
  6675.         if (str == null) {
  6676.             return null;
  6677.         }
  6678.         final int pads = size - str.length();
  6679.         if (pads <= 0) {
  6680.             return str; // returns original String when possible
  6681.         }
  6682.         if (pads > PAD_LIMIT) {
  6683.             return rightPad(str, size, String.valueOf(padChar));
  6684.         }
  6685.         return str.concat(repeat(padChar, pads));
  6686.     }

  6687.     /**
  6688.      * Right pad a String with a specified String.
  6689.      *
  6690.      * <p>The String is padded to the size of {@code size}.</p>
  6691.      *
  6692.      * <pre>
  6693.      * StringUtils.rightPad(null, *, *)      = null
  6694.      * StringUtils.rightPad("", 3, "z")      = "zzz"
  6695.      * StringUtils.rightPad("bat", 3, "yz")  = "bat"
  6696.      * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
  6697.      * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
  6698.      * StringUtils.rightPad("bat", 1, "yz")  = "bat"
  6699.      * StringUtils.rightPad("bat", -1, "yz") = "bat"
  6700.      * StringUtils.rightPad("bat", 5, null)  = "bat  "
  6701.      * StringUtils.rightPad("bat", 5, "")    = "bat  "
  6702.      * </pre>
  6703.      *
  6704.      * @param str  the String to pad out, may be null
  6705.      * @param size  the size to pad to
  6706.      * @param padStr  the String to pad with, null or empty treated as single space
  6707.      * @return right padded String or original String if no padding is necessary,
  6708.      *  {@code null} if null String input
  6709.      */
  6710.     public static String rightPad(final String str, final int size, String padStr) {
  6711.         if (str == null) {
  6712.             return null;
  6713.         }
  6714.         if (isEmpty(padStr)) {
  6715.             padStr = SPACE;
  6716.         }
  6717.         final int padLen = padStr.length();
  6718.         final int strLen = str.length();
  6719.         final int pads = size - strLen;
  6720.         if (pads <= 0) {
  6721.             return str; // returns original String when possible
  6722.         }
  6723.         if (padLen == 1 && pads <= PAD_LIMIT) {
  6724.             return rightPad(str, size, padStr.charAt(0));
  6725.         }

  6726.         if (pads == padLen) {
  6727.             return str.concat(padStr);
  6728.         }
  6729.         if (pads < padLen) {
  6730.             return str.concat(padStr.substring(0, pads));
  6731.         }
  6732.         final char[] padding = new char[pads];
  6733.         final char[] padChars = padStr.toCharArray();
  6734.         for (int i = 0; i < pads; i++) {
  6735.             padding[i] = padChars[i % padLen];
  6736.         }
  6737.         return str.concat(new String(padding));
  6738.     }

  6739.     /**
  6740.      * Rotate (circular shift) a String of {@code shift} characters.
  6741.      * <ul>
  6742.      *  <li>If {@code shift > 0}, right circular shift (ex : ABCDEF =&gt; FABCDE)</li>
  6743.      *  <li>If {@code shift < 0}, left circular shift (ex : ABCDEF =&gt; BCDEFA)</li>
  6744.      * </ul>
  6745.      *
  6746.      * <pre>
  6747.      * StringUtils.rotate(null, *)        = null
  6748.      * StringUtils.rotate("", *)          = ""
  6749.      * StringUtils.rotate("abcdefg", 0)   = "abcdefg"
  6750.      * StringUtils.rotate("abcdefg", 2)   = "fgabcde"
  6751.      * StringUtils.rotate("abcdefg", -2)  = "cdefgab"
  6752.      * StringUtils.rotate("abcdefg", 7)   = "abcdefg"
  6753.      * StringUtils.rotate("abcdefg", -7)  = "abcdefg"
  6754.      * StringUtils.rotate("abcdefg", 9)   = "fgabcde"
  6755.      * StringUtils.rotate("abcdefg", -9)  = "cdefgab"
  6756.      * </pre>
  6757.      *
  6758.      * @param str  the String to rotate, may be null
  6759.      * @param shift  number of time to shift (positive : right shift, negative : left shift)
  6760.      * @return the rotated String,
  6761.      *          or the original String if {@code shift == 0},
  6762.      *          or {@code null} if null String input
  6763.      * @since 3.5
  6764.      */
  6765.     public static String rotate(final String str, final int shift) {
  6766.         if (str == null) {
  6767.             return null;
  6768.         }

  6769.         final int strLen = str.length();
  6770.         if (shift == 0 || strLen == 0 || shift % strLen == 0) {
  6771.             return str;
  6772.         }

  6773.         final StringBuilder builder = new StringBuilder(strLen);
  6774.         final int offset = - (shift % strLen);
  6775.         builder.append(substring(str, offset));
  6776.         builder.append(substring(str, 0, offset));
  6777.         return builder.toString();
  6778.     }

  6779.     /**
  6780.      * Splits the provided text into an array, using whitespace as the
  6781.      * separator.
  6782.      * Whitespace is defined by {@link Character#isWhitespace(char)}.
  6783.      *
  6784.      * <p>The separator is not included in the returned String array.
  6785.      * Adjacent separators are treated as one separator.
  6786.      * For more control over the split use the StrTokenizer class.</p>
  6787.      *
  6788.      * <p>A {@code null} input String returns {@code null}.</p>
  6789.      *
  6790.      * <pre>
  6791.      * StringUtils.split(null)       = null
  6792.      * StringUtils.split("")         = []
  6793.      * StringUtils.split("abc def")  = ["abc", "def"]
  6794.      * StringUtils.split("abc  def") = ["abc", "def"]
  6795.      * StringUtils.split(" abc ")    = ["abc"]
  6796.      * </pre>
  6797.      *
  6798.      * @param str  the String to parse, may be null
  6799.      * @return an array of parsed Strings, {@code null} if null String input
  6800.      */
  6801.     public static String[] split(final String str) {
  6802.         return split(str, null, -1);
  6803.     }

  6804.     /**
  6805.      * Splits the provided text into an array, separator specified.
  6806.      * This is an alternative to using StringTokenizer.
  6807.      *
  6808.      * <p>The separator is not included in the returned String array.
  6809.      * Adjacent separators are treated as one separator.
  6810.      * For more control over the split use the StrTokenizer class.</p>
  6811.      *
  6812.      * <p>A {@code null} input String returns {@code null}.</p>
  6813.      *
  6814.      * <pre>
  6815.      * StringUtils.split(null, *)         = null
  6816.      * StringUtils.split("", *)           = []
  6817.      * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
  6818.      * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
  6819.      * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
  6820.      * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
  6821.      * </pre>
  6822.      *
  6823.      * @param str  the String to parse, may be null
  6824.      * @param separatorChar  the character used as the delimiter
  6825.      * @return an array of parsed Strings, {@code null} if null String input
  6826.      * @since 2.0
  6827.      */
  6828.     public static String[] split(final String str, final char separatorChar) {
  6829.         return splitWorker(str, separatorChar, false);
  6830.     }

  6831.     /**
  6832.      * Splits the provided text into an array, separators specified.
  6833.      * This is an alternative to using StringTokenizer.
  6834.      *
  6835.      * <p>The separator is not included in the returned String array.
  6836.      * Adjacent separators are treated as one separator.
  6837.      * For more control over the split use the StrTokenizer class.</p>
  6838.      *
  6839.      * <p>A {@code null} input String returns {@code null}.
  6840.      * A {@code null} separatorChars splits on whitespace.</p>
  6841.      *
  6842.      * <pre>
  6843.      * StringUtils.split(null, *)         = null
  6844.      * StringUtils.split("", *)           = []
  6845.      * StringUtils.split("abc def", null) = ["abc", "def"]
  6846.      * StringUtils.split("abc def", " ")  = ["abc", "def"]
  6847.      * StringUtils.split("abc  def", " ") = ["abc", "def"]
  6848.      * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
  6849.      * </pre>
  6850.      *
  6851.      * @param str  the String to parse, may be null
  6852.      * @param separatorChars  the characters used as the delimiters,
  6853.      *  {@code null} splits on whitespace
  6854.      * @return an array of parsed Strings, {@code null} if null String input
  6855.      */
  6856.     public static String[] split(final String str, final String separatorChars) {
  6857.         return splitWorker(str, separatorChars, -1, false);
  6858.     }

  6859.     /**
  6860.      * Splits the provided text into an array with a maximum length,
  6861.      * separators specified.
  6862.      *
  6863.      * <p>The separator is not included in the returned String array.
  6864.      * Adjacent separators are treated as one separator.</p>
  6865.      *
  6866.      * <p>A {@code null} input String returns {@code null}.
  6867.      * A {@code null} separatorChars splits on whitespace.</p>
  6868.      *
  6869.      * <p>If more than {@code max} delimited substrings are found, the last
  6870.      * returned string includes all characters after the first {@code max - 1}
  6871.      * returned strings (including separator characters).</p>
  6872.      *
  6873.      * <pre>
  6874.      * StringUtils.split(null, *, *)            = null
  6875.      * StringUtils.split("", *, *)              = []
  6876.      * StringUtils.split("ab cd ef", null, 0)   = ["ab", "cd", "ef"]
  6877.      * StringUtils.split("ab   cd ef", null, 0) = ["ab", "cd", "ef"]
  6878.      * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
  6879.      * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
  6880.      * </pre>
  6881.      *
  6882.      * @param str  the String to parse, may be null
  6883.      * @param separatorChars  the characters used as the delimiters,
  6884.      *  {@code null} splits on whitespace
  6885.      * @param max  the maximum number of elements to include in the
  6886.      *  array. A zero or negative value implies no limit
  6887.      * @return an array of parsed Strings, {@code null} if null String input
  6888.      */
  6889.     public static String[] split(final String str, final String separatorChars, final int max) {
  6890.         return splitWorker(str, separatorChars, max, false);
  6891.     }

  6892.     /**
  6893.      * Splits a String by Character type as returned by
  6894.      * {@code java.lang.Character.getType(char)}. Groups of contiguous
  6895.      * characters of the same type are returned as complete tokens.
  6896.      * <pre>
  6897.      * StringUtils.splitByCharacterType(null)         = null
  6898.      * StringUtils.splitByCharacterType("")           = []
  6899.      * StringUtils.splitByCharacterType("ab de fg")   = ["ab", " ", "de", " ", "fg"]
  6900.      * StringUtils.splitByCharacterType("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
  6901.      * StringUtils.splitByCharacterType("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
  6902.      * StringUtils.splitByCharacterType("number5")    = ["number", "5"]
  6903.      * StringUtils.splitByCharacterType("fooBar")     = ["foo", "B", "ar"]
  6904.      * StringUtils.splitByCharacterType("foo200Bar")  = ["foo", "200", "B", "ar"]
  6905.      * StringUtils.splitByCharacterType("ASFRules")   = ["ASFR", "ules"]
  6906.      * </pre>
  6907.      * @param str the String to split, may be {@code null}
  6908.      * @return an array of parsed Strings, {@code null} if null String input
  6909.      * @since 2.4
  6910.      */
  6911.     public static String[] splitByCharacterType(final String str) {
  6912.         return splitByCharacterType(str, false);
  6913.     }

  6914.     /**
  6915.      * <p>Splits a String by Character type as returned by
  6916.      * {@code java.lang.Character.getType(char)}. Groups of contiguous
  6917.      * characters of the same type are returned as complete tokens, with the
  6918.      * following exception: if {@code camelCase} is {@code true},
  6919.      * the character of type {@code Character.UPPERCASE_LETTER}, if any,
  6920.      * immediately preceding a token of type {@code Character.LOWERCASE_LETTER}
  6921.      * will belong to the following token rather than to the preceding, if any,
  6922.      * {@code Character.UPPERCASE_LETTER} token.
  6923.      * @param str the String to split, may be {@code null}
  6924.      * @param camelCase whether to use so-called "camel-case" for letter types
  6925.      * @return an array of parsed Strings, {@code null} if null String input
  6926.      * @since 2.4
  6927.      */
  6928.     private static String[] splitByCharacterType(final String str, final boolean camelCase) {
  6929.         if (str == null) {
  6930.             return null;
  6931.         }
  6932.         if (str.isEmpty()) {
  6933.             return ArrayUtils.EMPTY_STRING_ARRAY;
  6934.         }
  6935.         final char[] c = str.toCharArray();
  6936.         final List<String> list = new ArrayList<>();
  6937.         int tokenStart = 0;
  6938.         int currentType = Character.getType(c[tokenStart]);
  6939.         for (int pos = tokenStart + 1; pos < c.length; pos++) {
  6940.             final int type = Character.getType(c[pos]);
  6941.             if (type == currentType) {
  6942.                 continue;
  6943.             }
  6944.             if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
  6945.                 final int newTokenStart = pos - 1;
  6946.                 if (newTokenStart != tokenStart) {
  6947.                     list.add(new String(c, tokenStart, newTokenStart - tokenStart));
  6948.                     tokenStart = newTokenStart;
  6949.                 }
  6950.             } else {
  6951.                 list.add(new String(c, tokenStart, pos - tokenStart));
  6952.                 tokenStart = pos;
  6953.             }
  6954.             currentType = type;
  6955.         }
  6956.         list.add(new String(c, tokenStart, c.length - tokenStart));
  6957.         return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
  6958.     }

  6959.     /**
  6960.      * <p>Splits a String by Character type as returned by
  6961.      * {@code java.lang.Character.getType(char)}. Groups of contiguous
  6962.      * characters of the same type are returned as complete tokens, with the
  6963.      * following exception: the character of type
  6964.      * {@code Character.UPPERCASE_LETTER}, if any, immediately
  6965.      * preceding a token of type {@code Character.LOWERCASE_LETTER}
  6966.      * will belong to the following token rather than to the preceding, if any,
  6967.      * {@code Character.UPPERCASE_LETTER} token.
  6968.      * <pre>
  6969.      * StringUtils.splitByCharacterTypeCamelCase(null)         = null
  6970.      * StringUtils.splitByCharacterTypeCamelCase("")           = []
  6971.      * StringUtils.splitByCharacterTypeCamelCase("ab de fg")   = ["ab", " ", "de", " ", "fg"]
  6972.      * StringUtils.splitByCharacterTypeCamelCase("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
  6973.      * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
  6974.      * StringUtils.splitByCharacterTypeCamelCase("number5")    = ["number", "5"]
  6975.      * StringUtils.splitByCharacterTypeCamelCase("fooBar")     = ["foo", "Bar"]
  6976.      * StringUtils.splitByCharacterTypeCamelCase("foo200Bar")  = ["foo", "200", "Bar"]
  6977.      * StringUtils.splitByCharacterTypeCamelCase("ASFRules")   = ["ASF", "Rules"]
  6978.      * </pre>
  6979.      * @param str the String to split, may be {@code null}
  6980.      * @return an array of parsed Strings, {@code null} if null String input
  6981.      * @since 2.4
  6982.      */
  6983.     public static String[] splitByCharacterTypeCamelCase(final String str) {
  6984.         return splitByCharacterType(str, true);
  6985.     }

  6986.     /**
  6987.      * <p>Splits the provided text into an array, separator string specified.
  6988.      *
  6989.      * <p>The separator(s) will not be included in the returned String array.
  6990.      * Adjacent separators are treated as one separator.</p>
  6991.      *
  6992.      * <p>A {@code null} input String returns {@code null}.
  6993.      * A {@code null} separator splits on whitespace.</p>
  6994.      *
  6995.      * <pre>
  6996.      * StringUtils.splitByWholeSeparator(null, *)               = null
  6997.      * StringUtils.splitByWholeSeparator("", *)                 = []
  6998.      * StringUtils.splitByWholeSeparator("ab de fg", null)      = ["ab", "de", "fg"]
  6999.      * StringUtils.splitByWholeSeparator("ab   de fg", null)    = ["ab", "de", "fg"]
  7000.      * StringUtils.splitByWholeSeparator("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
  7001.      * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
  7002.      * </pre>
  7003.      *
  7004.      * @param str  the String to parse, may be null
  7005.      * @param separator  String containing the String to be used as a delimiter,
  7006.      *  {@code null} splits on whitespace
  7007.      * @return an array of parsed Strings, {@code null} if null String was input
  7008.      */
  7009.     public static String[] splitByWholeSeparator(final String str, final String separator) {
  7010.         return splitByWholeSeparatorWorker(str, separator, -1, false);
  7011.     }

  7012.     /**
  7013.      * Splits the provided text into an array, separator string specified.
  7014.      * Returns a maximum of {@code max} substrings.
  7015.      *
  7016.      * <p>The separator(s) will not be included in the returned String array.
  7017.      * Adjacent separators are treated as one separator.</p>
  7018.      *
  7019.      * <p>A {@code null} input String returns {@code null}.
  7020.      * A {@code null} separator splits on whitespace.</p>
  7021.      *
  7022.      * <pre>
  7023.      * StringUtils.splitByWholeSeparator(null, *, *)               = null
  7024.      * StringUtils.splitByWholeSeparator("", *, *)                 = []
  7025.      * StringUtils.splitByWholeSeparator("ab de fg", null, 0)      = ["ab", "de", "fg"]
  7026.      * StringUtils.splitByWholeSeparator("ab   de fg", null, 0)    = ["ab", "de", "fg"]
  7027.      * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
  7028.      * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
  7029.      * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
  7030.      * </pre>
  7031.      *
  7032.      * @param str  the String to parse, may be null
  7033.      * @param separator  String containing the String to be used as a delimiter,
  7034.      *  {@code null} splits on whitespace
  7035.      * @param max  the maximum number of elements to include in the returned
  7036.      *  array. A zero or negative value implies no limit.
  7037.      * @return an array of parsed Strings, {@code null} if null String was input
  7038.      */
  7039.     public static String[] splitByWholeSeparator(final String str, final String separator, final int max) {
  7040.         return splitByWholeSeparatorWorker(str, separator, max, false);
  7041.     }

  7042.     /**
  7043.      * Splits the provided text into an array, separator string specified.
  7044.      *
  7045.      * <p>The separator is not included in the returned String array.
  7046.      * Adjacent separators are treated as separators for empty tokens.
  7047.      * For more control over the split use the StrTokenizer class.</p>
  7048.      *
  7049.      * <p>A {@code null} input String returns {@code null}.
  7050.      * A {@code null} separator splits on whitespace.</p>
  7051.      *
  7052.      * <pre>
  7053.      * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *)               = null
  7054.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *)                 = []
  7055.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null)      = ["ab", "de", "fg"]
  7056.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null)    = ["ab", "", "", "de", "fg"]
  7057.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
  7058.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
  7059.      * </pre>
  7060.      *
  7061.      * @param str  the String to parse, may be null
  7062.      * @param separator  String containing the String to be used as a delimiter,
  7063.      *  {@code null} splits on whitespace
  7064.      * @return an array of parsed Strings, {@code null} if null String was input
  7065.      * @since 2.4
  7066.      */
  7067.     public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) {
  7068.         return splitByWholeSeparatorWorker(str, separator, -1, true);
  7069.     }

  7070.     /**
  7071.      * Splits the provided text into an array, separator string specified.
  7072.      * Returns a maximum of {@code max} substrings.
  7073.      *
  7074.      * <p>The separator is not included in the returned String array.
  7075.      * Adjacent separators are treated as separators for empty tokens.
  7076.      * For more control over the split use the StrTokenizer class.</p>
  7077.      *
  7078.      * <p>A {@code null} input String returns {@code null}.
  7079.      * A {@code null} separator splits on whitespace.</p>
  7080.      *
  7081.      * <pre>
  7082.      * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *)               = null
  7083.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *)                 = []
  7084.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0)      = ["ab", "de", "fg"]
  7085.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null, 0)    = ["ab", "", "", "de", "fg"]
  7086.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
  7087.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
  7088.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
  7089.      * </pre>
  7090.      *
  7091.      * @param str  the String to parse, may be null
  7092.      * @param separator  String containing the String to be used as a delimiter,
  7093.      *  {@code null} splits on whitespace
  7094.      * @param max  the maximum number of elements to include in the returned
  7095.      *  array. A zero or negative value implies no limit.
  7096.      * @return an array of parsed Strings, {@code null} if null String was input
  7097.      * @since 2.4
  7098.      */
  7099.     public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) {
  7100.         return splitByWholeSeparatorWorker(str, separator, max, true);
  7101.     }

  7102.     /**
  7103.      * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods.
  7104.      *
  7105.      * @param str  the String to parse, may be {@code null}
  7106.      * @param separator  String containing the String to be used as a delimiter,
  7107.      *  {@code null} splits on whitespace
  7108.      * @param max  the maximum number of elements to include in the returned
  7109.      *  array. A zero or negative value implies no limit.
  7110.      * @param preserveAllTokens if {@code true}, adjacent separators are
  7111.      * treated as empty token separators; if {@code false}, adjacent
  7112.      * separators are treated as one separator.
  7113.      * @return an array of parsed Strings, {@code null} if null String input
  7114.      * @since 2.4
  7115.      */
  7116.     private static String[] splitByWholeSeparatorWorker(
  7117.             final String str, final String separator, final int max, final boolean preserveAllTokens) {
  7118.         if (str == null) {
  7119.             return null;
  7120.         }

  7121.         final int len = str.length();

  7122.         if (len == 0) {
  7123.             return ArrayUtils.EMPTY_STRING_ARRAY;
  7124.         }

  7125.         if (separator == null || EMPTY.equals(separator)) {
  7126.             // Split on whitespace.
  7127.             return splitWorker(str, null, max, preserveAllTokens);
  7128.         }

  7129.         final int separatorLength = separator.length();

  7130.         final ArrayList<String> substrings = new ArrayList<>();
  7131.         int numberOfSubstrings = 0;
  7132.         int beg = 0;
  7133.         int end = 0;
  7134.         while (end < len) {
  7135.             end = str.indexOf(separator, beg);

  7136.             if (end > -1) {
  7137.                 if (end > beg) {
  7138.                     numberOfSubstrings += 1;

  7139.                     if (numberOfSubstrings == max) {
  7140.                         end = len;
  7141.                         substrings.add(str.substring(beg));
  7142.                     } else {
  7143.                         // The following is OK, because String.substring( beg, end ) excludes
  7144.                         // the character at the position 'end'.
  7145.                         substrings.add(str.substring(beg, end));

  7146.                         // Set the starting point for the next search.
  7147.                         // The following is equivalent to beg = end + (separatorLength - 1) + 1,
  7148.                         // which is the right calculation:
  7149.                         beg = end + separatorLength;
  7150.                     }
  7151.                 } else {
  7152.                     // We found a consecutive occurrence of the separator, so skip it.
  7153.                     if (preserveAllTokens) {
  7154.                         numberOfSubstrings += 1;
  7155.                         if (numberOfSubstrings == max) {
  7156.                             end = len;
  7157.                             substrings.add(str.substring(beg));
  7158.                         } else {
  7159.                             substrings.add(EMPTY);
  7160.                         }
  7161.                     }
  7162.                     beg = end + separatorLength;
  7163.                 }
  7164.             } else {
  7165.                 // String.substring( beg ) goes from 'beg' to the end of the String.
  7166.                 substrings.add(str.substring(beg));
  7167.                 end = len;
  7168.             }
  7169.         }

  7170.         return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
  7171.     }

  7172.     /**
  7173.      * Splits the provided text into an array, using whitespace as the
  7174.      * separator, preserving all tokens, including empty tokens created by
  7175.      * adjacent separators. This is an alternative to using StringTokenizer.
  7176.      * Whitespace is defined by {@link Character#isWhitespace(char)}.
  7177.      *
  7178.      * <p>The separator is not included in the returned String array.
  7179.      * Adjacent separators are treated as separators for empty tokens.
  7180.      * For more control over the split use the StrTokenizer class.</p>
  7181.      *
  7182.      * <p>A {@code null} input String returns {@code null}.</p>
  7183.      *
  7184.      * <pre>
  7185.      * StringUtils.splitPreserveAllTokens(null)       = null
  7186.      * StringUtils.splitPreserveAllTokens("")         = []
  7187.      * StringUtils.splitPreserveAllTokens("abc def")  = ["abc", "def"]
  7188.      * StringUtils.splitPreserveAllTokens("abc  def") = ["abc", "", "def"]
  7189.      * StringUtils.splitPreserveAllTokens(" abc ")    = ["", "abc", ""]
  7190.      * </pre>
  7191.      *
  7192.      * @param str  the String to parse, may be {@code null}
  7193.      * @return an array of parsed Strings, {@code null} if null String input
  7194.      * @since 2.1
  7195.      */
  7196.     public static String[] splitPreserveAllTokens(final String str) {
  7197.         return splitWorker(str, null, -1, true);
  7198.     }

  7199.     /**
  7200.      * Splits the provided text into an array, separator specified,
  7201.      * preserving all tokens, including empty tokens created by adjacent
  7202.      * separators. This is an alternative to using StringTokenizer.
  7203.      *
  7204.      * <p>The separator is not included in the returned String array.
  7205.      * Adjacent separators are treated as separators for empty tokens.
  7206.      * For more control over the split use the StrTokenizer class.</p>
  7207.      *
  7208.      * <p>A {@code null} input String returns {@code null}.</p>
  7209.      *
  7210.      * <pre>
  7211.      * StringUtils.splitPreserveAllTokens(null, *)         = null
  7212.      * StringUtils.splitPreserveAllTokens("", *)           = []
  7213.      * StringUtils.splitPreserveAllTokens("a.b.c", '.')    = ["a", "b", "c"]
  7214.      * StringUtils.splitPreserveAllTokens("a..b.c", '.')   = ["a", "", "b", "c"]
  7215.      * StringUtils.splitPreserveAllTokens("a:b:c", '.')    = ["a:b:c"]
  7216.      * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
  7217.      * StringUtils.splitPreserveAllTokens("a b c", ' ')    = ["a", "b", "c"]
  7218.      * StringUtils.splitPreserveAllTokens("a b c ", ' ')   = ["a", "b", "c", ""]
  7219.      * StringUtils.splitPreserveAllTokens("a b c  ", ' ')  = ["a", "b", "c", "", ""]
  7220.      * StringUtils.splitPreserveAllTokens(" a b c", ' ')   = ["", "a", "b", "c"]
  7221.      * StringUtils.splitPreserveAllTokens("  a b c", ' ')  = ["", "", "a", "b", "c"]
  7222.      * StringUtils.splitPreserveAllTokens(" a b c ", ' ')  = ["", "a", "b", "c", ""]
  7223.      * </pre>
  7224.      *
  7225.      * @param str  the String to parse, may be {@code null}
  7226.      * @param separatorChar  the character used as the delimiter,
  7227.      *  {@code null} splits on whitespace
  7228.      * @return an array of parsed Strings, {@code null} if null String input
  7229.      * @since 2.1
  7230.      */
  7231.     public static String[] splitPreserveAllTokens(final String str, final char separatorChar) {
  7232.         return splitWorker(str, separatorChar, true);
  7233.     }

  7234.     /**
  7235.      * Splits the provided text into an array, separators specified,
  7236.      * preserving all tokens, including empty tokens created by adjacent
  7237.      * separators. This is an alternative to using StringTokenizer.
  7238.      *
  7239.      * <p>The separator is not included in the returned String array.
  7240.      * Adjacent separators are treated as separators for empty tokens.
  7241.      * For more control over the split use the StrTokenizer class.</p>
  7242.      *
  7243.      * <p>A {@code null} input String returns {@code null}.
  7244.      * A {@code null} separatorChars splits on whitespace.</p>
  7245.      *
  7246.      * <pre>
  7247.      * StringUtils.splitPreserveAllTokens(null, *)           = null
  7248.      * StringUtils.splitPreserveAllTokens("", *)             = []
  7249.      * StringUtils.splitPreserveAllTokens("abc def", null)   = ["abc", "def"]
  7250.      * StringUtils.splitPreserveAllTokens("abc def", " ")    = ["abc", "def"]
  7251.      * StringUtils.splitPreserveAllTokens("abc  def", " ")   = ["abc", "", "def"]
  7252.      * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":")   = ["ab", "cd", "ef"]
  7253.      * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":")  = ["ab", "cd", "ef", ""]
  7254.      * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
  7255.      * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":")  = ["ab", "", "cd", "ef"]
  7256.      * StringUtils.splitPreserveAllTokens(":cd:ef", ":")     = ["", "cd", "ef"]
  7257.      * StringUtils.splitPreserveAllTokens("::cd:ef", ":")    = ["", "", "cd", "ef"]
  7258.      * StringUtils.splitPreserveAllTokens(":cd:ef:", ":")    = ["", "cd", "ef", ""]
  7259.      * </pre>
  7260.      *
  7261.      * @param str  the String to parse, may be {@code null}
  7262.      * @param separatorChars  the characters used as the delimiters,
  7263.      *  {@code null} splits on whitespace
  7264.      * @return an array of parsed Strings, {@code null} if null String input
  7265.      * @since 2.1
  7266.      */
  7267.     public static String[] splitPreserveAllTokens(final String str, final String separatorChars) {
  7268.         return splitWorker(str, separatorChars, -1, true);
  7269.     }

  7270.     /**
  7271.      * Splits the provided text into an array with a maximum length,
  7272.      * separators specified, preserving all tokens, including empty tokens
  7273.      * created by adjacent separators.
  7274.      *
  7275.      * <p>The separator is not included in the returned String array.
  7276.      * Adjacent separators are treated as separators for empty tokens.
  7277.      * Adjacent separators are treated as one separator.</p>
  7278.      *
  7279.      * <p>A {@code null} input String returns {@code null}.
  7280.      * A {@code null} separatorChars splits on whitespace.</p>
  7281.      *
  7282.      * <p>If more than {@code max} delimited substrings are found, the last
  7283.      * returned string includes all characters after the first {@code max - 1}
  7284.      * returned strings (including separator characters).</p>
  7285.      *
  7286.      * <pre>
  7287.      * StringUtils.splitPreserveAllTokens(null, *, *)            = null
  7288.      * StringUtils.splitPreserveAllTokens("", *, *)              = []
  7289.      * StringUtils.splitPreserveAllTokens("ab de fg", null, 0)   = ["ab", "de", "fg"]
  7290.      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 0) = ["ab", "", "", "de", "fg"]
  7291.      * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
  7292.      * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
  7293.      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 2) = ["ab", "  de fg"]
  7294.      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 3) = ["ab", "", " de fg"]
  7295.      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 4) = ["ab", "", "", "de fg"]
  7296.      * </pre>
  7297.      *
  7298.      * @param str  the String to parse, may be {@code null}
  7299.      * @param separatorChars  the characters used as the delimiters,
  7300.      *  {@code null} splits on whitespace
  7301.      * @param max  the maximum number of elements to include in the
  7302.      *  array. A zero or negative value implies no limit
  7303.      * @return an array of parsed Strings, {@code null} if null String input
  7304.      * @since 2.1
  7305.      */
  7306.     public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) {
  7307.         return splitWorker(str, separatorChars, max, true);
  7308.     }

  7309.     /**
  7310.      * Performs the logic for the {@code split} and
  7311.      * {@code splitPreserveAllTokens} methods that do not return a
  7312.      * maximum array length.
  7313.      *
  7314.      * @param str  the String to parse, may be {@code null}
  7315.      * @param separatorChar the separate character
  7316.      * @param preserveAllTokens if {@code true}, adjacent separators are
  7317.      * treated as empty token separators; if {@code false}, adjacent
  7318.      * separators are treated as one separator.
  7319.      * @return an array of parsed Strings, {@code null} if null String input
  7320.      */
  7321.     private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) {
  7322.         // Performance tuned for 2.0 (JDK1.4)
  7323.         if (str == null) {
  7324.             return null;
  7325.         }
  7326.         final int len = str.length();
  7327.         if (len == 0) {
  7328.             return ArrayUtils.EMPTY_STRING_ARRAY;
  7329.         }
  7330.         final List<String> list = new ArrayList<>();
  7331.         int i = 0;
  7332.         int start = 0;
  7333.         boolean match = false;
  7334.         boolean lastMatch = false;
  7335.         while (i < len) {
  7336.             if (str.charAt(i) == separatorChar) {
  7337.                 if (match || preserveAllTokens) {
  7338.                     list.add(str.substring(start, i));
  7339.                     match = false;
  7340.                     lastMatch = true;
  7341.                 }
  7342.                 start = ++i;
  7343.                 continue;
  7344.             }
  7345.             lastMatch = false;
  7346.             match = true;
  7347.             i++;
  7348.         }
  7349.         if (match || preserveAllTokens && lastMatch) {
  7350.             list.add(str.substring(start, i));
  7351.         }
  7352.         return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
  7353.     }

  7354.     /**
  7355.      * Performs the logic for the {@code split} and
  7356.      * {@code splitPreserveAllTokens} methods that return a maximum array
  7357.      * length.
  7358.      *
  7359.      * @param str  the String to parse, may be {@code null}
  7360.      * @param separatorChars the separate character
  7361.      * @param max  the maximum number of elements to include in the
  7362.      *  array. A zero or negative value implies no limit.
  7363.      * @param preserveAllTokens if {@code true}, adjacent separators are
  7364.      * treated as empty token separators; if {@code false}, adjacent
  7365.      * separators are treated as one separator.
  7366.      * @return an array of parsed Strings, {@code null} if null String input
  7367.      */
  7368.     private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) {
  7369.         // Performance tuned for 2.0 (JDK1.4)
  7370.         // Direct code is quicker than StringTokenizer.
  7371.         // Also, StringTokenizer uses isSpace() not isWhitespace()

  7372.         if (str == null) {
  7373.             return null;
  7374.         }
  7375.         final int len = str.length();
  7376.         if (len == 0) {
  7377.             return ArrayUtils.EMPTY_STRING_ARRAY;
  7378.         }
  7379.         final List<String> list = new ArrayList<>();
  7380.         int sizePlus1 = 1;
  7381.         int i = 0;
  7382.         int start = 0;
  7383.         boolean match = false;
  7384.         boolean lastMatch = false;
  7385.         if (separatorChars == null) {
  7386.             // Null separator means use whitespace
  7387.             while (i < len) {
  7388.                 if (Character.isWhitespace(str.charAt(i))) {
  7389.                     if (match || preserveAllTokens) {
  7390.                         lastMatch = true;
  7391.                         if (sizePlus1++ == max) {
  7392.                             i = len;
  7393.                             lastMatch = false;
  7394.                         }
  7395.                         list.add(str.substring(start, i));
  7396.                         match = false;
  7397.                     }
  7398.                     start = ++i;
  7399.                     continue;
  7400.                 }
  7401.                 lastMatch = false;
  7402.                 match = true;
  7403.                 i++;
  7404.             }
  7405.         } else if (separatorChars.length() == 1) {
  7406.             // Optimize 1 character case
  7407.             final char sep = separatorChars.charAt(0);
  7408.             while (i < len) {
  7409.                 if (str.charAt(i) == sep) {
  7410.                     if (match || preserveAllTokens) {
  7411.                         lastMatch = true;
  7412.                         if (sizePlus1++ == max) {
  7413.                             i = len;
  7414.                             lastMatch = false;
  7415.                         }
  7416.                         list.add(str.substring(start, i));
  7417.                         match = false;
  7418.                     }
  7419.                     start = ++i;
  7420.                     continue;
  7421.                 }
  7422.                 lastMatch = false;
  7423.                 match = true;
  7424.                 i++;
  7425.             }
  7426.         } else {
  7427.             // standard case
  7428.             while (i < len) {
  7429.                 if (separatorChars.indexOf(str.charAt(i)) >= 0) {
  7430.                     if (match || preserveAllTokens) {
  7431.                         lastMatch = true;
  7432.                         if (sizePlus1++ == max) {
  7433.                             i = len;
  7434.                             lastMatch = false;
  7435.                         }
  7436.                         list.add(str.substring(start, i));
  7437.                         match = false;
  7438.                     }
  7439.                     start = ++i;
  7440.                     continue;
  7441.                 }
  7442.                 lastMatch = false;
  7443.                 match = true;
  7444.                 i++;
  7445.             }
  7446.         }
  7447.         if (match || preserveAllTokens && lastMatch) {
  7448.             list.add(str.substring(start, i));
  7449.         }
  7450.         return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
  7451.     }

  7452.     /**
  7453.      * Tests if a CharSequence starts with a specified prefix.
  7454.      *
  7455.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  7456.      * references are considered to be equal. The comparison is case-sensitive.</p>
  7457.      *
  7458.      * <pre>
  7459.      * StringUtils.startsWith(null, null)      = true
  7460.      * StringUtils.startsWith(null, "abc")     = false
  7461.      * StringUtils.startsWith("abcdef", null)  = false
  7462.      * StringUtils.startsWith("abcdef", "abc") = true
  7463.      * StringUtils.startsWith("ABCDEF", "abc") = false
  7464.      * </pre>
  7465.      *
  7466.      * @see String#startsWith(String)
  7467.      * @param str  the CharSequence to check, may be null
  7468.      * @param prefix the prefix to find, may be null
  7469.      * @return {@code true} if the CharSequence starts with the prefix, case-sensitive, or
  7470.      *  both {@code null}
  7471.      * @since 2.4
  7472.      * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
  7473.      * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CS.startsWith(CharSequence, CharSequence)}
  7474.      */
  7475.     @Deprecated
  7476.     public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
  7477.         return Strings.CS.startsWith(str, prefix);
  7478.     }

  7479.     /**
  7480.      * Tests if a CharSequence starts with any of the provided case-sensitive prefixes.
  7481.      *
  7482.      * <pre>
  7483.      * StringUtils.startsWithAny(null, null)      = false
  7484.      * StringUtils.startsWithAny(null, new String[] {"abc"})  = false
  7485.      * StringUtils.startsWithAny("abcxyz", null)     = false
  7486.      * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true
  7487.      * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
  7488.      * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
  7489.      * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false
  7490.      * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false
  7491.      * </pre>
  7492.      *
  7493.      * @param sequence the CharSequence to check, may be null
  7494.      * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null}
  7495.      * @see StringUtils#startsWith(CharSequence, CharSequence)
  7496.      * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
  7497.      *   the input {@code sequence} begins with any of the provided case-sensitive {@code searchStrings}.
  7498.      * @since 2.5
  7499.      * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...)
  7500.      * @deprecated Use {@link Strings#startsWithAny(CharSequence, CharSequence...) Strings.CI.startsWithAny(CharSequence, CharSequence...)}
  7501.      */
  7502.     @Deprecated
  7503.     public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
  7504.         return Strings.CS.startsWithAny(sequence, searchStrings);
  7505.     }

  7506.     /**
  7507.      * Case-insensitive check if a CharSequence starts with a specified prefix.
  7508.      *
  7509.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  7510.      * references are considered to be equal. The comparison is case insensitive.</p>
  7511.      *
  7512.      * <pre>
  7513.      * StringUtils.startsWithIgnoreCase(null, null)      = true
  7514.      * StringUtils.startsWithIgnoreCase(null, "abc")     = false
  7515.      * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
  7516.      * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
  7517.      * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
  7518.      * </pre>
  7519.      *
  7520.      * @see String#startsWith(String)
  7521.      * @param str  the CharSequence to check, may be null
  7522.      * @param prefix the prefix to find, may be null
  7523.      * @return {@code true} if the CharSequence starts with the prefix, case-insensitive, or
  7524.      *  both {@code null}
  7525.      * @since 2.4
  7526.      * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
  7527.      * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CI.startsWith(CharSequence, CharSequence)}
  7528.      */
  7529.     @Deprecated
  7530.     public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
  7531.         return Strings.CI.startsWith(str, prefix);
  7532.     }

  7533.     /**
  7534.      * Strips whitespace from the start and end of a String.
  7535.      *
  7536.      * <p>This is similar to {@link #trim(String)} but removes whitespace.
  7537.      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  7538.      *
  7539.      * <p>A {@code null} input String returns {@code null}.</p>
  7540.      *
  7541.      * <pre>
  7542.      * StringUtils.strip(null)     = null
  7543.      * StringUtils.strip("")       = ""
  7544.      * StringUtils.strip("   ")    = ""
  7545.      * StringUtils.strip("abc")    = "abc"
  7546.      * StringUtils.strip("  abc")  = "abc"
  7547.      * StringUtils.strip("abc  ")  = "abc"
  7548.      * StringUtils.strip(" abc ")  = "abc"
  7549.      * StringUtils.strip(" ab c ") = "ab c"
  7550.      * </pre>
  7551.      *
  7552.      * @param str  the String to remove whitespace from, may be null
  7553.      * @return the stripped String, {@code null} if null String input
  7554.      */
  7555.     public static String strip(final String str) {
  7556.         return strip(str, null);
  7557.     }

  7558.     /**
  7559.      * Strips any of a set of characters from the start and end of a String.
  7560.      * This is similar to {@link String#trim()} but allows the characters
  7561.      * to be stripped to be controlled.
  7562.      *
  7563.      * <p>A {@code null} input String returns {@code null}.
  7564.      * An empty string ("") input returns the empty string.</p>
  7565.      *
  7566.      * <p>If the stripChars String is {@code null}, whitespace is
  7567.      * stripped as defined by {@link Character#isWhitespace(char)}.
  7568.      * Alternatively use {@link #strip(String)}.</p>
  7569.      *
  7570.      * <pre>
  7571.      * StringUtils.strip(null, *)          = null
  7572.      * StringUtils.strip("", *)            = ""
  7573.      * StringUtils.strip("abc", null)      = "abc"
  7574.      * StringUtils.strip("  abc", null)    = "abc"
  7575.      * StringUtils.strip("abc  ", null)    = "abc"
  7576.      * StringUtils.strip(" abc ", null)    = "abc"
  7577.      * StringUtils.strip("  abcyx", "xyz") = "  abc"
  7578.      * </pre>
  7579.      *
  7580.      * @param str  the String to remove characters from, may be null
  7581.      * @param stripChars  the characters to remove, null treated as whitespace
  7582.      * @return the stripped String, {@code null} if null String input
  7583.      */
  7584.     public static String strip(String str, final String stripChars) {
  7585.         str = stripStart(str, stripChars);
  7586.         return stripEnd(str, stripChars);
  7587.     }

  7588.     /**
  7589.      * Removes diacritics (~= accents) from a string. The case will not be altered.
  7590.      * <p>
  7591.      * For instance, '&agrave;' will be replaced by 'a'.
  7592.      * </p>
  7593.      * <p>
  7594.      * Decomposes ligatures and digraphs per the KD column in the <a href = "https://www.unicode.org/charts/normalization/">Unicode Normalization Chart.</a>
  7595.      * </p>
  7596.      * <pre>
  7597.      * StringUtils.stripAccents(null)         = null
  7598.      * StringUtils.stripAccents("")           = ""
  7599.      * StringUtils.stripAccents("control")    = "control"
  7600.      * StringUtils.stripAccents("&eacute;clair")     = "eclair"
  7601.      * StringUtils.stripAccents("\u1d43\u1d47\u1d9c\u00b9\u00b2\u00b3")     = "abc123"
  7602.      * StringUtils.stripAccents("\u00BC \u00BD \u00BE")      = "1⁄4 1⁄2 3⁄4"
  7603.      * </pre>
  7604.      * <p>
  7605.      * See also <a href="http://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode Standard Annex #15 Unicode Normalization Forms</a>.
  7606.      * </p>
  7607.      *
  7608.      * @param input String to be stripped
  7609.      * @return input text with diacritics removed
  7610.      * @since 3.0
  7611.      */
  7612.     // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907).
  7613.     public static String stripAccents(final String input) {
  7614.         if (isEmpty(input)) {
  7615.             return input;
  7616.         }
  7617.         final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFKD));
  7618.         convertRemainingAccentCharacters(decomposed);
  7619.         return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY);
  7620.     }

  7621.     /**
  7622.      * Strips whitespace from the start and end of every String in an array.
  7623.      * Whitespace is defined by {@link Character#isWhitespace(char)}.
  7624.      *
  7625.      * <p>A new array is returned each time, except for length zero.
  7626.      * A {@code null} array will return {@code null}.
  7627.      * An empty array will return itself.
  7628.      * A {@code null} array entry will be ignored.</p>
  7629.      *
  7630.      * <pre>
  7631.      * StringUtils.stripAll(null)             = null
  7632.      * StringUtils.stripAll([])               = []
  7633.      * StringUtils.stripAll(["abc", "  abc"]) = ["abc", "abc"]
  7634.      * StringUtils.stripAll(["abc  ", null])  = ["abc", null]
  7635.      * </pre>
  7636.      *
  7637.      * @param strs  the array to remove whitespace from, may be null
  7638.      * @return the stripped Strings, {@code null} if null array input
  7639.      */
  7640.     public static String[] stripAll(final String... strs) {
  7641.         return stripAll(strs, null);
  7642.     }

  7643.     /**
  7644.      * Strips any of a set of characters from the start and end of every
  7645.      * String in an array.
  7646.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  7647.      *
  7648.      * <p>A new array is returned each time, except for length zero.
  7649.      * A {@code null} array will return {@code null}.
  7650.      * An empty array will return itself.
  7651.      * A {@code null} array entry will be ignored.
  7652.      * A {@code null} stripChars will strip whitespace as defined by
  7653.      * {@link Character#isWhitespace(char)}.</p>
  7654.      *
  7655.      * <pre>
  7656.      * StringUtils.stripAll(null, *)                = null
  7657.      * StringUtils.stripAll([], *)                  = []
  7658.      * StringUtils.stripAll(["abc", "  abc"], null) = ["abc", "abc"]
  7659.      * StringUtils.stripAll(["abc  ", null], null)  = ["abc", null]
  7660.      * StringUtils.stripAll(["abc  ", null], "yz")  = ["abc  ", null]
  7661.      * StringUtils.stripAll(["yabcz", null], "yz")  = ["abc", null]
  7662.      * </pre>
  7663.      *
  7664.      * @param strs  the array to remove characters from, may be null
  7665.      * @param stripChars  the characters to remove, null treated as whitespace
  7666.      * @return the stripped Strings, {@code null} if null array input
  7667.      */
  7668.     public static String[] stripAll(final String[] strs, final String stripChars) {
  7669.         final int strsLen = ArrayUtils.getLength(strs);
  7670.         if (strsLen == 0) {
  7671.             return strs;
  7672.         }
  7673.         final String[] newArr = new String[strsLen];
  7674.         Arrays.setAll(newArr, i -> strip(strs[i], stripChars));
  7675.         return newArr;
  7676.     }

  7677.     /**
  7678.      * Strips any of a set of characters from the end of a String.
  7679.      *
  7680.      * <p>A {@code null} input String returns {@code null}.
  7681.      * An empty string ("") input returns the empty string.</p>
  7682.      *
  7683.      * <p>If the stripChars String is {@code null}, whitespace is
  7684.      * stripped as defined by {@link Character#isWhitespace(char)}.</p>
  7685.      *
  7686.      * <pre>
  7687.      * StringUtils.stripEnd(null, *)          = null
  7688.      * StringUtils.stripEnd("", *)            = ""
  7689.      * StringUtils.stripEnd("abc", "")        = "abc"
  7690.      * StringUtils.stripEnd("abc", null)      = "abc"
  7691.      * StringUtils.stripEnd("  abc", null)    = "  abc"
  7692.      * StringUtils.stripEnd("abc  ", null)    = "abc"
  7693.      * StringUtils.stripEnd(" abc ", null)    = " abc"
  7694.      * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
  7695.      * StringUtils.stripEnd("120.00", ".0")   = "12"
  7696.      * </pre>
  7697.      *
  7698.      * @param str  the String to remove characters from, may be null
  7699.      * @param stripChars  the set of characters to remove, null treated as whitespace
  7700.      * @return the stripped String, {@code null} if null String input
  7701.      */
  7702.     public static String stripEnd(final String str, final String stripChars) {
  7703.         int end = length(str);
  7704.         if (end == 0) {
  7705.             return str;
  7706.         }

  7707.         if (stripChars == null) {
  7708.             while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
  7709.                 end--;
  7710.             }
  7711.         } else if (stripChars.isEmpty()) {
  7712.             return str;
  7713.         } else {
  7714.             while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {
  7715.                 end--;
  7716.             }
  7717.         }
  7718.         return str.substring(0, end);
  7719.     }

  7720.     /**
  7721.      * Strips any of a set of characters from the start of a String.
  7722.      *
  7723.      * <p>A {@code null} input String returns {@code null}.
  7724.      * An empty string ("") input returns the empty string.</p>
  7725.      *
  7726.      * <p>If the stripChars String is {@code null}, whitespace is
  7727.      * stripped as defined by {@link Character#isWhitespace(char)}.</p>
  7728.      *
  7729.      * <pre>
  7730.      * StringUtils.stripStart(null, *)          = null
  7731.      * StringUtils.stripStart("", *)            = ""
  7732.      * StringUtils.stripStart("abc", "")        = "abc"
  7733.      * StringUtils.stripStart("abc", null)      = "abc"
  7734.      * StringUtils.stripStart("  abc", null)    = "abc"
  7735.      * StringUtils.stripStart("abc  ", null)    = "abc  "
  7736.      * StringUtils.stripStart(" abc ", null)    = "abc "
  7737.      * StringUtils.stripStart("yxabc  ", "xyz") = "abc  "
  7738.      * </pre>
  7739.      *
  7740.      * @param str  the String to remove characters from, may be null
  7741.      * @param stripChars  the characters to remove, null treated as whitespace
  7742.      * @return the stripped String, {@code null} if null String input
  7743.      */
  7744.     public static String stripStart(final String str, final String stripChars) {
  7745.         final int strLen = length(str);
  7746.         if (strLen == 0) {
  7747.             return str;
  7748.         }
  7749.         int start = 0;
  7750.         if (stripChars == null) {
  7751.             while (start != strLen && Character.isWhitespace(str.charAt(start))) {
  7752.                 start++;
  7753.             }
  7754.         } else if (stripChars.isEmpty()) {
  7755.             return str;
  7756.         } else {
  7757.             while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {
  7758.                 start++;
  7759.             }
  7760.         }
  7761.         return str.substring(start);
  7762.     }

  7763.     /**
  7764.      * Strips whitespace from the start and end of a String  returning
  7765.      * an empty String if {@code null} input.
  7766.      *
  7767.      * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.
  7768.      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  7769.      *
  7770.      * <pre>
  7771.      * StringUtils.stripToEmpty(null)     = ""
  7772.      * StringUtils.stripToEmpty("")       = ""
  7773.      * StringUtils.stripToEmpty("   ")    = ""
  7774.      * StringUtils.stripToEmpty("abc")    = "abc"
  7775.      * StringUtils.stripToEmpty("  abc")  = "abc"
  7776.      * StringUtils.stripToEmpty("abc  ")  = "abc"
  7777.      * StringUtils.stripToEmpty(" abc ")  = "abc"
  7778.      * StringUtils.stripToEmpty(" ab c ") = "ab c"
  7779.      * </pre>
  7780.      *
  7781.      * @param str  the String to be stripped, may be null
  7782.      * @return the trimmed String, or an empty String if {@code null} input
  7783.      * @since 2.0
  7784.      */
  7785.     public static String stripToEmpty(final String str) {
  7786.         return str == null ? EMPTY : strip(str, null);
  7787.     }

  7788.     /**
  7789.      * Strips whitespace from the start and end of a String  returning
  7790.      * {@code null} if the String is empty ("") after the strip.
  7791.      *
  7792.      * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.
  7793.      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  7794.      *
  7795.      * <pre>
  7796.      * StringUtils.stripToNull(null)     = null
  7797.      * StringUtils.stripToNull("")       = null
  7798.      * StringUtils.stripToNull("   ")    = null
  7799.      * StringUtils.stripToNull("abc")    = "abc"
  7800.      * StringUtils.stripToNull("  abc")  = "abc"
  7801.      * StringUtils.stripToNull("abc  ")  = "abc"
  7802.      * StringUtils.stripToNull(" abc ")  = "abc"
  7803.      * StringUtils.stripToNull(" ab c ") = "ab c"
  7804.      * </pre>
  7805.      *
  7806.      * @param str  the String to be stripped, may be null
  7807.      * @return the stripped String,
  7808.      *  {@code null} if whitespace, empty or null String input
  7809.      * @since 2.0
  7810.      */
  7811.     public static String stripToNull(String str) {
  7812.         if (str == null) {
  7813.             return null;
  7814.         }
  7815.         str = strip(str, null);
  7816.         return str.isEmpty() ? null : str; // NOSONARLINT str cannot be null here
  7817.     }

  7818.     /**
  7819.      * Gets a substring from the specified String avoiding exceptions.
  7820.      *
  7821.      * <p>A negative start position can be used to start {@code n}
  7822.      * characters from the end of the String.</p>
  7823.      *
  7824.      * <p>A {@code null} String will return {@code null}.
  7825.      * An empty ("") String will return "".</p>
  7826.      *
  7827.      * <pre>
  7828.      * StringUtils.substring(null, *)   = null
  7829.      * StringUtils.substring("", *)     = ""
  7830.      * StringUtils.substring("abc", 0)  = "abc"
  7831.      * StringUtils.substring("abc", 2)  = "c"
  7832.      * StringUtils.substring("abc", 4)  = ""
  7833.      * StringUtils.substring("abc", -2) = "bc"
  7834.      * StringUtils.substring("abc", -4) = "abc"
  7835.      * </pre>
  7836.      *
  7837.      * @param str  the String to get the substring from, may be null
  7838.      * @param start  the position to start from, negative means
  7839.      *  count back from the end of the String by this many characters
  7840.      * @return substring from start position, {@code null} if null String input
  7841.      */
  7842.     public static String substring(final String str, int start) {
  7843.         if (str == null) {
  7844.             return null;
  7845.         }

  7846.         // handle negatives, which means last n characters
  7847.         if (start < 0) {
  7848.             start = str.length() + start; // remember start is negative
  7849.         }

  7850.         if (start < 0) {
  7851.             start = 0;
  7852.         }
  7853.         if (start > str.length()) {
  7854.             return EMPTY;
  7855.         }

  7856.         return str.substring(start);
  7857.     }

  7858.     /**
  7859.      * Gets a substring from the specified String avoiding exceptions.
  7860.      *
  7861.      * <p>A negative start position can be used to start/end {@code n}
  7862.      * characters from the end of the String.</p>
  7863.      *
  7864.      * <p>The returned substring starts with the character in the {@code start}
  7865.      * position and ends before the {@code end} position. All position counting is
  7866.      * zero-based -- i.e., to start at the beginning of the string use
  7867.      * {@code start = 0}. Negative start and end positions can be used to
  7868.      * specify offsets relative to the end of the String.</p>
  7869.      *
  7870.      * <p>If {@code start} is not strictly to the left of {@code end}, ""
  7871.      * is returned.</p>
  7872.      *
  7873.      * <pre>
  7874.      * StringUtils.substring(null, *, *)    = null
  7875.      * StringUtils.substring("", * ,  *)    = "";
  7876.      * StringUtils.substring("abc", 0, 2)   = "ab"
  7877.      * StringUtils.substring("abc", 2, 0)   = ""
  7878.      * StringUtils.substring("abc", 2, 4)   = "c"
  7879.      * StringUtils.substring("abc", 4, 6)   = ""
  7880.      * StringUtils.substring("abc", 2, 2)   = ""
  7881.      * StringUtils.substring("abc", -2, -1) = "b"
  7882.      * StringUtils.substring("abc", -4, 2)  = "ab"
  7883.      * </pre>
  7884.      *
  7885.      * @param str  the String to get the substring from, may be null
  7886.      * @param start  the position to start from, negative means
  7887.      *  count back from the end of the String by this many characters
  7888.      * @param end  the position to end at (exclusive), negative means
  7889.      *  count back from the end of the String by this many characters
  7890.      * @return substring from start position to end position,
  7891.      *  {@code null} if null String input
  7892.      */
  7893.     public static String substring(final String str, int start, int end) {
  7894.         if (str == null) {
  7895.             return null;
  7896.         }

  7897.         // handle negatives
  7898.         if (end < 0) {
  7899.             end = str.length() + end; // remember end is negative
  7900.         }
  7901.         if (start < 0) {
  7902.             start = str.length() + start; // remember start is negative
  7903.         }

  7904.         // check length next
  7905.         if (end > str.length()) {
  7906.             end = str.length();
  7907.         }

  7908.         // if start is greater than end, return ""
  7909.         if (start > end) {
  7910.             return EMPTY;
  7911.         }

  7912.         if (start < 0) {
  7913.             start = 0;
  7914.         }
  7915.         if (end < 0) {
  7916.             end = 0;
  7917.         }

  7918.         return str.substring(start, end);
  7919.     }

  7920.     /**
  7921.      * Gets the substring after the first occurrence of a separator.
  7922.      * The separator is not returned.
  7923.      *
  7924.      * <p>A {@code null} string input will return {@code null}.
  7925.      * An empty ("") string input will return the empty string.
  7926.      *
  7927.      * <p>If nothing is found, the empty string is returned.</p>
  7928.      *
  7929.      * <pre>
  7930.      * StringUtils.substringAfter(null, *)      = null
  7931.      * StringUtils.substringAfter("", *)        = ""
  7932.      * StringUtils.substringAfter("abc", 'a')   = "bc"
  7933.      * StringUtils.substringAfter("abcba", 'b') = "cba"
  7934.      * StringUtils.substringAfter("abc", 'c')   = ""
  7935.      * StringUtils.substringAfter("abc", 'd')   = ""
  7936.      * StringUtils.substringAfter(" abc", 32)   = "abc"
  7937.      * </pre>
  7938.      *
  7939.      * @param str  the String to get a substring from, may be null
  7940.      * @param separator  the character (Unicode code point) to search.
  7941.      * @return the substring after the first occurrence of the separator,
  7942.      *  {@code null} if null String input
  7943.      * @since 3.11
  7944.      */
  7945.     public static String substringAfter(final String str, final int separator) {
  7946.         if (isEmpty(str)) {
  7947.             return str;
  7948.         }
  7949.         final int pos = str.indexOf(separator);
  7950.         if (pos == INDEX_NOT_FOUND) {
  7951.             return EMPTY;
  7952.         }
  7953.         return str.substring(pos + 1);
  7954.     }

  7955.     /**
  7956.      * Gets the substring after the first occurrence of a separator.
  7957.      * The separator is not returned.
  7958.      *
  7959.      * <p>A {@code null} string input will return {@code null}.
  7960.      * An empty ("") string input will return the empty string.
  7961.      * A {@code null} separator will return the empty string if the
  7962.      * input string is not {@code null}.</p>
  7963.      *
  7964.      * <p>If nothing is found, the empty string is returned.</p>
  7965.      *
  7966.      * <pre>
  7967.      * StringUtils.substringAfter(null, *)      = null
  7968.      * StringUtils.substringAfter("", *)        = ""
  7969.      * StringUtils.substringAfter(*, null)      = ""
  7970.      * StringUtils.substringAfter("abc", "a")   = "bc"
  7971.      * StringUtils.substringAfter("abcba", "b") = "cba"
  7972.      * StringUtils.substringAfter("abc", "c")   = ""
  7973.      * StringUtils.substringAfter("abc", "d")   = ""
  7974.      * StringUtils.substringAfter("abc", "")    = "abc"
  7975.      * </pre>
  7976.      *
  7977.      * @param str  the String to get a substring from, may be null
  7978.      * @param separator  the String to search for, may be null
  7979.      * @return the substring after the first occurrence of the separator,
  7980.      *  {@code null} if null String input
  7981.      * @since 2.0
  7982.      */
  7983.     public static String substringAfter(final String str, final String separator) {
  7984.         if (isEmpty(str)) {
  7985.             return str;
  7986.         }
  7987.         if (separator == null) {
  7988.             return EMPTY;
  7989.         }
  7990.         final int pos = str.indexOf(separator);
  7991.         if (pos == INDEX_NOT_FOUND) {
  7992.             return EMPTY;
  7993.         }
  7994.         return str.substring(pos + separator.length());
  7995.     }

  7996.     /**
  7997.      * Gets the substring after the last occurrence of a separator.
  7998.      * The separator is not returned.
  7999.      *
  8000.      * <p>A {@code null} string input will return {@code null}.
  8001.      * An empty ("") string input will return the empty string.
  8002.      *
  8003.      * <p>If nothing is found, the empty string is returned.</p>
  8004.      *
  8005.      * <pre>
  8006.      * StringUtils.substringAfterLast(null, *)      = null
  8007.      * StringUtils.substringAfterLast("", *)        = ""
  8008.      * StringUtils.substringAfterLast("abc", 'a')   = "bc"
  8009.      * StringUtils.substringAfterLast(" bc", 32)    = "bc"
  8010.      * StringUtils.substringAfterLast("abcba", 'b') = "a"
  8011.      * StringUtils.substringAfterLast("abc", 'c')   = ""
  8012.      * StringUtils.substringAfterLast("a", 'a')     = ""
  8013.      * StringUtils.substringAfterLast("a", 'z')     = ""
  8014.      * </pre>
  8015.      *
  8016.      * @param str  the String to get a substring from, may be null
  8017.      * @param separator  the character (Unicode code point) to search.
  8018.      * @return the substring after the last occurrence of the separator,
  8019.      *  {@code null} if null String input
  8020.      * @since 3.11
  8021.      */
  8022.     public static String substringAfterLast(final String str, final int separator) {
  8023.         if (isEmpty(str)) {
  8024.             return str;
  8025.         }
  8026.         final int pos = str.lastIndexOf(separator);
  8027.         if (pos == INDEX_NOT_FOUND || pos == str.length() - 1) {
  8028.             return EMPTY;
  8029.         }
  8030.         return str.substring(pos + 1);
  8031.     }

  8032.     /**
  8033.      * Gets the substring after the last occurrence of a separator.
  8034.      * The separator is not returned.
  8035.      *
  8036.      * <p>A {@code null} string input will return {@code null}.
  8037.      * An empty ("") string input will return the empty string.
  8038.      * An empty or {@code null} separator will return the empty string if
  8039.      * the input string is not {@code null}.</p>
  8040.      *
  8041.      * <p>If nothing is found, the empty string is returned.</p>
  8042.      *
  8043.      * <pre>
  8044.      * StringUtils.substringAfterLast(null, *)      = null
  8045.      * StringUtils.substringAfterLast("", *)        = ""
  8046.      * StringUtils.substringAfterLast(*, "")        = ""
  8047.      * StringUtils.substringAfterLast(*, null)      = ""
  8048.      * StringUtils.substringAfterLast("abc", "a")   = "bc"
  8049.      * StringUtils.substringAfterLast("abcba", "b") = "a"
  8050.      * StringUtils.substringAfterLast("abc", "c")   = ""
  8051.      * StringUtils.substringAfterLast("a", "a")     = ""
  8052.      * StringUtils.substringAfterLast("a", "z")     = ""
  8053.      * </pre>
  8054.      *
  8055.      * @param str  the String to get a substring from, may be null
  8056.      * @param separator  the String to search for, may be null
  8057.      * @return the substring after the last occurrence of the separator,
  8058.      *  {@code null} if null String input
  8059.      * @since 2.0
  8060.      */
  8061.     public static String substringAfterLast(final String str, final String separator) {
  8062.         if (isEmpty(str)) {
  8063.             return str;
  8064.         }
  8065.         if (isEmpty(separator)) {
  8066.             return EMPTY;
  8067.         }
  8068.         final int pos = str.lastIndexOf(separator);
  8069.         if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) {
  8070.             return EMPTY;
  8071.         }
  8072.         return str.substring(pos + separator.length());
  8073.     }

  8074.     /**
  8075.      * Gets the substring before the first occurrence of a separator. The separator is not returned.
  8076.      *
  8077.      * <p>
  8078.      * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string.
  8079.      * </p>
  8080.      *
  8081.      * <p>
  8082.      * If nothing is found, the string input is returned.
  8083.      * </p>
  8084.      *
  8085.      * <pre>
  8086.      * StringUtils.substringBefore(null, *)      = null
  8087.      * StringUtils.substringBefore("", *)        = ""
  8088.      * StringUtils.substringBefore("abc", 'a')   = ""
  8089.      * StringUtils.substringBefore("abcba", 'b') = "a"
  8090.      * StringUtils.substringBefore("abc", 'c')   = "ab"
  8091.      * StringUtils.substringBefore("abc", 'd')   = "abc"
  8092.      * </pre>
  8093.      *
  8094.      * @param str the String to get a substring from, may be null
  8095.      * @param separator the character (Unicode code point) to search.
  8096.      * @return the substring before the first occurrence of the separator, {@code null} if null String input
  8097.      * @since 3.12.0
  8098.      */
  8099.     public static String substringBefore(final String str, final int separator) {
  8100.         if (isEmpty(str)) {
  8101.             return str;
  8102.         }
  8103.         final int pos = str.indexOf(separator);
  8104.         if (pos == INDEX_NOT_FOUND) {
  8105.             return str;
  8106.         }
  8107.         return str.substring(0, pos);
  8108.     }

  8109.     /**
  8110.      * Gets the substring before the first occurrence of a separator.
  8111.      * The separator is not returned.
  8112.      *
  8113.      * <p>A {@code null} string input will return {@code null}.
  8114.      * An empty ("") string input will return the empty string.
  8115.      * A {@code null} separator will return the input string.</p>
  8116.      *
  8117.      * <p>If nothing is found, the string input is returned.</p>
  8118.      *
  8119.      * <pre>
  8120.      * StringUtils.substringBefore(null, *)      = null
  8121.      * StringUtils.substringBefore("", *)        = ""
  8122.      * StringUtils.substringBefore("abc", "a")   = ""
  8123.      * StringUtils.substringBefore("abcba", "b") = "a"
  8124.      * StringUtils.substringBefore("abc", "c")   = "ab"
  8125.      * StringUtils.substringBefore("abc", "d")   = "abc"
  8126.      * StringUtils.substringBefore("abc", "")    = ""
  8127.      * StringUtils.substringBefore("abc", null)  = "abc"
  8128.      * </pre>
  8129.      *
  8130.      * @param str  the String to get a substring from, may be null
  8131.      * @param separator  the String to search for, may be null
  8132.      * @return the substring before the first occurrence of the separator,
  8133.      *  {@code null} if null String input
  8134.      * @since 2.0
  8135.      */
  8136.     public static String substringBefore(final String str, final String separator) {
  8137.         if (isEmpty(str) || separator == null) {
  8138.             return str;
  8139.         }
  8140.         if (separator.isEmpty()) {
  8141.             return EMPTY;
  8142.         }
  8143.         final int pos = str.indexOf(separator);
  8144.         if (pos == INDEX_NOT_FOUND) {
  8145.             return str;
  8146.         }
  8147.         return str.substring(0, pos);
  8148.     }

  8149.     /**
  8150.      * Gets the substring before the last occurrence of a separator.
  8151.      * The separator is not returned.
  8152.      *
  8153.      * <p>A {@code null} string input will return {@code null}.
  8154.      * An empty ("") string input will return the empty string.
  8155.      * An empty or {@code null} separator will return the input string.</p>
  8156.      *
  8157.      * <p>If nothing is found, the string input is returned.</p>
  8158.      *
  8159.      * <pre>
  8160.      * StringUtils.substringBeforeLast(null, *)      = null
  8161.      * StringUtils.substringBeforeLast("", *)        = ""
  8162.      * StringUtils.substringBeforeLast("abcba", "b") = "abc"
  8163.      * StringUtils.substringBeforeLast("abc", "c")   = "ab"
  8164.      * StringUtils.substringBeforeLast("a", "a")     = ""
  8165.      * StringUtils.substringBeforeLast("a", "z")     = "a"
  8166.      * StringUtils.substringBeforeLast("a", null)    = "a"
  8167.      * StringUtils.substringBeforeLast("a", "")      = "a"
  8168.      * </pre>
  8169.      *
  8170.      * @param str  the String to get a substring from, may be null
  8171.      * @param separator  the String to search for, may be null
  8172.      * @return the substring before the last occurrence of the separator,
  8173.      *  {@code null} if null String input
  8174.      * @since 2.0
  8175.      */
  8176.     public static String substringBeforeLast(final String str, final String separator) {
  8177.         if (isEmpty(str) || isEmpty(separator)) {
  8178.             return str;
  8179.         }
  8180.         final int pos = str.lastIndexOf(separator);
  8181.         if (pos == INDEX_NOT_FOUND) {
  8182.             return str;
  8183.         }
  8184.         return str.substring(0, pos);
  8185.     }

  8186.     /**
  8187.      * Gets the String that is nested in between two instances of the
  8188.      * same String.
  8189.      *
  8190.      * <p>A {@code null} input String returns {@code null}.
  8191.      * A {@code null} tag returns {@code null}.</p>
  8192.      *
  8193.      * <pre>
  8194.      * StringUtils.substringBetween(null, *)            = null
  8195.      * StringUtils.substringBetween("", "")             = ""
  8196.      * StringUtils.substringBetween("", "tag")          = null
  8197.      * StringUtils.substringBetween("tagabctag", null)  = null
  8198.      * StringUtils.substringBetween("tagabctag", "")    = ""
  8199.      * StringUtils.substringBetween("tagabctag", "tag") = "abc"
  8200.      * </pre>
  8201.      *
  8202.      * @param str  the String containing the substring, may be null
  8203.      * @param tag  the String before and after the substring, may be null
  8204.      * @return the substring, {@code null} if no match
  8205.      * @since 2.0
  8206.      */
  8207.     public static String substringBetween(final String str, final String tag) {
  8208.         return substringBetween(str, tag, tag);
  8209.     }

  8210.     /**
  8211.      * Gets the String that is nested in between two Strings.
  8212.      * Only the first match is returned.
  8213.      *
  8214.      * <p>A {@code null} input String returns {@code null}.
  8215.      * A {@code null} open/close returns {@code null} (no match).
  8216.      * An empty ("") open and close returns an empty string.</p>
  8217.      *
  8218.      * <pre>
  8219.      * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
  8220.      * StringUtils.substringBetween(null, *, *)          = null
  8221.      * StringUtils.substringBetween(*, null, *)          = null
  8222.      * StringUtils.substringBetween(*, *, null)          = null
  8223.      * StringUtils.substringBetween("", "", "")          = ""
  8224.      * StringUtils.substringBetween("", "", "]")         = null
  8225.      * StringUtils.substringBetween("", "[", "]")        = null
  8226.      * StringUtils.substringBetween("yabcz", "", "")     = ""
  8227.      * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
  8228.      * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
  8229.      * </pre>
  8230.      *
  8231.      * @param str  the String containing the substring, may be null
  8232.      * @param open  the String before the substring, may be null
  8233.      * @param close  the String after the substring, may be null
  8234.      * @return the substring, {@code null} if no match
  8235.      * @since 2.0
  8236.      */
  8237.     public static String substringBetween(final String str, final String open, final String close) {
  8238.         if (!ObjectUtils.allNotNull(str, open, close)) {
  8239.             return null;
  8240.         }
  8241.         final int start = str.indexOf(open);
  8242.         if (start != INDEX_NOT_FOUND) {
  8243.             final int end = str.indexOf(close, start + open.length());
  8244.             if (end != INDEX_NOT_FOUND) {
  8245.                 return str.substring(start + open.length(), end);
  8246.             }
  8247.         }
  8248.         return null;
  8249.     }

  8250.     /**
  8251.      * Searches a String for substrings delimited by a start and end tag,
  8252.      * returning all matching substrings in an array.
  8253.      *
  8254.      * <p>A {@code null} input String returns {@code null}.
  8255.      * A {@code null} open/close returns {@code null} (no match).
  8256.      * An empty ("") open/close returns {@code null} (no match).</p>
  8257.      *
  8258.      * <pre>
  8259.      * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
  8260.      * StringUtils.substringsBetween(null, *, *)            = null
  8261.      * StringUtils.substringsBetween(*, null, *)            = null
  8262.      * StringUtils.substringsBetween(*, *, null)            = null
  8263.      * StringUtils.substringsBetween("", "[", "]")          = []
  8264.      * </pre>
  8265.      *
  8266.      * @param str  the String containing the substrings, null returns null, empty returns empty
  8267.      * @param open  the String identifying the start of the substring, empty returns null
  8268.      * @param close  the String identifying the end of the substring, empty returns null
  8269.      * @return a String Array of substrings, or {@code null} if no match
  8270.      * @since 2.3
  8271.      */
  8272.     public static String[] substringsBetween(final String str, final String open, final String close) {
  8273.         if (str == null || isEmpty(open) || isEmpty(close)) {
  8274.             return null;
  8275.         }
  8276.         final int strLen = str.length();
  8277.         if (strLen == 0) {
  8278.             return ArrayUtils.EMPTY_STRING_ARRAY;
  8279.         }
  8280.         final int closeLen = close.length();
  8281.         final int openLen = open.length();
  8282.         final List<String> list = new ArrayList<>();
  8283.         int pos = 0;
  8284.         while (pos < strLen - closeLen) {
  8285.             int start = str.indexOf(open, pos);
  8286.             if (start < 0) {
  8287.                 break;
  8288.             }
  8289.             start += openLen;
  8290.             final int end = str.indexOf(close, start);
  8291.             if (end < 0) {
  8292.                 break;
  8293.             }
  8294.             list.add(str.substring(start, end));
  8295.             pos = end + closeLen;
  8296.         }
  8297.         if (list.isEmpty()) {
  8298.             return null;
  8299.         }
  8300.         return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
  8301.     }

  8302.     /**
  8303.      * Swaps the case of a String changing upper and title case to
  8304.      * lower case, and lower case to upper case.
  8305.      *
  8306.      * <ul>
  8307.      *  <li>Upper case character converts to Lower case</li>
  8308.      *  <li>Title case character converts to Lower case</li>
  8309.      *  <li>Lower case character converts to Upper case</li>
  8310.      * </ul>
  8311.      *
  8312.      * <p>For a word based algorithm, see {@link org.apache.commons.text.WordUtils#swapCase(String)}.
  8313.      * A {@code null} input String returns {@code null}.</p>
  8314.      *
  8315.      * <pre>
  8316.      * StringUtils.swapCase(null)                 = null
  8317.      * StringUtils.swapCase("")                   = ""
  8318.      * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
  8319.      * </pre>
  8320.      *
  8321.      * <p>NOTE: This method changed in Lang version 2.0.
  8322.      * It no longer performs a word based algorithm.
  8323.      * If you only use ASCII, you will notice no change.
  8324.      * That functionality is available in org.apache.commons.lang3.text.WordUtils.</p>
  8325.      *
  8326.      * @param str  the String to swap case, may be null
  8327.      * @return the changed String, {@code null} if null String input
  8328.      */
  8329.     public static String swapCase(final String str) {
  8330.         if (isEmpty(str)) {
  8331.             return str;
  8332.         }

  8333.         final int strLen = str.length();
  8334.         final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array
  8335.         int outOffset = 0;
  8336.         for (int i = 0; i < strLen; ) {
  8337.             final int oldCodepoint = str.codePointAt(i);
  8338.             final int newCodePoint;
  8339.             if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) {
  8340.                 newCodePoint = Character.toLowerCase(oldCodepoint);
  8341.             } else if (Character.isLowerCase(oldCodepoint)) {
  8342.                 newCodePoint = Character.toUpperCase(oldCodepoint);
  8343.             } else {
  8344.                 newCodePoint = oldCodepoint;
  8345.             }
  8346.             newCodePoints[outOffset++] = newCodePoint;
  8347.             i += Character.charCount(newCodePoint);
  8348.          }
  8349.         return new String(newCodePoints, 0, outOffset);
  8350.     }

  8351.     /**
  8352.      * Converts a {@link CharSequence} into an array of code points.
  8353.      *
  8354.      * <p>Valid pairs of surrogate code units will be converted into a single supplementary
  8355.      * code point. Isolated surrogate code units (i.e. a high surrogate not followed by a low surrogate or
  8356.      * a low surrogate not preceded by a high surrogate) will be returned as-is.</p>
  8357.      *
  8358.      * <pre>
  8359.      * StringUtils.toCodePoints(null)   =  null
  8360.      * StringUtils.toCodePoints("")     =  []  // empty array
  8361.      * </pre>
  8362.      *
  8363.      * @param cs the character sequence to convert
  8364.      * @return an array of code points
  8365.      * @since 3.6
  8366.      */
  8367.     public static int[] toCodePoints(final CharSequence cs) {
  8368.         if (cs == null) {
  8369.             return null;
  8370.         }
  8371.         if (cs.length() == 0) {
  8372.             return ArrayUtils.EMPTY_INT_ARRAY;
  8373.         }
  8374.         return cs.toString().codePoints().toArray();
  8375.     }

  8376.     /**
  8377.      * Converts a {@code byte[]} to a String using the specified character encoding.
  8378.      *
  8379.      * @param bytes
  8380.      *            the byte array to read from
  8381.      * @param charset
  8382.      *            the encoding to use, if null then use the platform default
  8383.      * @return a new String
  8384.      * @throws NullPointerException
  8385.      *             if {@code bytes} is null
  8386.      * @since 3.2
  8387.      * @since 3.3 No longer throws {@link UnsupportedEncodingException}.
  8388.      */
  8389.     public static String toEncodedString(final byte[] bytes, final Charset charset) {
  8390.         return new String(bytes, Charsets.toCharset(charset));
  8391.     }

  8392.     /**
  8393.      * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner.
  8394.      *
  8395.      * @param source A source String or null.
  8396.      * @return the given source String as a lower-case using the {@link Locale#ROOT} locale or null.
  8397.      * @since 3.10
  8398.      */
  8399.     public static String toRootLowerCase(final String source) {
  8400.         return source == null ? null : source.toLowerCase(Locale.ROOT);
  8401.     }

  8402.     /**
  8403.      * Converts the given source String as an upper-case using the {@link Locale#ROOT} locale in a null-safe manner.
  8404.      *
  8405.      * @param source A source String or null.
  8406.      * @return the given source String as an upper-case using the {@link Locale#ROOT} locale or null.
  8407.      * @since 3.10
  8408.      */
  8409.     public static String toRootUpperCase(final String source) {
  8410.         return source == null ? null : source.toUpperCase(Locale.ROOT);
  8411.     }

  8412.     /**
  8413.      * Converts a {@code byte[]} to a String using the specified character encoding.
  8414.      *
  8415.      * @param bytes
  8416.      *            the byte array to read from
  8417.      * @param charsetName
  8418.      *            the encoding to use, if null then use the platform default
  8419.      * @return a new String
  8420.      * @throws NullPointerException
  8421.      *             if the input is null
  8422.      * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code
  8423.      * @since 3.1
  8424.      */
  8425.     @Deprecated
  8426.     public static String toString(final byte[] bytes, final String charsetName) {
  8427.         return new String(bytes, Charsets.toCharset(charsetName));
  8428.     }

  8429.     /**
  8430.      * Removes control characters (char &lt;= 32) from both
  8431.      * ends of this String, handling {@code null} by returning
  8432.      * {@code null}.
  8433.      *
  8434.      * <p>The String is trimmed using {@link String#trim()}.
  8435.      * Trim removes start and end characters &lt;= 32.
  8436.      * To strip whitespace use {@link #strip(String)}.</p>
  8437.      *
  8438.      * <p>To trim your choice of characters, use the
  8439.      * {@link #strip(String, String)} methods.</p>
  8440.      *
  8441.      * <pre>
  8442.      * StringUtils.trim(null)          = null
  8443.      * StringUtils.trim("")            = ""
  8444.      * StringUtils.trim("     ")       = ""
  8445.      * StringUtils.trim("abc")         = "abc"
  8446.      * StringUtils.trim("    abc    ") = "abc"
  8447.      * </pre>
  8448.      *
  8449.      * @param str  the String to be trimmed, may be null
  8450.      * @return the trimmed string, {@code null} if null String input
  8451.      */
  8452.     public static String trim(final String str) {
  8453.         return str == null ? null : str.trim();
  8454.     }

  8455.     /**
  8456.      * Removes control characters (char &lt;= 32) from both
  8457.      * ends of this String returning an empty String ("") if the String
  8458.      * is empty ("") after the trim or if it is {@code null}.
  8459.      *
  8460.      * <p>The String is trimmed using {@link String#trim()}.
  8461.      * Trim removes start and end characters &lt;= 32.
  8462.      * To strip whitespace use {@link #stripToEmpty(String)}.
  8463.      *
  8464.      * <pre>
  8465.      * StringUtils.trimToEmpty(null)          = ""
  8466.      * StringUtils.trimToEmpty("")            = ""
  8467.      * StringUtils.trimToEmpty("     ")       = ""
  8468.      * StringUtils.trimToEmpty("abc")         = "abc"
  8469.      * StringUtils.trimToEmpty("    abc    ") = "abc"
  8470.      * </pre>
  8471.      *
  8472.      * @param str  the String to be trimmed, may be null
  8473.      * @return the trimmed String, or an empty String if {@code null} input
  8474.      * @since 2.0
  8475.      */
  8476.     public static String trimToEmpty(final String str) {
  8477.         return str == null ? EMPTY : str.trim();
  8478.     }

  8479.     /**
  8480.      * Removes control characters (char &lt;= 32) from both
  8481.      * ends of this String returning {@code null} if the String is
  8482.      * empty ("") after the trim or if it is {@code null}.
  8483.      *
  8484.      * <p>The String is trimmed using {@link String#trim()}.
  8485.      * Trim removes start and end characters &lt;= 32.
  8486.      * To strip whitespace use {@link #stripToNull(String)}.
  8487.      *
  8488.      * <pre>
  8489.      * StringUtils.trimToNull(null)          = null
  8490.      * StringUtils.trimToNull("")            = null
  8491.      * StringUtils.trimToNull("     ")       = null
  8492.      * StringUtils.trimToNull("abc")         = "abc"
  8493.      * StringUtils.trimToNull("    abc    ") = "abc"
  8494.      * </pre>
  8495.      *
  8496.      * @param str  the String to be trimmed, may be null
  8497.      * @return the trimmed String,
  8498.      *  {@code null} if only chars &lt;= 32, empty or null String input
  8499.      * @since 2.0
  8500.      */
  8501.     public static String trimToNull(final String str) {
  8502.         final String ts = trim(str);
  8503.         return isEmpty(ts) ? null : ts;
  8504.     }

  8505.     /**
  8506.      * Truncates a String. This will turn
  8507.      * "Now is the time for all good men" into "Now is the time for".
  8508.      *
  8509.      * <p>Specifically:</p>
  8510.      * <ul>
  8511.      *   <li>If {@code str} is less than {@code maxWidth} characters
  8512.      *       long, return it.</li>
  8513.      *   <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li>
  8514.      *   <li>If {@code maxWidth} is less than {@code 0}, throw an
  8515.      *       {@link IllegalArgumentException}.</li>
  8516.      *   <li>In no case will it return a String of length greater than
  8517.      *       {@code maxWidth}.</li>
  8518.      * </ul>
  8519.      *
  8520.      * <pre>
  8521.      * StringUtils.truncate(null, 0)       = null
  8522.      * StringUtils.truncate(null, 2)       = null
  8523.      * StringUtils.truncate("", 4)         = ""
  8524.      * StringUtils.truncate("abcdefg", 4)  = "abcd"
  8525.      * StringUtils.truncate("abcdefg", 6)  = "abcdef"
  8526.      * StringUtils.truncate("abcdefg", 7)  = "abcdefg"
  8527.      * StringUtils.truncate("abcdefg", 8)  = "abcdefg"
  8528.      * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException
  8529.      * </pre>
  8530.      *
  8531.      * @param str  the String to truncate, may be null
  8532.      * @param maxWidth  maximum length of result String, must be positive
  8533.      * @return truncated String, {@code null} if null String input
  8534.      * @throws IllegalArgumentException If {@code maxWidth} is less than {@code 0}
  8535.      * @since 3.5
  8536.      */
  8537.     public static String truncate(final String str, final int maxWidth) {
  8538.         return truncate(str, 0, maxWidth);
  8539.     }

  8540.     /**
  8541.      * Truncates a String. This will turn
  8542.      * "Now is the time for all good men" into "is the time for all".
  8543.      *
  8544.      * <p>Works like {@code truncate(String, int)}, but allows you to specify
  8545.      * a "left edge" offset.
  8546.      *
  8547.      * <p>Specifically:</p>
  8548.      * <ul>
  8549.      *   <li>If {@code str} is less than {@code maxWidth} characters
  8550.      *       long, return it.</li>
  8551.      *   <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li>
  8552.      *   <li>If {@code maxWidth} is less than {@code 0}, throw an
  8553.      *       {@link IllegalArgumentException}.</li>
  8554.      *   <li>If {@code offset} is less than {@code 0}, throw an
  8555.      *       {@link IllegalArgumentException}.</li>
  8556.      *   <li>In no case will it return a String of length greater than
  8557.      *       {@code maxWidth}.</li>
  8558.      * </ul>
  8559.      *
  8560.      * <pre>
  8561.      * StringUtils.truncate(null, 0, 0) = null
  8562.      * StringUtils.truncate(null, 2, 4) = null
  8563.      * StringUtils.truncate("", 0, 10) = ""
  8564.      * StringUtils.truncate("", 2, 10) = ""
  8565.      * StringUtils.truncate("abcdefghij", 0, 3) = "abc"
  8566.      * StringUtils.truncate("abcdefghij", 5, 6) = "fghij"
  8567.      * StringUtils.truncate("raspberry peach", 10, 15) = "peach"
  8568.      * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij"
  8569.      * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException
  8570.      * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException
  8571.      * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException
  8572.      * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno"
  8573.      * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk"
  8574.      * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl"
  8575.      * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm"
  8576.      * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn"
  8577.      * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno"
  8578.      * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij"
  8579.      * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh"
  8580.      * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm"
  8581.      * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno"
  8582.      * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n"
  8583.      * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no"
  8584.      * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o"
  8585.      * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o"
  8586.      * StringUtils.truncate("abcdefghijklmno", 15, 1) = ""
  8587.      * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = ""
  8588.      * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = ""
  8589.      * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException
  8590.      * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException
  8591.      * </pre>
  8592.      *
  8593.      * @param str  the String to truncate, may be null
  8594.      * @param offset  left edge of source String
  8595.      * @param maxWidth  maximum length of result String, must be positive
  8596.      * @return truncated String, {@code null} if null String input
  8597.      * @throws IllegalArgumentException If {@code offset} or {@code maxWidth} is less than {@code 0}
  8598.      * @since 3.5
  8599.      */
  8600.     public static String truncate(final String str, final int offset, final int maxWidth) {
  8601.         if (offset < 0) {
  8602.             throw new IllegalArgumentException("offset cannot be negative");
  8603.         }
  8604.         if (maxWidth < 0) {
  8605.             throw new IllegalArgumentException("maxWith cannot be negative");
  8606.         }
  8607.         if (str == null) {
  8608.             return null;
  8609.         }
  8610.         if (offset > str.length()) {
  8611.             return EMPTY;
  8612.         }
  8613.         if (str.length() > maxWidth) {
  8614.             final int ix = Math.min(offset + maxWidth, str.length());
  8615.             return str.substring(offset, ix);
  8616.         }
  8617.         return str.substring(offset);
  8618.     }

  8619.     /**
  8620.      * Uncapitalizes a String, changing the first character to lower case as
  8621.      * per {@link Character#toLowerCase(int)}. No other characters are changed.
  8622.      *
  8623.      * <p>For a word based algorithm, see {@link org.apache.commons.text.WordUtils#uncapitalize(String)}.
  8624.      * A {@code null} input String returns {@code null}.</p>
  8625.      *
  8626.      * <pre>
  8627.      * StringUtils.uncapitalize(null)  = null
  8628.      * StringUtils.uncapitalize("")    = ""
  8629.      * StringUtils.uncapitalize("cat") = "cat"
  8630.      * StringUtils.uncapitalize("Cat") = "cat"
  8631.      * StringUtils.uncapitalize("CAT") = "cAT"
  8632.      * </pre>
  8633.      *
  8634.      * @param str the String to uncapitalize, may be null
  8635.      * @return the uncapitalized String, {@code null} if null String input
  8636.      * @see org.apache.commons.text.WordUtils#uncapitalize(String)
  8637.      * @see #capitalize(String)
  8638.      * @since 2.0
  8639.      */
  8640.     public static String uncapitalize(final String str) {
  8641.         final int strLen = length(str);
  8642.         if (strLen == 0) {
  8643.             return str;
  8644.         }
  8645.         final int firstCodePoint = str.codePointAt(0);
  8646.         final int newCodePoint = Character.toLowerCase(firstCodePoint);
  8647.         if (firstCodePoint == newCodePoint) {
  8648.             // already uncapitalized
  8649.             return str;
  8650.         }
  8651.         final int[] newCodePoints = str.codePoints().toArray();
  8652.         newCodePoints[0] = newCodePoint; // copy the first code point
  8653.         return new String(newCodePoints, 0, newCodePoints.length);
  8654.     }

  8655.     /**
  8656.      * Unwraps a given string from a character.
  8657.      *
  8658.      * <pre>
  8659.      * StringUtils.unwrap(null, null)         = null
  8660.      * StringUtils.unwrap(null, '\0')         = null
  8661.      * StringUtils.unwrap(null, '1')          = null
  8662.      * StringUtils.unwrap("a", 'a')           = "a"
  8663.      * StringUtils.unwrap("aa", 'a')           = ""
  8664.      * StringUtils.unwrap("\'abc\'", '\'')    = "abc"
  8665.      * StringUtils.unwrap("AABabcBAA", 'A')   = "ABabcBA"
  8666.      * StringUtils.unwrap("A", '#')           = "A"
  8667.      * StringUtils.unwrap("#A", '#')          = "#A"
  8668.      * StringUtils.unwrap("A#", '#')          = "A#"
  8669.      * </pre>
  8670.      *
  8671.      * @param str
  8672.      *          the String to be unwrapped, can be null
  8673.      * @param wrapChar
  8674.      *          the character used to unwrap
  8675.      * @return unwrapped String or the original string
  8676.      *          if it is not quoted properly with the wrapChar
  8677.      * @since 3.6
  8678.      */
  8679.     public static String unwrap(final String str, final char wrapChar) {
  8680.         if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) {
  8681.             return str;
  8682.         }

  8683.         if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) {
  8684.             final int startIndex = 0;
  8685.             final int endIndex = str.length() - 1;

  8686.             return str.substring(startIndex + 1, endIndex);
  8687.         }

  8688.         return str;
  8689.     }

  8690.     /**
  8691.      * Unwraps a given string from another string.
  8692.      *
  8693.      * <pre>
  8694.      * StringUtils.unwrap(null, null)         = null
  8695.      * StringUtils.unwrap(null, "")           = null
  8696.      * StringUtils.unwrap(null, "1")          = null
  8697.      * StringUtils.unwrap("a", "a")           = "a"
  8698.      * StringUtils.unwrap("aa", "a")          = ""
  8699.      * StringUtils.unwrap("\'abc\'", "\'")    = "abc"
  8700.      * StringUtils.unwrap("\"abc\"", "\"")    = "abc"
  8701.      * StringUtils.unwrap("AABabcBAA", "AA")  = "BabcB"
  8702.      * StringUtils.unwrap("A", "#")           = "A"
  8703.      * StringUtils.unwrap("#A", "#")          = "#A"
  8704.      * StringUtils.unwrap("A#", "#")          = "A#"
  8705.      * </pre>
  8706.      *
  8707.      * @param str
  8708.      *          the String to be unwrapped, can be null
  8709.      * @param wrapToken
  8710.      *          the String used to unwrap
  8711.      * @return unwrapped String or the original string
  8712.      *          if it is not quoted properly with the wrapToken
  8713.      * @since 3.6
  8714.      */
  8715.     public static String unwrap(final String str, final String wrapToken) {
  8716.         if (isEmpty(str) || isEmpty(wrapToken) || str.length() < 2 * wrapToken.length()) {
  8717.             return str;
  8718.         }

  8719.         if (Strings.CS.startsWith(str, wrapToken) && Strings.CS.endsWith(str, wrapToken)) {
  8720.             return str.substring(wrapToken.length(), str.lastIndexOf(wrapToken));
  8721.         }

  8722.         return str;
  8723.     }

  8724.     /**
  8725.      * Converts a String to upper case as per {@link String#toUpperCase()}.
  8726.      *
  8727.      * <p>A {@code null} input String returns {@code null}.</p>
  8728.      *
  8729.      * <pre>
  8730.      * StringUtils.upperCase(null)  = null
  8731.      * StringUtils.upperCase("")    = ""
  8732.      * StringUtils.upperCase("aBc") = "ABC"
  8733.      * </pre>
  8734.      *
  8735.      * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()},
  8736.      * the result of this method is affected by the current locale.
  8737.      * For platform-independent case transformations, the method {@link #upperCase(String, Locale)}
  8738.      * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
  8739.      *
  8740.      * @param str  the String to upper case, may be null
  8741.      * @return the upper-cased String, {@code null} if null String input
  8742.      */
  8743.     public static String upperCase(final String str) {
  8744.         if (str == null) {
  8745.             return null;
  8746.         }
  8747.         return str.toUpperCase();
  8748.     }

  8749.     /**
  8750.      * Converts a String to upper case as per {@link String#toUpperCase(Locale)}.
  8751.      *
  8752.      * <p>A {@code null} input String returns {@code null}.</p>
  8753.      *
  8754.      * <pre>
  8755.      * StringUtils.upperCase(null, Locale.ENGLISH)  = null
  8756.      * StringUtils.upperCase("", Locale.ENGLISH)    = ""
  8757.      * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
  8758.      * </pre>
  8759.      *
  8760.      * @param str  the String to upper case, may be null
  8761.      * @param locale  the locale that defines the case transformation rules, must not be null
  8762.      * @return the upper-cased String, {@code null} if null String input
  8763.      * @since 2.5
  8764.      */
  8765.     public static String upperCase(final String str, final Locale locale) {
  8766.         if (str == null) {
  8767.             return null;
  8768.         }
  8769.         return str.toUpperCase(LocaleUtils.toLocale(locale));
  8770.     }

  8771.     /**
  8772.      * Returns the string representation of the {@code char} array or null.
  8773.      *
  8774.      * @param value the character array.
  8775.      * @return a String or null
  8776.      * @see String#valueOf(char[])
  8777.      * @since 3.9
  8778.      */
  8779.     public static String valueOf(final char[] value) {
  8780.         return value == null ? null : String.valueOf(value);
  8781.     }

  8782.     /**
  8783.      * Wraps a string with a char.
  8784.      *
  8785.      * <pre>
  8786.      * StringUtils.wrap(null, *)        = null
  8787.      * StringUtils.wrap("", *)          = ""
  8788.      * StringUtils.wrap("ab", '\0')     = "ab"
  8789.      * StringUtils.wrap("ab", 'x')      = "xabx"
  8790.      * StringUtils.wrap("ab", '\'')     = "'ab'"
  8791.      * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\""
  8792.      * </pre>
  8793.      *
  8794.      * @param str
  8795.      *            the string to be wrapped, may be {@code null}
  8796.      * @param wrapWith
  8797.      *            the char that will wrap {@code str}
  8798.      * @return the wrapped string, or {@code null} if {@code str == null}
  8799.      * @since 3.4
  8800.      */
  8801.     public static String wrap(final String str, final char wrapWith) {

  8802.         if (isEmpty(str) || wrapWith == CharUtils.NUL) {
  8803.             return str;
  8804.         }

  8805.         return wrapWith + str + wrapWith;
  8806.     }

  8807.     /**
  8808.      * Wraps a String with another String.
  8809.      *
  8810.      * <p>
  8811.      * A {@code null} input String returns {@code null}.
  8812.      * </p>
  8813.      *
  8814.      * <pre>
  8815.      * StringUtils.wrap(null, *)         = null
  8816.      * StringUtils.wrap("", *)           = ""
  8817.      * StringUtils.wrap("ab", null)      = "ab"
  8818.      * StringUtils.wrap("ab", "x")       = "xabx"
  8819.      * StringUtils.wrap("ab", "\"")      = "\"ab\""
  8820.      * StringUtils.wrap("\"ab\"", "\"")  = "\"\"ab\"\""
  8821.      * StringUtils.wrap("ab", "'")       = "'ab'"
  8822.      * StringUtils.wrap("'abcd'", "'")   = "''abcd''"
  8823.      * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'"
  8824.      * StringUtils.wrap("'abcd'", "\"")  = "\"'abcd'\""
  8825.      * </pre>
  8826.      *
  8827.      * @param str
  8828.      *            the String to be wrapper, may be null
  8829.      * @param wrapWith
  8830.      *            the String that will wrap str
  8831.      * @return wrapped String, {@code null} if null String input
  8832.      * @since 3.4
  8833.      */
  8834.     public static String wrap(final String str, final String wrapWith) {

  8835.         if (isEmpty(str) || isEmpty(wrapWith)) {
  8836.             return str;
  8837.         }

  8838.         return wrapWith.concat(str).concat(wrapWith);
  8839.     }

  8840.     /**
  8841.      * Wraps a string with a char if that char is missing from the start or end of the given string.
  8842.      *
  8843.      * <p>A new {@link String} will not be created if {@code str} is already wrapped.</p>
  8844.      *
  8845.      * <pre>
  8846.      * StringUtils.wrapIfMissing(null, *)        = null
  8847.      * StringUtils.wrapIfMissing("", *)          = ""
  8848.      * StringUtils.wrapIfMissing("ab", '\0')     = "ab"
  8849.      * StringUtils.wrapIfMissing("ab", 'x')      = "xabx"
  8850.      * StringUtils.wrapIfMissing("ab", '\'')     = "'ab'"
  8851.      * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\""
  8852.      * StringUtils.wrapIfMissing("/", '/')  = "/"
  8853.      * StringUtils.wrapIfMissing("a/b/c", '/')  = "/a/b/c/"
  8854.      * StringUtils.wrapIfMissing("/a/b/c", '/')  = "/a/b/c/"
  8855.      * StringUtils.wrapIfMissing("a/b/c/", '/')  = "/a/b/c/"
  8856.      * </pre>
  8857.      *
  8858.      * @param str
  8859.      *            the string to be wrapped, may be {@code null}
  8860.      * @param wrapWith
  8861.      *            the char that will wrap {@code str}
  8862.      * @return the wrapped string, or {@code null} if {@code str == null}
  8863.      * @since 3.5
  8864.      */
  8865.     public static String wrapIfMissing(final String str, final char wrapWith) {
  8866.         if (isEmpty(str) || wrapWith == CharUtils.NUL) {
  8867.             return str;
  8868.         }
  8869.         final boolean wrapStart = str.charAt(0) != wrapWith;
  8870.         final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith;
  8871.         if (!wrapStart && !wrapEnd) {
  8872.             return str;
  8873.         }

  8874.         final StringBuilder builder = new StringBuilder(str.length() + 2);
  8875.         if (wrapStart) {
  8876.             builder.append(wrapWith);
  8877.         }
  8878.         builder.append(str);
  8879.         if (wrapEnd) {
  8880.             builder.append(wrapWith);
  8881.         }
  8882.         return builder.toString();
  8883.     }

  8884.     /**
  8885.      * Wraps a string with a string if that string is missing from the start or end of the given string.
  8886.      *
  8887.      * <p>A new {@link String} will not be created if {@code str} is already wrapped.</p>
  8888.      *
  8889.      * <pre>
  8890.      * StringUtils.wrapIfMissing(null, *)         = null
  8891.      * StringUtils.wrapIfMissing("", *)           = ""
  8892.      * StringUtils.wrapIfMissing("ab", null)      = "ab"
  8893.      * StringUtils.wrapIfMissing("ab", "x")       = "xabx"
  8894.      * StringUtils.wrapIfMissing("ab", "\"")      = "\"ab\""
  8895.      * StringUtils.wrapIfMissing("\"ab\"", "\"")  = "\"ab\""
  8896.      * StringUtils.wrapIfMissing("ab", "'")       = "'ab'"
  8897.      * StringUtils.wrapIfMissing("'abcd'", "'")   = "'abcd'"
  8898.      * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'"
  8899.      * StringUtils.wrapIfMissing("'abcd'", "\"")  = "\"'abcd'\""
  8900.      * StringUtils.wrapIfMissing("/", "/")  = "/"
  8901.      * StringUtils.wrapIfMissing("a/b/c", "/")  = "/a/b/c/"
  8902.      * StringUtils.wrapIfMissing("/a/b/c", "/")  = "/a/b/c/"
  8903.      * StringUtils.wrapIfMissing("a/b/c/", "/")  = "/a/b/c/"
  8904.      * </pre>
  8905.      *
  8906.      * @param str
  8907.      *            the string to be wrapped, may be {@code null}
  8908.      * @param wrapWith
  8909.      *            the string that will wrap {@code str}
  8910.      * @return the wrapped string, or {@code null} if {@code str == null}
  8911.      * @since 3.5
  8912.      */
  8913.     public static String wrapIfMissing(final String str, final String wrapWith) {
  8914.         if (isEmpty(str) || isEmpty(wrapWith)) {
  8915.             return str;
  8916.         }

  8917.         final boolean wrapStart = !str.startsWith(wrapWith);
  8918.         final boolean wrapEnd = !str.endsWith(wrapWith);
  8919.         if (!wrapStart && !wrapEnd) {
  8920.             return str;
  8921.         }

  8922.         final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length());
  8923.         if (wrapStart) {
  8924.             builder.append(wrapWith);
  8925.         }
  8926.         builder.append(str);
  8927.         if (wrapEnd) {
  8928.             builder.append(wrapWith);
  8929.         }
  8930.         return builder.toString();
  8931.     }

  8932.     /**
  8933.      * {@link StringUtils} instances should NOT be constructed in
  8934.      * standard programming. Instead, the class should be used as
  8935.      * {@code StringUtils.trim(" foo ");}.
  8936.      *
  8937.      * <p>This constructor is public to permit tools that require a JavaBean
  8938.      * instance to operate.</p>
  8939.      *
  8940.      * @deprecated TODO Make private in 4.0.
  8941.      */
  8942.     @Deprecated
  8943.     public StringUtils() {
  8944.         // empty
  8945.     }

  8946. }