/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.core.designer.util; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.StringTokenizer; import org.teiid.core.designer.TeiidDesignerRuntimeException; /** * This class contains static utilities that return strings that are the result of manipulating other strings or objects. * * @since 8.0 */ public class StringUtilities implements StringConstants { /** * Returns the path representing the concatenation of the specified path prefix and suffix. The resulting path is guaranteed to * have exactly one file separator between the prefix and suffix. * * @param prefix The path prefix * @param suffix The path suffix * @return The concatenated path prefix and suffix * @since 3.1 */ public static String buildPath( final String prefix, final String suffix ) { final StringBuffer path = new StringBuffer(prefix); if (!prefix.endsWith(File.separator)) path.append(File.separator); if (suffix.startsWith(File.separator)) path.append(suffix.substring(File.separator.length())); else path.append(suffix); return path.toString(); } /** * @param originalString * @param maxLength * @param endLength * @param middleString * @return * @since 5.0 */ public static String condenseToLength( final String originalString, final int maxLength, final int endLength, final String middleString ) { if (originalString.length() <= maxLength) return originalString; final int originalLength = originalString.length(); final StringBuffer sb = new StringBuffer(maxLength); sb.append(originalString.substring(0, maxLength - endLength - middleString.length())); sb.append(middleString); sb.append(originalString.substring(originalLength - endLength, originalLength)); return sb.toString(); } /** * @param string1 may be <code>null</code> * @param string2 may be <code>null</code> * @return <code>true</code> if the supplied strings are different. */ public static boolean areDifferent( final String string1, final String string2 ) { if (string1 == null) return string2 != null; return !string1.equals(string2); } /** * @param string1 may be <code>null</code> * @param string2 may be <code>null</code> * @return <code>true</code> if the supplied strings are equal. */ public static boolean equals( final String string1, final String string2 ) { if (string1 == null) return string2 == null; return string1.equals(string2); } /** * @param string1 may be <code>null</code> * @param string2 may be <code>null</code> * @return <code>true</code> if the supplied strings are equal, ignoring case. */ public static boolean equalsIgnoreCase( final String string1, final String string2 ) { if (string1 == null) return string2 == null; return string1.equalsIgnoreCase(string2); } /** * Returns a new string that represents the last fragment of the original string that begins with an uppercase char. Ex: * "getSuperTypes" would return "Types". * * @param value * @return String */ public static String getLastUpperCharToken( final String value ) { if (value == null) return null; final StringBuffer result = new StringBuffer(); for (int i = value.length() - 1; i >= 0; i--) { result.insert(0, value.charAt(i)); if (Character.isUpperCase(value.charAt(i))) return result.toString(); } return result.toString(); } /** * Returns a new string that represents the last fragment of the original string that begins with an uppercase char. Ex: * "getSuperTypes" would return "Types". * * @param value * @param lastToken - the last token tried... if not null will look backwards from the last token instead of the end of the * value param * @return String */ public static String getLastUpperCharToken( final String value, final String lastToken ) { if (value == null || lastToken == null) return value; final int index = value.lastIndexOf(lastToken); if (index == -1) return null; final StringBuffer result = new StringBuffer(); for (int i = index - 1; i >= 0; i--) { result.insert(0, value.charAt(i)); if (Character.isUpperCase(value.charAt(i))) return result.toString() + lastToken; } return result.toString() + lastToken; } public static String[] getLines( final String value ) { final StringReader stringReader = new StringReader(value); final BufferedReader reader = new BufferedReader(stringReader); final ArrayList<String> result = new ArrayList<String>(); try { String line = reader.readLine(); while (line != null) { result.add(line); line = reader.readLine(); } } catch (final IOException e) { throw new TeiidDesignerRuntimeException(e); } return (String[])result.toArray(new String[result.size()]); } public static String getLineSeparator() { return LINE_SEPARATOR; } /** * Indicates if the specified text is either empty or <code>null</code>. * * @param text the text being checked (may be <code>null</code>) * @return <code>true</code> if the specified text is either empty or <code>null</code> */ public static boolean isEmpty( final String text ) { return ((text == null) || (text.trim().length() == 0)); } /** * Indicates if the specified text is not empty or <code>null</code>. * * @param text the text being checked (may be not be <code>null</code>) * @return <code>true</code> if the specified text is not empty or <code>null</code> */ public static boolean isNotEmpty( final String text ) { return ((text != null) && (text.trim().length() > 0)); } /** * Returns a new string that lowercases the first character in the passed in value String * * @param value * @return String */ public static String lowerCaseFirstChar( final String value ) { if (value == null) return null; // Lower case the first char and try to look-up the SF String firstChar = new Character(value.charAt(0)).toString(); firstChar = firstChar.toLowerCase(); return (firstChar + value.substring(1)); } /** * Parses a comma-separated list into an array of strings into an array of strings * Values can contain whitespace, but whitespace at the beginning and end of each value is trimmed. * @return array of Strings * @param csvList a string of comma separated values */ public static String[] parseCommaDelimitedString(String csvString) { String[] result = parseList(csvString, COMMA); for (int i = 0; i < result.length; i++) { result[i] = result[i].trim(); } return result; } /** * Parses a delimited string using the specified delimiter. * @param list a string of token separated values * @param delimiter the delimiter character(s). Each character in the string is a single delimiter. * @return an array of strings */ public static String[] parseList(String delimitedString, String delimiter) { List<String> result = new ArrayList<String>(); StringTokenizer tokenizer = new StringTokenizer(delimitedString, delimiter); while (tokenizer.hasMoreTokens()) { result.add(tokenizer.nextToken()); } return result.toArray(new String[0]); } public static String removeChars( final String value, final char[] chars ) { final StringBuffer result = new StringBuffer(); if (value != null && chars != null && chars.length > 0) { final String removeChars = String.valueOf(chars); for (int i = 0; i < value.length(); i++) { final String character = value.substring(i, i + 1); if (removeChars.indexOf(character) == -1) result.append(character); } } else result.append(value); return result.toString(); } /** * Replaces multiple sequential "whitespace" characters from the specified string with a single space character, where * whitespace includes \r\t\n and other characters * * @param value the string to work with * @see java.util.regex.Pattern */ public static String removeExtraWhitespace( final String value ) { return value.replaceAll("\\s\\s+", " "); //$NON-NLS-1$//$NON-NLS-2$ } /** * Replaces all "whitespace" characters from the specified string with space characters, where whitespace includes \r\t\n and * other characters * * @param value the string to work with * @param stripExtras if true, replace multiple whitespace characters with a single character. * @see java.util.regex.Pattern */ public static String replaceWhitespace( final String value, final boolean stripExtras ) { return replaceWhitespace(value, " ", stripExtras); //$NON-NLS-1$ } /** * Replaces all "whitespace" characters from the specified string with space characters, where whitespace includes \r\t\n and * other characters * * @param value the string to work with * @param replaceWith the character to replace with * @param stripExtras if true, replace multiple whitespace characters with a single character. * @see java.util.regex.Pattern */ public static String replaceWhitespace( final String value, final String replaceWith, final boolean stripExtras ) { String rv = value.replaceAll("\\s+", replaceWith); //$NON-NLS-1$ if (stripExtras) rv = removeExtraWhitespace(rv); return rv; } /** * Returns a new string that uppercases the first character in the passed in value String * * @param value * @return String */ public static String upperCaseFirstChar( final String value ) { if (value == null) return null; // Lower case the first char and try to look-up the SF String firstChar = new Character(value.charAt(0)).toString(); firstChar = firstChar.toUpperCase(); return (firstChar + value.substring(1)); } /** * @param value * @return CamelCase version of the given string, ie. converting '_' to capital letters as well * as capitalising the first letter. */ public static String toCamelCase( final String value ) { StringBuffer sb = new StringBuffer(); for (String s : value.split(UNDERSCORE)) { sb.append(Character.toUpperCase(s.charAt(0))); if (s.length() > 1) { sb.append(s.substring(1, s.length()).toLowerCase()); } } return sb.toString(); } /** * Converts camel case string into 'normal' words-and-spaces, eg. BasicVdb -> Basic Vdb * <p> * <li>lowercase -> lowercase * <li>Class -> Class * <li>MyClass -> My Class * <li>HTML -> HTML * <li>PDFLoader -> PDF Loader * <li>AString -> A String * <li>SimpleXMLParser -> Simple XML Parser * <li>GL11Version -> GL 11 Version * <li>99Bottles -> 99 Bottles * <li>May5 -> May 5 * <li>BFG9000 -> BFG 9000 *</p> * * @param value * @return spaced version of camel case word */ public static String fromCamelCase(final String value) { if (value == null) return EMPTY_STRING; String regexp = String.format("%s|%s|%s", "(?<=[A-Z])(?=[A-Z][a-z])", //$NON-NLS-1$//$NON-NLS-2$ "(?<=[^A-Z])(?=[A-Z])", //$NON-NLS-1$ "(?<=[A-Za-z])(?=[^A-Za-z])"); //$NON-NLS-1$ return value.replaceAll(regexp, SPACE); } public static String getUniqueName(String baseName, Set<String> otherNames, boolean appendInteger, boolean appendWithSpace, int countLimit) { int count = 1; // Set the newName to baseName String newName = baseName; // append count to baseName if( appendWithSpace ) { newName = baseName + StringConstants.SPACE + count; } else { newName = baseName + count; } if( otherNames.contains(newName)) { if( appendWithSpace ) { newName = baseName + StringConstants.SPACE + count; } else { newName = baseName + count; } while( count < countLimit) { if(!otherNames.contains(newName)){ return newName; } else { count++; newName = baseName + StringConstants.SPACE + count; } } } else { return newName; } return baseName; } /** * @param c the character being checked * @return <code>true</code> if the character is a letter */ public static boolean isLetter( char c ) { return isBasicLatinLetter(c) || Character.isLetter(c); } /** * @param c the character being checked * @return <code>true</code> if the character is a letter or digit */ public static boolean isLetterOrDigit( char c ) { return isBasicLatinLetter(c) || isBasicLatinDigit(c) || Character.isLetterOrDigit(c); } /** * @param text * @return text is either null or empty */ public static boolean isBlank(final String text) { return ((text == null) || (text.trim().length() == 0)); } /** * @param text the text being checked (can be empty) * @return <code>true</code> if the text can be converted to a number */ public static boolean isNumber( final String text ) { return ( !isBlank( text ) && text.matches( "-?\\d+(\\.\\d+)?" ) ); //$NON-NLS-1$ } private static boolean isBasicLatinLetter( char c ) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } private static boolean isBasicLatinDigit( char c ) { return c >= '0' && c <= '9'; } /** * Replace all occurrences of the search string with the replace string * in the source string. If any of the strings is null or the search string * is zero length, the source string is returned. * @param source the source string whose contents will be altered * @param search the string to search for in source * @param replace the string to substitute for search if present * @return source string with *all* occurrences of the search string * replaced with the replace string */ public static String replaceAll( String source, String search, String replace ) { if (source != null && search != null && search.length() > 0 && replace != null) { int start = source.indexOf(search); if (start > -1) { StringBuffer newString = new StringBuffer(source); replaceAll(newString, search, replace); return newString.toString(); } } return source; } /** * @param source the source string whose contents will be altered * @param search the string to search for in source * @param replace the string to substitute for search if present */ public static void replaceAll( StringBuffer source, String search, String replace ) { if (source != null && search != null && search.length() > 0 && replace != null) { int start = source.toString().indexOf(search); while (start > -1) { int end = start + search.length(); source.replace(start, end, replace); start = source.toString().indexOf(search, start + replace.length()); } } } public static void main(String[] args) { // TODO Auto-generated method stub String startName = "XXXXX"; Set<String> otherNames = new HashSet<String>(); otherNames.add("XXXXX"); otherNames.add("YYYYY"); String newName = StringUtilities.getUniqueName(startName, otherNames, true, true, 1000); System.out.println(" START NAME = " + startName + " UNIQUE NAME = " + newName); otherNames.add("XXXXX 1"); newName = StringUtilities.getUniqueName(startName, otherNames, true, true, 1000); System.out.println(" START NAME = " + startName + " UNIQUE NAME = " + newName); otherNames.add("XXXXX 2"); newName = StringUtilities.getUniqueName(startName, otherNames, true, true, 1000); System.out.println(" START NAME = " + startName + " UNIQUE NAME = " + newName); } /** * Compares two strings lexicographically. * The comparison is based on the Unicode value of each character in * the strings. * @param str1 * @param str2 * * @return the value <code>0</code> if the str1 is equal to str2; * a value less than <code>0</code> if str1 * is lexicographically less than str2; * and a value greater than <code>0</code> if str1 is * lexicographically greater than str2. */ public static int compare(char[] str1, char[] str2) { int len1 = str1.length; int len2 = str2.length; int n = Math.min(len1, len2); int i = 0; while (n-- != 0) { char c1 = str1[i]; char c2 = str2[i++]; if (c1 != c2) { return c1 - c2; } } return len1 - len2; } /** * Returns the length of the common prefix between s1 and s2. * @param s1 * @param s2 * @return length of the prefix */ public static int prefixLength(char[] s1, char[] s2) { int len = 0; int max = Math.min(s1.length, s2.length); for (int i = 0; i < max && s1[i] == s2[i]; ++i) ++len; return len; } /** * Returns the length of the common prefix between s1 and s2. * @param s1 * @param s2 * @return length of the prefix */ public static int prefixLength(String s1, String s2) { int len = 0; int max = Math.min(s1.length(), s2.length()); for (int i = 0; i < max && s1.charAt(i) == s2.charAt(i); ++i) ++len; return len; } public static String removeXmiExtension(String input) { if( input.toUpperCase().endsWith(".XMI") ) { return input.substring(0, input.length() - 4); } return input; } public static String getQuotedValue(String value, String quoteStr) { if( value.length() > 3 && value.startsWith(quoteStr) && value.endsWith(quoteStr) ) { return value; } String quotedValue = quoteStr + value + quoteStr; return quotedValue; } public static boolean isSingleQuoted(String value) { return value.length() > 1 && value.startsWith(QUOTE_MARK) && value.endsWith(QUOTE_MARK); } private StringUtilities() { } }