0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: package org.apache.commons.lang;
0018:
0019: import java.util.ArrayList;
0020: import java.util.Collection;
0021: import java.util.Iterator;
0022: import java.util.List;
0023:
0024: /**
0025: * <p>Operations on {@link java.lang.String} that are
0026: * <code>null</code> safe.</p>
0027: *
0028: * <ul>
0029: * <li><b>IsEmpty/IsBlank</b>
0030: * - checks if a String contains text</li>
0031: * <li><b>Trim/Strip</b>
0032: * - removes leading and trailing whitespace</li>
0033: * <li><b>Equals</b>
0034: * - compares two strings null-safe</li>
0035: * <li><b>IndexOf/LastIndexOf/Contains</b>
0036: * - null-safe index-of checks
0037: * <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>
0038: * - index-of any of a set of Strings</li>
0039: * <li><b>ContainsOnly/ContainsNone</b>
0040: * - does String contains only/none of these characters</li>
0041: * <li><b>Substring/Left/Right/Mid</b>
0042: * - null-safe substring extractions</li>
0043: * <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>
0044: * - substring extraction relative to other strings</li>
0045: * <li><b>Split/Join</b>
0046: * - splits a String into an array of substrings and vice versa</li>
0047: * <li><b>Remove/Delete</b>
0048: * - removes part of a String</li>
0049: * <li><b>Replace/Overlay</b>
0050: * - Searches a String and replaces one String with another</li>
0051: * <li><b>Chomp/Chop</b>
0052: * - removes the last part of a String</li>
0053: * <li><b>LeftPad/RightPad/Center/Repeat</b>
0054: * - pads a String</li>
0055: * <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>
0056: * - changes the case of a String</li>
0057: * <li><b>CountMatches</b>
0058: * - counts the number of occurrences of one String in another</li>
0059: * <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>
0060: * - checks the characters in a String</li>
0061: * <li><b>DefaultString</b>
0062: * - protects against a null input String</li>
0063: * <li><b>Reverse/ReverseDelimited</b>
0064: * - reverses a String</li>
0065: * <li><b>Abbreviate</b>
0066: * - abbreviates a string using ellipsis</li>
0067: * <li><b>Difference</b>
0068: * - compares two Strings and reports on their differences</li>
0069: * <li><b>LevensteinDistance</b>
0070: * - the number of changes needed to change one String into another</li>
0071: * </ul>
0072: *
0073: * <p>The <code>StringUtils</code> class defines certain words related to
0074: * String handling.</p>
0075: *
0076: * <ul>
0077: * <li>null - <code>null</code></li>
0078: * <li>empty - a zero-length string (<code>""</code>)</li>
0079: * <li>space - the space character (<code>' '</code>, char 32)</li>
0080: * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
0081: * <li>trim - the characters <= 32 as in {@link String#trim()}</li>
0082: * </ul>
0083: *
0084: * <p><code>StringUtils</code> handles <code>null</code> input Strings quietly.
0085: * That is to say that a <code>null</code> input will return <code>null</code>.
0086: * Where a <code>boolean</code> or <code>int</code> is being returned
0087: * details vary by method.</p>
0088: *
0089: * <p>A side effect of the <code>null</code> handling is that a
0090: * <code>NullPointerException</code> should be considered a bug in
0091: * <code>StringUtils</code> (except for deprecated methods).</p>
0092: *
0093: * <p>Methods in this class give sample code to explain their operation.
0094: * The symbol <code>*</code> is used to indicate any input including <code>null</code>.</p>
0095: *
0096: * @see java.lang.String
0097: * @author <a href="http://jakarta.apache.org/turbine/">Apache Jakarta Turbine</a>
0098: * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
0099: * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
0100: * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
0101: * @author <a href="mailto:ed@apache.org">Ed Korthof</a>
0102: * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
0103: * @author Stephen Colebourne
0104: * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
0105: * @author Holger Krauth
0106: * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
0107: * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
0108: * @author Arun Mammen Thomas
0109: * @author Gary Gregory
0110: * @author Phil Steitz
0111: * @author Al Chou
0112: * @author Michael Davey
0113: * @author Reuben Sivan
0114: * @author Chris Hyzer
0115: * @since 1.0
0116: * @version $Id: StringUtils.java 492377 2007-01-04 01:20:30Z scolebourne $
0117: */
0118: public class StringUtils {
0119: // Performance testing notes (JDK 1.4, Jul03, scolebourne)
0120: // Whitespace:
0121: // Character.isWhitespace() is faster than WHITESPACE.indexOf()
0122: // where WHITESPACE is a string of all whitespace characters
0123: //
0124: // Character access:
0125: // String.charAt(n) versus toCharArray(), then array[n]
0126: // String.charAt(n) is about 15% worse for a 10K string
0127: // They are about equal for a length 50 string
0128: // String.charAt(n) is about 4 times better for a length 3 string
0129: // String.charAt(n) is best bet overall
0130: //
0131: // Append:
0132: // String.concat about twice as fast as StringBuffer.append
0133: // (not sure who tested this)
0134:
0135: /**
0136: * The empty String <code>""</code>.
0137: * @since 2.0
0138: */
0139: public static final String EMPTY = "";
0140:
0141: /**
0142: * Represents a failed index search.
0143: * @since 2.1
0144: */
0145: public static final int INDEX_NOT_FOUND = -1;
0146:
0147: /**
0148: * <p>The maximum size to which the padding constant(s) can expand.</p>
0149: */
0150: private static final int PAD_LIMIT = 8192;
0151:
0152: /**
0153: * <p><code>StringUtils</code> instances should NOT be constructed in
0154: * standard programming. Instead, the class should be used as
0155: * <code>StringUtils.trim(" foo ");</code>.</p>
0156: *
0157: * <p>This constructor is public to permit tools that require a JavaBean
0158: * instance to operate.</p>
0159: */
0160: public StringUtils() {
0161: super ();
0162: }
0163:
0164: // Empty checks
0165: //-----------------------------------------------------------------------
0166: /**
0167: * <p>Checks if a String is empty ("") or null.</p>
0168: *
0169: * <pre>
0170: * StringUtils.isEmpty(null) = true
0171: * StringUtils.isEmpty("") = true
0172: * StringUtils.isEmpty(" ") = false
0173: * StringUtils.isEmpty("bob") = false
0174: * StringUtils.isEmpty(" bob ") = false
0175: * </pre>
0176: *
0177: * <p>NOTE: This method changed in Lang version 2.0.
0178: * It no longer trims the String.
0179: * That functionality is available in isBlank().</p>
0180: *
0181: * @param str the String to check, may be null
0182: * @return <code>true</code> if the String is empty or null
0183: */
0184: public static boolean isEmpty(String str) {
0185: return str == null || str.length() == 0;
0186: }
0187:
0188: /**
0189: * <p>Checks if a String is not empty ("") and not null.</p>
0190: *
0191: * <pre>
0192: * StringUtils.isNotEmpty(null) = false
0193: * StringUtils.isNotEmpty("") = false
0194: * StringUtils.isNotEmpty(" ") = true
0195: * StringUtils.isNotEmpty("bob") = true
0196: * StringUtils.isNotEmpty(" bob ") = true
0197: * </pre>
0198: *
0199: * @param str the String to check, may be null
0200: * @return <code>true</code> if the String is not empty and not null
0201: */
0202: public static boolean isNotEmpty(String str) {
0203: return !StringUtils.isEmpty(str);
0204: }
0205:
0206: /**
0207: * <p>Checks if a String is whitespace, empty ("") or null.</p>
0208: *
0209: * <pre>
0210: * StringUtils.isBlank(null) = true
0211: * StringUtils.isBlank("") = true
0212: * StringUtils.isBlank(" ") = true
0213: * StringUtils.isBlank("bob") = false
0214: * StringUtils.isBlank(" bob ") = false
0215: * </pre>
0216: *
0217: * @param str the String to check, may be null
0218: * @return <code>true</code> if the String is null, empty or whitespace
0219: * @since 2.0
0220: */
0221: public static boolean isBlank(String str) {
0222: int strLen;
0223: if (str == null || (strLen = str.length()) == 0) {
0224: return true;
0225: }
0226: for (int i = 0; i < strLen; i++) {
0227: if ((Character.isWhitespace(str.charAt(i)) == false)) {
0228: return false;
0229: }
0230: }
0231: return true;
0232: }
0233:
0234: /**
0235: * <p>Checks if a String is not empty (""), not null and not whitespace only.</p>
0236: *
0237: * <pre>
0238: * StringUtils.isNotBlank(null) = false
0239: * StringUtils.isNotBlank("") = false
0240: * StringUtils.isNotBlank(" ") = false
0241: * StringUtils.isNotBlank("bob") = true
0242: * StringUtils.isNotBlank(" bob ") = true
0243: * </pre>
0244: *
0245: * @param str the String to check, may be null
0246: * @return <code>true</code> if the String is
0247: * not empty and not null and not whitespace
0248: * @since 2.0
0249: */
0250: public static boolean isNotBlank(String str) {
0251: return !StringUtils.isBlank(str);
0252: }
0253:
0254: // Trim
0255: //-----------------------------------------------------------------------
0256: /**
0257: * <p>Removes control characters (char <= 32) from both
0258: * ends of this String, handling <code>null</code> by returning
0259: * an empty String ("").</p>
0260: *
0261: * <pre>
0262: * StringUtils.clean(null) = ""
0263: * StringUtils.clean("") = ""
0264: * StringUtils.clean("abc") = "abc"
0265: * StringUtils.clean(" abc ") = "abc"
0266: * StringUtils.clean(" ") = ""
0267: * </pre>
0268: *
0269: * @see java.lang.String#trim()
0270: * @param str the String to clean, may be null
0271: * @return the trimmed text, never <code>null</code>
0272: * @deprecated Use the clearer named {@link #trimToEmpty(String)}.
0273: * Method will be removed in Commons Lang 3.0.
0274: */
0275: public static String clean(String str) {
0276: return str == null ? EMPTY : str.trim();
0277: }
0278:
0279: /**
0280: * <p>Removes control characters (char <= 32) from both
0281: * ends of this String, handling <code>null</code> by returning
0282: * <code>null</code>.</p>
0283: *
0284: * <p>The String is trimmed using {@link String#trim()}.
0285: * Trim removes start and end characters <= 32.
0286: * To strip whitespace use {@link #strip(String)}.</p>
0287: *
0288: * <p>To trim your choice of characters, use the
0289: * {@link #strip(String, String)} methods.</p>
0290: *
0291: * <pre>
0292: * StringUtils.trim(null) = null
0293: * StringUtils.trim("") = ""
0294: * StringUtils.trim(" ") = ""
0295: * StringUtils.trim("abc") = "abc"
0296: * StringUtils.trim(" abc ") = "abc"
0297: * </pre>
0298: *
0299: * @param str the String to be trimmed, may be null
0300: * @return the trimmed string, <code>null</code> if null String input
0301: */
0302: public static String trim(String str) {
0303: return str == null ? null : str.trim();
0304: }
0305:
0306: /**
0307: * <p>Removes control characters (char <= 32) from both
0308: * ends of this String returning <code>null</code> if the String is
0309: * empty ("") after the trim or if it is <code>null</code>.
0310: *
0311: * <p>The String is trimmed using {@link String#trim()}.
0312: * Trim removes start and end characters <= 32.
0313: * To strip whitespace use {@link #stripToNull(String)}.</p>
0314: *
0315: * <pre>
0316: * StringUtils.trimToNull(null) = null
0317: * StringUtils.trimToNull("") = null
0318: * StringUtils.trimToNull(" ") = null
0319: * StringUtils.trimToNull("abc") = "abc"
0320: * StringUtils.trimToNull(" abc ") = "abc"
0321: * </pre>
0322: *
0323: * @param str the String to be trimmed, may be null
0324: * @return the trimmed String,
0325: * <code>null</code> if only chars <= 32, empty or null String input
0326: * @since 2.0
0327: */
0328: public static String trimToNull(String str) {
0329: String ts = trim(str);
0330: return isEmpty(ts) ? null : ts;
0331: }
0332:
0333: /**
0334: * <p>Removes control characters (char <= 32) from both
0335: * ends of this String returning an empty String ("") if the String
0336: * is empty ("") after the trim or if it is <code>null</code>.
0337: *
0338: * <p>The String is trimmed using {@link String#trim()}.
0339: * Trim removes start and end characters <= 32.
0340: * To strip whitespace use {@link #stripToEmpty(String)}.</p>
0341: *
0342: * <pre>
0343: * StringUtils.trimToEmpty(null) = ""
0344: * StringUtils.trimToEmpty("") = ""
0345: * StringUtils.trimToEmpty(" ") = ""
0346: * StringUtils.trimToEmpty("abc") = "abc"
0347: * StringUtils.trimToEmpty(" abc ") = "abc"
0348: * </pre>
0349: *
0350: * @param str the String to be trimmed, may be null
0351: * @return the trimmed String, or an empty String if <code>null</code> input
0352: * @since 2.0
0353: */
0354: public static String trimToEmpty(String str) {
0355: return str == null ? EMPTY : str.trim();
0356: }
0357:
0358: // Stripping
0359: //-----------------------------------------------------------------------
0360: /**
0361: * <p>Strips whitespace from the start and end of a String.</p>
0362: *
0363: * <p>This is similar to {@link #trim(String)} but removes whitespace.
0364: * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
0365: *
0366: * <p>A <code>null</code> input String returns <code>null</code>.</p>
0367: *
0368: * <pre>
0369: * StringUtils.strip(null) = null
0370: * StringUtils.strip("") = ""
0371: * StringUtils.strip(" ") = ""
0372: * StringUtils.strip("abc") = "abc"
0373: * StringUtils.strip(" abc") = "abc"
0374: * StringUtils.strip("abc ") = "abc"
0375: * StringUtils.strip(" abc ") = "abc"
0376: * StringUtils.strip(" ab c ") = "ab c"
0377: * </pre>
0378: *
0379: * @param str the String to remove whitespace from, may be null
0380: * @return the stripped String, <code>null</code> if null String input
0381: */
0382: public static String strip(String str) {
0383: return strip(str, null);
0384: }
0385:
0386: /**
0387: * <p>Strips whitespace from the start and end of a String returning
0388: * <code>null</code> if the String is empty ("") after the strip.</p>
0389: *
0390: * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.
0391: * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
0392: *
0393: * <pre>
0394: * StringUtils.stripToNull(null) = null
0395: * StringUtils.stripToNull("") = null
0396: * StringUtils.stripToNull(" ") = null
0397: * StringUtils.stripToNull("abc") = "abc"
0398: * StringUtils.stripToNull(" abc") = "abc"
0399: * StringUtils.stripToNull("abc ") = "abc"
0400: * StringUtils.stripToNull(" abc ") = "abc"
0401: * StringUtils.stripToNull(" ab c ") = "ab c"
0402: * </pre>
0403: *
0404: * @param str the String to be stripped, may be null
0405: * @return the stripped String,
0406: * <code>null</code> if whitespace, empty or null String input
0407: * @since 2.0
0408: */
0409: public static String stripToNull(String str) {
0410: if (str == null) {
0411: return null;
0412: }
0413: str = strip(str, null);
0414: return str.length() == 0 ? null : str;
0415: }
0416:
0417: /**
0418: * <p>Strips whitespace from the start and end of a String returning
0419: * an empty String if <code>null</code> input.</p>
0420: *
0421: * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.
0422: * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
0423: *
0424: * <pre>
0425: * StringUtils.stripToEmpty(null) = ""
0426: * StringUtils.stripToEmpty("") = ""
0427: * StringUtils.stripToEmpty(" ") = ""
0428: * StringUtils.stripToEmpty("abc") = "abc"
0429: * StringUtils.stripToEmpty(" abc") = "abc"
0430: * StringUtils.stripToEmpty("abc ") = "abc"
0431: * StringUtils.stripToEmpty(" abc ") = "abc"
0432: * StringUtils.stripToEmpty(" ab c ") = "ab c"
0433: * </pre>
0434: *
0435: * @param str the String to be stripped, may be null
0436: * @return the trimmed String, or an empty String if <code>null</code> input
0437: * @since 2.0
0438: */
0439: public static String stripToEmpty(String str) {
0440: return str == null ? EMPTY : strip(str, null);
0441: }
0442:
0443: /**
0444: * <p>Strips any of a set of characters from the start and end of a String.
0445: * This is similar to {@link String#trim()} but allows the characters
0446: * to be stripped to be controlled.</p>
0447: *
0448: * <p>A <code>null</code> input String returns <code>null</code>.
0449: * An empty string ("") input returns the empty string.</p>
0450: *
0451: * <p>If the stripChars String is <code>null</code>, whitespace is
0452: * stripped as defined by {@link Character#isWhitespace(char)}.
0453: * Alternatively use {@link #strip(String)}.</p>
0454: *
0455: * <pre>
0456: * StringUtils.strip(null, *) = null
0457: * StringUtils.strip("", *) = ""
0458: * StringUtils.strip("abc", null) = "abc"
0459: * StringUtils.strip(" abc", null) = "abc"
0460: * StringUtils.strip("abc ", null) = "abc"
0461: * StringUtils.strip(" abc ", null) = "abc"
0462: * StringUtils.strip(" abcyx", "xyz") = " abc"
0463: * </pre>
0464: *
0465: * @param str the String to remove characters from, may be null
0466: * @param stripChars the characters to remove, null treated as whitespace
0467: * @return the stripped String, <code>null</code> if null String input
0468: */
0469: public static String strip(String str, String stripChars) {
0470: if (isEmpty(str)) {
0471: return str;
0472: }
0473: str = stripStart(str, stripChars);
0474: return stripEnd(str, stripChars);
0475: }
0476:
0477: /**
0478: * <p>Strips any of a set of characters from the start of a String.</p>
0479: *
0480: * <p>A <code>null</code> input String returns <code>null</code>.
0481: * An empty string ("") input returns the empty string.</p>
0482: *
0483: * <p>If the stripChars String is <code>null</code>, whitespace is
0484: * stripped as defined by {@link Character#isWhitespace(char)}.</p>
0485: *
0486: * <pre>
0487: * StringUtils.stripStart(null, *) = null
0488: * StringUtils.stripStart("", *) = ""
0489: * StringUtils.stripStart("abc", "") = "abc"
0490: * StringUtils.stripStart("abc", null) = "abc"
0491: * StringUtils.stripStart(" abc", null) = "abc"
0492: * StringUtils.stripStart("abc ", null) = "abc "
0493: * StringUtils.stripStart(" abc ", null) = "abc "
0494: * StringUtils.stripStart("yxabc ", "xyz") = "abc "
0495: * </pre>
0496: *
0497: * @param str the String to remove characters from, may be null
0498: * @param stripChars the characters to remove, null treated as whitespace
0499: * @return the stripped String, <code>null</code> if null String input
0500: */
0501: public static String stripStart(String str, String stripChars) {
0502: int strLen;
0503: if (str == null || (strLen = str.length()) == 0) {
0504: return str;
0505: }
0506: int start = 0;
0507: if (stripChars == null) {
0508: while ((start != strLen)
0509: && Character.isWhitespace(str.charAt(start))) {
0510: start++;
0511: }
0512: } else if (stripChars.length() == 0) {
0513: return str;
0514: } else {
0515: while ((start != strLen)
0516: && (stripChars.indexOf(str.charAt(start)) != -1)) {
0517: start++;
0518: }
0519: }
0520: return str.substring(start);
0521: }
0522:
0523: /**
0524: * <p>Strips any of a set of characters from the end of a String.</p>
0525: *
0526: * <p>A <code>null</code> input String returns <code>null</code>.
0527: * An empty string ("") input returns the empty string.</p>
0528: *
0529: * <p>If the stripChars String is <code>null</code>, whitespace is
0530: * stripped as defined by {@link Character#isWhitespace(char)}.</p>
0531: *
0532: * <pre>
0533: * StringUtils.stripEnd(null, *) = null
0534: * StringUtils.stripEnd("", *) = ""
0535: * StringUtils.stripEnd("abc", "") = "abc"
0536: * StringUtils.stripEnd("abc", null) = "abc"
0537: * StringUtils.stripEnd(" abc", null) = " abc"
0538: * StringUtils.stripEnd("abc ", null) = "abc"
0539: * StringUtils.stripEnd(" abc ", null) = " abc"
0540: * StringUtils.stripEnd(" abcyx", "xyz") = " abc"
0541: * </pre>
0542: *
0543: * @param str the String to remove characters from, may be null
0544: * @param stripChars the characters to remove, null treated as whitespace
0545: * @return the stripped String, <code>null</code> if null String input
0546: */
0547: public static String stripEnd(String str, String stripChars) {
0548: int end;
0549: if (str == null || (end = str.length()) == 0) {
0550: return str;
0551: }
0552:
0553: if (stripChars == null) {
0554: while ((end != 0)
0555: && Character.isWhitespace(str.charAt(end - 1))) {
0556: end--;
0557: }
0558: } else if (stripChars.length() == 0) {
0559: return str;
0560: } else {
0561: while ((end != 0)
0562: && (stripChars.indexOf(str.charAt(end - 1)) != -1)) {
0563: end--;
0564: }
0565: }
0566: return str.substring(0, end);
0567: }
0568:
0569: // StripAll
0570: //-----------------------------------------------------------------------
0571: /**
0572: * <p>Strips whitespace from the start and end of every String in an array.
0573: * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
0574: *
0575: * <p>A new array is returned each time, except for length zero.
0576: * A <code>null</code> array will return <code>null</code>.
0577: * An empty array will return itself.
0578: * A <code>null</code> array entry will be ignored.</p>
0579: *
0580: * <pre>
0581: * StringUtils.stripAll(null) = null
0582: * StringUtils.stripAll([]) = []
0583: * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"]
0584: * StringUtils.stripAll(["abc ", null]) = ["abc", null]
0585: * </pre>
0586: *
0587: * @param strs the array to remove whitespace from, may be null
0588: * @return the stripped Strings, <code>null</code> if null array input
0589: */
0590: public static String[] stripAll(String[] strs) {
0591: return stripAll(strs, null);
0592: }
0593:
0594: /**
0595: * <p>Strips any of a set of characters from the start and end of every
0596: * String in an array.</p>
0597: * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
0598: *
0599: * <p>A new array is returned each time, except for length zero.
0600: * A <code>null</code> array will return <code>null</code>.
0601: * An empty array will return itself.
0602: * A <code>null</code> array entry will be ignored.
0603: * A <code>null</code> stripChars will strip whitespace as defined by
0604: * {@link Character#isWhitespace(char)}.</p>
0605: *
0606: * <pre>
0607: * StringUtils.stripAll(null, *) = null
0608: * StringUtils.stripAll([], *) = []
0609: * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"]
0610: * StringUtils.stripAll(["abc ", null], null) = ["abc", null]
0611: * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null]
0612: * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null]
0613: * </pre>
0614: *
0615: * @param strs the array to remove characters from, may be null
0616: * @param stripChars the characters to remove, null treated as whitespace
0617: * @return the stripped Strings, <code>null</code> if null array input
0618: */
0619: public static String[] stripAll(String[] strs, String stripChars) {
0620: int strsLen;
0621: if (strs == null || (strsLen = strs.length) == 0) {
0622: return strs;
0623: }
0624: String[] newArr = new String[strsLen];
0625: for (int i = 0; i < strsLen; i++) {
0626: newArr[i] = strip(strs[i], stripChars);
0627: }
0628: return newArr;
0629: }
0630:
0631: // Equals
0632: //-----------------------------------------------------------------------
0633: /**
0634: * <p>Compares two Strings, returning <code>true</code> if they are equal.</p>
0635: *
0636: * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
0637: * references are considered to be equal. The comparison is case sensitive.</p>
0638: *
0639: * <pre>
0640: * StringUtils.equals(null, null) = true
0641: * StringUtils.equals(null, "abc") = false
0642: * StringUtils.equals("abc", null) = false
0643: * StringUtils.equals("abc", "abc") = true
0644: * StringUtils.equals("abc", "ABC") = false
0645: * </pre>
0646: *
0647: * @see java.lang.String#equals(Object)
0648: * @param str1 the first String, may be null
0649: * @param str2 the second String, may be null
0650: * @return <code>true</code> if the Strings are equal, case sensitive, or
0651: * both <code>null</code>
0652: */
0653: public static boolean equals(String str1, String str2) {
0654: return str1 == null ? str2 == null : str1.equals(str2);
0655: }
0656:
0657: /**
0658: * <p>Compares two Strings, returning <code>true</code> if they are equal ignoring
0659: * the case.</p>
0660: *
0661: * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
0662: * references are considered equal. Comparison is case insensitive.</p>
0663: *
0664: * <pre>
0665: * StringUtils.equalsIgnoreCase(null, null) = true
0666: * StringUtils.equalsIgnoreCase(null, "abc") = false
0667: * StringUtils.equalsIgnoreCase("abc", null) = false
0668: * StringUtils.equalsIgnoreCase("abc", "abc") = true
0669: * StringUtils.equalsIgnoreCase("abc", "ABC") = true
0670: * </pre>
0671: *
0672: * @see java.lang.String#equalsIgnoreCase(String)
0673: * @param str1 the first String, may be null
0674: * @param str2 the second String, may be null
0675: * @return <code>true</code> if the Strings are equal, case insensitive, or
0676: * both <code>null</code>
0677: */
0678: public static boolean equalsIgnoreCase(String str1, String str2) {
0679: return str1 == null ? str2 == null : str1
0680: .equalsIgnoreCase(str2);
0681: }
0682:
0683: // IndexOf
0684: //-----------------------------------------------------------------------
0685: /**
0686: * <p>Finds the first index within a String, handling <code>null</code>.
0687: * This method uses {@link String#indexOf(int)}.</p>
0688: *
0689: * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.</p>
0690: *
0691: * <pre>
0692: * StringUtils.indexOf(null, *) = -1
0693: * StringUtils.indexOf("", *) = -1
0694: * StringUtils.indexOf("aabaabaa", 'a') = 0
0695: * StringUtils.indexOf("aabaabaa", 'b') = 2
0696: * </pre>
0697: *
0698: * @param str the String to check, may be null
0699: * @param searchChar the character to find
0700: * @return the first index of the search character,
0701: * -1 if no match or <code>null</code> string input
0702: * @since 2.0
0703: */
0704: public static int indexOf(String str, char searchChar) {
0705: if (isEmpty(str)) {
0706: return -1;
0707: }
0708: return str.indexOf(searchChar);
0709: }
0710:
0711: /**
0712: * <p>Finds the first index within a String from a start position,
0713: * handling <code>null</code>.
0714: * This method uses {@link String#indexOf(int, int)}.</p>
0715: *
0716: * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.
0717: * A negative start position is treated as zero.
0718: * A start position greater than the string length returns <code>-1</code>.</p>
0719: *
0720: * <pre>
0721: * StringUtils.indexOf(null, *, *) = -1
0722: * StringUtils.indexOf("", *, *) = -1
0723: * StringUtils.indexOf("aabaabaa", 'b', 0) = 2
0724: * StringUtils.indexOf("aabaabaa", 'b', 3) = 5
0725: * StringUtils.indexOf("aabaabaa", 'b', 9) = -1
0726: * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
0727: * </pre>
0728: *
0729: * @param str the String to check, may be null
0730: * @param searchChar the character to find
0731: * @param startPos the start position, negative treated as zero
0732: * @return the first index of the search character,
0733: * -1 if no match or <code>null</code> string input
0734: * @since 2.0
0735: */
0736: public static int indexOf(String str, char searchChar, int startPos) {
0737: if (isEmpty(str)) {
0738: return -1;
0739: }
0740: return str.indexOf(searchChar, startPos);
0741: }
0742:
0743: /**
0744: * <p>Finds the first index within a String, handling <code>null</code>.
0745: * This method uses {@link String#indexOf(String)}.</p>
0746: *
0747: * <p>A <code>null</code> String will return <code>-1</code>.</p>
0748: *
0749: * <pre>
0750: * StringUtils.indexOf(null, *) = -1
0751: * StringUtils.indexOf(*, null) = -1
0752: * StringUtils.indexOf("", "") = 0
0753: * StringUtils.indexOf("aabaabaa", "a") = 0
0754: * StringUtils.indexOf("aabaabaa", "b") = 2
0755: * StringUtils.indexOf("aabaabaa", "ab") = 1
0756: * StringUtils.indexOf("aabaabaa", "") = 0
0757: * </pre>
0758: *
0759: * @param str the String to check, may be null
0760: * @param searchStr the String to find, may be null
0761: * @return the first index of the search String,
0762: * -1 if no match or <code>null</code> string input
0763: * @since 2.0
0764: */
0765: public static int indexOf(String str, String searchStr) {
0766: if (str == null || searchStr == null) {
0767: return -1;
0768: }
0769: return str.indexOf(searchStr);
0770: }
0771:
0772: /**
0773: * <p>Finds the n-th index within a String, handling <code>null</code>.
0774: * This method uses {@link String#indexOf(String)}.</p>
0775: *
0776: * <p>A <code>null</code> String will return <code>-1</code>.</p>
0777: *
0778: * <pre>
0779: * StringUtils.ordinalIndexOf(null, *, *) = -1
0780: * StringUtils.ordinalIndexOf(*, null, *) = -1
0781: * StringUtils.ordinalIndexOf("", "", *) = 0
0782: * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0
0783: * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1
0784: * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2
0785: * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5
0786: * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
0787: * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
0788: * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0
0789: * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0
0790: * </pre>
0791: *
0792: * @param str the String to check, may be null
0793: * @param searchStr the String to find, may be null
0794: * @param ordinal the n-th <code>searchStr</code> to find
0795: * @return the n-th index of the search String,
0796: * <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
0797: * @since 2.1
0798: */
0799: public static int ordinalIndexOf(String str, String searchStr,
0800: int ordinal) {
0801: if (str == null || searchStr == null || ordinal <= 0) {
0802: return INDEX_NOT_FOUND;
0803: }
0804: if (searchStr.length() == 0) {
0805: return 0;
0806: }
0807: int found = 0;
0808: int index = INDEX_NOT_FOUND;
0809: do {
0810: index = str.indexOf(searchStr, index + 1);
0811: if (index < 0) {
0812: return index;
0813: }
0814: found++;
0815: } while (found < ordinal);
0816: return index;
0817: }
0818:
0819: /**
0820: * <p>Finds the first index within a String, handling <code>null</code>.
0821: * This method uses {@link String#indexOf(String, int)}.</p>
0822: *
0823: * <p>A <code>null</code> String will return <code>-1</code>.
0824: * A negative start position is treated as zero.
0825: * An empty ("") search String always matches.
0826: * A start position greater than the string length only matches
0827: * an empty search String.</p>
0828: *
0829: * <pre>
0830: * StringUtils.indexOf(null, *, *) = -1
0831: * StringUtils.indexOf(*, null, *) = -1
0832: * StringUtils.indexOf("", "", 0) = 0
0833: * StringUtils.indexOf("aabaabaa", "a", 0) = 0
0834: * StringUtils.indexOf("aabaabaa", "b", 0) = 2
0835: * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
0836: * StringUtils.indexOf("aabaabaa", "b", 3) = 5
0837: * StringUtils.indexOf("aabaabaa", "b", 9) = -1
0838: * StringUtils.indexOf("aabaabaa", "b", -1) = 2
0839: * StringUtils.indexOf("aabaabaa", "", 2) = 2
0840: * StringUtils.indexOf("abc", "", 9) = 3
0841: * </pre>
0842: *
0843: * @param str the String to check, may be null
0844: * @param searchStr the String to find, may be null
0845: * @param startPos the start position, negative treated as zero
0846: * @return the first index of the search String,
0847: * -1 if no match or <code>null</code> string input
0848: * @since 2.0
0849: */
0850: public static int indexOf(String str, String searchStr, int startPos) {
0851: if (str == null || searchStr == null) {
0852: return -1;
0853: }
0854: // JDK1.2/JDK1.3 have a bug, when startPos > str.length for "", hence
0855: if (searchStr.length() == 0 && startPos >= str.length()) {
0856: return str.length();
0857: }
0858: return str.indexOf(searchStr, startPos);
0859: }
0860:
0861: // LastIndexOf
0862: //-----------------------------------------------------------------------
0863: /**
0864: * <p>Finds the last index within a String, handling <code>null</code>.
0865: * This method uses {@link String#lastIndexOf(int)}.</p>
0866: *
0867: * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.</p>
0868: *
0869: * <pre>
0870: * StringUtils.lastIndexOf(null, *) = -1
0871: * StringUtils.lastIndexOf("", *) = -1
0872: * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
0873: * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
0874: * </pre>
0875: *
0876: * @param str the String to check, may be null
0877: * @param searchChar the character to find
0878: * @return the last index of the search character,
0879: * -1 if no match or <code>null</code> string input
0880: * @since 2.0
0881: */
0882: public static int lastIndexOf(String str, char searchChar) {
0883: if (isEmpty(str)) {
0884: return -1;
0885: }
0886: return str.lastIndexOf(searchChar);
0887: }
0888:
0889: /**
0890: * <p>Finds the last index within a String from a start position,
0891: * handling <code>null</code>.
0892: * This method uses {@link String#lastIndexOf(int, int)}.</p>
0893: *
0894: * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.
0895: * A negative start position returns <code>-1</code>.
0896: * A start position greater than the string length searches the whole string.</p>
0897: *
0898: * <pre>
0899: * StringUtils.lastIndexOf(null, *, *) = -1
0900: * StringUtils.lastIndexOf("", *, *) = -1
0901: * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5
0902: * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2
0903: * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1
0904: * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5
0905: * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
0906: * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0
0907: * </pre>
0908: *
0909: * @param str the String to check, may be null
0910: * @param searchChar the character to find
0911: * @param startPos the start position
0912: * @return the last index of the search character,
0913: * -1 if no match or <code>null</code> string input
0914: * @since 2.0
0915: */
0916: public static int lastIndexOf(String str, char searchChar,
0917: int startPos) {
0918: if (isEmpty(str)) {
0919: return -1;
0920: }
0921: return str.lastIndexOf(searchChar, startPos);
0922: }
0923:
0924: /**
0925: * <p>Finds the last index within a String, handling <code>null</code>.
0926: * This method uses {@link String#lastIndexOf(String)}.</p>
0927: *
0928: * <p>A <code>null</code> String will return <code>-1</code>.</p>
0929: *
0930: * <pre>
0931: * StringUtils.lastIndexOf(null, *) = -1
0932: * StringUtils.lastIndexOf(*, null) = -1
0933: * StringUtils.lastIndexOf("", "") = 0
0934: * StringUtils.lastIndexOf("aabaabaa", "a") = 0
0935: * StringUtils.lastIndexOf("aabaabaa", "b") = 2
0936: * StringUtils.lastIndexOf("aabaabaa", "ab") = 1
0937: * StringUtils.lastIndexOf("aabaabaa", "") = 8
0938: * </pre>
0939: *
0940: * @param str the String to check, may be null
0941: * @param searchStr the String to find, may be null
0942: * @return the last index of the search String,
0943: * -1 if no match or <code>null</code> string input
0944: * @since 2.0
0945: */
0946: public static int lastIndexOf(String str, String searchStr) {
0947: if (str == null || searchStr == null) {
0948: return -1;
0949: }
0950: return str.lastIndexOf(searchStr);
0951: }
0952:
0953: /**
0954: * <p>Finds the first index within a String, handling <code>null</code>.
0955: * This method uses {@link String#lastIndexOf(String, int)}.</p>
0956: *
0957: * <p>A <code>null</code> String will return <code>-1</code>.
0958: * A negative start position returns <code>-1</code>.
0959: * An empty ("") search String always matches unless the start position is negative.
0960: * A start position greater than the string length searches the whole string.</p>
0961: *
0962: * <pre>
0963: * StringUtils.lastIndexOf(null, *, *) = -1
0964: * StringUtils.lastIndexOf(*, null, *) = -1
0965: * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7
0966: * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5
0967: * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
0968: * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5
0969: * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
0970: * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0
0971: * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1
0972: * </pre>
0973: *
0974: * @param str the String to check, may be null
0975: * @param searchStr the String to find, may be null
0976: * @param startPos the start position, negative treated as zero
0977: * @return the first index of the search String,
0978: * -1 if no match or <code>null</code> string input
0979: * @since 2.0
0980: */
0981: public static int lastIndexOf(String str, String searchStr,
0982: int startPos) {
0983: if (str == null || searchStr == null) {
0984: return -1;
0985: }
0986: return str.lastIndexOf(searchStr, startPos);
0987: }
0988:
0989: // Contains
0990: //-----------------------------------------------------------------------
0991: /**
0992: * <p>Checks if String contains a search character, handling <code>null</code>.
0993: * This method uses {@link String#indexOf(int)}.</p>
0994: *
0995: * <p>A <code>null</code> or empty ("") String will return <code>false</code>.</p>
0996: *
0997: * <pre>
0998: * StringUtils.contains(null, *) = false
0999: * StringUtils.contains("", *) = false
1000: * StringUtils.contains("abc", 'a') = true
1001: * StringUtils.contains("abc", 'z') = false
1002: * </pre>
1003: *
1004: * @param str the String to check, may be null
1005: * @param searchChar the character to find
1006: * @return true if the String contains the search character,
1007: * false if not or <code>null</code> string input
1008: * @since 2.0
1009: */
1010: public static boolean contains(String str, char searchChar) {
1011: if (isEmpty(str)) {
1012: return false;
1013: }
1014: return str.indexOf(searchChar) >= 0;
1015: }
1016:
1017: /**
1018: * <p>Checks if String contains a search String, handling <code>null</code>.
1019: * This method uses {@link String#indexOf(String)}.</p>
1020: *
1021: * <p>A <code>null</code> String will return <code>false</code>.</p>
1022: *
1023: * <pre>
1024: * StringUtils.contains(null, *) = false
1025: * StringUtils.contains(*, null) = false
1026: * StringUtils.contains("", "") = true
1027: * StringUtils.contains("abc", "") = true
1028: * StringUtils.contains("abc", "a") = true
1029: * StringUtils.contains("abc", "z") = false
1030: * </pre>
1031: *
1032: * @param str the String to check, may be null
1033: * @param searchStr the String to find, may be null
1034: * @return true if the String contains the search String,
1035: * false if not or <code>null</code> string input
1036: * @since 2.0
1037: */
1038: public static boolean contains(String str, String searchStr) {
1039: if (str == null || searchStr == null) {
1040: return false;
1041: }
1042: return str.indexOf(searchStr) >= 0;
1043: }
1044:
1045: /**
1046: * <p>Checks if String contains a search String irrespective of case,
1047: * handling <code>null</code>. This method uses
1048: * {@link #contains(String, String)}.</p>
1049: *
1050: * <p>A <code>null</code> String will return <code>false</code>.</p>
1051: *
1052: * <pre>
1053: * StringUtils.contains(null, *) = false
1054: * StringUtils.contains(*, null) = false
1055: * StringUtils.contains("", "") = true
1056: * StringUtils.contains("abc", "") = true
1057: * StringUtils.contains("abc", "a") = true
1058: * StringUtils.contains("abc", "z") = false
1059: * StringUtils.contains("abc", "A") = true
1060: * StringUtils.contains("abc", "Z") = false
1061: * </pre>
1062: *
1063: * @param str the String to check, may be null
1064: * @param searchStr the String to find, may be null
1065: * @return true if the String contains the search String irrespective of
1066: * case or false if not or <code>null</code> string input
1067: */
1068: public static boolean containsIgnoreCase(String str,
1069: String searchStr) {
1070: if (str == null || searchStr == null) {
1071: return false;
1072: }
1073: return contains(str.toUpperCase(), searchStr.toUpperCase());
1074: }
1075:
1076: // IndexOfAny chars
1077: //-----------------------------------------------------------------------
1078: /**
1079: * <p>Search a String to find the first index of any
1080: * character in the given set of characters.</p>
1081: *
1082: * <p>A <code>null</code> String will return <code>-1</code>.
1083: * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
1084: *
1085: * <pre>
1086: * StringUtils.indexOfAny(null, *) = -1
1087: * StringUtils.indexOfAny("", *) = -1
1088: * StringUtils.indexOfAny(*, null) = -1
1089: * StringUtils.indexOfAny(*, []) = -1
1090: * StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0
1091: * StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3
1092: * StringUtils.indexOfAny("aba", ['z']) = -1
1093: * </pre>
1094: *
1095: * @param str the String to check, may be null
1096: * @param searchChars the chars to search for, may be null
1097: * @return the index of any of the chars, -1 if no match or null input
1098: * @since 2.0
1099: */
1100: public static int indexOfAny(String str, char[] searchChars) {
1101: if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
1102: return -1;
1103: }
1104: for (int i = 0; i < str.length(); i++) {
1105: char ch = str.charAt(i);
1106: for (int j = 0; j < searchChars.length; j++) {
1107: if (searchChars[j] == ch) {
1108: return i;
1109: }
1110: }
1111: }
1112: return -1;
1113: }
1114:
1115: /**
1116: * <p>Search a String to find the first index of any
1117: * character in the given set of characters.</p>
1118: *
1119: * <p>A <code>null</code> String will return <code>-1</code>.
1120: * A <code>null</code> search string will return <code>-1</code>.</p>
1121: *
1122: * <pre>
1123: * StringUtils.indexOfAny(null, *) = -1
1124: * StringUtils.indexOfAny("", *) = -1
1125: * StringUtils.indexOfAny(*, null) = -1
1126: * StringUtils.indexOfAny(*, "") = -1
1127: * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
1128: * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
1129: * StringUtils.indexOfAny("aba","z") = -1
1130: * </pre>
1131: *
1132: * @param str the String to check, may be null
1133: * @param searchChars the chars to search for, may be null
1134: * @return the index of any of the chars, -1 if no match or null input
1135: * @since 2.0
1136: */
1137: public static int indexOfAny(String str, String searchChars) {
1138: if (isEmpty(str) || isEmpty(searchChars)) {
1139: return -1;
1140: }
1141: return indexOfAny(str, searchChars.toCharArray());
1142: }
1143:
1144: // IndexOfAnyBut chars
1145: //-----------------------------------------------------------------------
1146: /**
1147: * <p>Search a String to find the first index of any
1148: * character not in the given set of characters.</p>
1149: *
1150: * <p>A <code>null</code> String will return <code>-1</code>.
1151: * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
1152: *
1153: * <pre>
1154: * StringUtils.indexOfAnyBut(null, *) = -1
1155: * StringUtils.indexOfAnyBut("", *) = -1
1156: * StringUtils.indexOfAnyBut(*, null) = -1
1157: * StringUtils.indexOfAnyBut(*, []) = -1
1158: * StringUtils.indexOfAnyBut("zzabyycdxx",'za') = 3
1159: * StringUtils.indexOfAnyBut("zzabyycdxx", '') = 0
1160: * StringUtils.indexOfAnyBut("aba", 'ab') = -1
1161: * </pre>
1162: *
1163: * @param str the String to check, may be null
1164: * @param searchChars the chars to search for, may be null
1165: * @return the index of any of the chars, -1 if no match or null input
1166: * @since 2.0
1167: */
1168: public static int indexOfAnyBut(String str, char[] searchChars) {
1169: if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
1170: return -1;
1171: }
1172: outer: for (int i = 0; i < str.length(); i++) {
1173: char ch = str.charAt(i);
1174: for (int j = 0; j < searchChars.length; j++) {
1175: if (searchChars[j] == ch) {
1176: continue outer;
1177: }
1178: }
1179: return i;
1180: }
1181: return -1;
1182: }
1183:
1184: /**
1185: * <p>Search a String to find the first index of any
1186: * character not in the given set of characters.</p>
1187: *
1188: * <p>A <code>null</code> String will return <code>-1</code>.
1189: * A <code>null</code> search string will return <code>-1</code>.</p>
1190: *
1191: * <pre>
1192: * StringUtils.indexOfAnyBut(null, *) = -1
1193: * StringUtils.indexOfAnyBut("", *) = -1
1194: * StringUtils.indexOfAnyBut(*, null) = -1
1195: * StringUtils.indexOfAnyBut(*, "") = -1
1196: * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
1197: * StringUtils.indexOfAnyBut("zzabyycdxx", "") = 0
1198: * StringUtils.indexOfAnyBut("aba","ab") = -1
1199: * </pre>
1200: *
1201: * @param str the String to check, may be null
1202: * @param searchChars the chars to search for, may be null
1203: * @return the index of any of the chars, -1 if no match or null input
1204: * @since 2.0
1205: */
1206: public static int indexOfAnyBut(String str, String searchChars) {
1207: if (isEmpty(str) || isEmpty(searchChars)) {
1208: return -1;
1209: }
1210: for (int i = 0; i < str.length(); i++) {
1211: if (searchChars.indexOf(str.charAt(i)) < 0) {
1212: return i;
1213: }
1214: }
1215: return -1;
1216: }
1217:
1218: // ContainsOnly
1219: //-----------------------------------------------------------------------
1220: /**
1221: * <p>Checks if the String contains only certain characters.</p>
1222: *
1223: * <p>A <code>null</code> String will return <code>false</code>.
1224: * A <code>null</code> valid character array will return <code>false</code>.
1225: * An empty String ("") always returns <code>true</code>.</p>
1226: *
1227: * <pre>
1228: * StringUtils.containsOnly(null, *) = false
1229: * StringUtils.containsOnly(*, null) = false
1230: * StringUtils.containsOnly("", *) = true
1231: * StringUtils.containsOnly("ab", '') = false
1232: * StringUtils.containsOnly("abab", 'abc') = true
1233: * StringUtils.containsOnly("ab1", 'abc') = false
1234: * StringUtils.containsOnly("abz", 'abc') = false
1235: * </pre>
1236: *
1237: * @param str the String to check, may be null
1238: * @param valid an array of valid chars, may be null
1239: * @return true if it only contains valid chars and is non-null
1240: */
1241: public static boolean containsOnly(String str, char[] valid) {
1242: // All these pre-checks are to maintain API with an older version
1243: if ((valid == null) || (str == null)) {
1244: return false;
1245: }
1246: if (str.length() == 0) {
1247: return true;
1248: }
1249: if (valid.length == 0) {
1250: return false;
1251: }
1252: return indexOfAnyBut(str, valid) == -1;
1253: }
1254:
1255: /**
1256: * <p>Checks if the String contains only certain characters.</p>
1257: *
1258: * <p>A <code>null</code> String will return <code>false</code>.
1259: * A <code>null</code> valid character String will return <code>false</code>.
1260: * An empty String ("") always returns <code>true</code>.</p>
1261: *
1262: * <pre>
1263: * StringUtils.containsOnly(null, *) = false
1264: * StringUtils.containsOnly(*, null) = false
1265: * StringUtils.containsOnly("", *) = true
1266: * StringUtils.containsOnly("ab", "") = false
1267: * StringUtils.containsOnly("abab", "abc") = true
1268: * StringUtils.containsOnly("ab1", "abc") = false
1269: * StringUtils.containsOnly("abz", "abc") = false
1270: * </pre>
1271: *
1272: * @param str the String to check, may be null
1273: * @param validChars a String of valid chars, may be null
1274: * @return true if it only contains valid chars and is non-null
1275: * @since 2.0
1276: */
1277: public static boolean containsOnly(String str, String validChars) {
1278: if (str == null || validChars == null) {
1279: return false;
1280: }
1281: return containsOnly(str, validChars.toCharArray());
1282: }
1283:
1284: // ContainsNone
1285: //-----------------------------------------------------------------------
1286: /**
1287: * <p>Checks that the String does not contain certain characters.</p>
1288: *
1289: * <p>A <code>null</code> String will return <code>true</code>.
1290: * A <code>null</code> invalid character array will return <code>true</code>.
1291: * An empty String ("") always returns true.</p>
1292: *
1293: * <pre>
1294: * StringUtils.containsNone(null, *) = true
1295: * StringUtils.containsNone(*, null) = true
1296: * StringUtils.containsNone("", *) = true
1297: * StringUtils.containsNone("ab", '') = true
1298: * StringUtils.containsNone("abab", 'xyz') = true
1299: * StringUtils.containsNone("ab1", 'xyz') = true
1300: * StringUtils.containsNone("abz", 'xyz') = false
1301: * </pre>
1302: *
1303: * @param str the String to check, may be null
1304: * @param invalidChars an array of invalid chars, may be null
1305: * @return true if it contains none of the invalid chars, or is null
1306: * @since 2.0
1307: */
1308: public static boolean containsNone(String str, char[] invalidChars) {
1309: if (str == null || invalidChars == null) {
1310: return true;
1311: }
1312: int strSize = str.length();
1313: int validSize = invalidChars.length;
1314: for (int i = 0; i < strSize; i++) {
1315: char ch = str.charAt(i);
1316: for (int j = 0; j < validSize; j++) {
1317: if (invalidChars[j] == ch) {
1318: return false;
1319: }
1320: }
1321: }
1322: return true;
1323: }
1324:
1325: /**
1326: * <p>Checks that the String does not contain certain characters.</p>
1327: *
1328: * <p>A <code>null</code> String will return <code>true</code>.
1329: * A <code>null</code> invalid character array will return <code>true</code>.
1330: * An empty String ("") always returns true.</p>
1331: *
1332: * <pre>
1333: * StringUtils.containsNone(null, *) = true
1334: * StringUtils.containsNone(*, null) = true
1335: * StringUtils.containsNone("", *) = true
1336: * StringUtils.containsNone("ab", "") = true
1337: * StringUtils.containsNone("abab", "xyz") = true
1338: * StringUtils.containsNone("ab1", "xyz") = true
1339: * StringUtils.containsNone("abz", "xyz") = false
1340: * </pre>
1341: *
1342: * @param str the String to check, may be null
1343: * @param invalidChars a String of invalid chars, may be null
1344: * @return true if it contains none of the invalid chars, or is null
1345: * @since 2.0
1346: */
1347: public static boolean containsNone(String str, String invalidChars) {
1348: if (str == null || invalidChars == null) {
1349: return true;
1350: }
1351: return containsNone(str, invalidChars.toCharArray());
1352: }
1353:
1354: // IndexOfAny strings
1355: //-----------------------------------------------------------------------
1356: /**
1357: * <p>Find the first index of any of a set of potential substrings.</p>
1358: *
1359: * <p>A <code>null</code> String will return <code>-1</code>.
1360: * A <code>null</code> or zero length search array will return <code>-1</code>.
1361: * A <code>null</code> search array entry will be ignored, but a search
1362: * array containing "" will return <code>0</code> if <code>str</code> is not
1363: * null. This method uses {@link String#indexOf(String)}.</p>
1364: *
1365: * <pre>
1366: * StringUtils.indexOfAny(null, *) = -1
1367: * StringUtils.indexOfAny(*, null) = -1
1368: * StringUtils.indexOfAny(*, []) = -1
1369: * StringUtils.indexOfAny("zzabyycdxx", ["ab","cd"]) = 2
1370: * StringUtils.indexOfAny("zzabyycdxx", ["cd","ab"]) = 2
1371: * StringUtils.indexOfAny("zzabyycdxx", ["mn","op"]) = -1
1372: * StringUtils.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1
1373: * StringUtils.indexOfAny("zzabyycdxx", [""]) = 0
1374: * StringUtils.indexOfAny("", [""]) = 0
1375: * StringUtils.indexOfAny("", ["a"]) = -1
1376: * </pre>
1377: *
1378: * @param str the String to check, may be null
1379: * @param searchStrs the Strings to search for, may be null
1380: * @return the first index of any of the searchStrs in str, -1 if no match
1381: */
1382: public static int indexOfAny(String str, String[] searchStrs) {
1383: if ((str == null) || (searchStrs == null)) {
1384: return -1;
1385: }
1386: int sz = searchStrs.length;
1387:
1388: // String's can't have a MAX_VALUEth index.
1389: int ret = Integer.MAX_VALUE;
1390:
1391: int tmp = 0;
1392: for (int i = 0; i < sz; i++) {
1393: String search = searchStrs[i];
1394: if (search == null) {
1395: continue;
1396: }
1397: tmp = str.indexOf(search);
1398: if (tmp == -1) {
1399: continue;
1400: }
1401:
1402: if (tmp < ret) {
1403: ret = tmp;
1404: }
1405: }
1406:
1407: return (ret == Integer.MAX_VALUE) ? -1 : ret;
1408: }
1409:
1410: /**
1411: * <p>Find the latest index of any of a set of potential substrings.</p>
1412: *
1413: * <p>A <code>null</code> String will return <code>-1</code>.
1414: * A <code>null</code> search array will return <code>-1</code>.
1415: * A <code>null</code> or zero length search array entry will be ignored,
1416: * but a search array containing "" will return the length of <code>str</code>
1417: * if <code>str</code> is not null. This method uses {@link String#indexOf(String)}</p>
1418: *
1419: * <pre>
1420: * StringUtils.lastIndexOfAny(null, *) = -1
1421: * StringUtils.lastIndexOfAny(*, null) = -1
1422: * StringUtils.lastIndexOfAny(*, []) = -1
1423: * StringUtils.lastIndexOfAny(*, [null]) = -1
1424: * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6
1425: * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6
1426: * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
1427: * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
1428: * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn",""]) = 10
1429: * </pre>
1430: *
1431: * @param str the String to check, may be null
1432: * @param searchStrs the Strings to search for, may be null
1433: * @return the last index of any of the Strings, -1 if no match
1434: */
1435: public static int lastIndexOfAny(String str, String[] searchStrs) {
1436: if ((str == null) || (searchStrs == null)) {
1437: return -1;
1438: }
1439: int sz = searchStrs.length;
1440: int ret = -1;
1441: int tmp = 0;
1442: for (int i = 0; i < sz; i++) {
1443: String search = searchStrs[i];
1444: if (search == null) {
1445: continue;
1446: }
1447: tmp = str.lastIndexOf(search);
1448: if (tmp > ret) {
1449: ret = tmp;
1450: }
1451: }
1452: return ret;
1453: }
1454:
1455: // Substring
1456: //-----------------------------------------------------------------------
1457: /**
1458: * <p>Gets a substring from the specified String avoiding exceptions.</p>
1459: *
1460: * <p>A negative start position can be used to start <code>n</code>
1461: * characters from the end of the String.</p>
1462: *
1463: * <p>A <code>null</code> String will return <code>null</code>.
1464: * An empty ("") String will return "".</p>
1465: *
1466: * <pre>
1467: * StringUtils.substring(null, *) = null
1468: * StringUtils.substring("", *) = ""
1469: * StringUtils.substring("abc", 0) = "abc"
1470: * StringUtils.substring("abc", 2) = "c"
1471: * StringUtils.substring("abc", 4) = ""
1472: * StringUtils.substring("abc", -2) = "bc"
1473: * StringUtils.substring("abc", -4) = "abc"
1474: * </pre>
1475: *
1476: * @param str the String to get the substring from, may be null
1477: * @param start the position to start from, negative means
1478: * count back from the end of the String by this many characters
1479: * @return substring from start position, <code>null</code> if null String input
1480: */
1481: public static String substring(String str, int start) {
1482: if (str == null) {
1483: return null;
1484: }
1485:
1486: // handle negatives, which means last n characters
1487: if (start < 0) {
1488: start = str.length() + start; // remember start is negative
1489: }
1490:
1491: if (start < 0) {
1492: start = 0;
1493: }
1494: if (start > str.length()) {
1495: return EMPTY;
1496: }
1497:
1498: return str.substring(start);
1499: }
1500:
1501: /**
1502: * <p>Gets a substring from the specified String avoiding exceptions.</p>
1503: *
1504: * <p>A negative start position can be used to start/end <code>n</code>
1505: * characters from the end of the String.</p>
1506: *
1507: * <p>The returned substring starts with the character in the <code>start</code>
1508: * position and ends before the <code>end</code> position. All position counting is
1509: * zero-based -- i.e., to start at the beginning of the string use
1510: * <code>start = 0</code>. Negative start and end positions can be used to
1511: * specify offsets relative to the end of the String.</p>
1512: *
1513: * <p>If <code>start</code> is not strictly to the left of <code>end</code>, ""
1514: * is returned.</p>
1515: *
1516: * <pre>
1517: * StringUtils.substring(null, *, *) = null
1518: * StringUtils.substring("", * , *) = "";
1519: * StringUtils.substring("abc", 0, 2) = "ab"
1520: * StringUtils.substring("abc", 2, 0) = ""
1521: * StringUtils.substring("abc", 2, 4) = "c"
1522: * StringUtils.substring("abc", 4, 6) = ""
1523: * StringUtils.substring("abc", 2, 2) = ""
1524: * StringUtils.substring("abc", -2, -1) = "b"
1525: * StringUtils.substring("abc", -4, 2) = "ab"
1526: * </pre>
1527: *
1528: * @param str the String to get the substring from, may be null
1529: * @param start the position to start from, negative means
1530: * count back from the end of the String by this many characters
1531: * @param end the position to end at (exclusive), negative means
1532: * count back from the end of the String by this many characters
1533: * @return substring from start position to end positon,
1534: * <code>null</code> if null String input
1535: */
1536: public static String substring(String str, int start, int end) {
1537: if (str == null) {
1538: return null;
1539: }
1540:
1541: // handle negatives
1542: if (end < 0) {
1543: end = str.length() + end; // remember end is negative
1544: }
1545: if (start < 0) {
1546: start = str.length() + start; // remember start is negative
1547: }
1548:
1549: // check length next
1550: if (end > str.length()) {
1551: end = str.length();
1552: }
1553:
1554: // if start is greater than end, return ""
1555: if (start > end) {
1556: return EMPTY;
1557: }
1558:
1559: if (start < 0) {
1560: start = 0;
1561: }
1562: if (end < 0) {
1563: end = 0;
1564: }
1565:
1566: return str.substring(start, end);
1567: }
1568:
1569: // Left/Right/Mid
1570: //-----------------------------------------------------------------------
1571: /**
1572: * <p>Gets the leftmost <code>len</code> characters of a String.</p>
1573: *
1574: * <p>If <code>len</code> characters are not available, or the
1575: * String is <code>null</code>, the String will be returned without
1576: * an exception. An exception is thrown if len is negative.</p>
1577: *
1578: * <pre>
1579: * StringUtils.left(null, *) = null
1580: * StringUtils.left(*, -ve) = ""
1581: * StringUtils.left("", *) = ""
1582: * StringUtils.left("abc", 0) = ""
1583: * StringUtils.left("abc", 2) = "ab"
1584: * StringUtils.left("abc", 4) = "abc"
1585: * </pre>
1586: *
1587: * @param str the String to get the leftmost characters from, may be null
1588: * @param len the length of the required String, must be zero or positive
1589: * @return the leftmost characters, <code>null</code> if null String input
1590: */
1591: public static String left(String str, int len) {
1592: if (str == null) {
1593: return null;
1594: }
1595: if (len < 0) {
1596: return EMPTY;
1597: }
1598: if (str.length() <= len) {
1599: return str;
1600: } else {
1601: return str.substring(0, len);
1602: }
1603: }
1604:
1605: /**
1606: * <p>Gets the rightmost <code>len</code> characters of a String.</p>
1607: *
1608: * <p>If <code>len</code> characters are not available, or the String
1609: * is <code>null</code>, the String will be returned without an
1610: * an exception. An exception is thrown if len is negative.</p>
1611: *
1612: * <pre>
1613: * StringUtils.right(null, *) = null
1614: * StringUtils.right(*, -ve) = ""
1615: * StringUtils.right("", *) = ""
1616: * StringUtils.right("abc", 0) = ""
1617: * StringUtils.right("abc", 2) = "bc"
1618: * StringUtils.right("abc", 4) = "abc"
1619: * </pre>
1620: *
1621: * @param str the String to get the rightmost characters from, may be null
1622: * @param len the length of the required String, must be zero or positive
1623: * @return the rightmost characters, <code>null</code> if null String input
1624: */
1625: public static String right(String str, int len) {
1626: if (str == null) {
1627: return null;
1628: }
1629: if (len < 0) {
1630: return EMPTY;
1631: }
1632: if (str.length() <= len) {
1633: return str;
1634: } else {
1635: return str.substring(str.length() - len);
1636: }
1637: }
1638:
1639: /**
1640: * <p>Gets <code>len</code> characters from the middle of a String.</p>
1641: *
1642: * <p>If <code>len</code> characters are not available, the remainder
1643: * of the String will be returned without an exception. If the
1644: * String is <code>null</code>, <code>null</code> will be returned.
1645: * An exception is thrown if len is negative.</p>
1646: *
1647: * <pre>
1648: * StringUtils.mid(null, *, *) = null
1649: * StringUtils.mid(*, *, -ve) = ""
1650: * StringUtils.mid("", 0, *) = ""
1651: * StringUtils.mid("abc", 0, 2) = "ab"
1652: * StringUtils.mid("abc", 0, 4) = "abc"
1653: * StringUtils.mid("abc", 2, 4) = "c"
1654: * StringUtils.mid("abc", 4, 2) = ""
1655: * StringUtils.mid("abc", -2, 2) = "ab"
1656: * </pre>
1657: *
1658: * @param str the String to get the characters from, may be null
1659: * @param pos the position to start from, negative treated as zero
1660: * @param len the length of the required String, must be zero or positive
1661: * @return the middle characters, <code>null</code> if null String input
1662: */
1663: public static String mid(String str, int pos, int len) {
1664: if (str == null) {
1665: return null;
1666: }
1667: if (len < 0 || pos > str.length()) {
1668: return EMPTY;
1669: }
1670: if (pos < 0) {
1671: pos = 0;
1672: }
1673: if (str.length() <= (pos + len)) {
1674: return str.substring(pos);
1675: } else {
1676: return str.substring(pos, pos + len);
1677: }
1678: }
1679:
1680: // SubStringAfter/SubStringBefore
1681: //-----------------------------------------------------------------------
1682: /**
1683: * <p>Gets the substring before the first occurrence of a separator.
1684: * The separator is not returned.</p>
1685: *
1686: * <p>A <code>null</code> string input will return <code>null</code>.
1687: * An empty ("") string input will return the empty string.
1688: * A <code>null</code> separator will return the input string.</p>
1689: *
1690: * <pre>
1691: * StringUtils.substringBefore(null, *) = null
1692: * StringUtils.substringBefore("", *) = ""
1693: * StringUtils.substringBefore("abc", "a") = ""
1694: * StringUtils.substringBefore("abcba", "b") = "a"
1695: * StringUtils.substringBefore("abc", "c") = "ab"
1696: * StringUtils.substringBefore("abc", "d") = "abc"
1697: * StringUtils.substringBefore("abc", "") = ""
1698: * StringUtils.substringBefore("abc", null) = "abc"
1699: * </pre>
1700: *
1701: * @param str the String to get a substring from, may be null
1702: * @param separator the String to search for, may be null
1703: * @return the substring before the first occurrence of the separator,
1704: * <code>null</code> if null String input
1705: * @since 2.0
1706: */
1707: public static String substringBefore(String str, String separator) {
1708: if (isEmpty(str) || separator == null) {
1709: return str;
1710: }
1711: if (separator.length() == 0) {
1712: return EMPTY;
1713: }
1714: int pos = str.indexOf(separator);
1715: if (pos == -1) {
1716: return str;
1717: }
1718: return str.substring(0, pos);
1719: }
1720:
1721: /**
1722: * <p>Gets the substring after the first occurrence of a separator.
1723: * The separator is not returned.</p>
1724: *
1725: * <p>A <code>null</code> string input will return <code>null</code>.
1726: * An empty ("") string input will return the empty string.
1727: * A <code>null</code> separator will return the empty string if the
1728: * input string is not <code>null</code>.</p>
1729: *
1730: * <pre>
1731: * StringUtils.substringAfter(null, *) = null
1732: * StringUtils.substringAfter("", *) = ""
1733: * StringUtils.substringAfter(*, null) = ""
1734: * StringUtils.substringAfter("abc", "a") = "bc"
1735: * StringUtils.substringAfter("abcba", "b") = "cba"
1736: * StringUtils.substringAfter("abc", "c") = ""
1737: * StringUtils.substringAfter("abc", "d") = ""
1738: * StringUtils.substringAfter("abc", "") = "abc"
1739: * </pre>
1740: *
1741: * @param str the String to get a substring from, may be null
1742: * @param separator the String to search for, may be null
1743: * @return the substring after the first occurrence of the separator,
1744: * <code>null</code> if null String input
1745: * @since 2.0
1746: */
1747: public static String substringAfter(String str, String separator) {
1748: if (isEmpty(str)) {
1749: return str;
1750: }
1751: if (separator == null) {
1752: return EMPTY;
1753: }
1754: int pos = str.indexOf(separator);
1755: if (pos == -1) {
1756: return EMPTY;
1757: }
1758: return str.substring(pos + separator.length());
1759: }
1760:
1761: /**
1762: * <p>Gets the substring before the last occurrence of a separator.
1763: * The separator is not returned.</p>
1764: *
1765: * <p>A <code>null</code> string input will return <code>null</code>.
1766: * An empty ("") string input will return the empty string.
1767: * An empty or <code>null</code> separator will return the input string.</p>
1768: *
1769: * <pre>
1770: * StringUtils.substringBeforeLast(null, *) = null
1771: * StringUtils.substringBeforeLast("", *) = ""
1772: * StringUtils.substringBeforeLast("abcba", "b") = "abc"
1773: * StringUtils.substringBeforeLast("abc", "c") = "ab"
1774: * StringUtils.substringBeforeLast("a", "a") = ""
1775: * StringUtils.substringBeforeLast("a", "z") = "a"
1776: * StringUtils.substringBeforeLast("a", null) = "a"
1777: * StringUtils.substringBeforeLast("a", "") = "a"
1778: * </pre>
1779: *
1780: * @param str the String to get a substring from, may be null
1781: * @param separator the String to search for, may be null
1782: * @return the substring before the last occurrence of the separator,
1783: * <code>null</code> if null String input
1784: * @since 2.0
1785: */
1786: public static String substringBeforeLast(String str,
1787: String separator) {
1788: if (isEmpty(str) || isEmpty(separator)) {
1789: return str;
1790: }
1791: int pos = str.lastIndexOf(separator);
1792: if (pos == -1) {
1793: return str;
1794: }
1795: return str.substring(0, pos);
1796: }
1797:
1798: /**
1799: * <p>Gets the substring after the last occurrence of a separator.
1800: * The separator is not returned.</p>
1801: *
1802: * <p>A <code>null</code> string input will return <code>null</code>.
1803: * An empty ("") string input will return the empty string.
1804: * An empty or <code>null</code> separator will return the empty string if
1805: * the input string is not <code>null</code>.</p>
1806: *
1807: * <pre>
1808: * StringUtils.substringAfterLast(null, *) = null
1809: * StringUtils.substringAfterLast("", *) = ""
1810: * StringUtils.substringAfterLast(*, "") = ""
1811: * StringUtils.substringAfterLast(*, null) = ""
1812: * StringUtils.substringAfterLast("abc", "a") = "bc"
1813: * StringUtils.substringAfterLast("abcba", "b") = "a"
1814: * StringUtils.substringAfterLast("abc", "c") = ""
1815: * StringUtils.substringAfterLast("a", "a") = ""
1816: * StringUtils.substringAfterLast("a", "z") = ""
1817: * </pre>
1818: *
1819: * @param str the String to get a substring from, may be null
1820: * @param separator the String to search for, may be null
1821: * @return the substring after the last occurrence of the separator,
1822: * <code>null</code> if null String input
1823: * @since 2.0
1824: */
1825: public static String substringAfterLast(String str, String separator) {
1826: if (isEmpty(str)) {
1827: return str;
1828: }
1829: if (isEmpty(separator)) {
1830: return EMPTY;
1831: }
1832: int pos = str.lastIndexOf(separator);
1833: if (pos == -1 || pos == (str.length() - separator.length())) {
1834: return EMPTY;
1835: }
1836: return str.substring(pos + separator.length());
1837: }
1838:
1839: // Substring between
1840: //-----------------------------------------------------------------------
1841: /**
1842: * <p>Gets the String that is nested in between two instances of the
1843: * same String.</p>
1844: *
1845: * <p>A <code>null</code> input String returns <code>null</code>.
1846: * A <code>null</code> tag returns <code>null</code>.</p>
1847: *
1848: * <pre>
1849: * StringUtils.substringBetween(null, *) = null
1850: * StringUtils.substringBetween("", "") = ""
1851: * StringUtils.substringBetween("", "tag") = null
1852: * StringUtils.substringBetween("tagabctag", null) = null
1853: * StringUtils.substringBetween("tagabctag", "") = ""
1854: * StringUtils.substringBetween("tagabctag", "tag") = "abc"
1855: * </pre>
1856: *
1857: * @param str the String containing the substring, may be null
1858: * @param tag the String before and after the substring, may be null
1859: * @return the substring, <code>null</code> if no match
1860: * @since 2.0
1861: */
1862: public static String substringBetween(String str, String tag) {
1863: return substringBetween(str, tag, tag);
1864: }
1865:
1866: /**
1867: * <p>Gets the String that is nested in between two Strings.
1868: * Only the first match is returned.</p>
1869: *
1870: * <p>A <code>null</code> input String returns <code>null</code>.
1871: * A <code>null</code> open/close returns <code>null</code> (no match).
1872: * An empty ("") open and close returns an empty string.</p>
1873: *
1874: * <pre>
1875: * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
1876: * StringUtils.substringBetween(null, *, *) = null
1877: * StringUtils.substringBetween(*, null, *) = null
1878: * StringUtils.substringBetween(*, *, null) = null
1879: * StringUtils.substringBetween("", "", "") = ""
1880: * StringUtils.substringBetween("", "", "]") = null
1881: * StringUtils.substringBetween("", "[", "]") = null
1882: * StringUtils.substringBetween("yabcz", "", "") = ""
1883: * StringUtils.substringBetween("yabcz", "y", "z") = "abc"
1884: * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc"
1885: * </pre>
1886: *
1887: * @param str the String containing the substring, may be null
1888: * @param open the String before the substring, may be null
1889: * @param close the String after the substring, may be null
1890: * @return the substring, <code>null</code> if no match
1891: * @since 2.0
1892: */
1893: public static String substringBetween(String str, String open,
1894: String close) {
1895: if (str == null || open == null || close == null) {
1896: return null;
1897: }
1898: int start = str.indexOf(open);
1899: if (start != -1) {
1900: int end = str.indexOf(close, start + open.length());
1901: if (end != -1) {
1902: return str.substring(start + open.length(), end);
1903: }
1904: }
1905: return null;
1906: }
1907:
1908: /**
1909: * <p>Searches a String for substrings delimited by a start and end tag,
1910: * returning all matching substrings in an array.</p>
1911: *
1912: * <p>A <code>null</code> input String returns <code>null</code>.
1913: * A <code>null</code> open/close returns <code>null</code> (no match).
1914: * An empty ("") open/close returns <code>null</code> (no match).</p>
1915: *
1916: * <pre>
1917: * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
1918: * StringUtils.substringsBetween(null, *, *) = null
1919: * StringUtils.substringsBetween(*, null, *) = null
1920: * StringUtils.substringsBetween(*, *, null) = null
1921: * StringUtils.substringsBetween("", "[", "]") = []
1922: * </pre>
1923: *
1924: * @param str the String containing the substrings, null returns null, empty returns empty
1925: * @param open the String identifying the start of the substring, empty returns null
1926: * @param close the String identifying the end of the substring, empty returns null
1927: * @return a String Array of substrings, or <code>null</code> if no match
1928: * @since 2.3
1929: */
1930: public static String[] substringsBetween(String str, String open,
1931: String close) {
1932: if (str == null || isEmpty(open) || isEmpty(close)) {
1933: return null;
1934: }
1935: int strLen = str.length();
1936: if (strLen == 0) {
1937: return ArrayUtils.EMPTY_STRING_ARRAY;
1938: }
1939: int closeLen = close.length();
1940: int openLen = open.length();
1941: List list = new ArrayList();
1942: int pos = 0;
1943: while (pos < (strLen - closeLen)) {
1944: int start = str.indexOf(open, pos);
1945: if (start < 0) {
1946: break;
1947: }
1948: start += openLen;
1949: int end = str.indexOf(close, start);
1950: if (end < 0) {
1951: break;
1952: }
1953: list.add(str.substring(start, end));
1954: pos = end + closeLen;
1955: }
1956: if (list.size() > 0) {
1957: return (String[]) list.toArray(new String[list.size()]);
1958: } else {
1959: return null;
1960: }
1961: }
1962:
1963: // Nested extraction
1964: //-----------------------------------------------------------------------
1965: /**
1966: * <p>Gets the String that is nested in between two instances of the
1967: * same String.</p>
1968: *
1969: * <p>A <code>null</code> input String returns <code>null</code>.
1970: * A <code>null</code> tag returns <code>null</code>.</p>
1971: *
1972: * <pre>
1973: * StringUtils.getNestedString(null, *) = null
1974: * StringUtils.getNestedString("", "") = ""
1975: * StringUtils.getNestedString("", "tag") = null
1976: * StringUtils.getNestedString("tagabctag", null) = null
1977: * StringUtils.getNestedString("tagabctag", "") = ""
1978: * StringUtils.getNestedString("tagabctag", "tag") = "abc"
1979: * </pre>
1980: *
1981: * @param str the String containing nested-string, may be null
1982: * @param tag the String before and after nested-string, may be null
1983: * @return the nested String, <code>null</code> if no match
1984: * @deprecated Use the better named {@link #substringBetween(String, String)}.
1985: * Method will be removed in Commons Lang 3.0.
1986: */
1987: public static String getNestedString(String str, String tag) {
1988: return substringBetween(str, tag, tag);
1989: }
1990:
1991: /**
1992: * <p>Gets the String that is nested in between two Strings.
1993: * Only the first match is returned.</p>
1994: *
1995: * <p>A <code>null</code> input String returns <code>null</code>.
1996: * A <code>null</code> open/close returns <code>null</code> (no match).
1997: * An empty ("") open/close returns an empty string.</p>
1998: *
1999: * <pre>
2000: * StringUtils.getNestedString(null, *, *) = null
2001: * StringUtils.getNestedString("", "", "") = ""
2002: * StringUtils.getNestedString("", "", "tag") = null
2003: * StringUtils.getNestedString("", "tag", "tag") = null
2004: * StringUtils.getNestedString("yabcz", null, null) = null
2005: * StringUtils.getNestedString("yabcz", "", "") = ""
2006: * StringUtils.getNestedString("yabcz", "y", "z") = "abc"
2007: * StringUtils.getNestedString("yabczyabcz", "y", "z") = "abc"
2008: * </pre>
2009: *
2010: * @param str the String containing nested-string, may be null
2011: * @param open the String before nested-string, may be null
2012: * @param close the String after nested-string, may be null
2013: * @return the nested String, <code>null</code> if no match
2014: * @deprecated Use the better named {@link #substringBetween(String, String, String)}.
2015: * Method will be removed in Commons Lang 3.0.
2016: */
2017: public static String getNestedString(String str, String open,
2018: String close) {
2019: return substringBetween(str, open, close);
2020: }
2021:
2022: // Splitting
2023: //-----------------------------------------------------------------------
2024: /**
2025: * <p>Splits the provided text into an array, using whitespace as the
2026: * separator.
2027: * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
2028: *
2029: * <p>The separator is not included in the returned String array.
2030: * Adjacent separators are treated as one separator.
2031: * For more control over the split use the StrTokenizer class.</p>
2032: *
2033: * <p>A <code>null</code> input String returns <code>null</code>.</p>
2034: *
2035: * <pre>
2036: * StringUtils.split(null) = null
2037: * StringUtils.split("") = []
2038: * StringUtils.split("abc def") = ["abc", "def"]
2039: * StringUtils.split("abc def") = ["abc", "def"]
2040: * StringUtils.split(" abc ") = ["abc"]
2041: * </pre>
2042: *
2043: * @param str the String to parse, may be null
2044: * @return an array of parsed Strings, <code>null</code> if null String input
2045: */
2046: public static String[] split(String str) {
2047: return split(str, null, -1);
2048: }
2049:
2050: /**
2051: * <p>Splits the provided text into an array, separator specified.
2052: * This is an alternative to using StringTokenizer.</p>
2053: *
2054: * <p>The separator is not included in the returned String array.
2055: * Adjacent separators are treated as one separator.
2056: * For more control over the split use the StrTokenizer class.</p>
2057: *
2058: * <p>A <code>null</code> input String returns <code>null</code>.</p>
2059: *
2060: * <pre>
2061: * StringUtils.split(null, *) = null
2062: * StringUtils.split("", *) = []
2063: * StringUtils.split("a.b.c", '.') = ["a", "b", "c"]
2064: * StringUtils.split("a..b.c", '.') = ["a", "b", "c"]
2065: * StringUtils.split("a:b:c", '.') = ["a:b:c"]
2066: * StringUtils.split("a\tb\nc", null) = ["a", "b", "c"]
2067: * StringUtils.split("a b c", ' ') = ["a", "b", "c"]
2068: * </pre>
2069: *
2070: * @param str the String to parse, may be null
2071: * @param separatorChar the character used as the delimiter,
2072: * <code>null</code> splits on whitespace
2073: * @return an array of parsed Strings, <code>null</code> if null String input
2074: * @since 2.0
2075: */
2076: public static String[] split(String str, char separatorChar) {
2077: return splitWorker(str, separatorChar, false);
2078: }
2079:
2080: /**
2081: * <p>Splits the provided text into an array, separators specified.
2082: * This is an alternative to using StringTokenizer.</p>
2083: *
2084: * <p>The separator is not included in the returned String array.
2085: * Adjacent separators are treated as one separator.
2086: * For more control over the split use the StrTokenizer class.</p>
2087: *
2088: * <p>A <code>null</code> input String returns <code>null</code>.
2089: * A <code>null</code> separatorChars splits on whitespace.</p>
2090: *
2091: * <pre>
2092: * StringUtils.split(null, *) = null
2093: * StringUtils.split("", *) = []
2094: * StringUtils.split("abc def", null) = ["abc", "def"]
2095: * StringUtils.split("abc def", " ") = ["abc", "def"]
2096: * StringUtils.split("abc def", " ") = ["abc", "def"]
2097: * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
2098: * </pre>
2099: *
2100: * @param str the String to parse, may be null
2101: * @param separatorChars the characters used as the delimiters,
2102: * <code>null</code> splits on whitespace
2103: * @return an array of parsed Strings, <code>null</code> if null String input
2104: */
2105: public static String[] split(String str, String separatorChars) {
2106: return splitWorker(str, separatorChars, -1, false);
2107: }
2108:
2109: /**
2110: * <p>Splits the provided text into an array with a maximum length,
2111: * separators specified.</p>
2112: *
2113: * <p>The separator is not included in the returned String array.
2114: * Adjacent separators are treated as one separator.</p>
2115: *
2116: * <p>A <code>null</code> input String returns <code>null</code>.
2117: * A <code>null</code> separatorChars splits on whitespace.</p>
2118: *
2119: * <p>If more than <code>max</code> delimited substrings are found, the last
2120: * returned string includes all characters after the first <code>max - 1</code>
2121: * returned strings (including separator characters).</p>
2122: *
2123: * <pre>
2124: * StringUtils.split(null, *, *) = null
2125: * StringUtils.split("", *, *) = []
2126: * StringUtils.split("ab de fg", null, 0) = ["ab", "cd", "ef"]
2127: * StringUtils.split("ab de fg", null, 0) = ["ab", "cd", "ef"]
2128: * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
2129: * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
2130: * </pre>
2131: *
2132: * @param str the String to parse, may be null
2133: * @param separatorChars the characters used as the delimiters,
2134: * <code>null</code> splits on whitespace
2135: * @param max the maximum number of elements to include in the
2136: * array. A zero or negative value implies no limit
2137: * @return an array of parsed Strings, <code>null</code> if null String input
2138: */
2139: public static String[] split(String str, String separatorChars,
2140: int max) {
2141: return splitWorker(str, separatorChars, max, false);
2142: }
2143:
2144: /**
2145: * <p>Splits the provided text into an array, separator string specified.</p>
2146: *
2147: * <p>The separator(s) will not be included in the returned String array.
2148: * Adjacent separators are treated as one separator.</p>
2149: *
2150: * <p>A <code>null</code> input String returns <code>null</code>.
2151: * A <code>null</code> separator splits on whitespace.</p>
2152: *
2153: * <pre>
2154: * StringUtils.splitByWholeSeparator(null, *) = null
2155: * StringUtils.splitByWholeSeparator("", *) = []
2156: * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"]
2157: * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"]
2158: * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"]
2159: * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
2160: * </pre>
2161: *
2162: * @param str the String to parse, may be null
2163: * @param separator String containing the String to be used as a delimiter,
2164: * <code>null</code> splits on whitespace
2165: * @return an array of parsed Strings, <code>null</code> if null String was input
2166: */
2167: public static String[] splitByWholeSeparator(String str,
2168: String separator) {
2169: return splitByWholeSeparator(str, separator, -1);
2170: }
2171:
2172: /**
2173: * <p>Splits the provided text into an array, separator string specified.
2174: * Returns a maximum of <code>max</code> substrings.</p>
2175: *
2176: * <p>The separator(s) will not be included in the returned String array.
2177: * Adjacent separators are treated as one separator.</p>
2178: *
2179: * <p>A <code>null</code> input String returns <code>null</code>.
2180: * A <code>null</code> separator splits on whitespace.</p>
2181: *
2182: * <pre>
2183: * StringUtils.splitByWholeSeparator(null, *, *) = null
2184: * StringUtils.splitByWholeSeparator("", *, *) = []
2185: * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
2186: * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
2187: * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
2188: * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
2189: * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
2190: * </pre>
2191: *
2192: * @param str the String to parse, may be null
2193: * @param separator String containing the String to be used as a delimiter,
2194: * <code>null</code> splits on whitespace
2195: * @param max the maximum number of elements to include in the returned
2196: * array. A zero or negative value implies no limit.
2197: * @return an array of parsed Strings, <code>null</code> if null String was input
2198: */
2199: public static String[] splitByWholeSeparator(String str,
2200: String separator, int max) {
2201: if (str == null) {
2202: return null;
2203: }
2204:
2205: int len = str.length();
2206:
2207: if (len == 0) {
2208: return ArrayUtils.EMPTY_STRING_ARRAY;
2209: }
2210:
2211: if ((separator == null) || ("".equals(separator))) {
2212: // Split on whitespace.
2213: return split(str, null, max);
2214: }
2215:
2216: int separatorLength = separator.length();
2217:
2218: ArrayList substrings = new ArrayList();
2219: int numberOfSubstrings = 0;
2220: int beg = 0;
2221: int end = 0;
2222: while (end < len) {
2223: end = str.indexOf(separator, beg);
2224:
2225: if (end > -1) {
2226: if (end > beg) {
2227: numberOfSubstrings += 1;
2228:
2229: if (numberOfSubstrings == max) {
2230: end = len;
2231: substrings.add(str.substring(beg));
2232: } else {
2233: // The following is OK, because String.substring( beg, end ) excludes
2234: // the character at the position 'end'.
2235: substrings.add(str.substring(beg, end));
2236:
2237: // Set the starting point for the next search.
2238: // The following is equivalent to beg = end + (separatorLength - 1) + 1,
2239: // which is the right calculation:
2240: beg = end + separatorLength;
2241: }
2242: } else {
2243: // We found a consecutive occurrence of the separator, so skip it.
2244: beg = end + separatorLength;
2245: }
2246: } else {
2247: // String.substring( beg ) goes from 'beg' to the end of the String.
2248: substrings.add(str.substring(beg));
2249: end = len;
2250: }
2251: }
2252:
2253: return (String[]) substrings.toArray(new String[substrings
2254: .size()]);
2255: }
2256:
2257: //-----------------------------------------------------------------------
2258: /**
2259: * <p>Splits the provided text into an array, using whitespace as the
2260: * separator, preserving all tokens, including empty tokens created by
2261: * adjacent separators. This is an alternative to using StringTokenizer.
2262: * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
2263: *
2264: * <p>The separator is not included in the returned String array.
2265: * Adjacent separators are treated as separators for empty tokens.
2266: * For more control over the split use the StrTokenizer class.</p>
2267: *
2268: * <p>A <code>null</code> input String returns <code>null</code>.</p>
2269: *
2270: * <pre>
2271: * StringUtils.splitPreserveAllTokens(null) = null
2272: * StringUtils.splitPreserveAllTokens("") = []
2273: * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"]
2274: * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"]
2275: * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""]
2276: * </pre>
2277: *
2278: * @param str the String to parse, may be <code>null</code>
2279: * @return an array of parsed Strings, <code>null</code> if null String input
2280: * @since 2.1
2281: */
2282: public static String[] splitPreserveAllTokens(String str) {
2283: return splitWorker(str, null, -1, true);
2284: }
2285:
2286: /**
2287: * <p>Splits the provided text into an array, separator specified,
2288: * preserving all tokens, including empty tokens created by adjacent
2289: * separators. This is an alternative to using StringTokenizer.</p>
2290: *
2291: * <p>The separator is not included in the returned String array.
2292: * Adjacent separators are treated as separators for empty tokens.
2293: * For more control over the split use the StrTokenizer class.</p>
2294: *
2295: * <p>A <code>null</code> input String returns <code>null</code>.</p>
2296: *
2297: * <pre>
2298: * StringUtils.splitPreserveAllTokens(null, *) = null
2299: * StringUtils.splitPreserveAllTokens("", *) = []
2300: * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"]
2301: * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"]
2302: * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"]
2303: * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
2304: * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"]
2305: * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""]
2306: * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""]
2307: * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", a", "b", "c"]
2308: * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", a", "b", "c"]
2309: * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", a", "b", "c", ""]
2310: * </pre>
2311: *
2312: * @param str the String to parse, may be <code>null</code>
2313: * @param separatorChar the character used as the delimiter,
2314: * <code>null</code> splits on whitespace
2315: * @return an array of parsed Strings, <code>null</code> if null String input
2316: * @since 2.1
2317: */
2318: public static String[] splitPreserveAllTokens(String str,
2319: char separatorChar) {
2320: return splitWorker(str, separatorChar, true);
2321: }
2322:
2323: /**
2324: * Performs the logic for the <code>split</code> and
2325: * <code>splitPreserveAllTokens</code> methods that do not return a
2326: * maximum array length.
2327: *
2328: * @param str the String to parse, may be <code>null</code>
2329: * @param separatorChar the separate character
2330: * @param preserveAllTokens if <code>true</code>, adjacent separators are
2331: * treated as empty token separators; if <code>false</code>, adjacent
2332: * separators are treated as one separator.
2333: * @return an array of parsed Strings, <code>null</code> if null String input
2334: */
2335: private static String[] splitWorker(String str, char separatorChar,
2336: boolean preserveAllTokens) {
2337: // Performance tuned for 2.0 (JDK1.4)
2338:
2339: if (str == null) {
2340: return null;
2341: }
2342: int len = str.length();
2343: if (len == 0) {
2344: return ArrayUtils.EMPTY_STRING_ARRAY;
2345: }
2346: List list = new ArrayList();
2347: int i = 0, start = 0;
2348: boolean match = false;
2349: boolean lastMatch = false;
2350: while (i < len) {
2351: if (str.charAt(i) == separatorChar) {
2352: if (match || preserveAllTokens) {
2353: list.add(str.substring(start, i));
2354: match = false;
2355: lastMatch = true;
2356: }
2357: start = ++i;
2358: continue;
2359: } else {
2360: lastMatch = false;
2361: }
2362: match = true;
2363: i++;
2364: }
2365: if (match || (preserveAllTokens && lastMatch)) {
2366: list.add(str.substring(start, i));
2367: }
2368: return (String[]) list.toArray(new String[list.size()]);
2369: }
2370:
2371: /**
2372: * <p>Splits the provided text into an array, separators specified,
2373: * preserving all tokens, including empty tokens created by adjacent
2374: * separators. This is an alternative to using StringTokenizer.</p>
2375: *
2376: * <p>The separator is not included in the returned String array.
2377: * Adjacent separators are treated as separators for empty tokens.
2378: * For more control over the split use the StrTokenizer class.</p>
2379: *
2380: * <p>A <code>null</code> input String returns <code>null</code>.
2381: * A <code>null</code> separatorChars splits on whitespace.</p>
2382: *
2383: * <pre>
2384: * StringUtils.splitPreserveAllTokens(null, *) = null
2385: * StringUtils.splitPreserveAllTokens("", *) = []
2386: * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"]
2387: * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"]
2388: * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", def"]
2389: * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"]
2390: * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""]
2391: * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
2392: * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", cd", "ef"]
2393: * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", cd", "ef"]
2394: * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", cd", "ef"]
2395: * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", cd", "ef", ""]
2396: * </pre>
2397: *
2398: * @param str the String to parse, may be <code>null</code>
2399: * @param separatorChars the characters used as the delimiters,
2400: * <code>null</code> splits on whitespace
2401: * @return an array of parsed Strings, <code>null</code> if null String input
2402: * @since 2.1
2403: */
2404: public static String[] splitPreserveAllTokens(String str,
2405: String separatorChars) {
2406: return splitWorker(str, separatorChars, -1, true);
2407: }
2408:
2409: /**
2410: * <p>Splits the provided text into an array with a maximum length,
2411: * separators specified, preserving all tokens, including empty tokens
2412: * created by adjacent separators.</p>
2413: *
2414: * <p>The separator is not included in the returned String array.
2415: * Adjacent separators are treated as separators for empty tokens.
2416: * Adjacent separators are treated as one separator.</p>
2417: *
2418: * <p>A <code>null</code> input String returns <code>null</code>.
2419: * A <code>null</code> separatorChars splits on whitespace.</p>
2420: *
2421: * <p>If more than <code>max</code> delimited substrings are found, the last
2422: * returned string includes all characters after the first <code>max - 1</code>
2423: * returned strings (including separator characters).</p>
2424: *
2425: * <pre>
2426: * StringUtils.splitPreserveAllTokens(null, *, *) = null
2427: * StringUtils.splitPreserveAllTokens("", *, *) = []
2428: * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "cd", "ef"]
2429: * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "cd", "ef"]
2430: * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
2431: * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
2432: * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"]
2433: * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"]
2434: * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"]
2435: * </pre>
2436: *
2437: * @param str the String to parse, may be <code>null</code>
2438: * @param separatorChars the characters used as the delimiters,
2439: * <code>null</code> splits on whitespace
2440: * @param max the maximum number of elements to include in the
2441: * array. A zero or negative value implies no limit
2442: * @return an array of parsed Strings, <code>null</code> if null String input
2443: * @since 2.1
2444: */
2445: public static String[] splitPreserveAllTokens(String str,
2446: String separatorChars, int max) {
2447: return splitWorker(str, separatorChars, max, true);
2448: }
2449:
2450: /**
2451: * Performs the logic for the <code>split</code> and
2452: * <code>splitPreserveAllTokens</code> methods that return a maximum array
2453: * length.
2454: *
2455: * @param str the String to parse, may be <code>null</code>
2456: * @param separatorChars the separate character
2457: * @param max the maximum number of elements to include in the
2458: * array. A zero or negative value implies no limit.
2459: * @param preserveAllTokens if <code>true</code>, adjacent separators are
2460: * treated as empty token separators; if <code>false</code>, adjacent
2461: * separators are treated as one separator.
2462: * @return an array of parsed Strings, <code>null</code> if null String input
2463: */
2464: private static String[] splitWorker(String str,
2465: String separatorChars, int max, boolean preserveAllTokens) {
2466: // Performance tuned for 2.0 (JDK1.4)
2467: // Direct code is quicker than StringTokenizer.
2468: // Also, StringTokenizer uses isSpace() not isWhitespace()
2469:
2470: if (str == null) {
2471: return null;
2472: }
2473: int len = str.length();
2474: if (len == 0) {
2475: return ArrayUtils.EMPTY_STRING_ARRAY;
2476: }
2477: List list = new ArrayList();
2478: int sizePlus1 = 1;
2479: int i = 0, start = 0;
2480: boolean match = false;
2481: boolean lastMatch = false;
2482: if (separatorChars == null) {
2483: // Null separator means use whitespace
2484: while (i < len) {
2485: if (Character.isWhitespace(str.charAt(i))) {
2486: if (match || preserveAllTokens) {
2487: lastMatch = true;
2488: if (sizePlus1++ == max) {
2489: i = len;
2490: lastMatch = false;
2491: }
2492: list.add(str.substring(start, i));
2493: match = false;
2494: }
2495: start = ++i;
2496: continue;
2497: } else {
2498: lastMatch = false;
2499: }
2500: match = true;
2501: i++;
2502: }
2503: } else if (separatorChars.length() == 1) {
2504: // Optimise 1 character case
2505: char sep = separatorChars.charAt(0);
2506: while (i < len) {
2507: if (str.charAt(i) == sep) {
2508: if (match || preserveAllTokens) {
2509: lastMatch = true;
2510: if (sizePlus1++ == max) {
2511: i = len;
2512: lastMatch = false;
2513: }
2514: list.add(str.substring(start, i));
2515: match = false;
2516: }
2517: start = ++i;
2518: continue;
2519: } else {
2520: lastMatch = false;
2521: }
2522: match = true;
2523: i++;
2524: }
2525: } else {
2526: // standard case
2527: while (i < len) {
2528: if (separatorChars.indexOf(str.charAt(i)) >= 0) {
2529: if (match || preserveAllTokens) {
2530: lastMatch = true;
2531: if (sizePlus1++ == max) {
2532: i = len;
2533: lastMatch = false;
2534: }
2535: list.add(str.substring(start, i));
2536: match = false;
2537: }
2538: start = ++i;
2539: continue;
2540: } else {
2541: lastMatch = false;
2542: }
2543: match = true;
2544: i++;
2545: }
2546: }
2547: if (match || (preserveAllTokens && lastMatch)) {
2548: list.add(str.substring(start, i));
2549: }
2550: return (String[]) list.toArray(new String[list.size()]);
2551: }
2552:
2553: // Joining
2554: //-----------------------------------------------------------------------
2555: /**
2556: * <p>Concatenates elements of an array into a single String.
2557: * Null objects or empty strings within the array are represented by
2558: * empty strings.</p>
2559: *
2560: * <pre>
2561: * StringUtils.concatenate(null) = null
2562: * StringUtils.concatenate([]) = ""
2563: * StringUtils.concatenate([null]) = ""
2564: * StringUtils.concatenate(["a", "b", "c"]) = "abc"
2565: * StringUtils.concatenate([null, "", "a"]) = "a"
2566: * </pre>
2567: *
2568: * @param array the array of values to concatenate, may be null
2569: * @return the concatenated String, <code>null</code> if null array input
2570: * @deprecated Use the better named {@link #join(Object[])} instead.
2571: * Method will be removed in Commons Lang 3.0.
2572: */
2573: public static String concatenate(Object[] array) {
2574: return join(array, null);
2575: }
2576:
2577: /**
2578: * <p>Joins the elements of the provided array into a single String
2579: * containing the provided list of elements.</p>
2580: *
2581: * <p>No separator is added to the joined String.
2582: * Null objects or empty strings within the array are represented by
2583: * empty strings.</p>
2584: *
2585: * <pre>
2586: * StringUtils.join(null) = null
2587: * StringUtils.join([]) = ""
2588: * StringUtils.join([null]) = ""
2589: * StringUtils.join(["a", "b", "c"]) = "abc"
2590: * StringUtils.join([null, "", "a"]) = "a"
2591: * </pre>
2592: *
2593: * @param array the array of values to join together, may be null
2594: * @return the joined String, <code>null</code> if null array input
2595: * @since 2.0
2596: */
2597: public static String join(Object[] array) {
2598: return join(array, null);
2599: }
2600:
2601: /**
2602: * <p>Joins the elements of the provided array into a single String
2603: * containing the provided list of elements.</p>
2604: *
2605: * <p>No delimiter is added before or after the list.
2606: * Null objects or empty strings within the array are represented by
2607: * empty strings.</p>
2608: *
2609: * <pre>
2610: * StringUtils.join(null, *) = null
2611: * StringUtils.join([], *) = ""
2612: * StringUtils.join([null], *) = ""
2613: * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
2614: * StringUtils.join(["a", "b", "c"], null) = "abc"
2615: * StringUtils.join([null, "", "a"], ';') = ";;a"
2616: * </pre>
2617: *
2618: * @param array the array of values to join together, may be null
2619: * @param separator the separator character to use
2620: * @return the joined String, <code>null</code> if null array input
2621: * @since 2.0
2622: */
2623: public static String join(Object[] array, char separator) {
2624: if (array == null) {
2625: return null;
2626: }
2627:
2628: return join(array, separator, 0, array.length);
2629: }
2630:
2631: /**
2632: * <p>Joins the elements of the provided array into a single String
2633: * containing the provided list of elements.</p>
2634: *
2635: * <p>No delimiter is added before or after the list.
2636: * Null objects or empty strings within the array are represented by
2637: * empty strings.</p>
2638: *
2639: * <pre>
2640: * StringUtils.join(null, *) = null
2641: * StringUtils.join([], *) = ""
2642: * StringUtils.join([null], *) = ""
2643: * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
2644: * StringUtils.join(["a", "b", "c"], null) = "abc"
2645: * StringUtils.join([null, "", "a"], ';') = ";;a"
2646: * </pre>
2647: *
2648: * @param array the array of values to join together, may be null
2649: * @param separator the separator character to use
2650: * @param startIndex the first index to start joining from. It is
2651: * an error to pass in an end index past the end of the array
2652: * @param endIndex the index to stop joining from (exclusive). It is
2653: * an error to pass in an end index past the end of the array
2654: * @return the joined String, <code>null</code> if null array input
2655: * @since 2.0
2656: */
2657: public static String join(Object[] array, char separator,
2658: int startIndex, int endIndex) {
2659: if (array == null) {
2660: return null;
2661: }
2662: int bufSize = (endIndex - startIndex);
2663: if (bufSize <= 0) {
2664: return EMPTY;
2665: }
2666:
2667: bufSize *= ((array[startIndex] == null ? 16 : array[startIndex]
2668: .toString().length()) + 1);
2669: StringBuffer buf = new StringBuffer(bufSize);
2670:
2671: for (int i = startIndex; i < endIndex; i++) {
2672: if (i > startIndex) {
2673: buf.append(separator);
2674: }
2675: if (array[i] != null) {
2676: buf.append(array[i]);
2677: }
2678: }
2679: return buf.toString();
2680: }
2681:
2682: /**
2683: * <p>Joins the elements of the provided array into a single String
2684: * containing the provided list of elements.</p>
2685: *
2686: * <p>No delimiter is added before or after the list.
2687: * A <code>null</code> separator is the same as an empty String ("").
2688: * Null objects or empty strings within the array are represented by
2689: * empty strings.</p>
2690: *
2691: * <pre>
2692: * StringUtils.join(null, *) = null
2693: * StringUtils.join([], *) = ""
2694: * StringUtils.join([null], *) = ""
2695: * StringUtils.join(["a", "b", "c"], "--") = "a--b--c"
2696: * StringUtils.join(["a", "b", "c"], null) = "abc"
2697: * StringUtils.join(["a", "b", "c"], "") = "abc"
2698: * StringUtils.join([null, "", "a"], ',') = ",,a"
2699: * </pre>
2700: *
2701: * @param array the array of values to join together, may be null
2702: * @param separator the separator character to use, null treated as ""
2703: * @return the joined String, <code>null</code> if null array input
2704: */
2705: public static String join(Object[] array, String separator) {
2706: if (array == null) {
2707: return null;
2708: }
2709: return join(array, separator, 0, array.length);
2710: }
2711:
2712: /**
2713: * <p>Joins the elements of the provided array into a single String
2714: * containing the provided list of elements.</p>
2715: *
2716: * <p>No delimiter is added before or after the list.
2717: * A <code>null</code> separator is the same as an empty String ("").
2718: * Null objects or empty strings within the array are represented by
2719: * empty strings.</p>
2720: *
2721: * <pre>
2722: * StringUtils.join(null, *) = null
2723: * StringUtils.join([], *) = ""
2724: * StringUtils.join([null], *) = ""
2725: * StringUtils.join(["a", "b", "c"], "--") = "a--b--c"
2726: * StringUtils.join(["a", "b", "c"], null) = "abc"
2727: * StringUtils.join(["a", "b", "c"], "") = "abc"
2728: * StringUtils.join([null, "", "a"], ',') = ",,a"
2729: * </pre>
2730: *
2731: * @param array the array of values to join together, may be null
2732: * @param separator the separator character to use, null treated as ""
2733: * @param startIndex the first index to start joining from. It is
2734: * an error to pass in an end index past the end of the array
2735: * @param endIndex the index to stop joining from (exclusive). It is
2736: * an error to pass in an end index past the end of the array
2737: * @return the joined String, <code>null</code> if null array input
2738: */
2739: public static String join(Object[] array, String separator,
2740: int startIndex, int endIndex) {
2741: if (array == null) {
2742: return null;
2743: }
2744: if (separator == null) {
2745: separator = EMPTY;
2746: }
2747:
2748: // endIndex - startIndex > 0: Len = NofStrings *(len(firstString) + len(separator))
2749: // (Assuming that all Strings are roughly equally long)
2750: int bufSize = (endIndex - startIndex);
2751: if (bufSize <= 0) {
2752: return EMPTY;
2753: }
2754:
2755: bufSize *= ((array[startIndex] == null ? 16 : array[startIndex]
2756: .toString().length()) + separator.length());
2757:
2758: StringBuffer buf = new StringBuffer(bufSize);
2759:
2760: for (int i = startIndex; i < endIndex; i++) {
2761: if (i > startIndex) {
2762: buf.append(separator);
2763: }
2764: if (array[i] != null) {
2765: buf.append(array[i]);
2766: }
2767: }
2768: return buf.toString();
2769: }
2770:
2771: /**
2772: * <p>Joins the elements of the provided <code>Iterator</code> into
2773: * a single String containing the provided elements.</p>
2774: *
2775: * <p>No delimiter is added before or after the list. Null objects or empty
2776: * strings within the iteration are represented by empty strings.</p>
2777: *
2778: * <p>See the examples here: {@link #join(Object[],char)}. </p>
2779: *
2780: * @param iterator the <code>Iterator</code> of values to join together, may be null
2781: * @param separator the separator character to use
2782: * @return the joined String, <code>null</code> if null iterator input
2783: * @since 2.0
2784: */
2785: public static String join(Iterator iterator, char separator) {
2786:
2787: // handle null, zero and one elements before building a buffer
2788: if (iterator == null) {
2789: return null;
2790: }
2791: if (!iterator.hasNext()) {
2792: return EMPTY;
2793: }
2794: Object first = iterator.next();
2795: if (!iterator.hasNext()) {
2796: return ObjectUtils.toString(first);
2797: }
2798:
2799: // two or more elements
2800: StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
2801: if (first != null) {
2802: buf.append(first);
2803: }
2804:
2805: while (iterator.hasNext()) {
2806: buf.append(separator);
2807: Object obj = iterator.next();
2808: if (obj != null) {
2809: buf.append(obj);
2810: }
2811: }
2812:
2813: return buf.toString();
2814: }
2815:
2816: /**
2817: * <p>Joins the elements of the provided <code>Iterator</code> into
2818: * a single String containing the provided elements.</p>
2819: *
2820: * <p>No delimiter is added before or after the list.
2821: * A <code>null</code> separator is the same as an empty String ("").</p>
2822: *
2823: * <p>See the examples here: {@link #join(Object[],String)}. </p>
2824: *
2825: * @param iterator the <code>Iterator</code> of values to join together, may be null
2826: * @param separator the separator character to use, null treated as ""
2827: * @return the joined String, <code>null</code> if null iterator input
2828: */
2829: public static String join(Iterator iterator, String separator) {
2830:
2831: // handle null, zero and one elements before building a buffer
2832: if (iterator == null) {
2833: return null;
2834: }
2835: if (!iterator.hasNext()) {
2836: return EMPTY;
2837: }
2838: Object first = iterator.next();
2839: if (!iterator.hasNext()) {
2840: return ObjectUtils.toString(first);
2841: }
2842:
2843: // two or more elements
2844: StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
2845: if (first != null) {
2846: buf.append(first);
2847: }
2848:
2849: while (iterator.hasNext()) {
2850: if (separator != null) {
2851: buf.append(separator);
2852: }
2853: Object obj = iterator.next();
2854: if (obj != null) {
2855: buf.append(obj);
2856: }
2857: }
2858: return buf.toString();
2859: }
2860:
2861: /**
2862: * <p>Joins the elements of the provided <code>Collection</code> into
2863: * a single String containing the provided elements.</p>
2864: *
2865: * <p>No delimiter is added before or after the list. Null objects or empty
2866: * strings within the iteration are represented by empty strings.</p>
2867: *
2868: * <p>See the examples here: {@link #join(Object[],char)}. </p>
2869: *
2870: * @param collection the <code>Collection</code> of values to join together, may be null
2871: * @param separator the separator character to use
2872: * @return the joined String, <code>null</code> if null iterator input
2873: * @since 2.3
2874: */
2875: public static String join(Collection collection, char separator) {
2876: if (collection == null) {
2877: return null;
2878: }
2879: return join(collection.iterator(), separator);
2880: }
2881:
2882: /**
2883: * <p>Joins the elements of the provided <code>Collection</code> into
2884: * a single String containing the provided elements.</p>
2885: *
2886: * <p>No delimiter is added before or after the list.
2887: * A <code>null</code> separator is the same as an empty String ("").</p>
2888: *
2889: * <p>See the examples here: {@link #join(Object[],String)}. </p>
2890: *
2891: * @param collection the <code>Collection</code> of values to join together, may be null
2892: * @param separator the separator character to use, null treated as ""
2893: * @return the joined String, <code>null</code> if null iterator input
2894: * @since 2.3
2895: */
2896: public static String join(Collection collection, String separator) {
2897: if (collection == null) {
2898: return null;
2899: }
2900: return join(collection.iterator(), separator);
2901: }
2902:
2903: // Delete
2904: //-----------------------------------------------------------------------
2905: /**
2906: * <p>Deletes all 'space' characters from a String as defined by
2907: * {@link Character#isSpace(char)}.</p>
2908: *
2909: * <p>This is the only StringUtils method that uses the
2910: * <code>isSpace</code> definition. You are advised to use
2911: * {@link #deleteWhitespace(String)} instead as whitespace is much
2912: * better localized.</p>
2913: *
2914: * <pre>
2915: * StringUtils.deleteSpaces(null) = null
2916: * StringUtils.deleteSpaces("") = ""
2917: * StringUtils.deleteSpaces("abc") = "abc"
2918: * StringUtils.deleteSpaces(" \t abc \n ") = "abc"
2919: * StringUtils.deleteSpaces("ab c") = "abc"
2920: * StringUtils.deleteSpaces("a\nb\tc ") = "abc"
2921: * </pre>
2922: *
2923: * <p>Spaces are defined as <code>{' ', '\t', '\r', '\n', '\b'}</code>
2924: * in line with the deprecated <code>isSpace</code> method.</p>
2925: *
2926: * @param str the String to delete spaces from, may be null
2927: * @return the String without 'spaces', <code>null</code> if null String input
2928: * @deprecated Use the better localized {@link #deleteWhitespace(String)}.
2929: * Method will be removed in Commons Lang 3.0.
2930: */
2931: public static String deleteSpaces(String str) {
2932: if (str == null) {
2933: return null;
2934: }
2935: return CharSetUtils.delete(str, " \t\r\n\b");
2936: }
2937:
2938: /**
2939: * <p>Deletes all whitespaces from a String as defined by
2940: * {@link Character#isWhitespace(char)}.</p>
2941: *
2942: * <pre>
2943: * StringUtils.deleteWhitespace(null) = null
2944: * StringUtils.deleteWhitespace("") = ""
2945: * StringUtils.deleteWhitespace("abc") = "abc"
2946: * StringUtils.deleteWhitespace(" ab c ") = "abc"
2947: * </pre>
2948: *
2949: * @param str the String to delete whitespace from, may be null
2950: * @return the String without whitespaces, <code>null</code> if null String input
2951: */
2952: public static String deleteWhitespace(String str) {
2953: if (isEmpty(str)) {
2954: return str;
2955: }
2956: int sz = str.length();
2957: char[] chs = new char[sz];
2958: int count = 0;
2959: for (int i = 0; i < sz; i++) {
2960: if (!Character.isWhitespace(str.charAt(i))) {
2961: chs[count++] = str.charAt(i);
2962: }
2963: }
2964: if (count == sz) {
2965: return str;
2966: }
2967: return new String(chs, 0, count);
2968: }
2969:
2970: // Remove
2971: //-----------------------------------------------------------------------
2972: /**
2973: * <p>Removes a substring only if it is at the begining of a source string,
2974: * otherwise returns the source string.</p>
2975: *
2976: * <p>A <code>null</code> source string will return <code>null</code>.
2977: * An empty ("") source string will return the empty string.
2978: * A <code>null</code> search string will return the source string.</p>
2979: *
2980: * <pre>
2981: * StringUtils.removeStart(null, *) = null
2982: * StringUtils.removeStart("", *) = ""
2983: * StringUtils.removeStart(*, null) = *
2984: * StringUtils.removeStart("www.domain.com", "www.") = "domain.com"
2985: * StringUtils.removeStart("domain.com", "www.") = "domain.com"
2986: * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
2987: * StringUtils.removeStart("abc", "") = "abc"
2988: * </pre>
2989: *
2990: * @param str the source String to search, may be null
2991: * @param remove the String to search for and remove, may be null
2992: * @return the substring with the string removed if found,
2993: * <code>null</code> if null String input
2994: * @since 2.1
2995: */
2996: public static String removeStart(String str, String remove) {
2997: if (isEmpty(str) || isEmpty(remove)) {
2998: return str;
2999: }
3000: if (str.startsWith(remove)) {
3001: return str.substring(remove.length());
3002: }
3003: return str;
3004: }
3005:
3006: /**
3007: * <p>Removes a substring only if it is at the end of a source string,
3008: * otherwise returns the source string.</p>
3009: *
3010: * <p>A <code>null</code> source string will return <code>null</code>.
3011: * An empty ("") source string will return the empty string.
3012: * A <code>null</code> search string will return the source string.</p>
3013: *
3014: * <pre>
3015: * StringUtils.removeEnd(null, *) = null
3016: * StringUtils.removeEnd("", *) = ""
3017: * StringUtils.removeEnd(*, null) = *
3018: * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com."
3019: * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain"
3020: * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
3021: * StringUtils.removeEnd("abc", "") = "abc"
3022: * </pre>
3023: *
3024: * @param str the source String to search, may be null
3025: * @param remove the String to search for and remove, may be null
3026: * @return the substring with the string removed if found,
3027: * <code>null</code> if null String input
3028: * @since 2.1
3029: */
3030: public static String removeEnd(String str, String remove) {
3031: if (isEmpty(str) || isEmpty(remove)) {
3032: return str;
3033: }
3034: if (str.endsWith(remove)) {
3035: return str.substring(0, str.length() - remove.length());
3036: }
3037: return str;
3038: }
3039:
3040: /**
3041: * <p>Removes all occurances of a substring from within the source string.</p>
3042: *
3043: * <p>A <code>null</code> source string will return <code>null</code>.
3044: * An empty ("") source string will return the empty string.
3045: * A <code>null</code> remove string will return the source string.
3046: * An empty ("") remove string will return the source string.</p>
3047: *
3048: * <pre>
3049: * StringUtils.remove(null, *) = null
3050: * StringUtils.remove("", *) = ""
3051: * StringUtils.remove(*, null) = *
3052: * StringUtils.remove(*, "") = *
3053: * StringUtils.remove("queued", "ue") = "qd"
3054: * StringUtils.remove("queued", "zz") = "queued"
3055: * </pre>
3056: *
3057: * @param str the source String to search, may be null
3058: * @param remove the String to search for and remove, may be null
3059: * @return the substring with the string removed if found,
3060: * <code>null</code> if null String input
3061: * @since 2.1
3062: */
3063: public static String remove(String str, String remove) {
3064: if (isEmpty(str) || isEmpty(remove)) {
3065: return str;
3066: }
3067: return replace(str, remove, "", -1);
3068: }
3069:
3070: /**
3071: * <p>Removes all occurances of a character from within the source string.</p>
3072: *
3073: * <p>A <code>null</code> source string will return <code>null</code>.
3074: * An empty ("") source string will return the empty string.</p>
3075: *
3076: * <pre>
3077: * StringUtils.remove(null, *) = null
3078: * StringUtils.remove("", *) = ""
3079: * StringUtils.remove("queued", 'u') = "qeed"
3080: * StringUtils.remove("queued", 'z') = "queued"
3081: * </pre>
3082: *
3083: * @param str the source String to search, may be null
3084: * @param remove the char to search for and remove, may be null
3085: * @return the substring with the char removed if found,
3086: * <code>null</code> if null String input
3087: * @since 2.1
3088: */
3089: public static String remove(String str, char remove) {
3090: if (isEmpty(str) || str.indexOf(remove) == -1) {
3091: return str;
3092: }
3093: char[] chars = str.toCharArray();
3094: int pos = 0;
3095: for (int i = 0; i < chars.length; i++) {
3096: if (chars[i] != remove) {
3097: chars[pos++] = chars[i];
3098: }
3099: }
3100: return new String(chars, 0, pos);
3101: }
3102:
3103: // Replacing
3104: //-----------------------------------------------------------------------
3105: /**
3106: * <p>Replaces a String with another String inside a larger String, once.</p>
3107: *
3108: * <p>A <code>null</code> reference passed to this method is a no-op.</p>
3109: *
3110: * <pre>
3111: * StringUtils.replaceOnce(null, *, *) = null
3112: * StringUtils.replaceOnce("", *, *) = ""
3113: * StringUtils.replaceOnce("any", null, *) = "any"
3114: * StringUtils.replaceOnce("any", *, null) = "any"
3115: * StringUtils.replaceOnce("any", "", *) = "any"
3116: * StringUtils.replaceOnce("aba", "a", null) = "aba"
3117: * StringUtils.replaceOnce("aba", "a", "") = "ba"
3118: * StringUtils.replaceOnce("aba", "a", "z") = "zba"
3119: * </pre>
3120: *
3121: * @see #replace(String text, String repl, String with, int max)
3122: * @param text text to search and replace in, may be null
3123: * @param repl the String to search for, may be null
3124: * @param with the String to replace with, may be null
3125: * @return the text with any replacements processed,
3126: * <code>null</code> if null String input
3127: */
3128: public static String replaceOnce(String text, String repl,
3129: String with) {
3130: return replace(text, repl, with, 1);
3131: }
3132:
3133: /**
3134: * <p>Replaces all occurrences of a String within another String.</p>
3135: *
3136: * <p>A <code>null</code> reference passed to this method is a no-op.</p>
3137: *
3138: * <pre>
3139: * StringUtils.replace(null, *, *) = null
3140: * StringUtils.replace("", *, *) = ""
3141: * StringUtils.replace("any", null, *) = "any"
3142: * StringUtils.replace("any", *, null) = "any"
3143: * StringUtils.replace("any", "", *) = "any"
3144: * StringUtils.replace("aba", "a", null) = "aba"
3145: * StringUtils.replace("aba", "a", "") = "b"
3146: * StringUtils.replace("aba", "a", "z") = "zbz"
3147: * </pre>
3148: *
3149: * @see #replace(String text, String repl, String with, int max)
3150: * @param text text to search and replace in, may be null
3151: * @param repl the String to search for, may be null
3152: * @param with the String to replace with, may be null
3153: * @return the text with any replacements processed,
3154: * <code>null</code> if null String input
3155: */
3156: public static String replace(String text, String repl, String with) {
3157: return replace(text, repl, with, -1);
3158: }
3159:
3160: /**
3161: * <p>Replaces a String with another String inside a larger String,
3162: * for the first <code>max</code> values of the search String.</p>
3163: *
3164: * <p>A <code>null</code> reference passed to this method is a no-op.</p>
3165: *
3166: * <pre>
3167: * StringUtils.replace(null, *, *, *) = null
3168: * StringUtils.replace("", *, *, *) = ""
3169: * StringUtils.replace("any", null, *, *) = "any"
3170: * StringUtils.replace("any", *, null, *) = "any"
3171: * StringUtils.replace("any", "", *, *) = "any"
3172: * StringUtils.replace("any", *, *, 0) = "any"
3173: * StringUtils.replace("abaa", "a", null, -1) = "abaa"
3174: * StringUtils.replace("abaa", "a", "", -1) = "b"
3175: * StringUtils.replace("abaa", "a", "z", 0) = "abaa"
3176: * StringUtils.replace("abaa", "a", "z", 1) = "zbaa"
3177: * StringUtils.replace("abaa", "a", "z", 2) = "zbza"
3178: * StringUtils.replace("abaa", "a", "z", -1) = "zbzz"
3179: * </pre>
3180: *
3181: * @param text text to search and replace in, may be null
3182: * @param repl the String to search for, may be null
3183: * @param with the String to replace with, may be null
3184: * @param max maximum number of values to replace, or <code>-1</code> if no maximum
3185: * @return the text with any replacements processed,
3186: * <code>null</code> if null String input
3187: */
3188: public static String replace(String text, String repl, String with,
3189: int max) {
3190: if (isEmpty(text) || isEmpty(repl) || with == null || max == 0) {
3191: return text;
3192: }
3193: int start = 0;
3194: int end = text.indexOf(repl, start);
3195: if (end == -1) {
3196: return text;
3197: }
3198: int replLength = repl.length();
3199: int increase = with.length() - replLength;
3200: increase = (increase < 0 ? 0 : increase);
3201: increase *= (max < 0 ? 16 : (max > 64 ? 64 : max));
3202: StringBuffer buf = new StringBuffer(text.length() + increase);
3203: while (end != -1) {
3204: buf.append(text.substring(start, end)).append(with);
3205: start = end + replLength;
3206: if (--max == 0) {
3207: break;
3208: }
3209: end = text.indexOf(repl, start);
3210: }
3211: buf.append(text.substring(start));
3212: return buf.toString();
3213: }
3214:
3215: // Replace, character based
3216: //-----------------------------------------------------------------------
3217: /**
3218: * <p>Replaces all occurrences of a character in a String with another.
3219: * This is a null-safe version of {@link String#replace(char, char)}.</p>
3220: *
3221: * <p>A <code>null</code> string input returns <code>null</code>.
3222: * An empty ("") string input returns an empty string.</p>
3223: *
3224: * <pre>
3225: * StringUtils.replaceChars(null, *, *) = null
3226: * StringUtils.replaceChars("", *, *) = ""
3227: * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
3228: * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
3229: * </pre>
3230: *
3231: * @param str String to replace characters in, may be null
3232: * @param searchChar the character to search for, may be null
3233: * @param replaceChar the character to replace, may be null
3234: * @return modified String, <code>null</code> if null string input
3235: * @since 2.0
3236: */
3237: public static String replaceChars(String str, char searchChar,
3238: char replaceChar) {
3239: if (str == null) {
3240: return null;
3241: }
3242: return str.replace(searchChar, replaceChar);
3243: }
3244:
3245: /**
3246: * <p>Replaces multiple characters in a String in one go.
3247: * This method can also be used to delete characters.</p>
3248: *
3249: * <p>For example:<br />
3250: * <code>replaceChars("hello", "ho", "jy") = jelly</code>.</p>
3251: *
3252: * <p>A <code>null</code> string input returns <code>null</code>.
3253: * An empty ("") string input returns an empty string.
3254: * A null or empty set of search characters returns the input string.</p>
3255: *
3256: * <p>The length of the search characters should normally equal the length
3257: * of the replace characters.
3258: * If the search characters is longer, then the extra search characters
3259: * are deleted.
3260: * If the search characters is shorter, then the extra replace characters
3261: * are ignored.</p>
3262: *
3263: * <pre>
3264: * StringUtils.replaceChars(null, *, *) = null
3265: * StringUtils.replaceChars("", *, *) = ""
3266: * StringUtils.replaceChars("abc", null, *) = "abc"
3267: * StringUtils.replaceChars("abc", "", *) = "abc"
3268: * StringUtils.replaceChars("abc", "b", null) = "ac"
3269: * StringUtils.replaceChars("abc", "b", "") = "ac"
3270: * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya"
3271: * StringUtils.replaceChars("abcba", "bc", "y") = "ayya"
3272: * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
3273: * </pre>
3274: *
3275: * @param str String to replace characters in, may be null
3276: * @param searchChars a set of characters to search for, may be null
3277: * @param replaceChars a set of characters to replace, may be null
3278: * @return modified String, <code>null</code> if null string input
3279: * @since 2.0
3280: */
3281: public static String replaceChars(String str, String searchChars,
3282: String replaceChars) {
3283: if (isEmpty(str) || isEmpty(searchChars)) {
3284: return str;
3285: }
3286: if (replaceChars == null) {
3287: replaceChars = "";
3288: }
3289: boolean modified = false;
3290: int replaceCharsLength = replaceChars.length();
3291: int strLength = str.length();
3292: StringBuffer buf = new StringBuffer(strLength);
3293: for (int i = 0; i < strLength; i++) {
3294: char ch = str.charAt(i);
3295: int index = searchChars.indexOf(ch);
3296: if (index >= 0) {
3297: modified = true;
3298: if (index < replaceCharsLength) {
3299: buf.append(replaceChars.charAt(index));
3300: }
3301: } else {
3302: buf.append(ch);
3303: }
3304: }
3305: if (modified) {
3306: return buf.toString();
3307: } else {
3308: return str;
3309: }
3310: }
3311:
3312: // Overlay
3313: //-----------------------------------------------------------------------
3314: /**
3315: * <p>Overlays part of a String with another String.</p>
3316: *
3317: * <pre>
3318: * StringUtils.overlayString(null, *, *, *) = NullPointerException
3319: * StringUtils.overlayString(*, null, *, *) = NullPointerException
3320: * StringUtils.overlayString("", "abc", 0, 0) = "abc"
3321: * StringUtils.overlayString("abcdef", null, 2, 4) = "abef"
3322: * StringUtils.overlayString("abcdef", "", 2, 4) = "abef"
3323: * StringUtils.overlayString("abcdef", "zzzz", 2, 4) = "abzzzzef"
3324: * StringUtils.overlayString("abcdef", "zzzz", 4, 2) = "abcdzzzzcdef"
3325: * StringUtils.overlayString("abcdef", "zzzz", -1, 4) = IndexOutOfBoundsException
3326: * StringUtils.overlayString("abcdef", "zzzz", 2, 8) = IndexOutOfBoundsException
3327: * </pre>
3328: *
3329: * @param text the String to do overlaying in, may be null
3330: * @param overlay the String to overlay, may be null
3331: * @param start the position to start overlaying at, must be valid
3332: * @param end the position to stop overlaying before, must be valid
3333: * @return overlayed String, <code>null</code> if null String input
3334: * @throws NullPointerException if text or overlay is null
3335: * @throws IndexOutOfBoundsException if either position is invalid
3336: * @deprecated Use better named {@link #overlay(String, String, int, int)} instead.
3337: * Method will be removed in Commons Lang 3.0.
3338: */
3339: public static String overlayString(String text, String overlay,
3340: int start, int end) {
3341: return new StringBuffer(start + overlay.length()
3342: + text.length() - end + 1).append(
3343: text.substring(0, start)).append(overlay).append(
3344: text.substring(end)).toString();
3345: }
3346:
3347: /**
3348: * <p>Overlays part of a String with another String.</p>
3349: *
3350: * <p>A <code>null</code> string input returns <code>null</code>.
3351: * A negative index is treated as zero.
3352: * An index greater than the string length is treated as the string length.
3353: * The start index is always the smaller of the two indices.</p>
3354: *
3355: * <pre>
3356: * StringUtils.overlay(null, *, *, *) = null
3357: * StringUtils.overlay("", "abc", 0, 0) = "abc"
3358: * StringUtils.overlay("abcdef", null, 2, 4) = "abef"
3359: * StringUtils.overlay("abcdef", "", 2, 4) = "abef"
3360: * StringUtils.overlay("abcdef", "", 4, 2) = "abef"
3361: * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef"
3362: * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef"
3363: * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef"
3364: * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz"
3365: * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
3366: * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz"
3367: * </pre>
3368: *
3369: * @param str the String to do overlaying in, may be null
3370: * @param overlay the String to overlay, may be null
3371: * @param start the position to start overlaying at
3372: * @param end the position to stop overlaying before
3373: * @return overlayed String, <code>null</code> if null String input
3374: * @since 2.0
3375: */
3376: public static String overlay(String str, String overlay, int start,
3377: int end) {
3378: if (str == null) {
3379: return null;
3380: }
3381: if (overlay == null) {
3382: overlay = EMPTY;
3383: }
3384: int len = str.length();
3385: if (start < 0) {
3386: start = 0;
3387: }
3388: if (start > len) {
3389: start = len;
3390: }
3391: if (end < 0) {
3392: end = 0;
3393: }
3394: if (end > len) {
3395: end = len;
3396: }
3397: if (start > end) {
3398: int temp = start;
3399: start = end;
3400: end = temp;
3401: }
3402: return new StringBuffer(len + start - end + overlay.length()
3403: + 1).append(str.substring(0, start)).append(overlay)
3404: .append(str.substring(end)).toString();
3405: }
3406:
3407: // Chomping
3408: //-----------------------------------------------------------------------
3409: /**
3410: * <p>Removes one newline from end of a String if it's there,
3411: * otherwise leave it alone. A newline is "<code>\n</code>",
3412: * "<code>\r</code>", or "<code>\r\n</code>".</p>
3413: *
3414: * <p>NOTE: This method changed in 2.0.
3415: * It now more closely matches Perl chomp.</p>
3416: *
3417: * <pre>
3418: * StringUtils.chomp(null) = null
3419: * StringUtils.chomp("") = ""
3420: * StringUtils.chomp("abc \r") = "abc "
3421: * StringUtils.chomp("abc\n") = "abc"
3422: * StringUtils.chomp("abc\r\n") = "abc"
3423: * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
3424: * StringUtils.chomp("abc\n\r") = "abc\n"
3425: * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc"
3426: * StringUtils.chomp("\r") = ""
3427: * StringUtils.chomp("\n") = ""
3428: * StringUtils.chomp("\r\n") = ""
3429: * </pre>
3430: *
3431: * @param str the String to chomp a newline from, may be null
3432: * @return String without newline, <code>null</code> if null String input
3433: */
3434: public static String chomp(String str) {
3435: if (isEmpty(str)) {
3436: return str;
3437: }
3438:
3439: if (str.length() == 1) {
3440: char ch = str.charAt(0);
3441: if (ch == CharUtils.CR || ch == CharUtils.LF) {
3442: return EMPTY;
3443: } else {
3444: return str;
3445: }
3446: }
3447:
3448: int lastIdx = str.length() - 1;
3449: char last = str.charAt(lastIdx);
3450:
3451: if (last == CharUtils.LF) {
3452: if (str.charAt(lastIdx - 1) == CharUtils.CR) {
3453: lastIdx--;
3454: }
3455: } else if (last != CharUtils.CR) {
3456: lastIdx++;
3457: }
3458: return str.substring(0, lastIdx);
3459: }
3460:
3461: /**
3462: * <p>Removes <code>separator</code> from the end of
3463: * <code>str</code> if it's there, otherwise leave it alone.</p>
3464: *
3465: * <p>NOTE: This method changed in version 2.0.
3466: * It now more closely matches Perl chomp.
3467: * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
3468: * This method uses {@link String#endsWith(String)}.</p>
3469: *
3470: * <pre>
3471: * StringUtils.chomp(null, *) = null
3472: * StringUtils.chomp("", *) = ""
3473: * StringUtils.chomp("foobar", "bar") = "foo"
3474: * StringUtils.chomp("foobar", "baz") = "foobar"
3475: * StringUtils.chomp("foo", "foo") = ""
3476: * StringUtils.chomp("foo ", "foo") = "foo "
3477: * StringUtils.chomp(" foo", "foo") = " "
3478: * StringUtils.chomp("foo", "foooo") = "foo"
3479: * StringUtils.chomp("foo", "") = "foo"
3480: * StringUtils.chomp("foo", null) = "foo"
3481: * </pre>
3482: *
3483: * @param str the String to chomp from, may be null
3484: * @param separator separator String, may be null
3485: * @return String without trailing separator, <code>null</code> if null String input
3486: */
3487: public static String chomp(String str, String separator) {
3488: if (isEmpty(str) || separator == null) {
3489: return str;
3490: }
3491: if (str.endsWith(separator)) {
3492: return str.substring(0, str.length() - separator.length());
3493: }
3494: return str;
3495: }
3496:
3497: /**
3498: * <p>Remove any "\n" if and only if it is at the end
3499: * of the supplied String.</p>
3500: *
3501: * @param str the String to chomp from, must not be null
3502: * @return String without chomped ending
3503: * @throws NullPointerException if str is <code>null</code>
3504: * @deprecated Use {@link #chomp(String)} instead.
3505: * Method will be removed in Commons Lang 3.0.
3506: */
3507: public static String chompLast(String str) {
3508: return chompLast(str, "\n");
3509: }
3510:
3511: /**
3512: * <p>Remove a value if and only if the String ends with that value.</p>
3513: *
3514: * @param str the String to chomp from, must not be null
3515: * @param sep the String to chomp, must not be null
3516: * @return String without chomped ending
3517: * @throws NullPointerException if str or sep is <code>null</code>
3518: * @deprecated Use {@link #chomp(String,String)} instead.
3519: * Method will be removed in Commons Lang 3.0.
3520: */
3521: public static String chompLast(String str, String sep) {
3522: if (str.length() == 0) {
3523: return str;
3524: }
3525: String sub = str.substring(str.length() - sep.length());
3526: if (sep.equals(sub)) {
3527: return str.substring(0, str.length() - sep.length());
3528: } else {
3529: return str;
3530: }
3531: }
3532:
3533: /**
3534: * <p>Remove everything and return the last value of a supplied String, and
3535: * everything after it from a String.</p>
3536: *
3537: * @param str the String to chomp from, must not be null
3538: * @param sep the String to chomp, must not be null
3539: * @return String chomped
3540: * @throws NullPointerException if str or sep is <code>null</code>
3541: * @deprecated Use {@link #substringAfterLast(String, String)} instead
3542: * (although this doesn't include the separator)
3543: * Method will be removed in Commons Lang 3.0.
3544: */
3545: public static String getChomp(String str, String sep) {
3546: int idx = str.lastIndexOf(sep);
3547: if (idx == str.length() - sep.length()) {
3548: return sep;
3549: } else if (idx != -1) {
3550: return str.substring(idx);
3551: } else {
3552: return EMPTY;
3553: }
3554: }
3555:
3556: /**
3557: * <p>Remove the first value of a supplied String, and everything before it
3558: * from a String.</p>
3559: *
3560: * @param str the String to chomp from, must not be null
3561: * @param sep the String to chomp, must not be null
3562: * @return String without chomped beginning
3563: * @throws NullPointerException if str or sep is <code>null</code>
3564: * @deprecated Use {@link #substringAfter(String,String)} instead.
3565: * Method will be removed in Commons Lang 3.0.
3566: */
3567: public static String prechomp(String str, String sep) {
3568: int idx = str.indexOf(sep);
3569: if (idx != -1) {
3570: return str.substring(idx + sep.length());
3571: } else {
3572: return str;
3573: }
3574: }
3575:
3576: /**
3577: * <p>Remove and return everything before the first value of a
3578: * supplied String from another String.</p>
3579: *
3580: * @param str the String to chomp from, must not be null
3581: * @param sep the String to chomp, must not be null
3582: * @return String prechomped
3583: * @throws NullPointerException if str or sep is <code>null</code>
3584: * @deprecated Use {@link #substringBefore(String,String)} instead
3585: * (although this doesn't include the separator).
3586: * Method will be removed in Commons Lang 3.0.
3587: */
3588: public static String getPrechomp(String str, String sep) {
3589: int idx = str.indexOf(sep);
3590: if (idx != -1) {
3591: return str.substring(0, idx + sep.length());
3592: } else {
3593: return EMPTY;
3594: }
3595: }
3596:
3597: // Chopping
3598: //-----------------------------------------------------------------------
3599: /**
3600: * <p>Remove the last character from a String.</p>
3601: *
3602: * <p>If the String ends in <code>\r\n</code>, then remove both
3603: * of them.</p>
3604: *
3605: * <pre>
3606: * StringUtils.chop(null) = null
3607: * StringUtils.chop("") = ""
3608: * StringUtils.chop("abc \r") = "abc "
3609: * StringUtils.chop("abc\n") = "abc"
3610: * StringUtils.chop("abc\r\n") = "abc"
3611: * StringUtils.chop("abc") = "ab"
3612: * StringUtils.chop("abc\nabc") = "abc\nab"
3613: * StringUtils.chop("a") = ""
3614: * StringUtils.chop("\r") = ""
3615: * StringUtils.chop("\n") = ""
3616: * StringUtils.chop("\r\n") = ""
3617: * </pre>
3618: *
3619: * @param str the String to chop last character from, may be null
3620: * @return String without last character, <code>null</code> if null String input
3621: */
3622: public static String chop(String str) {
3623: if (str == null) {
3624: return null;
3625: }
3626: int strLen = str.length();
3627: if (strLen < 2) {
3628: return EMPTY;
3629: }
3630: int lastIdx = strLen - 1;
3631: String ret = str.substring(0, lastIdx);
3632: char last = str.charAt(lastIdx);
3633: if (last == CharUtils.LF) {
3634: if (ret.charAt(lastIdx - 1) == CharUtils.CR) {
3635: return ret.substring(0, lastIdx - 1);
3636: }
3637: }
3638: return ret;
3639: }
3640:
3641: /**
3642: * <p>Removes <code>\n</code> from end of a String if it's there.
3643: * If a <code>\r</code> precedes it, then remove that too.</p>
3644: *
3645: * @param str the String to chop a newline from, must not be null
3646: * @return String without newline
3647: * @throws NullPointerException if str is <code>null</code>
3648: * @deprecated Use {@link #chomp(String)} instead.
3649: * Method will be removed in Commons Lang 3.0.
3650: */
3651: public static String chopNewline(String str) {
3652: int lastIdx = str.length() - 1;
3653: if (lastIdx <= 0) {
3654: return EMPTY;
3655: }
3656: char last = str.charAt(lastIdx);
3657: if (last == CharUtils.LF) {
3658: if (str.charAt(lastIdx - 1) == CharUtils.CR) {
3659: lastIdx--;
3660: }
3661: } else {
3662: lastIdx++;
3663: }
3664: return str.substring(0, lastIdx);
3665: }
3666:
3667: // Conversion
3668: //-----------------------------------------------------------------------
3669: /**
3670: * <p>Escapes any values it finds into their String form.</p>
3671: *
3672: * <p>So a tab becomes the characters <code>'\\'</code> and
3673: * <code>'t'</code>.</p>
3674: *
3675: * <p>As of Lang 2.0, this calls {@link StringEscapeUtils#escapeJava(String)}
3676: * behind the scenes.
3677: * </p>
3678: * @see StringEscapeUtils#escapeJava(java.lang.String)
3679: * @param str String to escape values in
3680: * @return String with escaped values
3681: * @throws NullPointerException if str is <code>null</code>
3682: * @deprecated Use {@link StringEscapeUtils#escapeJava(String)}
3683: * This method will be removed in Commons Lang 3.0
3684: */
3685: public static String escape(String str) {
3686: return StringEscapeUtils.escapeJava(str);
3687: }
3688:
3689: // Padding
3690: //-----------------------------------------------------------------------
3691: /**
3692: * <p>Repeat a String <code>repeat</code> times to form a
3693: * new String.</p>
3694: *
3695: * <pre>
3696: * StringUtils.repeat(null, 2) = null
3697: * StringUtils.repeat("", 0) = ""
3698: * StringUtils.repeat("", 2) = ""
3699: * StringUtils.repeat("a", 3) = "aaa"
3700: * StringUtils.repeat("ab", 2) = "abab"
3701: * StringUtils.repeat("a", -2) = ""
3702: * </pre>
3703: *
3704: * @param str the String to repeat, may be null
3705: * @param repeat number of times to repeat str, negative treated as zero
3706: * @return a new String consisting of the original String repeated,
3707: * <code>null</code> if null String input
3708: */
3709: public static String repeat(String str, int repeat) {
3710: // Performance tuned for 2.0 (JDK1.4)
3711:
3712: if (str == null) {
3713: return null;
3714: }
3715: if (repeat <= 0) {
3716: return EMPTY;
3717: }
3718: int inputLength = str.length();
3719: if (repeat == 1 || inputLength == 0) {
3720: return str;
3721: }
3722: if (inputLength == 1 && repeat <= PAD_LIMIT) {
3723: return padding(repeat, str.charAt(0));
3724: }
3725:
3726: int outputLength = inputLength * repeat;
3727: switch (inputLength) {
3728: case 1:
3729: char ch = str.charAt(0);
3730: char[] output1 = new char[outputLength];
3731: for (int i = repeat - 1; i >= 0; i--) {
3732: output1[i] = ch;
3733: }
3734: return new String(output1);
3735: case 2:
3736: char ch0 = str.charAt(0);
3737: char ch1 = str.charAt(1);
3738: char[] output2 = new char[outputLength];
3739: for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
3740: output2[i] = ch0;
3741: output2[i + 1] = ch1;
3742: }
3743: return new String(output2);
3744: default:
3745: StringBuffer buf = new StringBuffer(outputLength);
3746: for (int i = 0; i < repeat; i++) {
3747: buf.append(str);
3748: }
3749: return buf.toString();
3750: }
3751: }
3752:
3753: /**
3754: * <p>Returns padding using the specified delimiter repeated
3755: * to a given length.</p>
3756: *
3757: * <pre>
3758: * StringUtils.padding(0, 'e') = ""
3759: * StringUtils.padding(3, 'e') = "eee"
3760: * StringUtils.padding(-2, 'e') = IndexOutOfBoundsException
3761: * </pre>
3762: *
3763: * <p>Note: this method doesn't not support padding with
3764: * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
3765: * as they require a pair of <code>char</code>s to be represented.
3766: * If you are needing to support full I18N of your applications
3767: * consider using {@link #repeat(String, int)} instead.
3768: * </p>
3769: *
3770: * @param repeat number of times to repeat delim
3771: * @param padChar character to repeat
3772: * @return String with repeated character
3773: * @throws IndexOutOfBoundsException if <code>repeat < 0</code>
3774: * @see #repeat(String, int)
3775: */
3776: private static String padding(int repeat, char padChar)
3777: throws IndexOutOfBoundsException {
3778: if (repeat < 0) {
3779: throw new IndexOutOfBoundsException(
3780: "Cannot pad a negative amount: " + repeat);
3781: }
3782: final char[] buf = new char[repeat];
3783: for (int i = 0; i < buf.length; i++) {
3784: buf[i] = padChar;
3785: }
3786: return new String(buf);
3787: }
3788:
3789: /**
3790: * <p>Right pad a String with spaces (' ').</p>
3791: *
3792: * <p>The String is padded to the size of <code>size</code>.</p>
3793: *
3794: * <pre>
3795: * StringUtils.rightPad(null, *) = null
3796: * StringUtils.rightPad("", 3) = " "
3797: * StringUtils.rightPad("bat", 3) = "bat"
3798: * StringUtils.rightPad("bat", 5) = "bat "
3799: * StringUtils.rightPad("bat", 1) = "bat"
3800: * StringUtils.rightPad("bat", -1) = "bat"
3801: * </pre>
3802: *
3803: * @param str the String to pad out, may be null
3804: * @param size the size to pad to
3805: * @return right padded String or original String if no padding is necessary,
3806: * <code>null</code> if null String input
3807: */
3808: public static String rightPad(String str, int size) {
3809: return rightPad(str, size, ' ');
3810: }
3811:
3812: /**
3813: * <p>Right pad a String with a specified character.</p>
3814: *
3815: * <p>The String is padded to the size of <code>size</code>.</p>
3816: *
3817: * <pre>
3818: * StringUtils.rightPad(null, *, *) = null
3819: * StringUtils.rightPad("", 3, 'z') = "zzz"
3820: * StringUtils.rightPad("bat", 3, 'z') = "bat"
3821: * StringUtils.rightPad("bat", 5, 'z') = "batzz"
3822: * StringUtils.rightPad("bat", 1, 'z') = "bat"
3823: * StringUtils.rightPad("bat", -1, 'z') = "bat"
3824: * </pre>
3825: *
3826: * @param str the String to pad out, may be null
3827: * @param size the size to pad to
3828: * @param padChar the character to pad with
3829: * @return right padded String or original String if no padding is necessary,
3830: * <code>null</code> if null String input
3831: * @since 2.0
3832: */
3833: public static String rightPad(String str, int size, char padChar) {
3834: if (str == null) {
3835: return null;
3836: }
3837: int pads = size - str.length();
3838: if (pads <= 0) {
3839: return str; // returns original String when possible
3840: }
3841: if (pads > PAD_LIMIT) {
3842: return rightPad(str, size, String.valueOf(padChar));
3843: }
3844: return str.concat(padding(pads, padChar));
3845: }
3846:
3847: /**
3848: * <p>Right pad a String with a specified String.</p>
3849: *
3850: * <p>The String is padded to the size of <code>size</code>.</p>
3851: *
3852: * <pre>
3853: * StringUtils.rightPad(null, *, *) = null
3854: * StringUtils.rightPad("", 3, "z") = "zzz"
3855: * StringUtils.rightPad("bat", 3, "yz") = "bat"
3856: * StringUtils.rightPad("bat", 5, "yz") = "batyz"
3857: * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy"
3858: * StringUtils.rightPad("bat", 1, "yz") = "bat"
3859: * StringUtils.rightPad("bat", -1, "yz") = "bat"
3860: * StringUtils.rightPad("bat", 5, null) = "bat "
3861: * StringUtils.rightPad("bat", 5, "") = "bat "
3862: * </pre>
3863: *
3864: * @param str the String to pad out, may be null
3865: * @param size the size to pad to
3866: * @param padStr the String to pad with, null or empty treated as single space
3867: * @return right padded String or original String if no padding is necessary,
3868: * <code>null</code> if null String input
3869: */
3870: public static String rightPad(String str, int size, String padStr) {
3871: if (str == null) {
3872: return null;
3873: }
3874: if (isEmpty(padStr)) {
3875: padStr = " ";
3876: }
3877: int padLen = padStr.length();
3878: int strLen = str.length();
3879: int pads = size - strLen;
3880: if (pads <= 0) {
3881: return str; // returns original String when possible
3882: }
3883: if (padLen == 1 && pads <= PAD_LIMIT) {
3884: return rightPad(str, size, padStr.charAt(0));
3885: }
3886:
3887: if (pads == padLen) {
3888: return str.concat(padStr);
3889: } else if (pads < padLen) {
3890: return str.concat(padStr.substring(0, pads));
3891: } else {
3892: char[] padding = new char[pads];
3893: char[] padChars = padStr.toCharArray();
3894: for (int i = 0; i < pads; i++) {
3895: padding[i] = padChars[i % padLen];
3896: }
3897: return str.concat(new String(padding));
3898: }
3899: }
3900:
3901: /**
3902: * <p>Left pad a String with spaces (' ').</p>
3903: *
3904: * <p>The String is padded to the size of <code>size<code>.</p>
3905: *
3906: * <pre>
3907: * StringUtils.leftPad(null, *) = null
3908: * StringUtils.leftPad("", 3) = " "
3909: * StringUtils.leftPad("bat", 3) = "bat"
3910: * StringUtils.leftPad("bat", 5) = " bat"
3911: * StringUtils.leftPad("bat", 1) = "bat"
3912: * StringUtils.leftPad("bat", -1) = "bat"
3913: * </pre>
3914: *
3915: * @param str the String to pad out, may be null
3916: * @param size the size to pad to
3917: * @return left padded String or original String if no padding is necessary,
3918: * <code>null</code> if null String input
3919: */
3920: public static String leftPad(String str, int size) {
3921: return leftPad(str, size, ' ');
3922: }
3923:
3924: /**
3925: * <p>Left pad a String with a specified character.</p>
3926: *
3927: * <p>Pad to a size of <code>size</code>.</p>
3928: *
3929: * <pre>
3930: * StringUtils.leftPad(null, *, *) = null
3931: * StringUtils.leftPad("", 3, 'z') = "zzz"
3932: * StringUtils.leftPad("bat", 3, 'z') = "bat"
3933: * StringUtils.leftPad("bat", 5, 'z') = "zzbat"
3934: * StringUtils.leftPad("bat", 1, 'z') = "bat"
3935: * StringUtils.leftPad("bat", -1, 'z') = "bat"
3936: * </pre>
3937: *
3938: * @param str the String to pad out, may be null
3939: * @param size the size to pad to
3940: * @param padChar the character to pad with
3941: * @return left padded String or original String if no padding is necessary,
3942: * <code>null</code> if null String input
3943: * @since 2.0
3944: */
3945: public static String leftPad(String str, int size, char padChar) {
3946: if (str == null) {
3947: return null;
3948: }
3949: int pads = size - str.length();
3950: if (pads <= 0) {
3951: return str; // returns original String when possible
3952: }
3953: if (pads > PAD_LIMIT) {
3954: return leftPad(str, size, String.valueOf(padChar));
3955: }
3956: return padding(pads, padChar).concat(str);
3957: }
3958:
3959: /**
3960: * <p>Left pad a String with a specified String.</p>
3961: *
3962: * <p>Pad to a size of <code>size</code>.</p>
3963: *
3964: * <pre>
3965: * StringUtils.leftPad(null, *, *) = null
3966: * StringUtils.leftPad("", 3, "z") = "zzz"
3967: * StringUtils.leftPad("bat", 3, "yz") = "bat"
3968: * StringUtils.leftPad("bat", 5, "yz") = "yzbat"
3969: * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat"
3970: * StringUtils.leftPad("bat", 1, "yz") = "bat"
3971: * StringUtils.leftPad("bat", -1, "yz") = "bat"
3972: * StringUtils.leftPad("bat", 5, null) = " bat"
3973: * StringUtils.leftPad("bat", 5, "") = " bat"
3974: * </pre>
3975: *
3976: * @param str the String to pad out, may be null
3977: * @param size the size to pad to
3978: * @param padStr the String to pad with, null or empty treated as single space
3979: * @return left padded String or original String if no padding is necessary,
3980: * <code>null</code> if null String input
3981: */
3982: public static String leftPad(String str, int size, String padStr) {
3983: if (str == null) {
3984: return null;
3985: }
3986: if (isEmpty(padStr)) {
3987: padStr = " ";
3988: }
3989: int padLen = padStr.length();
3990: int strLen = str.length();
3991: int pads = size - strLen;
3992: if (pads <= 0) {
3993: return str; // returns original String when possible
3994: }
3995: if (padLen == 1 && pads <= PAD_LIMIT) {
3996: return leftPad(str, size, padStr.charAt(0));
3997: }
3998:
3999: if (pads == padLen) {
4000: return padStr.concat(str);
4001: } else if (pads < padLen) {
4002: return padStr.substring(0, pads).concat(str);
4003: } else {
4004: char[] padding = new char[pads];
4005: char[] padChars = padStr.toCharArray();
4006: for (int i = 0; i < pads; i++) {
4007: padding[i] = padChars[i % padLen];
4008: }
4009: return new String(padding).concat(str);
4010: }
4011: }
4012:
4013: // Centering
4014: //-----------------------------------------------------------------------
4015: /**
4016: * <p>Centers a String in a larger String of size <code>size</code>
4017: * using the space character (' ').<p>
4018: *
4019: * <p>If the size is less than the String length, the String is returned.
4020: * A <code>null</code> String returns <code>null</code>.
4021: * A negative size is treated as zero.</p>
4022: *
4023: * <p>Equivalent to <code>center(str, size, " ")</code>.</p>
4024: *
4025: * <pre>
4026: * StringUtils.center(null, *) = null
4027: * StringUtils.center("", 4) = " "
4028: * StringUtils.center("ab", -1) = "ab"
4029: * StringUtils.center("ab", 4) = " ab "
4030: * StringUtils.center("abcd", 2) = "abcd"
4031: * StringUtils.center("a", 4) = " a "
4032: * </pre>
4033: *
4034: * @param str the String to center, may be null
4035: * @param size the int size of new String, negative treated as zero
4036: * @return centered String, <code>null</code> if null String input
4037: */
4038: public static String center(String str, int size) {
4039: return center(str, size, ' ');
4040: }
4041:
4042: /**
4043: * <p>Centers a String in a larger String of size <code>size</code>.
4044: * Uses a supplied character as the value to pad the String with.</p>
4045: *
4046: * <p>If the size is less than the String length, the String is returned.
4047: * A <code>null</code> String returns <code>null</code>.
4048: * A negative size is treated as zero.</p>
4049: *
4050: * <pre>
4051: * StringUtils.center(null, *, *) = null
4052: * StringUtils.center("", 4, ' ') = " "
4053: * StringUtils.center("ab", -1, ' ') = "ab"
4054: * StringUtils.center("ab", 4, ' ') = " ab"
4055: * StringUtils.center("abcd", 2, ' ') = "abcd"
4056: * StringUtils.center("a", 4, ' ') = " a "
4057: * StringUtils.center("a", 4, 'y') = "yayy"
4058: * </pre>
4059: *
4060: * @param str the String to center, may be null
4061: * @param size the int size of new String, negative treated as zero
4062: * @param padChar the character to pad the new String with
4063: * @return centered String, <code>null</code> if null String input
4064: * @since 2.0
4065: */
4066: public static String center(String str, int size, char padChar) {
4067: if (str == null || size <= 0) {
4068: return str;
4069: }
4070: int strLen = str.length();
4071: int pads = size - strLen;
4072: if (pads <= 0) {
4073: return str;
4074: }
4075: str = leftPad(str, strLen + pads / 2, padChar);
4076: str = rightPad(str, size, padChar);
4077: return str;
4078: }
4079:
4080: /**
4081: * <p>Centers a String in a larger String of size <code>size</code>.
4082: * Uses a supplied String as the value to pad the String with.</p>
4083: *
4084: * <p>If the size is less than the String length, the String is returned.
4085: * A <code>null</code> String returns <code>null</code>.
4086: * A negative size is treated as zero.</p>
4087: *
4088: * <pre>
4089: * StringUtils.center(null, *, *) = null
4090: * StringUtils.center("", 4, " ") = " "
4091: * StringUtils.center("ab", -1, " ") = "ab"
4092: * StringUtils.center("ab", 4, " ") = " ab"
4093: * StringUtils.center("abcd", 2, " ") = "abcd"
4094: * StringUtils.center("a", 4, " ") = " a "
4095: * StringUtils.center("a", 4, "yz") = "yayz"
4096: * StringUtils.center("abc", 7, null) = " abc "
4097: * StringUtils.center("abc", 7, "") = " abc "
4098: * </pre>
4099: *
4100: * @param str the String to center, may be null
4101: * @param size the int size of new String, negative treated as zero
4102: * @param padStr the String to pad the new String with, must not be null or empty
4103: * @return centered String, <code>null</code> if null String input
4104: * @throws IllegalArgumentException if padStr is <code>null</code> or empty
4105: */
4106: public static String center(String str, int size, String padStr) {
4107: if (str == null || size <= 0) {
4108: return str;
4109: }
4110: if (isEmpty(padStr)) {
4111: padStr = " ";
4112: }
4113: int strLen = str.length();
4114: int pads = size - strLen;
4115: if (pads <= 0) {
4116: return str;
4117: }
4118: str = leftPad(str, strLen + pads / 2, padStr);
4119: str = rightPad(str, size, padStr);
4120: return str;
4121: }
4122:
4123: // Case conversion
4124: //-----------------------------------------------------------------------
4125: /**
4126: * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p>
4127: *
4128: * <p>A <code>null</code> input String returns <code>null</code>.</p>
4129: *
4130: * <pre>
4131: * StringUtils.upperCase(null) = null
4132: * StringUtils.upperCase("") = ""
4133: * StringUtils.upperCase("aBc") = "ABC"
4134: * </pre>
4135: *
4136: * @param str the String to upper case, may be null
4137: * @return the upper cased String, <code>null</code> if null String input
4138: */
4139: public static String upperCase(String str) {
4140: if (str == null) {
4141: return null;
4142: }
4143: return str.toUpperCase();
4144: }
4145:
4146: /**
4147: * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p>
4148: *
4149: * <p>A <code>null</code> input String returns <code>null</code>.</p>
4150: *
4151: * <pre>
4152: * StringUtils.lowerCase(null) = null
4153: * StringUtils.lowerCase("") = ""
4154: * StringUtils.lowerCase("aBc") = "abc"
4155: * </pre>
4156: *
4157: * @param str the String to lower case, may be null
4158: * @return the lower cased String, <code>null</code> if null String input
4159: */
4160: public static String lowerCase(String str) {
4161: if (str == null) {
4162: return null;
4163: }
4164: return str.toLowerCase();
4165: }
4166:
4167: /**
4168: * <p>Capitalizes a String changing the first letter to title case as
4169: * per {@link Character#toTitleCase(char)}. No other letters are changed.</p>
4170: *
4171: * <p>For a word based algorithm, see {@link WordUtils#capitalize(String)}.
4172: * A <code>null</code> input String returns <code>null</code>.</p>
4173: *
4174: * <pre>
4175: * StringUtils.capitalize(null) = null
4176: * StringUtils.capitalize("") = ""
4177: * StringUtils.capitalize("cat") = "Cat"
4178: * StringUtils.capitalize("cAt") = "CAt"
4179: * </pre>
4180: *
4181: * @param str the String to capitalize, may be null
4182: * @return the capitalized String, <code>null</code> if null String input
4183: * @see WordUtils#capitalize(String)
4184: * @see #uncapitalize(String)
4185: * @since 2.0
4186: */
4187: public static String capitalize(String str) {
4188: int strLen;
4189: if (str == null || (strLen = str.length()) == 0) {
4190: return str;
4191: }
4192: return new StringBuffer(strLen).append(
4193: Character.toTitleCase(str.charAt(0))).append(
4194: str.substring(1)).toString();
4195: }
4196:
4197: /**
4198: * <p>Capitalizes a String changing the first letter to title case as
4199: * per {@link Character#toTitleCase(char)}. No other letters are changed.</p>
4200: *
4201: * @param str the String to capitalize, may be null
4202: * @return the capitalized String, <code>null</code> if null String input
4203: * @deprecated Use the standardly named {@link #capitalize(String)}.
4204: * Method will be removed in Commons Lang 3.0.
4205: */
4206: public static String capitalise(String str) {
4207: return capitalize(str);
4208: }
4209:
4210: /**
4211: * <p>Uncapitalizes a String changing the first letter to title case as
4212: * per {@link Character#toLowerCase(char)}. No other letters are changed.</p>
4213: *
4214: * <p>For a word based algorithm, see {@link WordUtils#uncapitalize(String)}.
4215: * A <code>null</code> input String returns <code>null</code>.</p>
4216: *
4217: * <pre>
4218: * StringUtils.uncapitalize(null) = null
4219: * StringUtils.uncapitalize("") = ""
4220: * StringUtils.uncapitalize("Cat") = "cat"
4221: * StringUtils.uncapitalize("CAT") = "cAT"
4222: * </pre>
4223: *
4224: * @param str the String to uncapitalize, may be null
4225: * @return the uncapitalized String, <code>null</code> if null String input
4226: * @see WordUtils#uncapitalize(String)
4227: * @see #capitalize(String)
4228: * @since 2.0
4229: */
4230: public static String uncapitalize(String str) {
4231: int strLen;
4232: if (str == null || (strLen = str.length()) == 0) {
4233: return str;
4234: }
4235: return new StringBuffer(strLen).append(
4236: Character.toLowerCase(str.charAt(0))).append(
4237: str.substring(1)).toString();
4238: }
4239:
4240: /**
4241: * <p>Uncapitalizes a String changing the first letter to title case as
4242: * per {@link Character#toLowerCase(char)}. No other letters are changed.</p>
4243: *
4244: * @param str the String to uncapitalize, may be null
4245: * @return the uncapitalized String, <code>null</code> if null String input
4246: * @deprecated Use the standardly named {@link #uncapitalize(String)}.
4247: * Method will be removed in Commons Lang 3.0.
4248: */
4249: public static String uncapitalise(String str) {
4250: return uncapitalize(str);
4251: }
4252:
4253: /**
4254: * <p>Swaps the case of a String changing upper and title case to
4255: * lower case, and lower case to upper case.</p>
4256: *
4257: * <ul>
4258: * <li>Upper case character converts to Lower case</li>
4259: * <li>Title case character converts to Lower case</li>
4260: * <li>Lower case character converts to Upper case</li>
4261: * </ul>
4262: *
4263: * <p>For a word based algorithm, see {@link WordUtils#swapCase(String)}.
4264: * A <code>null</code> input String returns <code>null</code>.</p>
4265: *
4266: * <pre>
4267: * StringUtils.swapCase(null) = null
4268: * StringUtils.swapCase("") = ""
4269: * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
4270: * </pre>
4271: *
4272: * <p>NOTE: This method changed in Lang version 2.0.
4273: * It no longer performs a word based algorithm.
4274: * If you only use ASCII, you will notice no change.
4275: * That functionality is available in WordUtils.</p>
4276: *
4277: * @param str the String to swap case, may be null
4278: * @return the changed String, <code>null</code> if null String input
4279: */
4280: public static String swapCase(String str) {
4281: int strLen;
4282: if (str == null || (strLen = str.length()) == 0) {
4283: return str;
4284: }
4285: StringBuffer buffer = new StringBuffer(strLen);
4286:
4287: char ch = 0;
4288: for (int i = 0; i < strLen; i++) {
4289: ch = str.charAt(i);
4290: if (Character.isUpperCase(ch)) {
4291: ch = Character.toLowerCase(ch);
4292: } else if (Character.isTitleCase(ch)) {
4293: ch = Character.toLowerCase(ch);
4294: } else if (Character.isLowerCase(ch)) {
4295: ch = Character.toUpperCase(ch);
4296: }
4297: buffer.append(ch);
4298: }
4299: return buffer.toString();
4300: }
4301:
4302: /**
4303: * <p>Capitalizes all the whitespace separated words in a String.
4304: * Only the first letter of each word is changed.</p>
4305: *
4306: * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
4307: * A <code>null</code> input String returns <code>null</code>.</p>
4308: *
4309: * @param str the String to capitalize, may be null
4310: * @return capitalized String, <code>null</code> if null String input
4311: * @deprecated Use the relocated {@link WordUtils#capitalize(String)}.
4312: * Method will be removed in Commons Lang 3.0.
4313: */
4314: public static String capitaliseAllWords(String str) {
4315: return WordUtils.capitalize(str);
4316: }
4317:
4318: // Count matches
4319: //-----------------------------------------------------------------------
4320: /**
4321: * <p>Counts how many times the substring appears in the larger String.</p>
4322: *
4323: * <p>A <code>null</code> or empty ("") String input returns <code>0</code>.</p>
4324: *
4325: * <pre>
4326: * StringUtils.countMatches(null, *) = 0
4327: * StringUtils.countMatches("", *) = 0
4328: * StringUtils.countMatches("abba", null) = 0
4329: * StringUtils.countMatches("abba", "") = 0
4330: * StringUtils.countMatches("abba", "a") = 2
4331: * StringUtils.countMatches("abba", "ab") = 1
4332: * StringUtils.countMatches("abba", "xxx") = 0
4333: * </pre>
4334: *
4335: * @param str the String to check, may be null
4336: * @param sub the substring to count, may be null
4337: * @return the number of occurrences, 0 if either String is <code>null</code>
4338: */
4339: public static int countMatches(String str, String sub) {
4340: if (isEmpty(str) || isEmpty(sub)) {
4341: return 0;
4342: }
4343: int count = 0;
4344: int idx = 0;
4345: while ((idx = str.indexOf(sub, idx)) != -1) {
4346: count++;
4347: idx += sub.length();
4348: }
4349: return count;
4350: }
4351:
4352: // Character Tests
4353: //-----------------------------------------------------------------------
4354: /**
4355: * <p>Checks if the String contains only unicode letters.</p>
4356: *
4357: * <p><code>null</code> will return <code>false</code>.
4358: * An empty String ("") will return <code>true</code>.</p>
4359: *
4360: * <pre>
4361: * StringUtils.isAlpha(null) = false
4362: * StringUtils.isAlpha("") = true
4363: * StringUtils.isAlpha(" ") = false
4364: * StringUtils.isAlpha("abc") = true
4365: * StringUtils.isAlpha("ab2c") = false
4366: * StringUtils.isAlpha("ab-c") = false
4367: * </pre>
4368: *
4369: * @param str the String to check, may be null
4370: * @return <code>true</code> if only contains letters, and is non-null
4371: */
4372: public static boolean isAlpha(String str) {
4373: if (str == null) {
4374: return false;
4375: }
4376: int sz = str.length();
4377: for (int i = 0; i < sz; i++) {
4378: if (Character.isLetter(str.charAt(i)) == false) {
4379: return false;
4380: }
4381: }
4382: return true;
4383: }
4384:
4385: /**
4386: * <p>Checks if the String contains only unicode letters and
4387: * space (' ').</p>
4388: *
4389: * <p><code>null</code> will return <code>false</code>
4390: * An empty String ("") will return <code>true</code>.</p>
4391: *
4392: * <pre>
4393: * StringUtils.isAlphaSpace(null) = false
4394: * StringUtils.isAlphaSpace("") = true
4395: * StringUtils.isAlphaSpace(" ") = true
4396: * StringUtils.isAlphaSpace("abc") = true
4397: * StringUtils.isAlphaSpace("ab c") = true
4398: * StringUtils.isAlphaSpace("ab2c") = false
4399: * StringUtils.isAlphaSpace("ab-c") = false
4400: * </pre>
4401: *
4402: * @param str the String to check, may be null
4403: * @return <code>true</code> if only contains letters and space,
4404: * and is non-null
4405: */
4406: public static boolean isAlphaSpace(String str) {
4407: if (str == null) {
4408: return false;
4409: }
4410: int sz = str.length();
4411: for (int i = 0; i < sz; i++) {
4412: if ((Character.isLetter(str.charAt(i)) == false)
4413: && (str.charAt(i) != ' ')) {
4414: return false;
4415: }
4416: }
4417: return true;
4418: }
4419:
4420: /**
4421: * <p>Checks if the String contains only unicode letters or digits.</p>
4422: *
4423: * <p><code>null</code> will return <code>false</code>.
4424: * An empty String ("") will return <code>true</code>.</p>
4425: *
4426: * <pre>
4427: * StringUtils.isAlphanumeric(null) = false
4428: * StringUtils.isAlphanumeric("") = true
4429: * StringUtils.isAlphanumeric(" ") = false
4430: * StringUtils.isAlphanumeric("abc") = true
4431: * StringUtils.isAlphanumeric("ab c") = false
4432: * StringUtils.isAlphanumeric("ab2c") = true
4433: * StringUtils.isAlphanumeric("ab-c") = false
4434: * </pre>
4435: *
4436: * @param str the String to check, may be null
4437: * @return <code>true</code> if only contains letters or digits,
4438: * and is non-null
4439: */
4440: public static boolean isAlphanumeric(String str) {
4441: if (str == null) {
4442: return false;
4443: }
4444: int sz = str.length();
4445: for (int i = 0; i < sz; i++) {
4446: if (Character.isLetterOrDigit(str.charAt(i)) == false) {
4447: return false;
4448: }
4449: }
4450: return true;
4451: }
4452:
4453: /**
4454: * <p>Checks if the String contains only unicode letters, digits
4455: * or space (<code>' '</code>).</p>
4456: *
4457: * <p><code>null</code> will return <code>false</code>.
4458: * An empty String ("") will return <code>true</code>.</p>
4459: *
4460: * <pre>
4461: * StringUtils.isAlphanumeric(null) = false
4462: * StringUtils.isAlphanumeric("") = true
4463: * StringUtils.isAlphanumeric(" ") = true
4464: * StringUtils.isAlphanumeric("abc") = true
4465: * StringUtils.isAlphanumeric("ab c") = true
4466: * StringUtils.isAlphanumeric("ab2c") = true
4467: * StringUtils.isAlphanumeric("ab-c") = false
4468: * </pre>
4469: *
4470: * @param str the String to check, may be null
4471: * @return <code>true</code> if only contains letters, digits or space,
4472: * and is non-null
4473: */
4474: public static boolean isAlphanumericSpace(String str) {
4475: if (str == null) {
4476: return false;
4477: }
4478: int sz = str.length();
4479: for (int i = 0; i < sz; i++) {
4480: if ((Character.isLetterOrDigit(str.charAt(i)) == false)
4481: && (str.charAt(i) != ' ')) {
4482: return false;
4483: }
4484: }
4485: return true;
4486: }
4487:
4488: /**
4489: * <p>Checks if the string contains only ASCII printable characters.</p>
4490: *
4491: * <p><code>null</code> will return <code>false</code>.
4492: * An empty String ("") will return <code>true</code>.</p>
4493: *
4494: * <pre>
4495: * StringUtils.isAsciiPrintable(null) = false
4496: * StringUtils.isAsciiPrintable("") = true
4497: * StringUtils.isAsciiPrintable(" ") = true
4498: * StringUtils.isAsciiPrintable("Ceki") = true
4499: * StringUtils.isAsciiPrintable("ab2c") = true
4500: * StringUtils.isAsciiPrintable("!ab-c~") = true
4501: * StringUtils.isAsciiPrintable("\u0020") = true
4502: * StringUtils.isAsciiPrintable("\u0021") = true
4503: * StringUtils.isAsciiPrintable("\u007e") = true
4504: * StringUtils.isAsciiPrintable("\u007f") = false
4505: * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
4506: * </pre>
4507: *
4508: * @param str the string to check, may be null
4509: * @return <code>true</code> if every character is in the range
4510: * 32 thru 126
4511: * @since 2.1
4512: */
4513: public static boolean isAsciiPrintable(String str) {
4514: if (str == null) {
4515: return false;
4516: }
4517: int sz = str.length();
4518: for (int i = 0; i < sz; i++) {
4519: if (CharUtils.isAsciiPrintable(str.charAt(i)) == false) {
4520: return false;
4521: }
4522: }
4523: return true;
4524: }
4525:
4526: /**
4527: * <p>Checks if the String contains only unicode digits.
4528: * A decimal point is not a unicode digit and returns false.</p>
4529: *
4530: * <p><code>null</code> will return <code>false</code>.
4531: * An empty String ("") will return <code>true</code>.</p>
4532: *
4533: * <pre>
4534: * StringUtils.isNumeric(null) = false
4535: * StringUtils.isNumeric("") = true
4536: * StringUtils.isNumeric(" ") = false
4537: * StringUtils.isNumeric("123") = true
4538: * StringUtils.isNumeric("12 3") = false
4539: * StringUtils.isNumeric("ab2c") = false
4540: * StringUtils.isNumeric("12-3") = false
4541: * StringUtils.isNumeric("12.3") = false
4542: * </pre>
4543: *
4544: * @param str the String to check, may be null
4545: * @return <code>true</code> if only contains digits, and is non-null
4546: */
4547: public static boolean isNumeric(String str) {
4548: if (str == null) {
4549: return false;
4550: }
4551: int sz = str.length();
4552: for (int i = 0; i < sz; i++) {
4553: if (Character.isDigit(str.charAt(i)) == false) {
4554: return false;
4555: }
4556: }
4557: return true;
4558: }
4559:
4560: /**
4561: * <p>Checks if the String contains only unicode digits or space
4562: * (<code>' '</code>).
4563: * A decimal point is not a unicode digit and returns false.</p>
4564: *
4565: * <p><code>null</code> will return <code>false</code>.
4566: * An empty String ("") will return <code>true</code>.</p>
4567: *
4568: * <pre>
4569: * StringUtils.isNumeric(null) = false
4570: * StringUtils.isNumeric("") = true
4571: * StringUtils.isNumeric(" ") = true
4572: * StringUtils.isNumeric("123") = true
4573: * StringUtils.isNumeric("12 3") = true
4574: * StringUtils.isNumeric("ab2c") = false
4575: * StringUtils.isNumeric("12-3") = false
4576: * StringUtils.isNumeric("12.3") = false
4577: * </pre>
4578: *
4579: * @param str the String to check, may be null
4580: * @return <code>true</code> if only contains digits or space,
4581: * and is non-null
4582: */
4583: public static boolean isNumericSpace(String str) {
4584: if (str == null) {
4585: return false;
4586: }
4587: int sz = str.length();
4588: for (int i = 0; i < sz; i++) {
4589: if ((Character.isDigit(str.charAt(i)) == false)
4590: && (str.charAt(i) != ' ')) {
4591: return false;
4592: }
4593: }
4594: return true;
4595: }
4596:
4597: /**
4598: * <p>Checks if the String contains only whitespace.</p>
4599: *
4600: * <p><code>null</code> will return <code>false</code>.
4601: * An empty String ("") will return <code>true</code>.</p>
4602: *
4603: * <pre>
4604: * StringUtils.isWhitespace(null) = false
4605: * StringUtils.isWhitespace("") = true
4606: * StringUtils.isWhitespace(" ") = true
4607: * StringUtils.isWhitespace("abc") = false
4608: * StringUtils.isWhitespace("ab2c") = false
4609: * StringUtils.isWhitespace("ab-c") = false
4610: * </pre>
4611: *
4612: * @param str the String to check, may be null
4613: * @return <code>true</code> if only contains whitespace, and is non-null
4614: * @since 2.0
4615: */
4616: public static boolean isWhitespace(String str) {
4617: if (str == null) {
4618: return false;
4619: }
4620: int sz = str.length();
4621: for (int i = 0; i < sz; i++) {
4622: if ((Character.isWhitespace(str.charAt(i)) == false)) {
4623: return false;
4624: }
4625: }
4626: return true;
4627: }
4628:
4629: // Defaults
4630: //-----------------------------------------------------------------------
4631: /**
4632: * <p>Returns either the passed in String,
4633: * or if the String is <code>null</code>, an empty String ("").</p>
4634: *
4635: * <pre>
4636: * StringUtils.defaultString(null) = ""
4637: * StringUtils.defaultString("") = ""
4638: * StringUtils.defaultString("bat") = "bat"
4639: * </pre>
4640: *
4641: * @see ObjectUtils#toString(Object)
4642: * @see String#valueOf(Object)
4643: * @param str the String to check, may be null
4644: * @return the passed in String, or the empty String if it
4645: * was <code>null</code>
4646: */
4647: public static String defaultString(String str) {
4648: return str == null ? EMPTY : str;
4649: }
4650:
4651: /**
4652: * <p>Returns either the passed in String, or if the String is
4653: * <code>null</code>, the value of <code>defaultStr</code>.</p>
4654: *
4655: * <pre>
4656: * StringUtils.defaultString(null, "NULL") = "NULL"
4657: * StringUtils.defaultString("", "NULL") = ""
4658: * StringUtils.defaultString("bat", "NULL") = "bat"
4659: * </pre>
4660: *
4661: * @see ObjectUtils#toString(Object,String)
4662: * @see String#valueOf(Object)
4663: * @param str the String to check, may be null
4664: * @param defaultStr the default String to return
4665: * if the input is <code>null</code>, may be null
4666: * @return the passed in String, or the default if it was <code>null</code>
4667: */
4668: public static String defaultString(String str, String defaultStr) {
4669: return str == null ? defaultStr : str;
4670: }
4671:
4672: /**
4673: * <p>Returns either the passed in String, or if the String is
4674: * empty or <code>null</code>, the value of <code>defaultStr</code>.</p>
4675: *
4676: * <pre>
4677: * StringUtils.defaultIfEmpty(null, "NULL") = "NULL"
4678: * StringUtils.defaultIfEmpty("", "NULL") = "NULL"
4679: * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
4680: * </pre>
4681: *
4682: * @see StringUtils#defaultString(String, String)
4683: * @param str the String to check, may be null
4684: * @param defaultStr the default String to return
4685: * if the input is empty ("") or <code>null</code>, may be null
4686: * @return the passed in String, or the default
4687: */
4688: public static String defaultIfEmpty(String str, String defaultStr) {
4689: return StringUtils.isEmpty(str) ? defaultStr : str;
4690: }
4691:
4692: // Reversing
4693: //-----------------------------------------------------------------------
4694: /**
4695: * <p>Reverses a String as per {@link StringBuffer#reverse()}.</p>
4696: *
4697: * <p>A <code>null</code> String returns <code>null</code>.</p>
4698: *
4699: * <pre>
4700: * StringUtils.reverse(null) = null
4701: * StringUtils.reverse("") = ""
4702: * StringUtils.reverse("bat") = "tab"
4703: * </pre>
4704: *
4705: * @param str the String to reverse, may be null
4706: * @return the reversed String, <code>null</code> if null String input
4707: */
4708: public static String reverse(String str) {
4709: if (str == null) {
4710: return null;
4711: }
4712: return new StringBuffer(str).reverse().toString();
4713: }
4714:
4715: /**
4716: * <p>Reverses a String that is delimited by a specific character.</p>
4717: *
4718: * <p>The Strings between the delimiters are not reversed.
4719: * Thus java.lang.String becomes String.lang.java (if the delimiter
4720: * is <code>'.'</code>).</p>
4721: *
4722: * <pre>
4723: * StringUtils.reverseDelimited(null, *) = null
4724: * StringUtils.reverseDelimited("", *) = ""
4725: * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
4726: * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
4727: * </pre>
4728: *
4729: * @param str the String to reverse, may be null
4730: * @param separatorChar the separator character to use
4731: * @return the reversed String, <code>null</code> if null String input
4732: * @since 2.0
4733: */
4734: public static String reverseDelimited(String str, char separatorChar) {
4735: if (str == null) {
4736: return null;
4737: }
4738: // could implement manually, but simple way is to reuse other,
4739: // probably slower, methods.
4740: String[] strs = split(str, separatorChar);
4741: ArrayUtils.reverse(strs);
4742: return join(strs, separatorChar);
4743: }
4744:
4745: /**
4746: * <p>Reverses a String that is delimited by a specific character.</p>
4747: *
4748: * <p>The Strings between the delimiters are not reversed.
4749: * Thus java.lang.String becomes String.lang.java (if the delimiter
4750: * is <code>"."</code>).</p>
4751: *
4752: * <pre>
4753: * StringUtils.reverseDelimitedString(null, *) = null
4754: * StringUtils.reverseDelimitedString("",*) = ""
4755: * StringUtils.reverseDelimitedString("a.b.c", null) = "a.b.c"
4756: * StringUtils.reverseDelimitedString("a.b.c", ".") = "c.b.a"
4757: * </pre>
4758: *
4759: * @param str the String to reverse, may be null
4760: * @param separatorChars the separator characters to use, null treated as whitespace
4761: * @return the reversed String, <code>null</code> if null String input
4762: * @deprecated Use {@link #reverseDelimited(String, char)} instead.
4763: * This method is broken as the join doesn't know which char to use.
4764: * Method will be removed in Commons Lang 3.0.
4765: *
4766: */
4767: public static String reverseDelimitedString(String str,
4768: String separatorChars) {
4769: if (str == null) {
4770: return null;
4771: }
4772: // could implement manually, but simple way is to reuse other,
4773: // probably slower, methods.
4774: String[] strs = split(str, separatorChars);
4775: ArrayUtils.reverse(strs);
4776: if (separatorChars == null) {
4777: return join(strs, ' ');
4778: }
4779: return join(strs, separatorChars);
4780: }
4781:
4782: // Abbreviating
4783: //-----------------------------------------------------------------------
4784: /**
4785: * <p>Abbreviates a String using ellipses. This will turn
4786: * "Now is the time for all good men" into "Now is the time for..."</p>
4787: *
4788: * <p>Specifically:
4789: * <ul>
4790: * <li>If <code>str</code> is less than <code>maxWidth</code> characters
4791: * long, return it.</li>
4792: * <li>Else abbreviate it to <code>(substring(str, 0, max-3) + "...")</code>.</li>
4793: * <li>If <code>maxWidth</code> is less than <code>4</code>, throw an
4794: * <code>IllegalArgumentException</code>.</li>
4795: * <li>In no case will it return a String of length greater than
4796: * <code>maxWidth</code>.</li>
4797: * </ul>
4798: * </p>
4799: *
4800: * <pre>
4801: * StringUtils.abbreviate(null, *) = null
4802: * StringUtils.abbreviate("", 4) = ""
4803: * StringUtils.abbreviate("abcdefg", 6) = "abc..."
4804: * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
4805: * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
4806: * StringUtils.abbreviate("abcdefg", 4) = "a..."
4807: * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
4808: * </pre>
4809: *
4810: * @param str the String to check, may be null
4811: * @param maxWidth maximum length of result String, must be at least 4
4812: * @return abbreviated String, <code>null</code> if null String input
4813: * @throws IllegalArgumentException if the width is too small
4814: * @since 2.0
4815: */
4816: public static String abbreviate(String str, int maxWidth) {
4817: return abbreviate(str, 0, maxWidth);
4818: }
4819:
4820: /**
4821: * <p>Abbreviates a String using ellipses. This will turn
4822: * "Now is the time for all good men" into "...is the time for..."</p>
4823: *
4824: * <p>Works like <code>abbreviate(String, int)</code>, but allows you to specify
4825: * a "left edge" offset. Note that this left edge is not necessarily going to
4826: * be the leftmost character in the result, or the first character following the
4827: * ellipses, but it will appear somewhere in the result.
4828: *
4829: * <p>In no case will it return a String of length greater than
4830: * <code>maxWidth</code>.</p>
4831: *
4832: * <pre>
4833: * StringUtils.abbreviate(null, *, *) = null
4834: * StringUtils.abbreviate("", 0, 4) = ""
4835: * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
4836: * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..."
4837: * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..."
4838: * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..."
4839: * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..."
4840: * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..."
4841: * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno"
4842: * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
4843: * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
4844: * StringUtils.abbreviate("abcdefghij", 0, 3) = IllegalArgumentException
4845: * StringUtils.abbreviate("abcdefghij", 5, 6) = IllegalArgumentException
4846: * </pre>
4847: *
4848: * @param str the String to check, may be null
4849: * @param offset left edge of source String
4850: * @param maxWidth maximum length of result String, must be at least 4
4851: * @return abbreviated String, <code>null</code> if null String input
4852: * @throws IllegalArgumentException if the width is too small
4853: * @since 2.0
4854: */
4855: public static String abbreviate(String str, int offset, int maxWidth) {
4856: if (str == null) {
4857: return null;
4858: }
4859: if (maxWidth < 4) {
4860: throw new IllegalArgumentException(
4861: "Minimum abbreviation width is 4");
4862: }
4863: if (str.length() <= maxWidth) {
4864: return str;
4865: }
4866: if (offset > str.length()) {
4867: offset = str.length();
4868: }
4869: if ((str.length() - offset) < (maxWidth - 3)) {
4870: offset = str.length() - (maxWidth - 3);
4871: }
4872: if (offset <= 4) {
4873: return str.substring(0, maxWidth - 3) + "...";
4874: }
4875: if (maxWidth < 7) {
4876: throw new IllegalArgumentException(
4877: "Minimum abbreviation width with offset is 7");
4878: }
4879: if ((offset + (maxWidth - 3)) < str.length()) {
4880: return "..."
4881: + abbreviate(str.substring(offset), maxWidth - 3);
4882: }
4883: return "..." + str.substring(str.length() - (maxWidth - 3));
4884: }
4885:
4886: // Difference
4887: //-----------------------------------------------------------------------
4888: /**
4889: * <p>Compares two Strings, and returns the portion where they differ.
4890: * (More precisely, return the remainder of the second String,
4891: * starting from where it's different from the first.)</p>
4892: *
4893: * <p>For example,
4894: * <code>difference("i am a machine", "i am a robot") -> "robot"</code>.</p>
4895: *
4896: * <pre>
4897: * StringUtils.difference(null, null) = null
4898: * StringUtils.difference("", "") = ""
4899: * StringUtils.difference("", "abc") = "abc"
4900: * StringUtils.difference("abc", "") = ""
4901: * StringUtils.difference("abc", "abc") = ""
4902: * StringUtils.difference("ab", "abxyz") = "xyz"
4903: * StringUtils.difference("abcde", "abxyz") = "xyz"
4904: * StringUtils.difference("abcde", "xyz") = "xyz"
4905: * </pre>
4906: *
4907: * @param str1 the first String, may be null
4908: * @param str2 the second String, may be null
4909: * @return the portion of str2 where it differs from str1; returns the
4910: * empty String if they are equal
4911: * @since 2.0
4912: */
4913: public static String difference(String str1, String str2) {
4914: if (str1 == null) {
4915: return str2;
4916: }
4917: if (str2 == null) {
4918: return str1;
4919: }
4920: int at = indexOfDifference(str1, str2);
4921: if (at == -1) {
4922: return EMPTY;
4923: }
4924: return str2.substring(at);
4925: }
4926:
4927: /**
4928: * <p>Compares two Strings, and returns the index at which the
4929: * Strings begin to differ.</p>
4930: *
4931: * <p>For example,
4932: * <code>indexOfDifference("i am a machine", "i am a robot") -> 7</code></p>
4933: *
4934: * <pre>
4935: * StringUtils.indexOfDifference(null, null) = -1
4936: * StringUtils.indexOfDifference("", "") = -1
4937: * StringUtils.indexOfDifference("", "abc") = 0
4938: * StringUtils.indexOfDifference("abc", "") = 0
4939: * StringUtils.indexOfDifference("abc", "abc") = -1
4940: * StringUtils.indexOfDifference("ab", "abxyz") = 2
4941: * StringUtils.indexOfDifference("abcde", "abxyz") = 2
4942: * StringUtils.indexOfDifference("abcde", "xyz") = 0
4943: * </pre>
4944: *
4945: * @param str1 the first String, may be null
4946: * @param str2 the second String, may be null
4947: * @return the index where str2 and str1 begin to differ; -1 if they are equal
4948: * @since 2.0
4949: */
4950: public static int indexOfDifference(String str1, String str2) {
4951: if (str1 == str2) {
4952: return -1;
4953: }
4954: if (str1 == null || str2 == null) {
4955: return 0;
4956: }
4957: int i;
4958: for (i = 0; i < str1.length() && i < str2.length(); ++i) {
4959: if (str1.charAt(i) != str2.charAt(i)) {
4960: break;
4961: }
4962: }
4963: if (i < str2.length() || i < str1.length()) {
4964: return i;
4965: }
4966: return -1;
4967: }
4968:
4969: // Misc
4970: //-----------------------------------------------------------------------
4971: /**
4972: * <p>Find the Levenshtein distance between two Strings.</p>
4973: *
4974: * <p>This is the number of changes needed to change one String into
4975: * another, where each change is a single character modification (deletion,
4976: * insertion or substitution).</p>
4977: *
4978: * <p>The previous implementation of the Levenshtein distance algorithm
4979: * was from <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
4980: *
4981: * <p>Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError
4982: * which can occur when my Java implementation is used with very large strings.<br>
4983: * This implementation of the Levenshtein distance algorithm
4984: * is from <a href="http://www.merriampark.com/ldjava.htm">http://www.merriampark.com/ldjava.htm</a></p>
4985: *
4986: * <pre>
4987: * StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException
4988: * StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException
4989: * StringUtils.getLevenshteinDistance("","") = 0
4990: * StringUtils.getLevenshteinDistance("","a") = 1
4991: * StringUtils.getLevenshteinDistance("aaapppp", "") = 7
4992: * StringUtils.getLevenshteinDistance("frog", "fog") = 1
4993: * StringUtils.getLevenshteinDistance("fly", "ant") = 3
4994: * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
4995: * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
4996: * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
4997: * StringUtils.getLevenshteinDistance("hello", "hallo") = 1
4998: * </pre>
4999: *
5000: * @param s the first String, must not be null
5001: * @param t the second String, must not be null
5002: * @return result distance
5003: * @throws IllegalArgumentException if either String input <code>null</code>
5004: */
5005: public static int getLevenshteinDistance(String s, String t) {
5006: if (s == null || t == null) {
5007: throw new IllegalArgumentException(
5008: "Strings must not be null");
5009: }
5010:
5011: /*
5012: The difference between this impl. and the previous is that, rather
5013: than creating and retaining a matrix of size s.length()+1 by t.length()+1,
5014: we maintain two single-dimensional arrays of length s.length()+1. The first, d,
5015: is the 'current working' distance array that maintains the newest distance cost
5016: counts as we iterate through the characters of String s. Each time we increment
5017: the index of String t we are comparing, d is copied to p, the second int[]. Doing so
5018: allows us to retain the previous cost counts as required by the algorithm (taking
5019: the minimum of the cost count to the left, up one, and diagonally up and to the left
5020: of the current cost count being calculated). (Note that the arrays aren't really
5021: copied anymore, just switched...this is clearly much better than cloning an array
5022: or doing a System.arraycopy() each time through the outer loop.)
5023:
5024: Effectively, the difference between the two implementations is this one does not
5025: cause an out of memory condition when calculating the LD over two very large strings.
5026: */
5027:
5028: int n = s.length(); // length of s
5029: int m = t.length(); // length of t
5030:
5031: if (n == 0) {
5032: return m;
5033: } else if (m == 0) {
5034: return n;
5035: }
5036:
5037: int p[] = new int[n + 1]; //'previous' cost array, horizontally
5038: int d[] = new int[n + 1]; // cost array, horizontally
5039: int _d[]; //placeholder to assist in swapping p and d
5040:
5041: // indexes into strings s and t
5042: int i; // iterates through s
5043: int j; // iterates through t
5044:
5045: char t_j; // jth character of t
5046:
5047: int cost; // cost
5048:
5049: for (i = 0; i <= n; i++) {
5050: p[i] = i;
5051: }
5052:
5053: for (j = 1; j <= m; j++) {
5054: t_j = t.charAt(j - 1);
5055: d[0] = j;
5056:
5057: for (i = 1; i <= n; i++) {
5058: cost = s.charAt(i - 1) == t_j ? 0 : 1;
5059: // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
5060: d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1),
5061: p[i - 1] + cost);
5062: }
5063:
5064: // copy current distance counts to 'previous row' distance counts
5065: _d = p;
5066: p = d;
5067: d = _d;
5068: }
5069:
5070: // our last action in the above loop was to switch d and p, so p now
5071: // actually has the most recent cost counts
5072: return p[n];
5073: }
5074:
5075: /**
5076: * <p>Gets the minimum of three <code>int</code> values.</p>
5077: *
5078: * @param a value 1
5079: * @param b value 2
5080: * @param c value 3
5081: * @return the smallest of the values
5082: */
5083: /*
5084: private static int min(int a, int b, int c) {
5085: // Method copied from NumberUtils to avoid dependency on subpackage
5086: if (b < a) {
5087: a = b;
5088: }
5089: if (c < a) {
5090: a = c;
5091: }
5092: return a;
5093: }
5094: */
5095:
5096: }
|