package org.smartly.commons.util; import org.smartly.IConstants; import org.smartly.Smartly; import org.smartly.commons.lang.CharEncoding; import java.io.*; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.*; public final class StringUtils { /** * <code>\u000a</code> linefeed LF ('\n'). * * @see <a href="http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#101089">JLF: Escape Sequences * for Character and String Literals</a> */ public static final char LF = '\n'; /** * <code>\u000d</code> carriage return CR ('\r'). * * @see <a href="http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#101089">JLF: Escape Sequences * for Character and String Literals</a> */ public static final char CR = '\r'; private StringUtils() { } /** * Split a string into an array of strings. Use comma and space * as delimiters. * * @param str the string to split * @return the string split into a string array */ public static String[] split(final String str) { return split(str, ", \t\n\r\f"); } /** * Take a String which is a delimited list and convert it to a String array. * <p>A single delimiter can consists of more than one character: It will * still be considered as single delimiter string, rather than as bunch of * potential delimiter characters - in contrast to * <code>tokenizeToStringArray</code>. * * @param str the input String * @param delim the delimiter between elements (this is a single * delimiter, rather than a bunch individual delimiter characters) * @return an array of the tokens in the list */ public static String[] split(final String str, final String delim) { return split(str, delim, true); } /** * Split a string into an array of strings. * * @param str the string to split * @param delimiters the delimiter characters, assembled as String (each of * those characters is individually considered as delimiter) * @param trimTokens trim the tokens via String's * @return the string split into a string array */ public static String[] split(final String str, final String delimiters, final boolean trimTokens) { if (str == null) { return new String[0]; } final StringTokenizer st = new StringTokenizer(str, delimiters); final String[] s = new String[st.countTokens()]; for (int i = 0; i < s.length; i++) { s[i] = trimTokens ? st.nextToken().trim() : st.nextToken(); } return s; /* final String[] result = RegExUtils.split(trim ? str.trim() : str, delim); if (trim) { for (int i = 0; i < result.length; i++) { result[i] = result[i].trim(); } } return result;*/ } public static String[] split(final String str, final String delimiters, final boolean trimTokens, final boolean ignoreEmptyTokens) { return split(str, delimiters, trimTokens, ignoreEmptyTokens, false); } /** * Tokenize the given String into a String array via a StringTokenizer. * <p>The given delimiters string is supposed to consist of any number of * delimiter characters. Each of those characters can be used to separate * tokens. A delimiter is always a single character; for multi-character * delimiters, consider using * <code>delimitedListToStringArray</code> * * @param str the String to tokenize * @param delimiters the delimiter characters, assembled as String (each of * those characters is individually considered as delimiter) * @param trimTokens trim the tokens via String's * <code>trim</code> * @param ignoreEmptyTokens omit empty tokens from the result array (only * applies to tokens that are empty after trimming; StringTokenizer will not * consider subsequent delimiters as token in the first place). * @return an array of the tokens * @see java.util.StringTokenizer * @see String#trim */ public static String[] split(final String str, final String delimiters, final boolean trimTokens, final boolean ignoreEmptyTokens, final boolean unique) { final StringTokenizer st = new StringTokenizer(str, delimiters); final Collection<String> result = unique ? new LinkedHashSet<String>() :new LinkedList<String>(); while (st.hasMoreTokens()) { String token = st.nextToken(); if (trimTokens) { token = token.trim(); } if (!ignoreEmptyTokens || token.length() > 0) { result.add(token); } } return result.toArray(new String[result.size()]); } /** * @param str * @param delimiters Array of valid delimiters. i.e. {". ", "; "} (both * delimiters are valid) * @return */ public static String[] split(final String str, final String[] delimiters) { return split(str, delimiters, true, true, false); } public static String[] splitUnique(final String str, final String[] delimiters) { return split(str, delimiters, true, true, true); } public static String[] split(final String str, final String[] delimiters, final boolean trimTokens, final boolean ignoreEmptyTokens, final boolean unique) { final String placeholder = "___DELIM___"; final Collection<String> result = unique ? new LinkedHashSet<String>() : new LinkedList<String>(); if (null != delimiters && delimiters.length > 0) { String s_tokens = str; for (final String delimiter : delimiters) { s_tokens = StringUtils.replace(s_tokens, delimiter, placeholder); } String[] tokens = RegExUtils.split(s_tokens, placeholder); if (null != tokens && tokens.length > 0) { for (final String token : tokens) { final String value = trimTokens ? trim(token) : token; if (ignoreEmptyTokens) { if (StringUtils.hasText(value)) { result.add(value); } } else { result.add(value); } } } } return result.toArray(new String[result.size()]); } public static String[] split(final String text, final String[] delims, final boolean trim, final boolean removeDuplicates, final int minLenght) { return split(text, delims, trim, removeDuplicates, minLenght, null); } /** * Take a String which is a delimited list and convert it to a String array. * <p>A single delimiter can consists of more than one character: It will * still be considered as single delimiter string, rather than as bunch of * potential delimiter characters - in contrast to * <code>tokenizeToStringArray</code>. * * @param str the input String * @param delim the delimiters between elements (this is a single delimiter, * rather than a bunch individual delimiter characters) * @param trim If true, values are trimmed. @minLenght minimum lenght of * token (useful if you need tokens of min lenght) * @return an array of the tokens in the list */ public static String[] split(final String str, final String delim, final boolean trim, final boolean removeDuplicates, final int minLenght) { return split(str, new String[]{delim}, trim, removeDuplicates, minLenght); } /** * Take a String which is a delimited list and convert it to a String array. * <p>A single delimiter can consists of more than one character: It will * still be considered as single delimiter string, rather than as bunch of * potential delimiter characters - in contrast to * <code>tokenizeToStringArray</code>. * * @param text * @param delims Array of delimiters between elements. * @param trim If true, values are trimmed. * @param removeDuplicates Boolean. True if you want only unique values. * @param excludes Optional (default = null). Array of keywords to exclude * @return an array of the tokens in the list * @minLenght minimum lenght of token (useful if you need tokens of min * lenght) */ public static String[] split(final String text, final String[] delims, final boolean trim, final boolean removeDuplicates, final int minLenght, final String[] excludes) { if (text == null) { return new String[0]; } if (delims == null || delims.length == 0) { return new String[]{trim ? text.trim() : text}; } final List<String> result = new ArrayList<String>(); // loop for each delimiter in array. final int count = delims.length; for (int j = 0; j < count; j++) { final String delim = delims[j]; final String str = count > 1 ? StringUtils.replace(text, delims, delim) : text; if ("".equals(delim)) { for (int i = 0; i < str.length(); i++) { final String value = str.substring(i, i + 1); // ADD CollectionUtils.add(result, value, minLenght, trim, !removeDuplicates, excludes); } } else { int pos = 0; int delPos = 0; while ((delPos = str.indexOf(delim, pos)) != -1) { final String value = str.substring(pos, delPos); // ADD CollectionUtils.add(result, value, minLenght, trim, !removeDuplicates, excludes); pos = delPos + delim.length(); } if (str.length() > 0 && pos <= str.length()) { // Add rest of String, but not in case of empty input. final String value = str.substring(pos); // ADD CollectionUtils.add(result, value, minLenght, trim, !removeDuplicates, excludes); } } } return result.toArray(new String[result.size()]); } /** * @param str String to split * @param delimiter * @param trim * @param minLenght * @param maxSize Maximum length for return Array. * @return */ public static String[] split(final String str, final String delimiter, final boolean trim, final boolean removeDuplicates, final int minLenght, final int maxSize) { final String[] tokens = split(str, delimiter, trim, removeDuplicates, minLenght); if (maxSize > 0 && tokens.length > maxSize) { return CollectionUtils.resizeArray(tokens, maxSize); } return tokens; } /** * Split a String at the first occurrence of the delimiter. Does not include * the delimiter in the result.<br> i.e. : "hello.world.wide" ('.' is * delimiter) -> {"hello", "world.wide"} * * @param toSplit the string to split * @param delimiter to split the string up with * @return a two element array with index 0 being before the delimiter, and * index 1 being after the delimiter (neither element includes the * delimiter); or * <code>null</code> if the delimiter wasn't found in the given input String */ public static String[] splitFirst(final String toSplit, final String delimiter) { final String[] result = _splitLastOrFirst(toSplit, delimiter, false); return null != result ? result : new String[]{toSplit}; } /** * Split string into an array of 2 elements. * * @param toSplit String to split. i.e. "this.is.a.string" * @param delimiter Delimiter. i.e. "." * @return Array of 2 elements. i.e. ["this.is.a", "string"] */ public static String[] splitLast(final String toSplit, final String delimiter) { final String[] result = _splitLastOrFirst(toSplit, delimiter, true); return null != result ? result : new String[]{toSplit}; } /** * Split a String at the "count" occurrence of the delimiter. Does not * include the delimiter in the result.<br> i.e. : "hello.world.wide" ('.' * is delimiter) -> {"hello", "world.wide"} * * @param toSplit the string to split * @param delimiter to split the string up with * @return a two element array with index 0 being before the delimiter, and * index 1 being after the delimiter (neither element includes the * delimiter); or * <code>null</code> if the delimiter wasn't found in the given input String */ public static String[] splitAt(final int count, final String toSplit, final String delimiter) { if (!StringUtils.hasLength(toSplit) || !StringUtils.hasLength(delimiter)) { return null; } int offset = -1; for (int i = 0; i < count; i++) { offset = toSplit.indexOf(delimiter, offset + 1); } if (offset < 0) { return null; } final String beforeDelimiter = toSplit.substring(0, offset); final String afterDelimiter = toSplit.substring(offset + delimiter.length()); return new String[]{beforeDelimiter, afterDelimiter}; } public static String concatArgs(final Object... args) { final StringBuilder result = new StringBuilder(); if (null != args && args.length > 0) { for (final Object arg : args) { if (!isNULL(arg)) { result.append(arg); } } } return result.toString(); } public static String concatArgsEx(final String separator, final Object... args) { final StringBuilder result = new StringBuilder(); if (null != args && args.length > 0) { for (final Object arg : args) { if (!isNULL(arg)) { if (hasText(separator) && result.length() > 0) { result.append(separator); } result.append(arg); } } } return result.toString(); } public static String concatDot(final Object... args) { return concatArgsEx(".", args); } public static String concatUnderscore(final Object... args) { return concatArgsEx("_", args); } public static String concatPaths(final String path1, final String path2) { if (StringUtils.hasText(path1)) { if (!path1.endsWith(IConstants.FOLDER_SEPARATOR) && !path2.startsWith(IConstants.FOLDER_SEPARATOR)) { return path1.concat(IConstants.FOLDER_SEPARATOR).concat(path2); } else { return path1.concat(path2); } } else { return path2; } } /** * Append a value separated from comma (",") from other values to a * StringBuilder. * * @param value * @param sb */ public static void append(final Object value, final StringBuilder sb) { append(value, sb, ","); } /** * Append a value and a separator to a StringBuilder. * * @param value * @param sb * @param delim */ public static void append(final Object value, final StringBuilder sb, final String delim) { if (null != sb && null != value) { if (sb.length() > 0) { sb.append(delim); } sb.append(value); } } /** * Compare two strings also if null. * * @param str1 * @param str2 * @return */ public static boolean equalsIgnoreCase(final Object str1, final Object str2) { if (null != str1 && null != str2) { return str1.toString().equalsIgnoreCase(str2.toString()); } return null == str1 && null == str2; } public static boolean equalsTrim(final Object str1, final Object str2) { if (null != str1 && null != str2) { return str1.toString().trim().equalsIgnoreCase(str2.toString().trim()); } return null == str1 && null == str2; } public static boolean equals(final Object str1, final Object str2) { if (null != str1 && null != str2) { return str1.toString().equals(str2.toString()); } return null == str1 && null == str2; } //--------------------------------------------------------------------- // General convenience methods for working with Strings //--------------------------------------------------------------------- /** * Case insensitive method. * * @param text * @param charSequence * @return */ public static boolean contains(final String text, final String charSequence) { if (hasText(text) && hasText(charSequence)) { return text.toLowerCase().contains(charSequence.toLowerCase()); } return false; } /** * Case insentive method. * * @param text * @param tokens * @return */ public static boolean contains(final String text, final String[] tokens) { for (final String charSequence : tokens) { if (StringUtils.contains(text, charSequence)) { return true; } } return false; } /** * <p>Checks if the String contains any character in the given * set of characters.</p> * <p/> * <p>A <code>null</code> String will return <code>false</code>. * A <code>null</code> or zero length search array will return <code>false</code>.</p> * <p/> * <pre> * StringUtils.containsAny(null, *) = false * StringUtils.containsAny("", *) = false * StringUtils.containsAny(*, null) = false * StringUtils.containsAny(*, []) = false * StringUtils.containsAny("zzabyycdxx",['z','a']) = true * StringUtils.containsAny("zzabyycdxx",['b','y']) = true * StringUtils.containsAny("aba", ['z']) = false * </pre> * * @param str the String to check, may be null * @param searchChars the chars to search for, may be null * @return the <code>true</code> if any of the chars are found, * <code>false</code> if no match or null input * @since 2.4 */ public static boolean containsAny(final String str, final char[] searchChars) { if (str == null || str.length() == 0 || searchChars == null || searchChars.length == 0) { return false; } for (int i = 0; i < str.length(); i++) { char ch = str.charAt(i); for (int j = 0; j < searchChars.length; j++) { if (searchChars[j] == ch) { return true; } } } return false; } /** * <p>Checks that the String does not contain certain characters.</p> * <p/> * <p>A <code>null</code> String will return <code>true</code>. * A <code>null</code> invalid character array will return <code>true</code>. * An empty String ("") always returns true.</p> * <p/> * <pre> * StringUtils.containsNone(null, *) = true * StringUtils.containsNone(*, null) = true * StringUtils.containsNone("", *) = true * StringUtils.containsNone("ab", '') = true * StringUtils.containsNone("abab", 'xyz') = true * StringUtils.containsNone("ab1", 'xyz') = true * StringUtils.containsNone("abz", 'xyz') = false * </pre> * * @param str the String to check, may be null * @param invalidChars an array of invalid chars, may be null * @return true if it contains none of the invalid chars, or is null * @since 2.0 */ public static boolean containsNone(String str, char[] invalidChars) { if (str == null || invalidChars == null) { return true; } int strSize = str.length(); int validSize = invalidChars.length; for (int i = 0; i < strSize; i++) { char ch = str.charAt(i); for (int j = 0; j < validSize; j++) { if (invalidChars[j] == ch) { return false; } } } return true; } public static String toString(final InputStream is) { if (null != is) { try { final Reader reader = new InputStreamReader(is); return FileUtils.copyToString(reader); } catch (IOException ex) { //-- Error reading stream --// } } return null; } public static String toString(final char c) { return new String(new char[]{c}); } public static String toString(final Character c) { return null != c ? c.toString() : null; } /* * Return allways a string, even if passed value is null. <p><pre> * StringUtils.toString(null) = "" StringUtils.toString("") = "" * StringUtils.toString(" ") = " " StringUtils.toString("Hello") = "Hello" * </pre> @param obj Object @return a string. */ public static String toString(final Object obj) { if (null == obj) { return ""; } else if (obj instanceof Object[]) { return toString((Object[]) obj, ","); } else { return obj.toString(); } } /* * Return allways a string, even if passed value is null. If passed value is * null, the default value is returned. <p><pre> StringUtils.toString(null) * = "" StringUtils.toString("") = "" StringUtils.toString(" ") = " " * StringUtils.toString("Hello") = "Hello" </pre> @param obj Object @param * defaultValue the default value to return if passed value is null. @return * a string. */ public static String toString(final Object obj, final String defaultValue) { if (null == obj) { return defaultValue; } else { return toString(obj); } } /* * Return allways a string, even if passed value is null.<br> If passed * value is null, the default value is returned.<br> If "zerolength" is * false and passed value is empty string, the default value is returned. * <p><pre> StringUtils.toString(null) = "" StringUtils.toString("") = "" * StringUtils.toString(" ") = " " StringUtils.toString("Hello") = "Hello" * </pre> @param obj Object @param defaultValue the default value to return * if passed value is null. @param True/False parameter to indicate if * "zero-lenght" values are allowed. If False, the default value is * returned. @return a string. */ public static String toString(final Object obj, final String defaultValue, boolean zerolength) { if (null == obj) { return defaultValue; } else if (obj.toString().length() == 0) { return zerolength ? "" : defaultValue; } else { return obj.toString(); } } public static String toString(final byte[] arr, final String charset) { try { return new String(arr, charset); } catch (Throwable ignore) { } return new String(arr); } public static String toString(final byte[] arr) { return toString(arr, CharEncoding.getDefault()); } public static String toString(final Object[] array, final String separator) { return toString(array, separator, null); } public static String toString(final Object[] array, final String separator, final String defaultValue) { if (null == array) { return defaultValue; } else { StringBuilder result = new StringBuilder(); for (int i = 0; i < array.length; i++) { if (result.length() > 0) { result.append(separator); } result.append(toString(array[i])); } return result.toString(); } } /** * @param array Array of objects to convert into String * @param separator Separator for String * @param defaultValue Default value if array is null or empty * @param maxOutputLen Max length of output string. Default is -1. * @return Concatenating string of array items. */ public static String toString(final Object[] array, final String separator, final String defaultValue, final int maxOutputLen) { if (null == array) { return defaultValue; } else { final StringBuilder result = new StringBuilder(); for (int i = 0; i < array.length; i++) { if (result.length() > 0) { result.append(separator); } final String value = toString(array[i]); if (maxOutputLen > 0) { if (value.length() + separator.length() + result.length() > maxOutputLen) { break; } } result.append(value); } return result.toString(); } } public static String toQueryString(final Map<String, ?> params) { return toQueryString(params, "&"); } public static String toQueryString(final Map<String, ?> params, final String separator) { final String sep = StringUtils.hasText(separator) ? separator : "&"; if (!CollectionUtils.isEmpty(params)) { final StringBuilder result = new StringBuilder(); final Set<String> keys = params.keySet(); for (final String key : keys) { final String value = StringUtils.notNull(params.get(key), ""); if (StringUtils.hasText(value)) { StringUtils.append(key.concat("=").concat(encode(value)), result, sep); } } return result.toString(); } return ""; } public static InputStream toInputStream(final String text) { return toInputStream(CharEncoding.getDefault(), text); } public static InputStream toInputStream(final byte[] bytes) { final String text = StringUtils.toString(bytes); return toInputStream(CharEncoding.getDefault(), text); } public static InputStream toInputStream(final String encoding, final String text) { try { final ByteArrayInputStream result = new ByteArrayInputStream( text.getBytes(encoding)); return result; } catch (Exception ex) { } return null; } /** * Check if a String has length. <p><pre> * StringUtils.hasLength(null) = false * StringUtils.hasLength("") = false * StringUtils.hasLength(" ") = true * StringUtils.hasLength("Hello") = true * </pre> * * @param str the String to check, may be * <code>null</code> * @return <code>true</code> if the String is not null and has length */ public static boolean hasLength(final String str) { return hasLength(str, 1); } public static boolean hasLength(final String str, final int minLenght) { return (str != null && str.length() > minLenght - 1); } /** * Check if a String has text. More specifically, returns * <code>true</code> if the string not * <code>null<code>, it's * <code>length is > 0</code>, and it has at least one non-whitespace * character. <p><pre> * StringUtils.hasText(null) = false * StringUtils.hasText("") = false * StringUtils.hasText(" ") = false * StringUtils.hasText("12345") = true * StringUtils.hasText(" 12345 ") = true * </pre> * * @param str the String to check, may be * <code>null</code> * @return <code>true</code> if the String is not null, length > 0, and not * whitespace only * @see java.lang.Character#isWhitespace */ public static boolean hasText(final String str) { int strLen; if (str == null || (strLen = str.length()) == 0) { return false; } for (int i = 0; i < strLen; i++) { if (!Character.isWhitespace(str.charAt(i))) { return true; } } return false; } public static boolean hasTextAll(final String... args) { if (null != args) { for (final String str : args) { if (!StringUtils.hasText(str)) { return false; } } return true; } return false; } /** * Validate a JSON string * * @param value String * @return true if value is JSON string */ public static boolean isJSON(final Object value) { return isJSONObject(value) || isJSONArray(value); } public static boolean isJSONObject(final Object value) { final String string = null != value ? RegExUtils.replaceLineTerminators(value.toString()) : ""; return string.startsWith("{") && string.endsWith("}"); } public static boolean isJSONArray(final Object value) { final String string = null != value ? RegExUtils.replaceLineTerminators(value.toString()) : ""; return string.startsWith("[") && string.endsWith("]"); } /** * Return true if passed value is empty string or null string or a string * containig "NULL" text. * * @param value Value to check * @return Boolean value. */ public static boolean isNULL(final Object value) { if (null == value) { return true; } final String svalue = value.toString().trim(); return !StringUtils.hasText(svalue) || svalue.equalsIgnoreCase(IConstants.NULL); } /** * Return true iv passed value is not null and equals "NULL" text.<br> It's * a shortcut to 'IBeeConstants.NULL.equalsIgnoreCase(value)'. * * @param value Value to check * @return Boolean value */ public static boolean equalsNULL(final String value) { return null != value ? value.equalsIgnoreCase(IConstants.NULL) : false; } /** * Trim and remove duplicates \n inside text * * @param text * @return */ public static String trimTokens(final String text) { final StringBuilder result = new StringBuilder(); final StringTokenizer tokenizer = new StringTokenizer(text, "\n"); while (tokenizer.hasMoreTokens()) { final String token = tokenizer.nextToken().trim(); if (StringUtils.hasText(token)) { if (result.length() > 0) { result.append("\n"); } result.append(token); } } return result.toString(); } public static String trim(final String str) { if (str == null) { return null; } return str.trim(); } public static String trimToNull(String str) { if (str == null) { return null; } str = str.trim(); if (!hasText(str)) { return null; } return str; } /** * Return a not null value. If passed parameter is null, an empty string is * returned. * * @param str String * @return Never null value. */ public static String notNull(final Object str) { if (str == null) { return ""; } return str.toString(); } /** * Return a not null value. If passed parameter is null, default value is * returned.<br> You cann use also ObjectUtils.notNull method. * * @param str String * @param def String - the default value to return if passed string is null * @return Never null value. */ public static String notNull(final Object str, final String def) { if (str == null) { return def; } return str.toString(); } /** * Return a not empty string. If parameter is null or empty string, "NULL" * is returned. * * @param str String * @return */ public static String notEmpty(final Object str) { return notEmpty(str, IConstants.NULL); } /** * Return a not enpty value. If passed parameter is null or empty string, * default value is returned. * * @param str * @param def * @return */ public static String notEmpty(final Object str, final String def) { if (str == null) { return def; } return hasText(str.toString()) ? str.toString() : def; } /** * Test if the given String starts with the specified prefix, ignoring * upper/lower case. * * @param str the String to check * @param prefix the prefix to look for * @see java.lang.String#startsWith */ public static boolean startsWithIgnoreCase(String str, String prefix) { if (str == null || prefix == null) { return false; } if (str.startsWith(prefix)) { return true; } if (str.length() < prefix.length()) { return false; } String lcStr = str.substring(0, prefix.length()).toLowerCase(); String lcPrefix = prefix.toLowerCase(); return lcStr.equals(lcPrefix); } /** * Test if the given String ends with the specified suffix, ignoring * upper/lower case. * * @param str the String to check * @param suffix the suffix to look for * @see java.lang.String#endsWith */ public static boolean endsWithIgnoreCase(String str, String suffix) { if (str == null || suffix == null) { return false; } if (str.endsWith(suffix)) { return true; } if (str.length() < suffix.length()) { return false; } String lcStr = str.toLowerCase(); String lcSuffix = suffix.toLowerCase(); return lcStr.endsWith(lcSuffix); } /** * Count the occurrences of the substring in string s. * * @param str string to search in. Return 0 if this is null. * @param sub string to search for. Return 0 if this is null. */ public static int countOccurrencesOf(String str, String sub) { if (str == null || sub == null || str.length() == 0 || sub.length() == 0) { return 0; } int count = 0, pos = 0, idx = 0; while ((idx = str.indexOf(sub, pos)) != -1) { ++count; pos = idx + sub.length(); } return count; } /** * Returns a left filled string with passed chars. * * @param s A String * @param fillChar Characters to append * @param size Size of result * @return A String of defined size, filled with passed chars. i.e. "0000000123" // 10 characters string filled with "0" */ public static String fillString(final String s, final String fillChar, final int size) { final StringBuilder result = new StringBuilder(substring(s, 0, size)); int len = result.length(); if (len < size) { int diff = size - len; for (int i = 0; i < diff; i++) { result.insert(0, fillChar); } } return result.toString(); } /** * Returns a right filled string with passed chars. * * @param s A String * @param fillChar Characters to append * @param size Size of result * @return A String of defined size, filled with passed chars. i.e. "123-------" // 10 characters string filled with "-" */ public static String fillRightString(final String s, final String fillChar, final int size) { final StringBuilder result = new StringBuilder(substring(s, 0, size)); int len = result.length(); if (len < size) { int diff = size - len; for (int i = 0; i < diff; i++) { result.append(fillChar); } } return result.toString(); } /** * Extract a substring from a source string with max 'charCount' char.<br> * Ex: String s = substring("Hello World.", 0, 2);<br> s equals 'He'.<br> * Ex: String s = substring("Hello World.", 2, 2);<br> s equals 'll'.<br> * Ex: String s = substring("Hello World.", 2, 100);<br> s equals 'llo * World.'.<br> This method doesn't throw exception if char count is major * then string lenght. * * @param s Source string * @param start Start index (base 0) * @param charCount Number of chars to include in substring (ex: if need a * substring of max 10 chars, charCount value will be 10) * @return Substring */ public static String substring(String s, int start, int charCount) { if (null == s) { return ""; } int len = s.length(); int toIndex = start + charCount; if (toIndex > len) { toIndex = len; } return s.substring(start, toIndex); } /** * Extract a substring from a source text starting from position of * 'matcher' string.<br> i.e. substring("prefixHello world!", "prefix") * returns "Hello world!". * * @param text Original text. i.e. "prefixHello world!" * @param matcher String to serach inside original text. i.e. "prefix" * @return The subtring or the original text if no matcher was found in * original text. i.e. "Hello world!" */ public static String substring(final String text, final String matcher) { if (StringUtils.hasText(text) && StringUtils.hasText(matcher)) { final int i = text.indexOf(matcher); if (i >= 0) { return text.substring(i + matcher.length()); } } return text; } /** * @param text Text to parse. i.e. ".class{font=arial; size=12px;}" * @param prefix Prefix. i.e. ".class{" * @param suffix Suffix. i.e. "}" * @return Content between prefix and suffix. i.e. "font=arial; size=12px;" */ public static String substring(final String text, final String prefix, final String suffix) { if (StringUtils.hasText(text) && StringUtils.hasText(prefix)) { final int startIndex = text.indexOf(prefix); final int endIndex = text.indexOf(suffix, startIndex); if (startIndex >= 0) { return text.substring(startIndex + prefix.length(), endIndex); } } return text; } /** * Return a substring starting from left side. * * @param text Original text * @param numChars Number of characters to return * @return A substring starting from left side. */ public static String leftStr(final String text, final int numChars) { return leftStr(text, numChars, false); } /** * Return a substring starting from left side. * * @param text Original text * @param numChars Number of characters to return * @param addDots add dots at end of result. i.e. "result..." * @return A substring starting from left side. */ public static String leftStr(final Object text, final int numChars, final boolean addDots) { if (null != text) { final String stext = text.toString(); final int len = StringUtils.hasText(stext) ? stext.length() : 0; if (len > numChars) { final String result = stext.substring(0, numChars); return addDots ? result.concat("...") : result; } return stext; } return ""; } /** * Return a substring starting from right side. * * @param text Original text * @param numChars Number of characters to return * @return A substring starting from right side. */ public static String rightStr(final String text, final int numChars) { return rightStr(text, numChars, false); } /** * Return a substring starting from right side. * * @param text Original text * @param numChars Number of characters to return * * @param addDots add dots at begin of result. i.e. "...result" * @return A substring starting from right side. */ public static String rightStr(final String text, final int numChars, final boolean addDots) { final int len = StringUtils.hasText(text) ? text.length() : 0; if (len > numChars) { final int startIndex = len - numChars; final String result = text.substring(startIndex, startIndex + numChars); return addDots ? "...".concat(result) : result; } return null != text ? text : ""; } /** * Replace all occurences of a substring within a string with another * string. * * @param inString Original String. i.e. "hello item1 item2" * @param oldPatterns Array of substrings to replace. i.e. {"item1", * "item2"} * @param newPattern String to insert. i.e. "angelo" * @return a String with the replacements. i.e. "hello angelo angelo" */ public static String replace(final String inString, final String[] oldPatterns, final String newPattern) { String result = inString; for (final String oldPattern : oldPatterns) { result = StringUtils.replace(result, oldPattern, newPattern); } return result; } /** * Replace all occurences of a substring within a string with another * string. * * @param inString String to examine * @param oldPattern String to replace * @param newPattern String to insert * @return a String with the replacements */ public static String replace(final String inString, final String oldPattern, final String newPattern) { if (inString == null) { return null; } if (oldPattern == null || newPattern == null) { return inString; } final StringBuilder sbuf = new StringBuilder(); // output StringBuffer we'll build up int pos = 0; // our position in the old string int index = inString.indexOf(oldPattern); // the index of an occurrence we've found, or -1 int patLen = oldPattern.length(); while (index >= 0) { sbuf.append(inString.substring(pos, index)); sbuf.append(newPattern); pos = index + patLen; index = inString.indexOf(oldPattern, pos); } sbuf.append(inString.substring(pos)); // remember to append any characters to the right of a match return sbuf.toString(); } public static String replaceDuplicates(final String text, final String[] symbols) { String result = text; for (final String symbol : symbols) { while (result.indexOf(symbol + symbol) > -1) { result = result.replace(symbol + symbol, symbol); } } return result; } /** * Replace all duplicates characters with a single character.<br> i.e. : * <code>"c:\\folder\\file" -> "c:\folder\file"</code><br> i.e. : * <code>"it------IT" -> "it-IT"</code><br> * * @param text input string * @param symbol character to remove duplicates * @return cleaned from duplicates string */ public static String replaceDuplicates(final String text, final String symbol) { String result = text; while (result.indexOf(symbol + symbol) > -1) { result = result.replace(symbol + symbol, symbol); } return result; } /** * Replace duplicates with some exclusions. * * @param text Text to check for duplicates * @param symbol character to remove duplicates * @param exclusions Array of strings. i.e. ["file://", "http://"] * @return cleaned from duplicates string */ public static String replaceDuplicates(final String text, final String symbol, final String[] exclusions) { final StringBuilder result = new StringBuilder(); final String exclusionRegEx = getExclusionRegEx(text, exclusions); if (StringUtils.hasText(exclusionRegEx)) { final String regex = exclusionRegEx + "[" + symbol + "]"; final String[] tokens = text.split(regex); for (final String token : tokens) { if (StringUtils.hasText(token)) { if (token.startsWith(symbol)) { result.append(replaceDuplicates(token, symbol)); } else { if (result.length() > 0) { result.append(symbol).append(token); } else { result.append(token); } } } } } else { result.append(StringUtils.replaceDuplicates(text, symbol)); } return result.toString(); } /** * Delete all occurrences of the given substring. * * @param pattern the pattern to delete all occurrences of * @return */ public static String delete(final String inString, final String pattern) { return replace(inString, pattern, ""); } /** * Delete all occurrences of the given substrings. * * @param patterns the patterns to delete all occurrences of * @return */ public static String delete(final String inString, final String[] patterns) { return replace(inString, patterns, ""); } /** * Delete any character in a given string. * * @param charsToDelete a set of characters to delete. E.g. "az\n" will * delete 'a's, 'z's and new lines. */ public static String deleteAny(String inString, String charsToDelete) { if (inString == null || charsToDelete == null) { return inString; } StringBuilder out = new StringBuilder(); for (int i = 0; i < inString.length(); i++) { char c = inString.charAt(i); if (charsToDelete.indexOf(c) == -1) { out.append(c); } } return out.toString(); } public static String insert(final String text, final int position, final String target) { if (null != text && hasText(target)) { final StringBuilder sb = new StringBuilder(target); sb.insert(position, text); return sb.toString(); } return target; } //--------------------------------------------------------------------- // Convenience methods for working with formatted Strings //--------------------------------------------------------------------- /** * Quote the given String with single quotes. * * @param str the input String (e.g. "myString") * @return the quoted String (e.g. "'myString'"), or * <code>null<code> if the input was * <code>null</code> */ public static String quote(String str) { return (str != null ? "'" + str + "'" : null); } /** * Quote the given String with passed quoteChar. * * @param str the input String (e.g. "myString") * @param quoteChar Character to use for quote. * @return the quoted String (e.g. "'myString'"), or * <code>null<code> if the input was * <code>null</code> */ public static String quote(String str, String quoteChar) { return (str != null ? quoteChar + str + quoteChar : null); } /** * Turn the given Object into a String with single quotes if it is a String; * keeping the Object as-is else. * * @param obj the input Object (e.g. "myString") * @return the quoted String (e.g. "'myString'"), or the input object as-is * if not a String */ public static Object quoteIfString(Object obj) { return (obj instanceof String ? quote((String) obj) : obj); } /** * Unqualify a string qualified by a '.' dot character. For example, * "this.name.is.qualified", returns "qualified". * * @param qualifiedName the qualified name */ public static String unqualify(String qualifiedName) { return unqualify(qualifiedName, '.'); } /** * Unqualify a string qualified by a separator character. For example, * "this:name:is:qualified" returns "qualified" if using a ':' separator. * * @param qualifiedName the qualified name * @param separator the separator */ public static String unqualify(String qualifiedName, char separator) { return qualifiedName.substring(qualifiedName.lastIndexOf(separator) + 1); } /** * Capitalize a * <code>String</code>, changing the first letter to upper case as per {@link Character#toUpperCase(char)}. * No other letters are changed. * * @param str the String to capitalize, may be * <code>null</code> * @return the capitalized String, * <code>null</code> if null */ public static String capitalize(String str) { return changeFirstCharacterCase(str, true); } /** * Uncapitalize a * <code>String</code>, changing the first letter to lower case as per {@link Character#toLowerCase(char)}. * No other letters are changed. * * @param str the String to uncapitalize, may be * <code>null</code> * @return the uncapitalized String, * <code>null</code> if null */ public static String uncapitalize(String str) { return changeFirstCharacterCase(str, false); } public static String toLowerCase(final char c) { final String text = new String(new char[]{c}); return text.toLowerCase(); } public static String toLowerCase(final String text) { if (StringUtils.hasText(text)) { return text.toLowerCase(); } return ""; } public static String toUpperCase(final String text) { if (StringUtils.hasText(text)) { return text.toUpperCase(); } return ""; } public static String toUpperCase(final char c) { final String text = new String(new char[]{c}); return text.toUpperCase(); } public static boolean isURLEncoded(final String value) { try { return !URLDecoder.decode(value, Smartly.getCharset()).equalsIgnoreCase(value); } catch (Exception ignored) { } return false; } // ------------------------------------------------------------------------ // p r i v a t e // ------------------------------------------------------------------------ private static String changeFirstCharacterCase(final String str, final boolean capitalize) { if (str == null || str.length() == 0) { return str; } final StringBuilder buf = new StringBuilder(str.length()); if (capitalize) { buf.append(Character.toUpperCase(str.charAt(0))); } else { buf.append(str.charAt(0)); } buf.append(str.substring(1)); return buf.toString(); } private static String getExclusionRegEx(final String checkText, final String[] controlArray) { final List<String> matches = new ArrayList<String>(); if (null != controlArray && controlArray.length > 0) { for (final String item : controlArray) { if (checkText.indexOf(item) > -1) { matches.add(item); } } } //-- creates regex --// final StringBuilder regex = new StringBuilder(); if (matches.size() > 0) { for (final String match : matches) { if (regex.length() > 0) { regex.append("|"); } regex.append(match); } regex.insert(0, "(?<!["); regex.append("])"); } return regex.toString(); } private static String encode(final String s) { try { return URLEncoder.encode(s, CharEncoding.getDefault()); } catch (Exception ignored) { } return s; } private static String[] _splitLastOrFirst(final String toSplit, final String delimiter, final boolean last) { if (!StringUtils.hasLength(toSplit) || !StringUtils.hasLength(delimiter)) { return null; } int offset = last ? toSplit.lastIndexOf(delimiter) : toSplit.indexOf(delimiter); if (offset < 0) { return null; } final String beforeDelimiter = toSplit.substring(0, offset); final String afterDelimiter = toSplit.substring(offset + delimiter.length()); return new String[]{beforeDelimiter, afterDelimiter}; } }