package org.csstudio.domain.common.strings; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.naming.NamingEnumeration; import javax.naming.NamingException; /** * Utility methods for handling strings. * * @author <code>splitIgnoreInQuotes</code> by Xihui Chen */ @SuppressWarnings("nls") public final class StringUtil { /** * Constructor. */ private StringUtil() { // Don't instantiate } public static String printArrays(final Object value) { String result = null; if (value == null) { result = "null"; } else if (value instanceof double[]) { result = Arrays.toString((double[]) value); } else if (value instanceof long[]) { result = Arrays.toString((long[]) value); } else if (value instanceof String[]) { result = Arrays.toString((String[]) value); } else if (value instanceof Object[]) { result = Arrays.toString((Object[]) value); } else { result = value.toString(); } return result; } public static String capitalize(final String s) { String result = s; if (hasLength(s)) { result = s.substring(0,1).toUpperCase() + s.substring(1); } return result; } /** * Checks if a String is whitespace, empty ("") or null. <code> StringUtils.isBlank(null) = true StringUtils.isBlank("") = true StringUtils.isBlank(" ") = true StringUtils.isBlank("bob") = false StringUtils.isBlank(" bob ") = false </code> * @param s * @return true if the string is null, empty, or does only contain whitespaces */ public static boolean isBlank(final String s) { return s == null || s.trim().equals(""); } public static boolean hasLength(final String s) { return s != null && s.length() > 0; } /** * Returns the Substring of the String. * * @param str String * @param end the last char Position (not included in the Substring) * @return <code>null</code> if the String is <code>null</code>, * the Substring from the beginning to the position <code>endIdx</code>, * or the String if the position <code>endIdx</code> * is larger than length of the String. */ public static String checkedSubstring(final String str, final int end) { if (str == null) { return null; } if (str.length() < end) { return str; } return str.substring(0, end); } public static String toSeparatedString(final Collection<String> collection, final String separator) { final StringBuffer sb = new StringBuffer(); if(!collection.isEmpty()) { final Iterator<String> it = collection.iterator(); sb.append(it.next()); while(it.hasNext()) { sb.append(separator); sb.append(it.next()); } } return sb.toString(); } public static String trimNull(final String s) { return hasLength(s) ? s : ""; } private static final char SPACE = ' '; private static final char QUOTE = '"'; /** * Split source string into an array of elements by the splitting character, * but the split characters between two quotes will be ignored. * * @param trimmedSource * string to be split * @param splitChar * the character used to split the source string * @param deleteHeadTailQuotes * delete the quotes in the head and tail of individual elements * if true * @return an array of individual elements * @throws Exception * Exception on parse error (missing end of quoted string) */ public static String[] splitIgnoreInQuotes(final String source, final char splitChar, final boolean deleteHeadTailQuotes) throws Exception { // Trim, replace tabs with spaces so we only need to handle // space in the following final String trimmedSource = source.replace('\t', SPACE).trim(); final List<String> resultList = new ArrayList<String>(); int pos = 0; int start = 0; while(pos < trimmedSource.length()) { start = pos; //skip multiple splitChars while(start < trimmedSource.length() && trimmedSource.charAt(start) == splitChar) { start++; } if(start >= trimmedSource.length()) { break; } pos = start; while(pos < trimmedSource.length() && trimmedSource.charAt(pos) !=splitChar) { //in case of quote, go to the end of next quote if(trimmedSource.charAt(pos) == QUOTE) { // When locating the ending quote, ignore escaped quotes int end = trimmedSource.indexOf(QUOTE, pos+1); while (end > 0 && trimmedSource.charAt(end-1) == '\\') end = trimmedSource.indexOf(QUOTE, end+1); if(end < 0) { throw new Exception("Missing end of quoted text in '" + trimmedSource + "'"); } pos = end + 1; } else { pos++; } } String subString = trimmedSource.substring(start, pos); subString = subString.trim(); if(deleteHeadTailQuotes) { //only delete quotes when both head and tail are quote if(subString.charAt(0) == QUOTE && subString.charAt(subString.length()-1) == QUOTE) { subString = subString.substring(1, subString.length()-1); } } resultList.add(subString); } return resultList.toArray(new String[resultList.size()]); } /**If a String contains the regular expression. * @param source the source string. * @param regex the regular expression. * @return true if the source string contains the input regex. false other wise. */ public static boolean containRegex(final String source, final String regex) { final Pattern p = Pattern.compile(regex); final Matcher m = p.matcher(source); return m.find(); } /** * <p>Joins the elements of the provided array into a single String * containing the provided list of elements.</p> * * <p>No delimiter is added before or after the list. * A <code>null</code> separator is the same as an empty String (""). * Null objects or empty strings within the array are represented by * empty strings.</p> * * <pre> * StringUtils.join(null, *) = null * StringUtils.join([], *) = "" * StringUtils.join([null], *) = "" * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" * StringUtils.join(["a", "b", "c"], null) = "abc" * StringUtils.join(["a", "b", "c"], "") = "abc" * StringUtils.join([null, "", "a"], ',') = ",,a" * </pre> * * @param array the array of values to join together, may be null * @param separator the separator character to use, null treated as "" * @return the joined String, <code>null</code> if null array input */ public static String join(final Object[] array, final String sep) { if (array == null) { return null; } if (array.length <= 0) { return ""; } final String separator = sep != null ? sep : ""; final StringBuilder builder = new StringBuilder(); for (final Object object : array) { if (object != null) { builder.append(object); } builder.append(separator); } // remove the last separator, if there is one if (!"".equals(separator)) { builder.delete(builder.length() - separator.length(), builder.length()); } return builder.toString(); } /** * Joins the enumeration entries to a String object separated by the given String sep. * * @param values the string values in a enumeration * @param separator the separating string * @return the joined string with separated entries * @throws NamingException */ public static String join(final NamingEnumeration<String> values, final String separator) throws NamingException { final String sep = separator != null ? separator : ""; if (values == null || !values.hasMoreElements()) { return null; } String resultString; boolean nonNullAttrValueFound = false; final StringBuilder builder = new StringBuilder(); while (values.hasMore()) { final String next = values.next(); if (next != null) { // null is permitted as value of a present attribute - not my idea! builder.append(next).append(sep); nonNullAttrValueFound = true; } } if (!nonNullAttrValueFound) { return null; // StringBuilder.toString would return an empty string in that case } if (!StringUtil.isBlank(sep)) { builder.delete(builder.length() - sep.length(), builder.length()); } resultString = builder.toString(); return resultString; } }