/**
* <copyright>
* </copyright>
*
*
*/
package org.feature.multi.perspective.mapping.viewmapping.resource.mtext.util;
/**
* A utility class that provides some common methods to work with Strings.
*/
public class MtextStringUtil {
public final static String HEX_DIGIT_REGEXP = "[0-9a-fA-F]";
public final static String UNICODE_SEQUENCE_REGEXP = "\\\\u" + HEX_DIGIT_REGEXP + HEX_DIGIT_REGEXP + HEX_DIGIT_REGEXP + HEX_DIGIT_REGEXP;
public final static String ESC_OTHER = "\\\\(n|r|t|b|f|\"|'|>)";
public final static String ESC_REGEXP = "\\A((" + UNICODE_SEQUENCE_REGEXP + ")|(" + ESC_OTHER + ")).*";
/**
* Capitalizes the first letter of the given string.
*
* @param text the string to capitalize.
*
* @return the modified string.
*/
public static String capitalize(String text) {
String h = text.substring(0, 1).toUpperCase();
String t = text.substring(1);
return h + t;
}
/**
* Returns the part of 'tail' that is not present at the end of 'text'. For
* example if text = 'abc' and tail = 'cd' this method returns 'd'. If 'tail' can
* not be found at the end of 'text', 'tail' is returned as is.
*/
public static String getMissingTail(String text, String tail) {
for (int i = 1; i < tail.length(); i++) {
int endIndex = text.length();
int end = Math.max(0, endIndex);
int start = Math.max(0, end - i);
String contentTail = text.substring(start, end);
String proposalHead = tail.substring(0, i);
if (contentTail.equals(proposalHead)) {
return tail.substring(i);
}
}
return tail;
}
/**
* Converts a string that contains upper-case letter and underscores (e.g.,
* constant names) to a camel-case string. For example, MY_CONSTANT is converted
* to myConstant.
*
* @param text the string to convert
*
* @return a camel-case version of text
*/
public static String convertAllCapsToLowerCamelCase(String text) {
String lowerCase = text.toLowerCase();
while (true) {
int i = lowerCase.indexOf('_');
if (i < 0) {
break;
}
String head = lowerCase.substring(0, i);
if (i + 1 == lowerCase.length()) {
lowerCase = head;
break;
} else {
char charAfterUnderscore = lowerCase.charAt(i + 1);
char upperCase = Character.toUpperCase(charAfterUnderscore);
if (i + 2 < lowerCase.length()) {
String tail = lowerCase.substring(i + 2, lowerCase.length());
lowerCase = head + upperCase + tail;
} else {
lowerCase = head + upperCase;
break;
}
}
}
return lowerCase;
}
/**
* Concatenates the given parts and puts 'glue' between them.
*/
public static String explode(java.util.Collection<? extends Object> parts, String glue) {
return explode(parts.toArray(new Object[parts.size()]), glue);
}
/**
* Concatenates the given parts and puts 'glue' between them.
*/
public static String explode(Object[] parts, String glue) {
StringBuilder sb = new StringBuilder();
int length = parts.length;
for (int i = 0; i < length; i++) {
Object next = parts[i];
sb.append(next.toString());
if (i < length - 1) {
sb.append(glue);
}
}
return sb.toString();
}
/**
* Concatenates the given parts and puts 'glue' between them. The toStringFunction
* is used to convert the parts to strings.
*/
public static <T> String explode(java.util.Collection<T> parts, String glue, org.feature.multi.perspective.mapping.viewmapping.resource.mtext.IMtextFunction1<String, T> toStringFunction) {
String[] partsAsArray = new String[parts.size()];
int i = 0;
for (T part : parts) {
partsAsArray[i] = toStringFunction.execute(part);
i++;
}
return explode(partsAsArray, glue);
}
/**
* Concatenates the given parts and puts 'glue' between them. The toStringFunction
* is used to convert the parts to strings.
*/
public static <T> String explode(T[] parts, String glue, org.feature.multi.perspective.mapping.viewmapping.resource.mtext.IMtextFunction1<String, T> toStringFunction) {
String[] partsAsArray = new String[parts.length];
int i = 0;
for (T part : parts) {
partsAsArray[i] = toStringFunction.execute(part);
i++;
}
return explode(partsAsArray, glue);
}
/**
* Removes single quotes at the start and end of tokenName.
*/
public static String formatTokenName(String tokenName) {
if (tokenName.length() > 0 && tokenName.startsWith("'")) {
tokenName = tokenName.substring(1, tokenName.length());
}
if (tokenName.length() > 0 && tokenName.endsWith("'")) {
tokenName = tokenName.substring(0, tokenName.length() - 1);
}
return tokenName;
}
public static int getLine(String text, int offset) {
return getLineAndCharPosition(text, offset)[0];
}
public static int getCharPositionInLine(String text, int offset) {
return getLineAndCharPosition(text, offset)[1];
}
public static Integer[] getLineAndCharPosition(String text, int offset) {
int index = 0;
int line = 0;
int positionInLine = 0;
while (true) {
line++;
positionInLine = offset - index + 1;
int nextN = text.indexOf("\n", index);
int nextR = text.indexOf("\r", index);
int nextNorR = Integer.MAX_VALUE;
if (nextN >= 0) {
nextNorR = nextN;
} else if (nextR >= 0 && nextR < nextNorR) {
nextNorR = nextR;
} else {
// found no EOL character
break;
}
index = nextNorR + 1;
if (index == nextN) {
index++;
}
if (index == nextR) {
index++;
}
if (index > offset) {
break;
}
}
return new Integer[] {line, positionInLine};
}
public static String escapeQuotes(String s) {
s = s.replace("\\", "\\\\");
s = s.replace("\"", "\\\"");
return s;
}
public static String convertCamelCaseToAllCaps(String qualifiedClassName) {
StringBuffer sb = new StringBuffer();
final char[] charArray = qualifiedClassName.toCharArray();
for (int c = 0; c < charArray.length; c++) {
char character = charArray[c];
final boolean isEnd = c + 1 == charArray.length;
boolean nextIsUpper = !isEnd && Character.isUpperCase(charArray[c + 1]);
boolean nextNextIsLower = c + 2 < (charArray.length) && Character.isLowerCase(charArray[c + 2]);
sb.append(Character.toUpperCase(character));
if (Character.isLowerCase(character) && nextIsUpper) {
sb.append('_');
} else {
if (nextIsUpper && nextNextIsLower) {
sb.append('_');
}
}
}
return sb.toString();
}
/**
* Escapes the given text such that it can be safely embedded in a string literal
* in Java source code.
*
* @param text the text to escape
*
* @return the escaped text
*/
public static String escapeToJavaString(String text) {
if (text == null) {
return null;
}
String result = text.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"").replace("\b", "\\b").replace("\f", "\\f").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t");
StringBuilder complete = new StringBuilder();
for (int i = 0; i < result.length(); i++) {
int codePointI = result.codePointAt(i);
if (codePointI >= 32 && codePointI <= 127) {
complete.append(Character.toChars(codePointI));
} else {
// use Unicode representation
complete.append("\\u");
String hex = Integer.toHexString(codePointI);
complete.append(getRepeatingString(4 - hex.length(), '0'));
complete.append(hex);
}
}
return complete.toString();
}
/**
* Escapes the given text such that it can be safely embedded in an ANTLR grammar
* as keyword (i.e., an in-line token). Single quotes are escaped using a
* backslash. Backslashes are escaped using a backslash.
*
* @param value the text to escape
*
* @return the escaped text
*/
public static String escapeToANTLRKeyword(String value) {
return escapeToJavaString(value).replace("'", "\\'").replace("%", "\\u0025");
}
public static boolean isUnicodeSequence(String text) {
return text.matches(UNICODE_SEQUENCE_REGEXP);
}
public static String matchCamelCase(String query, String str) {
if (!query.matches("[A-Za-z\\*]+")) {
return null;
}
String head = "";
int i;
for (i = 0; i < query.length(); i++) {
char charI = query.charAt(i);
if (Character.isLowerCase(charI)) {
head += charI;
} else {
break;
}
}
if (i > 0) {
head += "[^A-Z]*";
}
String tail = query.substring(i);
String re = "\\b(";
tail = tail.replaceAll("\\*", ".*?");
re += head + tail.replaceAll("([A-Z][^A-Z]*)", "$1[^A-Z]*");
re += ".*?)\\b";
java.util.regex.Pattern regex = java.util.regex.Pattern.compile(re);
java.util.regex.Matcher m = regex.matcher(str);
if (m.find()) {
return m.group();
} else {
return null;
}
}
public static String getRepeatingString(int count, char character) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < count; i++) {
result.append(character);
}
return result.toString();
}
private static int minimum(int a, int b, int c) {
return Math.min(Math.min(a, b), c);
}
public static int computeLevenshteinDistance(CharSequence str1, CharSequence str2) {
int[][] distance = new int[str1.length() + 1][str2.length() + 1];
for (int i = 0; i <= str1.length(); i++) {
distance[i][0] = i;
}
for (int j = 0; j <= str2.length(); j++) {
distance[0][j] = j;
}
for (int i = 1; i <= str1.length(); i++) {
for (int j = 1; j <= str2.length(); j++) {
distance[i][j] = minimum(distance[i - 1][j] + 1, distance[i][j - 1] + 1, distance[i - 1][j - 1] + ((str1.charAt(i - 1) == str2.charAt(j - 1)) ? 0 : 1));
}
}
return distance[str1.length()][str2.length()];
}
public static String encode(char delimiter, String[] parts) {
java.util.List<String> partList = new java.util.ArrayList<String>();
for (String part : parts) {
partList.add(part);
}
return encode(delimiter, partList);
}
public static String encode(char delimiter, Iterable<String> parts) {
StringBuilder result = new StringBuilder();
for (String part : parts) {
String encodedPart = part.replace("\\", "\\\\");
encodedPart = encodedPart.replace("" + delimiter, "\\" + delimiter);
result.append(encodedPart);
result.append(delimiter);
}
return result.toString();
}
public static java.util.List<String> decode(String text, char delimiter) {
java.util.List<String> parts = new java.util.ArrayList<String>();
boolean escapeMode = false;
String part = "";
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c == delimiter) {
if (escapeMode) {
part += delimiter;
escapeMode = false;
} else {
// end of part
parts.add(part);
part = "";
}
} else if (c == '\\') {
if (escapeMode) {
part += '\\';
escapeMode = false;
} else {
escapeMode = true;
}
} else {
part += c;
}
}
return parts;
}
public static String convertToString(java.util.Map<String, Object> properties) {
java.util.List<String> parts = new java.util.ArrayList<String>();
for (String key : properties.keySet()) {
Object value = properties.get(key);
if (value instanceof String) {
parts.add(encode('=', new String[] {key, (String) value}));
} else {
throw new RuntimeException("Can't encode " + value);
}
}
return encode(';', parts);
}
public static java.util.Map<String, String> convertFromString(String text) {
java.util.Map<String, String> result = new java.util.LinkedHashMap<String, String>();
java.util.List<String> keyValuePairs = decode(text, ';');
for (String pair : keyValuePairs) {
java.util.List<String> keyAndValue = decode(pair, '=');
String key = keyAndValue.get(0);
String value = keyAndValue.get(1);
result.put(key, value);
}
return result;
}
}