package spiffy.core.lang; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.util.HashMap; import java.util.Iterator; /** * Helper methods for string manipulations and/or string representations of various entities * * @author Kasper B. Graversen, (c) 2007 */ public class StringHelper { /** * Given a string check to see if it is in a collection of strings (using <tt>equals()</tt>) * * @param searchString * string to search for. If <tt>null</tt> false is returned. * @param searchStringList * list of strings to search within * @return true if string is in the search list, or false if searchString is <tt>null</tt> or not present in the * list * @throws IllegalArgumentException * when argument SearchStringList has length > 0 * @since 0.03 */ public static boolean in(final String searchString, final String... searchStringList) { if( searchString == null ) { return false; } if( searchStringList.length == 0 ) { throw new IllegalArgumentException( "argument SearchStringList must have length > 0"); } for(final String s : searchStringList) { if( s.equals(searchString) ) { return true; } } return false; } /** * Given a string, trim it, and if different from the string "", check to see if it is in a collection of strings * (using <tt>equals()</tt>). * <P> * This is quite often used in web programming, where input on the server side may either be <tt>null</tt>, * <tt>""</tt> or some string. * <p> * * @param searchString * string to search for * @param searchStringList * list of strings to search within * @return true if string is in the search list, or false if searchString is <tt>null</tt> or not present in the * list * @throws IllegalArgumentException * when argument SearchStringList has length > 0 * @see #in(String, String[]) * @since 0.03 */ public static boolean inAndNonEmpty(final String searchString, final String... searchStringList) { if( searchString == null ) { return false; } if( searchStringList.length == 0 ) { throw new IllegalArgumentException( "argument SearchStringList must have length > 0"); } final String trimmedString = searchString.trim(); if( trimmedString.equals("") ) { return false; } for(final String s : searchStringList) { if( s.equals(trimmedString) ) { return true; } } return false; } /** * Join 0..n strings separated by a delimiter. The delimiter is not concatenated after the last element. e.g. given * an iterator with the elements <tt>", ", "a", "b", "c"</tt> * <pre> * join(iterator) * </pre> * * becomes * * <pre> * "a, b, c" * </pre> * * @param delimiter * the delimiter to insert between each string. * @param iterator * the iterator of elements to concatenate. * @return the delimiter-concatenated string. If <tt>null</tt> is given as input strings, <tt>null</tt> is * returned. */ public static String join(final String delimiter, final Iterator<?> iterator) { if( iterator == null ) { return null; } final StringBuilder sb = new StringBuilder(); while(iterator.hasNext()) { sb.append(iterator.next().toString()); sb.append(delimiter); } // remove last delimiter final int bufLen = sb.length(); if( bufLen > 0 ) { // only removed if we ever added anything sb.delete(bufLen - delimiter.length(), bufLen); } return sb.toString(); } /** * Join 0..n strings separated by a delimiter. The delimiter is not concatenated after the last element. e.g. * * <pre> * join(", ", "a", "b", "c") * </pre> * * becomes * * <pre> * "a, b, c" * </pre> * * @param delimiter * the delimiter to insert between each string. * @param strings * the array of strings to concatenate. * @return the delimiter-concatenated string. If <tt>null</tt> is given as input strings, <tt>null</tt> is * returned. */ public static String join(final String delimiter, final String... strings) { if( strings == null ) { return null; } if( strings.length == 0 ) { return ""; } final StringBuilder sb = new StringBuilder(); // add first 1.. n-1 final int len = strings.length - 1; int i = 0; for(; i < len; i++) { sb.append(strings[i]); sb.append(delimiter); } // add last sb.append(strings[i]); return sb.toString(); } /** * Remove all occurrences of all specified characters. * <p> * This is an easy way to e.g. remove all formatting chars such as ' ', '\t', '\n' from Strings for easy comparison * of code generated String. * * @param baseString * the string to trim * @param removeChars * the characters to remove * @return a string with the specified characters removed. */ public static String removeAll(final String baseString, final Character... removeChars) { final StringBuffer resultString = new StringBuffer(); // cache for quick lookup final HashMap<Character, Object> charMatchMap = new HashMap<Character, Object>(); for(final Character c : removeChars) { charMatchMap.put(c, c); } for(int i = 0; i < baseString.length(); i++) { final char c = baseString.charAt(i); if( charMatchMap.containsKey(c) == false ) { resultString.append(c); } } return resultString.toString(); } private static String repeatJoin(final String baseString, final int endSize, final boolean isLeftJoin, final String... joinStrings) { if( baseString == null ) { throw new IllegalArgumentException("Argument baseString is null"); } if( joinStrings == null ) { throw new IllegalArgumentException("argument joinStrings is null"); } if( joinStrings.length == 0 ) { return baseString; } if( endSize < baseString.length() ) { throw new IllegalArgumentException( "Argument endSize is less than the length of baseString"); } // appending as many times possible final int resultingSize = endSize - baseString.length(); final StringBuilder joiningStrings = new StringBuilder(resultingSize); int i = 0; while(true) { if( joiningStrings.length() + joinStrings[i].length() <= resultingSize ) { joiningStrings.append(joinStrings[i]); } else { break; } i = (i + 1) % joinStrings.length;// round-robin the joinStrings } // final join if( isLeftJoin ) { joiningStrings.append(baseString); } else { joiningStrings.insert(0, baseString); } return joiningStrings.toString(); } /** * Create a string by repeatedly joining/appending one or more strings in front of the string until the resulting * string is equal to or as close possible to some length. E.g. * <code> * repeatLeftJoin("100", 6, "#")); * </code> * yields <code>"fully fill", "###100"</code> * * <code> * repeatLeftJoin("100", 6, "##")); * </pre> * * Yields <code> "##100",</code> * * @param baseString * the string to join strings onto * @param endSize * the resulting size * @param joinStrings * one or more strings to join onto the basestring. If the empty list is given, the baseString is returned. * @return a joined string */ public static String repeatLeftJoin(final String baseString, final int endSize, final String... joinStrings) { return repeatJoin(baseString, endSize, true, joinStrings); } /** * Create a string by repeatedly joining/appending one or more strings at the end of the string until the resulting * string is equal to or as close possible to some length. E.g. * * <pre> * repeatLeftJoin("100", 6, "#")); * </pre> * * Yields <code>"fully fill", "###100"</code> * * <pre> * repeatLeftJoin("100", 6, "##")); * </pre> * * Yields <code> "##100",</code> * * @param baseString * the string to join strings onto * @param endSize * the resulting size * @param joinStrings * one or more strings to join onto the basestring. If the empty list is given, the baseString is * returned. * @return a joined string */ public static String repeatRightJoin(final String baseString, final int endSize, final String... joinStrings) { return repeatJoin(baseString, endSize, false, joinStrings); } /** * Returns a string representation of any throwable (e.g. exceptions) * * @param throwable * the throwable/exception to get a representation from * @return a string representing the throwable * @since 0.1 */ public static String toString(final Throwable throwable) { final Writer result = new StringWriter(); final PrintWriter printWriter = new PrintWriter(result); throwable.printStackTrace(printWriter); return result.toString(); } }