You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by cm...@apache.org on 2013/05/05 05:40:06 UTC
svn commit: r1479234 [7/15] - in /lucene/dev/branches/lucene4956:
dev-tools/idea/.idea/ dev-tools/idea/lucene/analysis/arirang/
lucene/analysis/ lucene/analysis/arirang/ lucene/analysis/arirang/src/
lucene/analysis/arirang/src/java/ lucene/analysis/ari...
Added: lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/StringUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/StringUtil.java?rev=1479234&view=auto
==============================================================================
--- lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/StringUtil.java (added)
+++ lucene/dev/branches/lucene4956/lucene/analysis/arirang/src/java/org/apache/lucene/analysis/kr/utils/StringUtil.java Sun May 5 03:39:51 2013
@@ -0,0 +1,5839 @@
+package org.apache.lucene.analysis.kr.utils;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * <p>Operations on {@link java.lang.String} that are
+ * <code>null</code> safe.</p>
+ *
+ * <ul>
+ * <li><b>IsEmpty/IsBlank</b>
+ * - checks if a String contains text</li>
+ * <li><b>Trim/Strip</b>
+ * - removes leading and trailing whitespace</li>
+ * <li><b>Equals</b>
+ * - compares two strings null-safe</li>
+ * <li><b>startsWith</b>
+ * - check if a String starts with a prefix null-safe</li>
+ * <li><b>endsWith</b>
+ * - check if a String ends with a suffix null-safe</li>
+ * <li><b>IndexOf/LastIndexOf/Contains</b>
+ * - null-safe index-of checks
+ * <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>
+ * - index-of any of a set of Strings</li>
+ * <li><b>ContainsOnly/ContainsNone/ContainsAny</b>
+ * - does String contains only/none/any of these characters</li>
+ * <li><b>Substring/Left/Right/Mid</b>
+ * - null-safe substring extractions</li>
+ * <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>
+ * - substring extraction relative to other strings</li>
+ * <li><b>Split/Join</b>
+ * - splits a String into an array of substrings and vice versa</li>
+ * <li><b>Remove/Delete</b>
+ * - removes part of a String</li>
+ * <li><b>Replace/Overlay</b>
+ * - Searches a String and replaces one String with another</li>
+ * <li><b>Chomp/Chop</b>
+ * - removes the last part of a String</li>
+ * <li><b>LeftPad/RightPad/Center/Repeat</b>
+ * - pads a String</li>
+ * <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>
+ * - changes the case of a String</li>
+ * <li><b>CountMatches</b>
+ * - counts the number of occurrences of one String in another</li>
+ * <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>
+ * - checks the characters in a String</li>
+ * <li><b>DefaultString</b>
+ * - protects against a null input String</li>
+ * <li><b>Reverse/ReverseDelimited</b>
+ * - reverses a String</li>
+ * <li><b>Abbreviate</b>
+ * - abbreviates a string using ellipsis</li>
+ * <li><b>Difference</b>
+ * - compares Strings and reports on their differences</li>
+ * <li><b>LevensteinDistance</b>
+ * - the number of changes needed to change one String into another</li>
+ * </ul>
+ *
+ * <p>The <code>StringUtil</code> class defines certain words related to
+ * String handling.</p>
+ *
+ * <ul>
+ * <li>null - <code>null</code></li>
+ * <li>empty - a zero-length string (<code>""</code>)</li>
+ * <li>space - the space character (<code>' '</code>, char 32)</li>
+ * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
+ * <li>trim - the characters <= 32 as in {@link String#trim()}</li>
+ * </ul>
+ *
+ * <p><code>StringUtil</code> handles <code>null</code> input Strings quietly.
+ * That is to say that a <code>null</code> input will return <code>null</code>.
+ * Where a <code>boolean</code> or <code>int</code> is being returned
+ * details vary by method.</p>
+ *
+ * <p>A side effect of the <code>null</code> handling is that a
+ * <code>NullPointerException</code> should be considered a bug in
+ * <code>StringUtil</code> (except for deprecated methods).</p>
+ *
+ * <p>Methods in this class give sample code to explain their operation.
+ * The symbol <code>*</code> is used to indicate any input including <code>null</code>.</p>
+ *
+ * @see java.lang.String
+ * @author <a href="http://jakarta.apache.org/turbine/">Apache Jakarta Turbine</a>
+ * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
+ * @author Daniel L. Rall
+ * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
+ * @author <a href="mailto:ed@apache.org">Ed Korthof</a>
+ * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
+ * @author Stephen Colebourne
+ * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
+ * @author Holger Krauth
+ * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
+ * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
+ * @author Arun Mammen Thomas
+ * @author Gary Gregory
+ * @author Phil Steitz
+ * @author Al Chou
+ * @author Michael Davey
+ * @author Reuben Sivan
+ * @author Chris Hyzer
+ * @author Scott Johnson
+ * @since 1.0
+ * @version $Id: StringUtil.java,v 1.1 2010/05/25 01:40:12 smlee0818 Exp $
+ */
+public class StringUtil {
+ // Performance testing notes (JDK 1.4, Jul03, scolebourne)
+ // Whitespace:
+ // Character.isWhitespace() is faster than WHITESPACE.indexOf()
+ // where WHITESPACE is a string of all whitespace characters
+ //
+ // Character access:
+ // String.charAt(n) versus toCharArray(), then array[n]
+ // String.charAt(n) is about 15% worse for a 10K string
+ // They are about equal for a length 50 string
+ // String.charAt(n) is about 4 times better for a length 3 string
+ // String.charAt(n) is best bet overall
+ //
+ // Append:
+ // String.concat about twice as fast as StringBuffer.append
+ // (not sure who tested this)
+
+ /**
+ * The default buffer size to use.
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+ /**
+ * An empty immutable <code>String</code> array.
+ */
+ public static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+ /**
+ * The empty String <code>""</code>.
+ * @since 2.0
+ */
+ public static final String EMPTY = "";
+
+ /**
+ * Represents a failed index search.
+ * @since 2.1
+ */
+ public static final int INDEX_NOT_FOUND = -1;
+
+ /**
+ * <p>The maximum size to which the padding constant(s) can expand.</p>
+ */
+ private static final int PAD_LIMIT = 8192;
+
+ /**
+ * <p><code>StringUtil</code> instances should NOT be constructed in
+ * standard programming. Instead, the class should be used as
+ * <code>StringUtil.trim(" foo ");</code>.</p>
+ *
+ * <p>This constructor is public to permit tools that require a JavaBean
+ * instance to operate.</p>
+ */
+ public StringUtil() {
+ super();
+ }
+
+ // Empty checks
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Checks if a String is empty ("") or null.</p>
+ *
+ * <pre>
+ * StringUtil.isEmpty(null) = true
+ * StringUtil.isEmpty("") = true
+ * StringUtil.isEmpty(" ") = false
+ * StringUtil.isEmpty("bob") = false
+ * StringUtil.isEmpty(" bob ") = false
+ * </pre>
+ *
+ * <p>NOTE: This method changed in Lang version 2.0.
+ * It no longer trims the String.
+ * That functionality is available in isBlank().</p>
+ *
+ * @param str the String to check, may be null
+ * @return <code>true</code> if the String is empty or null
+ */
+ public static boolean isEmpty(String str) {
+ return str == null || str.length() == 0;
+ }
+
+ /**
+ * <p>Checks if a String is not empty ("") and not null.</p>
+ *
+ * <pre>
+ * StringUtil.isNotEmpty(null) = false
+ * StringUtil.isNotEmpty("") = false
+ * StringUtil.isNotEmpty(" ") = true
+ * StringUtil.isNotEmpty("bob") = true
+ * StringUtil.isNotEmpty(" bob ") = true
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @return <code>true</code> if the String is not empty and not null
+ */
+ public static boolean isNotEmpty(String str) {
+ return !StringUtil.isEmpty(str);
+ }
+
+ /**
+ * <p>Checks if a String is whitespace, empty ("") or null.</p>
+ *
+ * <pre>
+ * StringUtil.isBlank(null) = true
+ * StringUtil.isBlank("") = true
+ * StringUtil.isBlank(" ") = true
+ * StringUtil.isBlank("bob") = false
+ * StringUtil.isBlank(" bob ") = false
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @return <code>true</code> if the String is null, empty or whitespace
+ * @since 2.0
+ */
+ public static boolean isBlank(String str) {
+ int strLen;
+ if (str == null || (strLen = str.length()) == 0) {
+ return true;
+ }
+ for (int i = 0; i < strLen; i++) {
+ if ((Character.isWhitespace(str.charAt(i)) == false)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks if a String is not empty (""), not null and not whitespace only.</p>
+ *
+ * <pre>
+ * StringUtil.isNotBlank(null) = false
+ * StringUtil.isNotBlank("") = false
+ * StringUtil.isNotBlank(" ") = false
+ * StringUtil.isNotBlank("bob") = true
+ * StringUtil.isNotBlank(" bob ") = true
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @return <code>true</code> if the String is
+ * not empty and not null and not whitespace
+ * @since 2.0
+ */
+ public static boolean isNotBlank(String str) {
+ return !StringUtil.isBlank(str);
+ }
+
+ // Trim
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Removes control characters (char <= 32) from both
+ * ends of this String, handling <code>null</code> by returning
+ * an empty String ("").</p>
+ *
+ * <pre>
+ * StringUtil.clean(null) = ""
+ * StringUtil.clean("") = ""
+ * StringUtil.clean("abc") = "abc"
+ * StringUtil.clean(" abc ") = "abc"
+ * StringUtil.clean(" ") = ""
+ * </pre>
+ *
+ * @see java.lang.String#trim()
+ * @param str the String to clean, may be null
+ * @return the trimmed text, never <code>null</code>
+ * @deprecated Use the clearer named {@link #trimToEmpty(String)}.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ public static String clean(String str) {
+ return str == null ? EMPTY : str.trim();
+ }
+
+ /**
+ * <p>Removes control characters (char <= 32) from both
+ * ends of this String, handling <code>null</code> by returning
+ * <code>null</code>.</p>
+ *
+ * <p>The String is trimmed using {@link String#trim()}.
+ * Trim removes start and end characters <= 32.
+ * To strip whitespace use {@link #strip(String)}.</p>
+ *
+ * <p>To trim your choice of characters, use the
+ * {@link #strip(String, String)} methods.</p>
+ *
+ * <pre>
+ * StringUtil.trim(null) = null
+ * StringUtil.trim("") = ""
+ * StringUtil.trim(" ") = ""
+ * StringUtil.trim("abc") = "abc"
+ * StringUtil.trim(" abc ") = "abc"
+ * </pre>
+ *
+ * @param str the String to be trimmed, may be null
+ * @return the trimmed string, <code>null</code> if null String input
+ */
+ public static String trim(String str) {
+ return str == null ? null : str.trim();
+ }
+
+ /**
+ * <p>Removes control characters (char <= 32) from both
+ * ends of this String returning <code>null</code> if the String is
+ * empty ("") after the trim or if it is <code>null</code>.
+ *
+ * <p>The String is trimmed using {@link String#trim()}.
+ * Trim removes start and end characters <= 32.
+ * To strip whitespace use {@link #stripToNull(String)}.</p>
+ *
+ * <pre>
+ * StringUtil.trimToNull(null) = null
+ * StringUtil.trimToNull("") = null
+ * StringUtil.trimToNull(" ") = null
+ * StringUtil.trimToNull("abc") = "abc"
+ * StringUtil.trimToNull(" abc ") = "abc"
+ * </pre>
+ *
+ * @param str the String to be trimmed, may be null
+ * @return the trimmed String,
+ * <code>null</code> if only chars <= 32, empty or null String input
+ * @since 2.0
+ */
+ public static String trimToNull(String str) {
+ String ts = trim(str);
+ return isEmpty(ts) ? null : ts;
+ }
+
+ /**
+ * <p>Removes control characters (char <= 32) from both
+ * ends of this String returning an empty String ("") if the String
+ * is empty ("") after the trim or if it is <code>null</code>.
+ *
+ * <p>The String is trimmed using {@link String#trim()}.
+ * Trim removes start and end characters <= 32.
+ * To strip whitespace use {@link #stripToEmpty(String)}.</p>
+ *
+ * <pre>
+ * StringUtil.trimToEmpty(null) = ""
+ * StringUtil.trimToEmpty("") = ""
+ * StringUtil.trimToEmpty(" ") = ""
+ * StringUtil.trimToEmpty("abc") = "abc"
+ * StringUtil.trimToEmpty(" abc ") = "abc"
+ * </pre>
+ *
+ * @param str the String to be trimmed, may be null
+ * @return the trimmed String, or an empty String if <code>null</code> input
+ * @since 2.0
+ */
+ public static String trimToEmpty(String str) {
+ return str == null ? EMPTY : str.trim();
+ }
+
+ // Stripping
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Strips whitespace from the start and end of a String.</p>
+ *
+ * <p>This is similar to {@link #trim(String)} but removes whitespace.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.</p>
+ *
+ * <pre>
+ * StringUtil.strip(null) = null
+ * StringUtil.strip("") = ""
+ * StringUtil.strip(" ") = ""
+ * StringUtil.strip("abc") = "abc"
+ * StringUtil.strip(" abc") = "abc"
+ * StringUtil.strip("abc ") = "abc"
+ * StringUtil.strip(" abc ") = "abc"
+ * StringUtil.strip(" ab c ") = "ab c"
+ * </pre>
+ *
+ * @param str the String to remove whitespace from, may be null
+ * @return the stripped String, <code>null</code> if null String input
+ */
+ public static String strip(String str) {
+ return strip(str, null);
+ }
+
+ /**
+ * <p>Strips whitespace from the start and end of a String returning
+ * <code>null</code> if the String is empty ("") after the strip.</p>
+ *
+ * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+ *
+ * <pre>
+ * StringUtil.stripToNull(null) = null
+ * StringUtil.stripToNull("") = null
+ * StringUtil.stripToNull(" ") = null
+ * StringUtil.stripToNull("abc") = "abc"
+ * StringUtil.stripToNull(" abc") = "abc"
+ * StringUtil.stripToNull("abc ") = "abc"
+ * StringUtil.stripToNull(" abc ") = "abc"
+ * StringUtil.stripToNull(" ab c ") = "ab c"
+ * </pre>
+ *
+ * @param str the String to be stripped, may be null
+ * @return the stripped String,
+ * <code>null</code> if whitespace, empty or null String input
+ * @since 2.0
+ */
+ public static String stripToNull(String str) {
+ if (str == null) {
+ return null;
+ }
+ str = strip(str, null);
+ return str.length() == 0 ? null : str;
+ }
+
+ /**
+ * <p>Strips whitespace from the start and end of a String returning
+ * an empty String if <code>null</code> input.</p>
+ *
+ * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+ *
+ * <pre>
+ * StringUtil.stripToEmpty(null) = ""
+ * StringUtil.stripToEmpty("") = ""
+ * StringUtil.stripToEmpty(" ") = ""
+ * StringUtil.stripToEmpty("abc") = "abc"
+ * StringUtil.stripToEmpty(" abc") = "abc"
+ * StringUtil.stripToEmpty("abc ") = "abc"
+ * StringUtil.stripToEmpty(" abc ") = "abc"
+ * StringUtil.stripToEmpty(" ab c ") = "ab c"
+ * </pre>
+ *
+ * @param str the String to be stripped, may be null
+ * @return the trimmed String, or an empty String if <code>null</code> input
+ * @since 2.0
+ */
+ public static String stripToEmpty(String str) {
+ return str == null ? EMPTY : strip(str, null);
+ }
+
+ /**
+ * <p>Strips any of a set of characters from the start and end of a String.
+ * This is similar to {@link String#trim()} but allows the characters
+ * to be stripped to be controlled.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.
+ * An empty string ("") input returns the empty string.</p>
+ *
+ * <p>If the stripChars String is <code>null</code>, whitespace is
+ * stripped as defined by {@link Character#isWhitespace(char)}.
+ * Alternatively use {@link #strip(String)}.</p>
+ *
+ * <pre>
+ * StringUtil.strip(null, *) = null
+ * StringUtil.strip("", *) = ""
+ * StringUtil.strip("abc", null) = "abc"
+ * StringUtil.strip(" abc", null) = "abc"
+ * StringUtil.strip("abc ", null) = "abc"
+ * StringUtil.strip(" abc ", null) = "abc"
+ * StringUtil.strip(" abcyx", "xyz") = " abc"
+ * </pre>
+ *
+ * @param str the String to remove characters from, may be null
+ * @param stripChars the characters to remove, null treated as whitespace
+ * @return the stripped String, <code>null</code> if null String input
+ */
+ public static String strip(String str, String stripChars) {
+ if (isEmpty(str)) {
+ return str;
+ }
+ str = stripStart(str, stripChars);
+ return stripEnd(str, stripChars);
+ }
+
+ /**
+ * <p>Strips any of a set of characters from the start of a String.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.
+ * An empty string ("") input returns the empty string.</p>
+ *
+ * <p>If the stripChars String is <code>null</code>, whitespace is
+ * stripped as defined by {@link Character#isWhitespace(char)}.</p>
+ *
+ * <pre>
+ * StringUtil.stripStart(null, *) = null
+ * StringUtil.stripStart("", *) = ""
+ * StringUtil.stripStart("abc", "") = "abc"
+ * StringUtil.stripStart("abc", null) = "abc"
+ * StringUtil.stripStart(" abc", null) = "abc"
+ * StringUtil.stripStart("abc ", null) = "abc "
+ * StringUtil.stripStart(" abc ", null) = "abc "
+ * StringUtil.stripStart("yxabc ", "xyz") = "abc "
+ * </pre>
+ *
+ * @param str the String to remove characters from, may be null
+ * @param stripChars the characters to remove, null treated as whitespace
+ * @return the stripped String, <code>null</code> if null String input
+ */
+ public static String stripStart(String str, String stripChars) {
+ int strLen;
+ if (str == null || (strLen = str.length()) == 0) {
+ return str;
+ }
+ int start = 0;
+ if (stripChars == null) {
+ while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {
+ start++;
+ }
+ } else if (stripChars.length() == 0) {
+ return str;
+ } else {
+ while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != -1)) {
+ start++;
+ }
+ }
+ return str.substring(start);
+ }
+
+ /**
+ * <p>Strips any of a set of characters from the end of a String.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.
+ * An empty string ("") input returns the empty string.</p>
+ *
+ * <p>If the stripChars String is <code>null</code>, whitespace is
+ * stripped as defined by {@link Character#isWhitespace(char)}.</p>
+ *
+ * <pre>
+ * StringUtil.stripEnd(null, *) = null
+ * StringUtil.stripEnd("", *) = ""
+ * StringUtil.stripEnd("abc", "") = "abc"
+ * StringUtil.stripEnd("abc", null) = "abc"
+ * StringUtil.stripEnd(" abc", null) = " abc"
+ * StringUtil.stripEnd("abc ", null) = "abc"
+ * StringUtil.stripEnd(" abc ", null) = " abc"
+ * StringUtil.stripEnd(" abcyx", "xyz") = " abc"
+ * </pre>
+ *
+ * @param str the String to remove characters from, may be null
+ * @param stripChars the characters to remove, null treated as whitespace
+ * @return the stripped String, <code>null</code> if null String input
+ */
+ public static String stripEnd(String str, String stripChars) {
+ int end;
+ if (str == null || (end = str.length()) == 0) {
+ return str;
+ }
+
+ if (stripChars == null) {
+ while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
+ end--;
+ }
+ } else if (stripChars.length() == 0) {
+ return str;
+ } else {
+ while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) {
+ end--;
+ }
+ }
+ return str.substring(0, end);
+ }
+
+ // StripAll
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Strips whitespace from the start and end of every String in an array.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+ *
+ * <p>A new array is returned each time, except for length zero.
+ * A <code>null</code> array will return <code>null</code>.
+ * An empty array will return itself.
+ * A <code>null</code> array entry will be ignored.</p>
+ *
+ * <pre>
+ * StringUtil.stripAll(null) = null
+ * StringUtil.stripAll([]) = []
+ * StringUtil.stripAll(["abc", " abc"]) = ["abc", "abc"]
+ * StringUtil.stripAll(["abc ", null]) = ["abc", null]
+ * </pre>
+ *
+ * @param strs the array to remove whitespace from, may be null
+ * @return the stripped Strings, <code>null</code> if null array input
+ */
+ public static String[] stripAll(String[] strs) {
+ return stripAll(strs, null);
+ }
+
+ /**
+ * <p>Strips any of a set of characters from the start and end of every
+ * String in an array.</p>
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+ *
+ * <p>A new array is returned each time, except for length zero.
+ * A <code>null</code> array will return <code>null</code>.
+ * An empty array will return itself.
+ * A <code>null</code> array entry will be ignored.
+ * A <code>null</code> stripChars will strip whitespace as defined by
+ * {@link Character#isWhitespace(char)}.</p>
+ *
+ * <pre>
+ * StringUtil.stripAll(null, *) = null
+ * StringUtil.stripAll([], *) = []
+ * StringUtil.stripAll(["abc", " abc"], null) = ["abc", "abc"]
+ * StringUtil.stripAll(["abc ", null], null) = ["abc", null]
+ * StringUtil.stripAll(["abc ", null], "yz") = ["abc ", null]
+ * StringUtil.stripAll(["yabcz", null], "yz") = ["abc", null]
+ * </pre>
+ *
+ * @param strs the array to remove characters from, may be null
+ * @param stripChars the characters to remove, null treated as whitespace
+ * @return the stripped Strings, <code>null</code> if null array input
+ */
+ public static String[] stripAll(String[] strs, String stripChars) {
+ int strsLen;
+ if (strs == null || (strsLen = strs.length) == 0) {
+ return strs;
+ }
+ String[] newArr = new String[strsLen];
+ for (int i = 0; i < strsLen; i++) {
+ newArr[i] = strip(strs[i], stripChars);
+ }
+ return newArr;
+ }
+
+ // Equals
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Compares two Strings, returning <code>true</code> if they are equal.</p>
+ *
+ * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
+ * references are considered to be equal. The comparison is case sensitive.</p>
+ *
+ * <pre>
+ * StringUtil.equals(null, null) = true
+ * StringUtil.equals(null, "abc") = false
+ * StringUtil.equals("abc", null) = false
+ * StringUtil.equals("abc", "abc") = true
+ * StringUtil.equals("abc", "ABC") = false
+ * </pre>
+ *
+ * @see java.lang.String#equals(Object)
+ * @param str1 the first String, may be null
+ * @param str2 the second String, may be null
+ * @return <code>true</code> if the Strings are equal, case sensitive, or
+ * both <code>null</code>
+ */
+ public static boolean equals(String str1, String str2) {
+ return str1 == null ? str2 == null : str1.equals(str2);
+ }
+
+ /**
+ * <p>Compares two Strings, returning <code>true</code> if they are equal ignoring
+ * the case.</p>
+ *
+ * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
+ * references are considered equal. Comparison is case insensitive.</p>
+ *
+ * <pre>
+ * StringUtil.equalsIgnoreCase(null, null) = true
+ * StringUtil.equalsIgnoreCase(null, "abc") = false
+ * StringUtil.equalsIgnoreCase("abc", null) = false
+ * StringUtil.equalsIgnoreCase("abc", "abc") = true
+ * StringUtil.equalsIgnoreCase("abc", "ABC") = true
+ * </pre>
+ *
+ * @see java.lang.String#equalsIgnoreCase(String)
+ * @param str1 the first String, may be null
+ * @param str2 the second String, may be null
+ * @return <code>true</code> if the Strings are equal, case insensitive, or
+ * both <code>null</code>
+ */
+ public static boolean equalsIgnoreCase(String str1, String str2) {
+ return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
+ }
+
+ // IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Finds the first index within a String, handling <code>null</code>.
+ * This method uses {@link String#indexOf(int)}.</p>
+ *
+ * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.</p>
+ *
+ * <pre>
+ * StringUtil.indexOf(null, *) = -1
+ * StringUtil.indexOf("", *) = -1
+ * StringUtil.indexOf("aabaabaa", 'a') = 0
+ * StringUtil.indexOf("aabaabaa", 'b') = 2
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchChar the character to find
+ * @return the first index of the search character,
+ * -1 if no match or <code>null</code> string input
+ * @since 2.0
+ */
+ public static int indexOf(String str, char searchChar) {
+ if (isEmpty(str)) {
+ return -1;
+ }
+ return str.indexOf(searchChar);
+ }
+
+ /**
+ * <p>Finds the first index within a String from a start position,
+ * handling <code>null</code>.
+ * This method uses {@link String#indexOf(int, int)}.</p>
+ *
+ * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.
+ * A negative start position is treated as zero.
+ * A start position greater than the string length returns <code>-1</code>.</p>
+ *
+ * <pre>
+ * StringUtil.indexOf(null, *, *) = -1
+ * StringUtil.indexOf("", *, *) = -1
+ * StringUtil.indexOf("aabaabaa", 'b', 0) = 2
+ * StringUtil.indexOf("aabaabaa", 'b', 3) = 5
+ * StringUtil.indexOf("aabaabaa", 'b', 9) = -1
+ * StringUtil.indexOf("aabaabaa", 'b', -1) = 2
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchChar the character to find
+ * @param startPos the start position, negative treated as zero
+ * @return the first index of the search character,
+ * -1 if no match or <code>null</code> string input
+ * @since 2.0
+ */
+ public static int indexOf(String str, char searchChar, int startPos) {
+ if (isEmpty(str)) {
+ return -1;
+ }
+ return str.indexOf(searchChar, startPos);
+ }
+
+ /**
+ * <p>Finds the first index within a String, handling <code>null</code>.
+ * This method uses {@link String#indexOf(String)}.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.</p>
+ *
+ * <pre>
+ * StringUtil.indexOf(null, *) = -1
+ * StringUtil.indexOf(*, null) = -1
+ * StringUtil.indexOf("", "") = 0
+ * StringUtil.indexOf("aabaabaa", "a") = 0
+ * StringUtil.indexOf("aabaabaa", "b") = 2
+ * StringUtil.indexOf("aabaabaa", "ab") = 1
+ * StringUtil.indexOf("aabaabaa", "") = 0
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @return the first index of the search String,
+ * -1 if no match or <code>null</code> string input
+ * @since 2.0
+ */
+ public static int indexOf(String str, String searchStr) {
+ if (str == null || searchStr == null) {
+ return -1;
+ }
+ return str.indexOf(searchStr);
+ }
+
+ /**
+ * <p>Finds the n-th index within a String, handling <code>null</code>.
+ * This method uses {@link String#indexOf(String)}.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.</p>
+ *
+ * <pre>
+ * StringUtil.ordinalIndexOf(null, *, *) = -1
+ * StringUtil.ordinalIndexOf(*, null, *) = -1
+ * StringUtil.ordinalIndexOf("", "", *) = 0
+ * StringUtil.ordinalIndexOf("aabaabaa", "a", 1) = 0
+ * StringUtil.ordinalIndexOf("aabaabaa", "a", 2) = 1
+ * StringUtil.ordinalIndexOf("aabaabaa", "b", 1) = 2
+ * StringUtil.ordinalIndexOf("aabaabaa", "b", 2) = 5
+ * StringUtil.ordinalIndexOf("aabaabaa", "ab", 1) = 1
+ * StringUtil.ordinalIndexOf("aabaabaa", "ab", 2) = 4
+ * StringUtil.ordinalIndexOf("aabaabaa", "", 1) = 0
+ * StringUtil.ordinalIndexOf("aabaabaa", "", 2) = 0
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @param ordinal the n-th <code>searchStr</code> to find
+ * @return the n-th index of the search String,
+ * <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
+ * @since 2.1
+ */
+ public static int ordinalIndexOf(String str, String searchStr, int ordinal) {
+ if (str == null || searchStr == null || ordinal <= 0) {
+ return INDEX_NOT_FOUND;
+ }
+ if (searchStr.length() == 0) {
+ return 0;
+ }
+ int found = 0;
+ int index = INDEX_NOT_FOUND;
+ do {
+ index = str.indexOf(searchStr, index + 1);
+ if (index < 0) {
+ return index;
+ }
+ found++;
+ } while (found < ordinal);
+ return index;
+ }
+
+ /**
+ * <p>Finds the first index within a String, handling <code>null</code>.
+ * This method uses {@link String#indexOf(String, int)}.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.
+ * A negative start position is treated as zero.
+ * An empty ("") search String always matches.
+ * A start position greater than the string length only matches
+ * an empty search String.</p>
+ *
+ * <pre>
+ * StringUtil.indexOf(null, *, *) = -1
+ * StringUtil.indexOf(*, null, *) = -1
+ * StringUtil.indexOf("", "", 0) = 0
+ * StringUtil.indexOf("aabaabaa", "a", 0) = 0
+ * StringUtil.indexOf("aabaabaa", "b", 0) = 2
+ * StringUtil.indexOf("aabaabaa", "ab", 0) = 1
+ * StringUtil.indexOf("aabaabaa", "b", 3) = 5
+ * StringUtil.indexOf("aabaabaa", "b", 9) = -1
+ * StringUtil.indexOf("aabaabaa", "b", -1) = 2
+ * StringUtil.indexOf("aabaabaa", "", 2) = 2
+ * StringUtil.indexOf("abc", "", 9) = 3
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @param startPos the start position, negative treated as zero
+ * @return the first index of the search String,
+ * -1 if no match or <code>null</code> string input
+ * @since 2.0
+ */
+ public static int indexOf(String str, String searchStr, int startPos) {
+ if (str == null || searchStr == null) {
+ return -1;
+ }
+ // JDK1.2/JDK1.3 have a bug, when startPos > str.length for "", hence
+ if (searchStr.length() == 0 && startPos >= str.length()) {
+ return str.length();
+ }
+ return str.indexOf(searchStr, startPos);
+ }
+
+ // LastIndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Finds the last index within a String, handling <code>null</code>.
+ * This method uses {@link String#lastIndexOf(int)}.</p>
+ *
+ * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.</p>
+ *
+ * <pre>
+ * StringUtil.lastIndexOf(null, *) = -1
+ * StringUtil.lastIndexOf("", *) = -1
+ * StringUtil.lastIndexOf("aabaabaa", 'a') = 7
+ * StringUtil.lastIndexOf("aabaabaa", 'b') = 5
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchChar the character to find
+ * @return the last index of the search character,
+ * -1 if no match or <code>null</code> string input
+ * @since 2.0
+ */
+ public static int lastIndexOf(String str, char searchChar) {
+ if (isEmpty(str)) {
+ return -1;
+ }
+ return str.lastIndexOf(searchChar);
+ }
+
+ /**
+ * <p>Finds the last index within a String from a start position,
+ * handling <code>null</code>.
+ * This method uses {@link String#lastIndexOf(int, int)}.</p>
+ *
+ * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.
+ * A negative start position returns <code>-1</code>.
+ * A start position greater than the string length searches the whole string.</p>
+ *
+ * <pre>
+ * StringUtil.lastIndexOf(null, *, *) = -1
+ * StringUtil.lastIndexOf("", *, *) = -1
+ * StringUtil.lastIndexOf("aabaabaa", 'b', 8) = 5
+ * StringUtil.lastIndexOf("aabaabaa", 'b', 4) = 2
+ * StringUtil.lastIndexOf("aabaabaa", 'b', 0) = -1
+ * StringUtil.lastIndexOf("aabaabaa", 'b', 9) = 5
+ * StringUtil.lastIndexOf("aabaabaa", 'b', -1) = -1
+ * StringUtil.lastIndexOf("aabaabaa", 'a', 0) = 0
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchChar the character to find
+ * @param startPos the start position
+ * @return the last index of the search character,
+ * -1 if no match or <code>null</code> string input
+ * @since 2.0
+ */
+ public static int lastIndexOf(String str, char searchChar, int startPos) {
+ if (isEmpty(str)) {
+ return -1;
+ }
+ return str.lastIndexOf(searchChar, startPos);
+ }
+
+ /**
+ * <p>Finds the last index within a String, handling <code>null</code>.
+ * This method uses {@link String#lastIndexOf(String)}.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.</p>
+ *
+ * <pre>
+ * StringUtil.lastIndexOf(null, *) = -1
+ * StringUtil.lastIndexOf(*, null) = -1
+ * StringUtil.lastIndexOf("", "") = 0
+ * StringUtil.lastIndexOf("aabaabaa", "a") = 0
+ * StringUtil.lastIndexOf("aabaabaa", "b") = 2
+ * StringUtil.lastIndexOf("aabaabaa", "ab") = 1
+ * StringUtil.lastIndexOf("aabaabaa", "") = 8
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @return the last index of the search String,
+ * -1 if no match or <code>null</code> string input
+ * @since 2.0
+ */
+ public static int lastIndexOf(String str, String searchStr) {
+ if (str == null || searchStr == null) {
+ return -1;
+ }
+ return str.lastIndexOf(searchStr);
+ }
+
+ /**
+ * <p>Finds the first index within a String, handling <code>null</code>.
+ * This method uses {@link String#lastIndexOf(String, int)}.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.
+ * A negative start position returns <code>-1</code>.
+ * An empty ("") search String always matches unless the start position is negative.
+ * A start position greater than the string length searches the whole string.</p>
+ *
+ * <pre>
+ * StringUtil.lastIndexOf(null, *, *) = -1
+ * StringUtil.lastIndexOf(*, null, *) = -1
+ * StringUtil.lastIndexOf("aabaabaa", "a", 8) = 7
+ * StringUtil.lastIndexOf("aabaabaa", "b", 8) = 5
+ * StringUtil.lastIndexOf("aabaabaa", "ab", 8) = 4
+ * StringUtil.lastIndexOf("aabaabaa", "b", 9) = 5
+ * StringUtil.lastIndexOf("aabaabaa", "b", -1) = -1
+ * StringUtil.lastIndexOf("aabaabaa", "a", 0) = 0
+ * StringUtil.lastIndexOf("aabaabaa", "b", 0) = -1
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @param startPos the start position, negative treated as zero
+ * @return the first index of the search String,
+ * -1 if no match or <code>null</code> string input
+ * @since 2.0
+ */
+ public static int lastIndexOf(String str, String searchStr, int startPos) {
+ if (str == null || searchStr == null) {
+ return -1;
+ }
+ return str.lastIndexOf(searchStr, startPos);
+ }
+
+ // Contains
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Checks if String contains a search character, handling <code>null</code>.
+ * This method uses {@link String#indexOf(int)}.</p>
+ *
+ * <p>A <code>null</code> or empty ("") String will return <code>false</code>.</p>
+ *
+ * <pre>
+ * StringUtil.contains(null, *) = false
+ * StringUtil.contains("", *) = false
+ * StringUtil.contains("abc", 'a') = true
+ * StringUtil.contains("abc", 'z') = false
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchChar the character to find
+ * @return true if the String contains the search character,
+ * false if not or <code>null</code> string input
+ * @since 2.0
+ */
+ public static boolean contains(String str, char searchChar) {
+ if (isEmpty(str)) {
+ return false;
+ }
+ return str.indexOf(searchChar) >= 0;
+ }
+
+ /**
+ * <p>Checks if String contains a search String, handling <code>null</code>.
+ * This method uses {@link String#indexOf(String)}.</p>
+ *
+ * <p>A <code>null</code> String will return <code>false</code>.</p>
+ *
+ * <pre>
+ * StringUtil.contains(null, *) = false
+ * StringUtil.contains(*, null) = false
+ * StringUtil.contains("", "") = true
+ * StringUtil.contains("abc", "") = true
+ * StringUtil.contains("abc", "a") = true
+ * StringUtil.contains("abc", "z") = false
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @return true if the String contains the search String,
+ * false if not or <code>null</code> string input
+ * @since 2.0
+ */
+ public static boolean contains(String str, String searchStr) {
+ if (str == null || searchStr == null) {
+ return false;
+ }
+ return str.indexOf(searchStr) >= 0;
+ }
+
+ /**
+ * <p>Checks if String contains a search String irrespective of case,
+ * handling <code>null</code>. This method uses
+ * {@link #contains(String, String)}.</p>
+ *
+ * <p>A <code>null</code> String will return <code>false</code>.</p>
+ *
+ * <pre>
+ * StringUtil.contains(null, *) = false
+ * StringUtil.contains(*, null) = false
+ * StringUtil.contains("", "") = true
+ * StringUtil.contains("abc", "") = true
+ * StringUtil.contains("abc", "a") = true
+ * StringUtil.contains("abc", "z") = false
+ * StringUtil.contains("abc", "A") = true
+ * StringUtil.contains("abc", "Z") = false
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @return true if the String contains the search String irrespective of
+ * case or false if not or <code>null</code> string input
+ */
+ public static boolean containsIgnoreCase(String str, String searchStr) {
+ if (str == null || searchStr == null) {
+ return false;
+ }
+ return contains(str.toUpperCase(), searchStr.toUpperCase());
+ }
+
+ // IndexOfAny chars
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Search a String to find the first index of any
+ * character in the given set of characters.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.
+ * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
+ *
+ * <pre>
+ * StringUtil.indexOfAny(null, *) = -1
+ * StringUtil.indexOfAny("", *) = -1
+ * StringUtil.indexOfAny(*, null) = -1
+ * StringUtil.indexOfAny(*, []) = -1
+ * StringUtil.indexOfAny("zzabyycdxx",['z','a']) = 0
+ * StringUtil.indexOfAny("zzabyycdxx",['b','y']) = 3
+ * StringUtil.indexOfAny("aba", ['z']) = -1
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the index of any of the chars, -1 if no match or null input
+ * @since 2.0
+ */
+ public static int indexOfAny(String str, char[] searchChars) {
+ if (isEmpty(str) || isArrayEmpty(searchChars)) {
+ return -1;
+ }
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ for (int j = 0; j < searchChars.length; j++) {
+ if (searchChars[j] == ch) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Search a String to find the first index of any
+ * character in the given set of characters.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.
+ * A <code>null</code> search string will return <code>-1</code>.</p>
+ *
+ * <pre>
+ * StringUtil.indexOfAny(null, *) = -1
+ * StringUtil.indexOfAny("", *) = -1
+ * StringUtil.indexOfAny(*, null) = -1
+ * StringUtil.indexOfAny(*, "") = -1
+ * StringUtil.indexOfAny("zzabyycdxx", "za") = 0
+ * StringUtil.indexOfAny("zzabyycdxx", "by") = 3
+ * StringUtil.indexOfAny("aba","z") = -1
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the index of any of the chars, -1 if no match or null input
+ * @since 2.0
+ */
+ public static int indexOfAny(String str, String searchChars) {
+ if (isEmpty(str) || isEmpty(searchChars)) {
+ return -1;
+ }
+ return indexOfAny(str, searchChars.toCharArray());
+ }
+
+ // ContainsAny
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Checks if the String contains any character in the given
+ * set of characters.</p>
+ *
+ * <p>A <code>null</code> String will return <code>false</code>.
+ * A <code>null</code> or zero length search array will return <code>false</code>.</p>
+ *
+ * <pre>
+ * StringUtil.containsAny(null, *) = false
+ * StringUtil.containsAny("", *) = false
+ * StringUtil.containsAny(*, null) = false
+ * StringUtil.containsAny(*, []) = false
+ * StringUtil.containsAny("zzabyycdxx",['z','a']) = true
+ * StringUtil.containsAny("zzabyycdxx",['b','y']) = true
+ * StringUtil.containsAny("aba", ['z']) = false
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the <code>true</code> if any of the chars are found,
+ * <code>false</code> if no match or null input
+ * @since 2.4
+ */
+ public static boolean containsAny(String str, char[] searchChars) {
+ if (str == null || str.length() == 0 || searchChars == null || searchChars.length == 0) {
+ return false;
+ }
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ for (int j = 0; j < searchChars.length; j++) {
+ if (searchChars[j] == ch) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * <p>
+ * Checks if the String contains any character in the given set of characters.
+ * </p>
+ *
+ * <p>
+ * A <code>null</code> String will return <code>false</code>. A <code>null</code> search string will return
+ * <code>false</code>.
+ * </p>
+ *
+ * <pre>
+ * StringUtil.containsAny(null, *) = false
+ * StringUtil.containsAny("", *) = false
+ * StringUtil.containsAny(*, null) = false
+ * StringUtil.containsAny(*, "") = false
+ * StringUtil.containsAny("zzabyycdxx", "za") = true
+ * StringUtil.containsAny("zzabyycdxx", "by") = true
+ * StringUtil.containsAny("aba","z") = false
+ * </pre>
+ *
+ * @param str
+ * the String to check, may be null
+ * @param searchChars
+ * the chars to search for, may be null
+ * @return the <code>true</code> if any of the chars are found, <code>false</code> if no match or null input
+ * @since 2.4
+ */
+ public static boolean containsAny(String str, String searchChars) {
+ if (searchChars == null) {
+ return false;
+ }
+ return containsAny(str, searchChars.toCharArray());
+ }
+
+ // IndexOfAnyBut chars
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Search a String to find the first index of any
+ * character not in the given set of characters.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.
+ * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
+ *
+ * <pre>
+ * StringUtil.indexOfAnyBut(null, *) = -1
+ * StringUtil.indexOfAnyBut("", *) = -1
+ * StringUtil.indexOfAnyBut(*, null) = -1
+ * StringUtil.indexOfAnyBut(*, []) = -1
+ * StringUtil.indexOfAnyBut("zzabyycdxx",'za') = 3
+ * StringUtil.indexOfAnyBut("zzabyycdxx", '') = 0
+ * StringUtil.indexOfAnyBut("aba", 'ab') = -1
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the index of any of the chars, -1 if no match or null input
+ * @since 2.0
+ */
+ public static int indexOfAnyBut(String str, char[] searchChars) {
+ if (isEmpty(str) || isArrayEmpty(searchChars)) {
+ return -1;
+ }
+ outer : for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ for (int j = 0; j < searchChars.length; j++) {
+ if (searchChars[j] == ch) {
+ continue outer;
+ }
+ }
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Search a String to find the first index of any
+ * character not in the given set of characters.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.
+ * A <code>null</code> search string will return <code>-1</code>.</p>
+ *
+ * <pre>
+ * StringUtil.indexOfAnyBut(null, *) = -1
+ * StringUtil.indexOfAnyBut("", *) = -1
+ * StringUtil.indexOfAnyBut(*, null) = -1
+ * StringUtil.indexOfAnyBut(*, "") = -1
+ * StringUtil.indexOfAnyBut("zzabyycdxx", "za") = 3
+ * StringUtil.indexOfAnyBut("zzabyycdxx", "") = 0
+ * StringUtil.indexOfAnyBut("aba","ab") = -1
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the index of any of the chars, -1 if no match or null input
+ * @since 2.0
+ */
+ public static int indexOfAnyBut(String str, String searchChars) {
+ if (isEmpty(str) || isEmpty(searchChars)) {
+ return -1;
+ }
+ for (int i = 0; i < str.length(); i++) {
+ if (searchChars.indexOf(str.charAt(i)) < 0) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ // ContainsOnly
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Checks if the String contains only certain characters.</p>
+ *
+ * <p>A <code>null</code> String will return <code>false</code>.
+ * A <code>null</code> valid character array will return <code>false</code>.
+ * An empty String ("") always returns <code>true</code>.</p>
+ *
+ * <pre>
+ * StringUtil.containsOnly(null, *) = false
+ * StringUtil.containsOnly(*, null) = false
+ * StringUtil.containsOnly("", *) = true
+ * StringUtil.containsOnly("ab", '') = false
+ * StringUtil.containsOnly("abab", 'abc') = true
+ * StringUtil.containsOnly("ab1", 'abc') = false
+ * StringUtil.containsOnly("abz", 'abc') = false
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param valid an array of valid chars, may be null
+ * @return true if it only contains valid chars and is non-null
+ */
+ public static boolean containsOnly(String str, char[] valid) {
+ // All these pre-checks are to maintain API with an older version
+ if ((valid == null) || (str == null)) {
+ return false;
+ }
+ if (str.length() == 0) {
+ return true;
+ }
+ if (valid.length == 0) {
+ return false;
+ }
+ return indexOfAnyBut(str, valid) == -1;
+ }
+
+ /**
+ * <p>Checks if the String contains only certain characters.</p>
+ *
+ * <p>A <code>null</code> String will return <code>false</code>.
+ * A <code>null</code> valid character String will return <code>false</code>.
+ * An empty String ("") always returns <code>true</code>.</p>
+ *
+ * <pre>
+ * StringUtil.containsOnly(null, *) = false
+ * StringUtil.containsOnly(*, null) = false
+ * StringUtil.containsOnly("", *) = true
+ * StringUtil.containsOnly("ab", "") = false
+ * StringUtil.containsOnly("abab", "abc") = true
+ * StringUtil.containsOnly("ab1", "abc") = false
+ * StringUtil.containsOnly("abz", "abc") = false
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param validChars a String of valid chars, may be null
+ * @return true if it only contains valid chars and is non-null
+ * @since 2.0
+ */
+ public static boolean containsOnly(String str, String validChars) {
+ if (str == null || validChars == null) {
+ return false;
+ }
+ return containsOnly(str, validChars.toCharArray());
+ }
+
+ // ContainsNone
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Checks that the String does not contain certain characters.</p>
+ *
+ * <p>A <code>null</code> String will return <code>true</code>.
+ * A <code>null</code> invalid character array will return <code>true</code>.
+ * An empty String ("") always returns true.</p>
+ *
+ * <pre>
+ * StringUtil.containsNone(null, *) = true
+ * StringUtil.containsNone(*, null) = true
+ * StringUtil.containsNone("", *) = true
+ * StringUtil.containsNone("ab", '') = true
+ * StringUtil.containsNone("abab", 'xyz') = true
+ * StringUtil.containsNone("ab1", 'xyz') = true
+ * StringUtil.containsNone("abz", 'xyz') = false
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param invalidChars an array of invalid chars, may be null
+ * @return true if it contains none of the invalid chars, or is null
+ * @since 2.0
+ */
+ public static boolean containsNone(String str, char[] invalidChars) {
+ if (str == null || invalidChars == null) {
+ return true;
+ }
+ int strSize = str.length();
+ int validSize = invalidChars.length;
+ for (int i = 0; i < strSize; i++) {
+ char ch = str.charAt(i);
+ for (int j = 0; j < validSize; j++) {
+ if (invalidChars[j] == ch) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * <p>Checks that the String does not contain certain characters.</p>
+ *
+ * <p>A <code>null</code> String will return <code>true</code>.
+ * A <code>null</code> invalid character array will return <code>true</code>.
+ * An empty String ("") always returns true.</p>
+ *
+ * <pre>
+ * StringUtil.containsNone(null, *) = true
+ * StringUtil.containsNone(*, null) = true
+ * StringUtil.containsNone("", *) = true
+ * StringUtil.containsNone("ab", "") = true
+ * StringUtil.containsNone("abab", "xyz") = true
+ * StringUtil.containsNone("ab1", "xyz") = true
+ * StringUtil.containsNone("abz", "xyz") = false
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param invalidChars a String of invalid chars, may be null
+ * @return true if it contains none of the invalid chars, or is null
+ * @since 2.0
+ */
+ public static boolean containsNone(String str, String invalidChars) {
+ if (str == null || invalidChars == null) {
+ return true;
+ }
+ return containsNone(str, invalidChars.toCharArray());
+ }
+
+ // IndexOfAny strings
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Find the first index of any of a set of potential substrings.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.
+ * A <code>null</code> or zero length search array will return <code>-1</code>.
+ * A <code>null</code> search array entry will be ignored, but a search
+ * array containing "" will return <code>0</code> if <code>str</code> is not
+ * null. This method uses {@link String#indexOf(String)}.</p>
+ *
+ * <pre>
+ * StringUtil.indexOfAny(null, *) = -1
+ * StringUtil.indexOfAny(*, null) = -1
+ * StringUtil.indexOfAny(*, []) = -1
+ * StringUtil.indexOfAny("zzabyycdxx", ["ab","cd"]) = 2
+ * StringUtil.indexOfAny("zzabyycdxx", ["cd","ab"]) = 2
+ * StringUtil.indexOfAny("zzabyycdxx", ["mn","op"]) = -1
+ * StringUtil.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1
+ * StringUtil.indexOfAny("zzabyycdxx", [""]) = 0
+ * StringUtil.indexOfAny("", [""]) = 0
+ * StringUtil.indexOfAny("", ["a"]) = -1
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchStrs the Strings to search for, may be null
+ * @return the first index of any of the searchStrs in str, -1 if no match
+ */
+ public static int indexOfAny(String str, String[] searchStrs) {
+ if ((str == null) || (searchStrs == null)) {
+ return -1;
+ }
+ int sz = searchStrs.length;
+
+ // String's can't have a MAX_VALUEth index.
+ int ret = Integer.MAX_VALUE;
+
+ int tmp = 0;
+ for (int i = 0; i < sz; i++) {
+ String search = searchStrs[i];
+ if (search == null) {
+ continue;
+ }
+ tmp = str.indexOf(search);
+ if (tmp == -1) {
+ continue;
+ }
+
+ if (tmp < ret) {
+ ret = tmp;
+ }
+ }
+
+ return (ret == Integer.MAX_VALUE) ? -1 : ret;
+ }
+
+ /**
+ * <p>Find the latest index of any of a set of potential substrings.</p>
+ *
+ * <p>A <code>null</code> String will return <code>-1</code>.
+ * A <code>null</code> search array will return <code>-1</code>.
+ * A <code>null</code> or zero length search array entry will be ignored,
+ * but a search array containing "" will return the length of <code>str</code>
+ * if <code>str</code> is not null. This method uses {@link String#indexOf(String)}</p>
+ *
+ * <pre>
+ * StringUtil.lastIndexOfAny(null, *) = -1
+ * StringUtil.lastIndexOfAny(*, null) = -1
+ * StringUtil.lastIndexOfAny(*, []) = -1
+ * StringUtil.lastIndexOfAny(*, [null]) = -1
+ * StringUtil.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6
+ * StringUtil.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6
+ * StringUtil.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
+ * StringUtil.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
+ * StringUtil.lastIndexOfAny("zzabyycdxx", ["mn",""]) = 10
+ * </pre>
+ *
+ * @param str the String to check, may be null
+ * @param searchStrs the Strings to search for, may be null
+ * @return the last index of any of the Strings, -1 if no match
+ */
+ public static int lastIndexOfAny(String str, String[] searchStrs) {
+ if ((str == null) || (searchStrs == null)) {
+ return -1;
+ }
+ int sz = searchStrs.length;
+ int ret = -1;
+ int tmp = 0;
+ for (int i = 0; i < sz; i++) {
+ String search = searchStrs[i];
+ if (search == null) {
+ continue;
+ }
+ tmp = str.lastIndexOf(search);
+ if (tmp > ret) {
+ ret = tmp;
+ }
+ }
+ return ret;
+ }
+
+ // Substring
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets a substring from the specified String avoiding exceptions.</p>
+ *
+ * <p>A negative start position can be used to start <code>n</code>
+ * characters from the end of the String.</p>
+ *
+ * <p>A <code>null</code> String will return <code>null</code>.
+ * An empty ("") String will return "".</p>
+ *
+ * <pre>
+ * StringUtil.substring(null, *) = null
+ * StringUtil.substring("", *) = ""
+ * StringUtil.substring("abc", 0) = "abc"
+ * StringUtil.substring("abc", 2) = "c"
+ * StringUtil.substring("abc", 4) = ""
+ * StringUtil.substring("abc", -2) = "bc"
+ * StringUtil.substring("abc", -4) = "abc"
+ * </pre>
+ *
+ * @param str the String to get the substring from, may be null
+ * @param start the position to start from, negative means
+ * count back from the end of the String by this many characters
+ * @return substring from start position, <code>null</code> if null String input
+ */
+ public static String substring(String str, int start) {
+ if (str == null) {
+ return null;
+ }
+
+ // handle negatives, which means last n characters
+ if (start < 0) {
+ start = str.length() + start; // remember start is negative
+ }
+
+ if (start < 0) {
+ start = 0;
+ }
+ if (start > str.length()) {
+ return EMPTY;
+ }
+
+ return str.substring(start);
+ }
+
+ /**
+ * <p>Gets a substring from the specified String avoiding exceptions.</p>
+ *
+ * <p>A negative start position can be used to start/end <code>n</code>
+ * characters from the end of the String.</p>
+ *
+ * <p>The returned substring starts with the character in the <code>start</code>
+ * position and ends before the <code>end</code> position. All position counting is
+ * zero-based -- i.e., to start at the beginning of the string use
+ * <code>start = 0</code>. Negative start and end positions can be used to
+ * specify offsets relative to the end of the String.</p>
+ *
+ * <p>If <code>start</code> is not strictly to the left of <code>end</code>, ""
+ * is returned.</p>
+ *
+ * <pre>
+ * StringUtil.substring(null, *, *) = null
+ * StringUtil.substring("", * , *) = "";
+ * StringUtil.substring("abc", 0, 2) = "ab"
+ * StringUtil.substring("abc", 2, 0) = ""
+ * StringUtil.substring("abc", 2, 4) = "c"
+ * StringUtil.substring("abc", 4, 6) = ""
+ * StringUtil.substring("abc", 2, 2) = ""
+ * StringUtil.substring("abc", -2, -1) = "b"
+ * StringUtil.substring("abc", -4, 2) = "ab"
+ * </pre>
+ *
+ * @param str the String to get the substring from, may be null
+ * @param start the position to start from, negative means
+ * count back from the end of the String by this many characters
+ * @param end the position to end at (exclusive), negative means
+ * count back from the end of the String by this many characters
+ * @return substring from start position to end positon,
+ * <code>null</code> if null String input
+ */
+ public static String substring(String str, int start, int end) {
+ if (str == null) {
+ return null;
+ }
+
+ // handle negatives
+ if (end < 0) {
+ end = str.length() + end; // remember end is negative
+ }
+ if (start < 0) {
+ start = str.length() + start; // remember start is negative
+ }
+
+ // check length next
+ if (end > str.length()) {
+ end = str.length();
+ }
+
+ // if start is greater than end, return ""
+ if (start > end) {
+ return EMPTY;
+ }
+
+ if (start < 0) {
+ start = 0;
+ }
+ if (end < 0) {
+ end = 0;
+ }
+
+ return str.substring(start, end);
+ }
+
+ // Left/Right/Mid
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets the leftmost <code>len</code> characters of a String.</p>
+ *
+ * <p>If <code>len</code> characters are not available, or the
+ * String is <code>null</code>, the String will be returned without
+ * an exception. An exception is thrown if len is negative.</p>
+ *
+ * <pre>
+ * StringUtil.left(null, *) = null
+ * StringUtil.left(*, -ve) = ""
+ * StringUtil.left("", *) = ""
+ * StringUtil.left("abc", 0) = ""
+ * StringUtil.left("abc", 2) = "ab"
+ * StringUtil.left("abc", 4) = "abc"
+ * </pre>
+ *
+ * @param str the String to get the leftmost characters from, may be null
+ * @param len the length of the required String, must be zero or positive
+ * @return the leftmost characters, <code>null</code> if null String input
+ */
+ public static String left(String str, int len) {
+ if (str == null) {
+ return null;
+ }
+ if (len < 0) {
+ return EMPTY;
+ }
+ if (str.length() <= len) {
+ return str;
+ }
+ return str.substring(0, len);
+ }
+
+ /**
+ * <p>Gets the rightmost <code>len</code> characters of a String.</p>
+ *
+ * <p>If <code>len</code> characters are not available, or the String
+ * is <code>null</code>, the String will be returned without an
+ * an exception. An exception is thrown if len is negative.</p>
+ *
+ * <pre>
+ * StringUtil.right(null, *) = null
+ * StringUtil.right(*, -ve) = ""
+ * StringUtil.right("", *) = ""
+ * StringUtil.right("abc", 0) = ""
+ * StringUtil.right("abc", 2) = "bc"
+ * StringUtil.right("abc", 4) = "abc"
+ * </pre>
+ *
+ * @param str the String to get the rightmost characters from, may be null
+ * @param len the length of the required String, must be zero or positive
+ * @return the rightmost characters, <code>null</code> if null String input
+ */
+ public static String right(String str, int len) {
+ if (str == null) {
+ return null;
+ }
+ if (len < 0) {
+ return EMPTY;
+ }
+ if (str.length() <= len) {
+ return str;
+ }
+ return str.substring(str.length() - len);
+ }
+
+ /**
+ * <p>Gets <code>len</code> characters from the middle of a String.</p>
+ *
+ * <p>If <code>len</code> characters are not available, the remainder
+ * of the String will be returned without an exception. If the
+ * String is <code>null</code>, <code>null</code> will be returned.
+ * An exception is thrown if len is negative.</p>
+ *
+ * <pre>
+ * StringUtil.mid(null, *, *) = null
+ * StringUtil.mid(*, *, -ve) = ""
+ * StringUtil.mid("", 0, *) = ""
+ * StringUtil.mid("abc", 0, 2) = "ab"
+ * StringUtil.mid("abc", 0, 4) = "abc"
+ * StringUtil.mid("abc", 2, 4) = "c"
+ * StringUtil.mid("abc", 4, 2) = ""
+ * StringUtil.mid("abc", -2, 2) = "ab"
+ * </pre>
+ *
+ * @param str the String to get the characters from, may be null
+ * @param pos the position to start from, negative treated as zero
+ * @param len the length of the required String, must be zero or positive
+ * @return the middle characters, <code>null</code> if null String input
+ */
+ public static String mid(String str, int pos, int len) {
+ if (str == null) {
+ return null;
+ }
+ if (len < 0 || pos > str.length()) {
+ return EMPTY;
+ }
+ if (pos < 0) {
+ pos = 0;
+ }
+ if (str.length() <= (pos + len)) {
+ return str.substring(pos);
+ }
+ return str.substring(pos, pos + len);
+ }
+
+ // SubStringAfter/SubStringBefore
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets the substring before the first occurrence of a separator.
+ * The separator is not returned.</p>
+ *
+ * <p>A <code>null</code> string input will return <code>null</code>.
+ * An empty ("") string input will return the empty string.
+ * A <code>null</code> separator will return the input string.</p>
+ *
+ * <pre>
+ * StringUtil.substringBefore(null, *) = null
+ * StringUtil.substringBefore("", *) = ""
+ * StringUtil.substringBefore("abc", "a") = ""
+ * StringUtil.substringBefore("abcba", "b") = "a"
+ * StringUtil.substringBefore("abc", "c") = "ab"
+ * StringUtil.substringBefore("abc", "d") = "abc"
+ * StringUtil.substringBefore("abc", "") = ""
+ * StringUtil.substringBefore("abc", null) = "abc"
+ * </pre>
+ *
+ * @param str the String to get a substring from, may be null
+ * @param separator the String to search for, may be null
+ * @return the substring before the first occurrence of the separator,
+ * <code>null</code> if null String input
+ * @since 2.0
+ */
+ public static String substringBefore(String str, String separator) {
+ if (isEmpty(str) || separator == null) {
+ return str;
+ }
+ if (separator.length() == 0) {
+ return EMPTY;
+ }
+ int pos = str.indexOf(separator);
+ if (pos == -1) {
+ return str;
+ }
+ return str.substring(0, pos);
+ }
+
+ /**
+ * <p>Gets the substring after the first occurrence of a separator.
+ * The separator is not returned.</p>
+ *
+ * <p>A <code>null</code> string input will return <code>null</code>.
+ * An empty ("") string input will return the empty string.
+ * A <code>null</code> separator will return the empty string if the
+ * input string is not <code>null</code>.</p>
+ *
+ * <pre>
+ * StringUtil.substringAfter(null, *) = null
+ * StringUtil.substringAfter("", *) = ""
+ * StringUtil.substringAfter(*, null) = ""
+ * StringUtil.substringAfter("abc", "a") = "bc"
+ * StringUtil.substringAfter("abcba", "b") = "cba"
+ * StringUtil.substringAfter("abc", "c") = ""
+ * StringUtil.substringAfter("abc", "d") = ""
+ * StringUtil.substringAfter("abc", "") = "abc"
+ * </pre>
+ *
+ * @param str the String to get a substring from, may be null
+ * @param separator the String to search for, may be null
+ * @return the substring after the first occurrence of the separator,
+ * <code>null</code> if null String input
+ * @since 2.0
+ */
+ public static String substringAfter(String str, String separator) {
+ if (isEmpty(str)) {
+ return str;
+ }
+ if (separator == null) {
+ return EMPTY;
+ }
+ int pos = str.indexOf(separator);
+ if (pos == -1) {
+ return EMPTY;
+ }
+ return str.substring(pos + separator.length());
+ }
+
+ /**
+ * <p>Gets the substring before the last occurrence of a separator.
+ * The separator is not returned.</p>
+ *
+ * <p>A <code>null</code> string input will return <code>null</code>.
+ * An empty ("") string input will return the empty string.
+ * An empty or <code>null</code> separator will return the input string.</p>
+ *
+ * <pre>
+ * StringUtil.substringBeforeLast(null, *) = null
+ * StringUtil.substringBeforeLast("", *) = ""
+ * StringUtil.substringBeforeLast("abcba", "b") = "abc"
+ * StringUtil.substringBeforeLast("abc", "c") = "ab"
+ * StringUtil.substringBeforeLast("a", "a") = ""
+ * StringUtil.substringBeforeLast("a", "z") = "a"
+ * StringUtil.substringBeforeLast("a", null) = "a"
+ * StringUtil.substringBeforeLast("a", "") = "a"
+ * </pre>
+ *
+ * @param str the String to get a substring from, may be null
+ * @param separator the String to search for, may be null
+ * @return the substring before the last occurrence of the separator,
+ * <code>null</code> if null String input
+ * @since 2.0
+ */
+ public static String substringBeforeLast(String str, String separator) {
+ if (isEmpty(str) || isEmpty(separator)) {
+ return str;
+ }
+ int pos = str.lastIndexOf(separator);
+ if (pos == -1) {
+ return str;
+ }
+ return str.substring(0, pos);
+ }
+
+ /**
+ * <p>Gets the substring after the last occurrence of a separator.
+ * The separator is not returned.</p>
+ *
+ * <p>A <code>null</code> string input will return <code>null</code>.
+ * An empty ("") string input will return the empty string.
+ * An empty or <code>null</code> separator will return the empty string if
+ * the input string is not <code>null</code>.</p>
+ *
+ * <pre>
+ * StringUtil.substringAfterLast(null, *) = null
+ * StringUtil.substringAfterLast("", *) = ""
+ * StringUtil.substringAfterLast(*, "") = ""
+ * StringUtil.substringAfterLast(*, null) = ""
+ * StringUtil.substringAfterLast("abc", "a") = "bc"
+ * StringUtil.substringAfterLast("abcba", "b") = "a"
+ * StringUtil.substringAfterLast("abc", "c") = ""
+ * StringUtil.substringAfterLast("a", "a") = ""
+ * StringUtil.substringAfterLast("a", "z") = ""
+ * </pre>
+ *
+ * @param str the String to get a substring from, may be null
+ * @param separator the String to search for, may be null
+ * @return the substring after the last occurrence of the separator,
+ * <code>null</code> if null String input
+ * @since 2.0
+ */
+ public static String substringAfterLast(String str, String separator) {
+ if (isEmpty(str)) {
+ return str;
+ }
+ if (isEmpty(separator)) {
+ return EMPTY;
+ }
+ int pos = str.lastIndexOf(separator);
+ if (pos == -1 || pos == (str.length() - separator.length())) {
+ return EMPTY;
+ }
+ return str.substring(pos + separator.length());
+ }
+
+ // Substring between
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets the String that is nested in between two instances of the
+ * same String.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.
+ * A <code>null</code> tag returns <code>null</code>.</p>
+ *
+ * <pre>
+ * StringUtil.substringBetween(null, *) = null
+ * StringUtil.substringBetween("", "") = ""
+ * StringUtil.substringBetween("", "tag") = null
+ * StringUtil.substringBetween("tagabctag", null) = null
+ * StringUtil.substringBetween("tagabctag", "") = ""
+ * StringUtil.substringBetween("tagabctag", "tag") = "abc"
+ * </pre>
+ *
+ * @param str the String containing the substring, may be null
+ * @param tag the String before and after the substring, may be null
+ * @return the substring, <code>null</code> if no match
+ * @since 2.0
+ */
+ public static String substringBetween(String str, String tag) {
+ return substringBetween(str, tag, tag);
+ }
+
+ /**
+ * <p>Gets the String that is nested in between two Strings.
+ * Only the first match is returned.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.
+ * A <code>null</code> open/close returns <code>null</code> (no match).
+ * An empty ("") open and close returns an empty string.</p>
+ *
+ * <pre>
+ * StringUtil.substringBetween("wx[b]yz", "[", "]") = "b"
+ * StringUtil.substringBetween(null, *, *) = null
+ * StringUtil.substringBetween(*, null, *) = null
+ * StringUtil.substringBetween(*, *, null) = null
+ * StringUtil.substringBetween("", "", "") = ""
+ * StringUtil.substringBetween("", "", "]") = null
+ * StringUtil.substringBetween("", "[", "]") = null
+ * StringUtil.substringBetween("yabcz", "", "") = ""
+ * StringUtil.substringBetween("yabcz", "y", "z") = "abc"
+ * StringUtil.substringBetween("yabczyabcz", "y", "z") = "abc"
+ * </pre>
+ *
+ * @param str the String containing the substring, may be null
+ * @param open the String before the substring, may be null
+ * @param close the String after the substring, may be null
+ * @return the substring, <code>null</code> if no match
+ * @since 2.0
+ */
+ public static String substringBetween(String str, String open, String close) {
+ if (str == null || open == null || close == null) {
+ return null;
+ }
+ int start = str.indexOf(open);
+ if (start != -1) {
+ int end = str.indexOf(close, start + open.length());
+ if (end != -1) {
+ return str.substring(start + open.length(), end);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * <p>Searches a String for substrings delimited by a start and end tag,
+ * returning all matching substrings in an array.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.
+ * A <code>null</code> open/close returns <code>null</code> (no match).
+ * An empty ("") open/close returns <code>null</code> (no match).</p>
+ *
+ * <pre>
+ * StringUtil.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
+ * StringUtil.substringsBetween(null, *, *) = null
+ * StringUtil.substringsBetween(*, null, *) = null
+ * StringUtil.substringsBetween(*, *, null) = null
+ * StringUtil.substringsBetween("", "[", "]") = []
+ * </pre>
+ *
+ * @param str the String containing the substrings, null returns null, empty returns empty
+ * @param open the String identifying the start of the substring, empty returns null
+ * @param close the String identifying the end of the substring, empty returns null
+ * @return a String Array of substrings, or <code>null</code> if no match
+ * @since 2.3
+ */
+ public static String[] substringsBetween(String str, String open, String close) {
+ if (str == null || isEmpty(open) || isEmpty(close)) {
+ return null;
+ }
+ int strLen = str.length();
+ if (strLen == 0) {
+ return EMPTY_STRING_ARRAY;
+ }
+ int closeLen = close.length();
+ int openLen = open.length();
+ List list = new ArrayList();
+ int pos = 0;
+ while (pos < (strLen - closeLen)) {
+ int start = str.indexOf(open, pos);
+ if (start < 0) {
+ break;
+ }
+ start += openLen;
+ int end = str.indexOf(close, start);
+ if (end < 0) {
+ break;
+ }
+ list.add(str.substring(start, end));
+ pos = end + closeLen;
+ }
+ if (list.isEmpty()) {
+ return null;
+ }
+ return (String[]) list.toArray(new String [list.size()]);
+ }
+
+ // Nested extraction
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Gets the String that is nested in between two instances of the
+ * same String.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.
+ * A <code>null</code> tag returns <code>null</code>.</p>
+ *
+ * <pre>
+ * StringUtil.getNestedString(null, *) = null
+ * StringUtil.getNestedString("", "") = ""
+ * StringUtil.getNestedString("", "tag") = null
+ * StringUtil.getNestedString("tagabctag", null) = null
+ * StringUtil.getNestedString("tagabctag", "") = ""
+ * StringUtil.getNestedString("tagabctag", "tag") = "abc"
+ * </pre>
+ *
+ * @param str the String containing nested-string, may be null
+ * @param tag the String before and after nested-string, may be null
+ * @return the nested String, <code>null</code> if no match
+ * @deprecated Use the better named {@link #substringBetween(String, String)}.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ public static String getNestedString(String str, String tag) {
+ return substringBetween(str, tag, tag);
+ }
+
+ /**
+ * <p>Gets the String that is nested in between two Strings.
+ * Only the first match is returned.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.
+ * A <code>null</code> open/close returns <code>null</code> (no match).
+ * An empty ("") open/close returns an empty string.</p>
+ *
+ * <pre>
+ * StringUtil.getNestedString(null, *, *) = null
+ * StringUtil.getNestedString("", "", "") = ""
+ * StringUtil.getNestedString("", "", "tag") = null
+ * StringUtil.getNestedString("", "tag", "tag") = null
+ * StringUtil.getNestedString("yabcz", null, null) = null
+ * StringUtil.getNestedString("yabcz", "", "") = ""
+ * StringUtil.getNestedString("yabcz", "y", "z") = "abc"
+ * StringUtil.getNestedString("yabczyabcz", "y", "z") = "abc"
+ * </pre>
+ *
+ * @param str the String containing nested-string, may be null
+ * @param open the String before nested-string, may be null
+ * @param close the String after nested-string, may be null
+ * @return the nested String, <code>null</code> if no match
+ * @deprecated Use the better named {@link #substringBetween(String, String, String)}.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ public static String getNestedString(String str, String open, String close) {
+ return substringBetween(str, open, close);
+ }
+
+ // Splitting
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Splits the provided text into an array, using whitespace as the
+ * separator.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+ *
+ * <p>The separator is not included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ * For more control over the split use the StrTokenizer class.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.</p>
+ *
+ * <pre>
+ * StringUtil.split(null) = null
+ * StringUtil.split("") = []
+ * StringUtil.split("abc def") = ["abc", "def"]
+ * StringUtil.split("abc def") = ["abc", "def"]
+ * StringUtil.split(" abc ") = ["abc"]
+ * </pre>
+ *
+ * @param str the String to parse, may be null
+ * @return an array of parsed Strings, <code>null</code> if null String input
+ */
+ public static String[] split(String str) {
+ return split(str, null, -1);
+ }
+
+ /**
+ * <p>Splits the provided text into an array, separator specified.
+ * This is an alternative to using StringTokenizer.</p>
+ *
+ * <p>The separator is not included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ * For more control over the split use the StrTokenizer class.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.</p>
+ *
+ * <pre>
+ * StringUtil.split(null, *) = null
+ * StringUtil.split("", *) = []
+ * StringUtil.split("a.b.c", '.') = ["a", "b", "c"]
+ * StringUtil.split("a..b.c", '.') = ["a", "b", "c"]
+ * StringUtil.split("a:b:c", '.') = ["a:b:c"]
+ * StringUtil.split("a b c", ' ') = ["a", "b", "c"]
+ * </pre>
+ *
+ * @param str the String to parse, may be null
+ * @param separatorChar the character used as the delimiter
+ * @return an array of parsed Strings, <code>null</code> if null String input
+ * @since 2.0
+ */
+ public static String[] split(String str, char separatorChar) {
+ return splitWorker(str, separatorChar, false);
+ }
+
+ /**
+ * <p>Splits the provided text into an array, separators specified.
+ * This is an alternative to using StringTokenizer.</p>
+ *
+ * <p>The separator is not included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ * For more control over the split use the StrTokenizer class.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.
+ * A <code>null</code> separatorChars splits on whitespace.</p>
+ *
+ * <pre>
+ * StringUtil.split(null, *) = null
+ * StringUtil.split("", *) = []
+ * StringUtil.split("abc def", null) = ["abc", "def"]
+ * StringUtil.split("abc def", " ") = ["abc", "def"]
+ * StringUtil.split("abc def", " ") = ["abc", "def"]
+ * StringUtil.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+ * </pre>
+ *
+ * @param str the String to parse, may be null
+ * @param separatorChars the characters used as the delimiters,
+ * <code>null</code> splits on whitespace
+ * @return an array of parsed Strings, <code>null</code> if null String input
+ */
+ public static String[] split(String str, String separatorChars) {
+ return splitWorker(str, separatorChars, -1, false);
+ }
+
+ /**
+ * <p>Splits the provided text into an array with a maximum length,
+ * separators specified.</p>
+ *
+ * <p>The separator is not included in the returned String array.
+ * Adjacent separators are treated as one separator.</p>
+ *
+ * <p>A <code>null</code> input String returns <code>null</code>.
+ * A <code>null</code> separatorChars splits on whitespace.</p>
+ *
+ * <p>If more than <code>max</code> delimited substrings are found, the last
+ * returned string includes all characters after the first <code>max - 1</code>
+ * returned strings (including separator characters).</p>
+ *
+ * <pre>
+ * StringUtil.split(null, *, *) = null
+ * StringUtil.split("", *, *) = []
+ * StringUtil.split("ab de fg", null, 0) = ["ab", "cd", "ef"]
+ * StringUtil.split("ab de fg", null, 0) = ["ab", "cd", "ef"]
+ * StringUtil.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
[... 3632 lines stripped ...]