/* * Copyright 2011 cruxframework.org. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.cruxframework.crux.core.client.utils; import com.google.gwt.core.client.GWT; /** * @author Gesse S. F. Dafe * @author Thiago da Rosa de Bustamante * @author Samuel Almeida Cardoso (samuel@cruxframework.org) */ public class StringUtils { public static final String EMPTY = ""; public static final String SPACE = " "; private static Collator collator = null; public static int localeCompare(String source, String target) { return localeCompare(source, target, false); } public static int localeCompare(String source, String target, boolean caseSensitive) { return getCollatorStaticInstance().compare( caseSensitive ? source : source.toLowerCase(), caseSensitive ? target : target.toLowerCase()); } private static Collator getCollatorStaticInstance() { if (collator == null) { collator = GWT.create(Collator.class); } return collator; } /** * @author Samuel Almeida Cardoso (samuel@cruxframework.org) */ public interface Collator { public int compare(String source, String target); } public static class CollatorFFandIE implements Collator { @Override public native int compare(String source, String target) /*-{ return source.localeCompare(target); }-*/; } public static class CollatorSafari implements Collator { @Override public int compare(String source, String target) { return removeAccents(source).compareTo(removeAccents(target)); } } public static String removeAccents(String value){ value = value.replaceAll("[ÂÀÁÄÃ]","A"); value = value.replaceAll("[âãàáä]","a"); value = value.replaceAll("[ÊÈÉË]","E"); value = value.replaceAll("[êèéë]","e"); value = value.replaceAll("ÎÍÌÏ","I"); value = value.replaceAll("îíìï","i"); value = value.replaceAll("[ÔÕÒÓÖ]","O"); value = value.replaceAll("[ôõòóö]","o"); value = value.replaceAll("[ÛÙÚÜ]","U"); value = value.replaceAll("[ûúùü]","u"); value = value.replaceAll("Ç","C"); value = value.replaceAll("ç","c"); value = value.replaceAll("[ýÿ]","y"); value = value.replaceAll("Ý","Y"); value = value.replaceAll("ñ","n"); value = value.replaceAll("Ñ","N"); return value; } /** * @param src * @param length * @param padding * @return */ public static String lpad(String src, int length, char padding) { if(src == null) { src = ""; } while(src.length() < length) { src = padding + src; } return src; } /** * @param src * @param length * @param padding * @return */ public static String rpad(String src, int length, char padding) { if(src == null) { src = ""; } while(src.length() < length) { src += padding; } return src; } /** * @param value * @return */ public static boolean isEmpty(String value) { return (value == null || value.length() == 0); } /** * @param text * @param searchString * @param replacement * @return */ public static String replace(String text, String searchString, String replacement) { return replace(text, searchString, replacement, -1); } /** * @param text * @param searchString * @param replacement * @param max * @return */ public static String replace(String text, String searchString, String replacement, int max) { if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) { return text; } int start = 0; int end = text.indexOf(searchString, start); if (end == -1) { return text; } int replLength = searchString.length(); int increase = replacement.length() - replLength; increase = (increase < 0 ? 0 : increase); increase *= (max < 0 ? 16 : (max > 64 ? 64 : max)); StringBuffer buf = new StringBuffer(text.length() + increase); while (end != -1) { buf.append(text.substring(start, end)).append(replacement); start = end + replLength; if (--max == 0) { break; } end = text.indexOf(searchString, start); } buf.append(text.substring(start)); return buf.toString(); } /** * Transforms "some text" into "Some text" * @param text * @return */ public static String toUpperCaseFirstChar(String text) { if(text != null && text.length() > 0) { return text.substring(0,1).toUpperCase() + text.substring(1); } return text; } /** * This method generates a faster string comparison than {@code String.equals()} * for web mode code. * * The GWT generated {@code String.equals()} method makes a check in its parameter's type in runtime. * That method makes that assertion on compilation time (once its parameters are both * Strings). * * @param a * @param b * @return */ public static boolean equals(String a, String b) { if (GWT.isScript()) { if (a==null) return (b==null); return (b!= null && a==b); } else { if (a==null) return (b==null); return (b!= null && a.equals(b)); } } /** * This method generate a faster string comparison than {@code String.equals()} * for web mode code. It is similar to {@code StringUtils.equals()} method. * The only difference is that this one does not check for null parameters. * * @param a * @param b * @return */ public static boolean unsafeEquals(String a, String b) { if (GWT.isScript()) { return a==b; } else { return a.equals(b); } } /** * * @param value * @return */ public static double safeParseDouble(String value) { if (!isEmpty(value)) { return Double.parseDouble(value); } return Double.MIN_VALUE; } /** * * @param multiValuedProperty * @param value * @return */ public static boolean containsValue(String multiValuedProperty, String value) { if (isEmpty(value) || isEmpty(multiValuedProperty)) { return false; } String[] parts = multiValuedProperty.split(","); for (String part : parts) { if (part.trim().equals(value)) { return true; } } return false; } public static String rTrim(String value) { if (value==null) { return null; } int index = value.length(); while (index > 0 && isWhitespace(value.charAt(index - 1))) { index--; } return value.substring(0, index); } public static boolean isWhitespace(char c) { return c == ' ' || c == '\t' || c == '\n'; } /** * * <p>Find the Levenshtein distance between two Strings.</p> * * <pre> * StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException * StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException * StringUtils.getLevenshteinDistance("","") = 0 * StringUtils.getLevenshteinDistance("","a") = 1 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7 * StringUtils.getLevenshteinDistance("frog", "fog") = 1 * StringUtils.getLevenshteinDistance("fly", "ant") = 3 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1 * </pre> * * @param s the first String, must not be null * @param t the second String, must not be null * @return result distance * @throws IllegalArgumentException if either String input <code>null</code> */ public static int getLevenshteinDistance(String s, String t) { if (s == null || t == null) { throw new IllegalArgumentException("Strings must not be null"); } int n = s.length(); int m = t.length(); if (n == 0) { return m; } else if (m == 0) { return n; } if (n > m) { String tmp = s; s = t; t = tmp; n = m; m = t.length(); } int p[] = new int[n+1]; int d[] = new int[n+1]; int _d[]; int i; int j; char t_j; int cost; for (i = 0; i<=n; i++) { p[i] = i; } for (j = 1; j<=m; j++) { t_j = t.charAt(j-1); d[0] = j; for (i=1; i<=n; i++) { cost = s.charAt(i-1)==t_j ? 0 : 1; d[i] = Math.min(Math.min(d[i-1]+1, p[i]+1), p[i-1]+cost); } _d = p; p = d; d = _d; } return p[n]; } /** * Check if the given string represents a number * @param str * @return */ public static boolean isNumeric(String str) { if (str == null || str.length() == 0) { return false; } int sz = str.length(); int start = 0; if(sz > 0 && str.charAt(0) == '-') { if (sz == 1) { return false; } start = 1; } for (int i = start; i < sz; i++) { if (Character.isDigit(str.charAt(i)) == false) { return false; } } return true; } public static native int charCodeAt(String str, int i)/*-{ return str.charCodeAt(i); }-*/; /** * Encode an UTF-16 string (Unicode) to UTF-8. DOM Strings are UTF-16 by default * @param utf16String * @return utf-8 encoded string */ public static native String toUTF8(String utf16String)/*-{ var output = ""; var i = -1; var x, y; while(++i < utf16String.length) { // Decode utf-16 surrogate pairs x = utf16String.charCodeAt(i); y = i + 1 < utf16String.length ? utf16String.charCodeAt(i + 1) : 0; if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); i++; } // Encode output as utf-8 if(x <= 0x7F) output += String.fromCharCode(x); else if(x <= 0x7FF) output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), 0x80 | ( x & 0x3F)); else if(x <= 0xFFFF) output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), 0x80 | ((x >>> 6 ) & 0x3F), 0x80 | ( x & 0x3F)); else if(x <= 0x1FFFFF) output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), 0x80 | ((x >>> 12) & 0x3F), 0x80 | ((x >>> 6 ) & 0x3F), 0x80 | ( x & 0x3F)); } return output; }-*/; /** * Convert a raw UTF-8 string to a hex string. * @param input * @return */ public static String toHEXString(String input) { String hexTab = "0123456789ABCDEF"; StringBuilder output = new StringBuilder(); int x; for(int i = 0; i < input.length(); i++) { x = charCodeAt(input, i); output.append(hexTab.charAt((x >>> 4) & 0x0F)); output.append(hexTab.charAt(x & 0x0F)); } return output.toString(); } /** * Join all string parts into one string, using the join parameter between each string part * @param parts * @param join * @return */ public static String join(String[] parts, String join) { return join(parts, join, null); } /** * * @param parts * @param join * @param filter * @return */ public static String join(String[] parts, String join, StringFilter filter) { StringBuilder str = new StringBuilder(); boolean first = true; for (String part : parts) { if (!first) { str.append(join); } first = false; if (filter!= null) { str.append(filter.filter(part)); } else { str.append(part); } } return str.toString(); } /** * A String Filter that can be applied on join operations * @author Thiago da Rosa de Bustamante * */ public static interface StringFilter { String filter(String input); } }