blob: 15e79dc868c8c4a1bfd82b0ab1fe25345fc34020 [file] [log] [blame]
/*
* Copyright (c) 2014, 2015 Eike Stepper (Loehne, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Eike Stepper - initial API and implementation
* Yatta Solutions - [466264] Enhance UX in simple installer
*/
package org.eclipse.oomph.util;
import org.eclipse.emf.common.util.URI;
import org.eclipse.osgi.util.NLS;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Various static helper methods for dealing with strings.
*
* @author Eike Stepper
*/
public final class StringUtil
{
public static final String EMPTY = ""; //$NON-NLS-1$
public static final String NL = PropertiesUtil.getProperty("line.separator"); //$NON-NLS-1$
public static String HORIZONTAL_ELLIPSIS = "\u2026"; //$NON-NLS-1$
private static final Pattern WILDCARD_FILTER_PATTERN = Pattern.compile("(\\\\.|[*?])"); //$NON-NLS-1$
private StringUtil()
{
}
public static String escape(String str)
{
if (str == null)
{
return null;
}
int len = str.length();
StringBuilder builder = new StringBuilder(len);
for (int i = 0; i < len; i++)
{
char c = str.charAt(i);
if (c > 0xfff)
{
builder.append("\\u" + HexUtil.charToHex(c)); //$NON-NLS-1$
}
else if (c > 0xff)
{
builder.append("\\u0" + HexUtil.charToHex(c)); //$NON-NLS-1$
}
else if (c > 0x7f)
{
builder.append("\\u00" + HexUtil.charToHex(c)); //$NON-NLS-1$
}
else if (c < 32)
{
switch (c)
{
case '\r':
builder.append('\\');
builder.append('r');
break;
case '\n':
builder.append('\\');
builder.append('n');
break;
case '\t':
builder.append('\\');
builder.append('t');
break;
case '\f':
builder.append('\\');
builder.append('f');
break;
case '\b':
builder.append('\\');
builder.append('b');
break;
default:
if (c > 0xf)
{
builder.append("\\u00" + HexUtil.charToHex(c)); //$NON-NLS-1$
}
else
{
builder.append("\\u000" + HexUtil.charToHex(c)); //$NON-NLS-1$
}
}
}
else if (c == '\\')
{
builder.append('\\');
builder.append('\\');
}
else
{
builder.append(c);
}
}
return builder.toString();
}
public static String unescape(String str)
{
if (str == null)
{
return null;
}
int len = str.length();
StringBuilder builder = new StringBuilder(len);
StringBuilder unicodeBuilder = new StringBuilder(4);
boolean unicode = false;
boolean slash = false;
for (int i = 0; i < len; i++)
{
char c = str.charAt(i);
if (unicode)
{
unicodeBuilder.append(c);
if (unicodeBuilder.length() == 4)
{
try
{
char value = HexUtil.hexToChar(unicodeBuilder.toString());
builder.append(value);
unicodeBuilder.setLength(0);
unicode = false;
slash = false;
}
catch (NumberFormatException ex)
{
builder.append('\\');
builder.append('u');
builder.append(unicodeBuilder);
}
}
continue;
}
if (slash)
{
slash = false;
switch (c)
{
case '\\':
builder.append('\\');
break;
case 'r':
builder.append('\r');
break;
case 'n':
builder.append('\n');
break;
case 't':
builder.append('\t');
break;
case 'f':
builder.append('\f');
break;
case 'b':
builder.append('\b');
break;
case 'u':
unicode = true;
break;
case '0':
case '1':
case '2':
case '3':
if (i + 2 < len && str.charAt(i + 1) >= '0' && str.charAt(i + 1) <= '7' && str.charAt(i + 2) >= '0' && str.charAt(i + 2) <= '7')
{
builder.append((char)Integer.parseInt(str.substring(i, i + 3), 8));
i += 2;
continue;
}
//$FALL-THROUGH$
default:
{
builder.append(c);
}
}
continue;
}
else if (c == '\\')
{
slash = true;
continue;
}
builder.append(c);
}
if (slash)
{
builder.append('\\');
}
return builder.toString();
}
public static boolean isEmpty(String str)
{
return str == null || str.length() == 0;
}
public static String safe(String str)
{
return safe(str, EMPTY);
}
private static String safe(String str, String def)
{
if (str == null)
{
return def;
}
return str;
}
public static String cap(String str)
{
if (str == null || str.length() == 0)
{
return str;
}
char first = str.charAt(0);
if (Character.isUpperCase(first))
{
return str;
}
if (str.length() == 1)
{
return str.toUpperCase();
}
StringBuilder builder = new StringBuilder(str);
builder.setCharAt(0, Character.toUpperCase(first));
return builder.toString();
}
public static String capAll(String str)
{
if (str == null || str.length() == 0)
{
return str;
}
boolean inWhiteSpace = true;
StringBuilder builder = new StringBuilder(str);
for (int i = 0; i < builder.length(); i++)
{
char c = builder.charAt(i);
boolean isWhiteSpace = Character.isWhitespace(c);
if (!isWhiteSpace && inWhiteSpace)
{
builder.setCharAt(i, Character.toUpperCase(c));
}
inWhiteSpace = isWhiteSpace;
}
return builder.toString();
}
public static String uncap(String str)
{
if (str == null || str.length() == 0)
{
return str;
}
char first = str.charAt(0);
if (Character.isLowerCase(first))
{
return str;
}
if (str.length() == 1)
{
return str.toLowerCase();
}
StringBuilder builder = new StringBuilder(str);
builder.setCharAt(0, Character.toLowerCase(first));
return builder.toString();
}
public static String uncapAll(String str)
{
if (str == null || str.length() == 0)
{
return str;
}
boolean inWhiteSpace = true;
StringBuilder builder = new StringBuilder(str);
for (int i = 0; i < builder.length(); i++)
{
char c = builder.charAt(i);
boolean isWhiteSpace = Character.isWhitespace(c);
if (!isWhiteSpace && inWhiteSpace)
{
builder.setCharAt(i, Character.toLowerCase(c));
}
inWhiteSpace = isWhiteSpace;
}
return builder.toString();
}
public static List<String> explode(String string, String separators)
{
return explode(string, separators, '\\');
}
public static List<String> explode(String string, String separators, char escapeCharacter)
{
List<String> tokens = new ArrayList<String>();
StringBuilder builder = new StringBuilder();
boolean separator = false;
boolean escape = false;
for (int i = 0; i < string.length(); i++)
{
separator = false;
char c = string.charAt(i);
if (!escape && c == escapeCharacter)
{
escape = true;
}
else
{
if (!escape && separators.indexOf(c) != -1)
{
tokens.add(builder.toString());
builder.setLength(0);
separator = true;
}
else
{
builder.append(c);
}
escape = false;
}
}
if (separator || builder.length() != 0)
{
tokens.add(builder.toString());
}
return tokens;
}
public static String implode(List<String> tokens, char separator)
{
return implode(tokens, separator, '\\');
}
public static String implode(List<String> tokens, char separator, char escapeCharacter)
{
String escapeString = Character.toString(escapeCharacter);
String escapeString2 = escapeString + escapeString;
String separatorString = Character.toString(separator);
String separatorString2 = escapeString + separatorString;
StringBuilder builder = new StringBuilder();
boolean firstTime = true;
for (String token : tokens)
{
if (firstTime)
{
firstTime = false;
}
else
{
builder.append(separator);
}
if (token != null)
{
token = token.replace(escapeString, escapeString2);
token = token.replace(separatorString, separatorString2);
builder.append(token);
}
}
return builder.toString();
}
public static String toOSString(String uri)
{
if (!isEmpty(uri))
{
URI emfURI = URI.createURI(uri);
if (emfURI.isFile())
{
uri = emfURI.toFileString();
}
}
return uri;
}
/**
* Shortens the given text to be as long as the given length (including the
* appended ellipsis).
*
* @param input The text to shorten.
* @param length The maximum length of the resulting text, ellipsis included.
* @param wholeWord Whether to take care for splitting the text at word
* boundaries only.
*/
public static String shorten(String input, int length, boolean wholeWord)
{
if (input == null)
{
return EMPTY;
}
if (length <= HORIZONTAL_ELLIPSIS.length())
{
throw new IllegalArgumentException(NLS.bind(Messages.StringUtil_TooShort_exception, HORIZONTAL_ELLIPSIS.length() + 1));
}
if (input.length() <= length)
{
return input;
}
int ellipsisPos = length - HORIZONTAL_ELLIPSIS.length() - 1;
if (wholeWord)
{
ellipsisPos = findLastSpaceBetween(input, 0, ellipsisPos);
}
String result = input.substring(0, ellipsisPos);
result += HORIZONTAL_ELLIPSIS;
return result;
}
public static String wrapText(String input, int maxCharactersPerLine, boolean wholeWord)
{
int startIndex = 0;
int endIndex = startIndex + maxCharactersPerLine;
boolean finished = false;
StringBuilder builder = new StringBuilder();
do
{
if (endIndex >= input.length())
{
endIndex = input.length();
finished = true;
}
if (!finished && wholeWord)
{
int spaceIndex = findLastSpaceBetween(input, startIndex, endIndex);
if (spaceIndex > 0)
{
endIndex = spaceIndex;
}
else
{
// No more spaces till end.
endIndex = input.length();
finished = true;
}
}
builder.append(input.substring(startIndex, endIndex));
if (!finished)
{
builder.append(StringUtil.NL);
}
startIndex = wholeWord ? endIndex + 1 : endIndex;
endIndex += maxCharactersPerLine;
} while (!finished);
return builder.toString();
}
private static int findLastSpaceBetween(String text, int startPosition, int endPosition)
{
int index = endPosition;
char lastBeforeEllipsis = text.charAt(index);
while (lastBeforeEllipsis != ' ')
{
index--;
if (index <= startPosition)
{
index = -1;
break;
}
lastBeforeEllipsis = text.charAt(index);
}
return index;
}
public static String removePrefix(String string, String... prefixes)
{
for (int i = 0; i < prefixes.length; i++)
{
String prefix = prefixes[i];
if (string.startsWith(prefix))
{
return string.substring(prefix.length());
}
}
return string;
}
public static String removeSuffix(String string, String... suffixes)
{
for (int i = 0; i < suffixes.length; i++)
{
String suffix = suffixes[i];
if (string.endsWith(suffix))
{
return string.substring(0, string.length() - suffix.length());
}
}
return string;
}
public static String trimLeft(String str)
{
int len = str.length();
int st = 0;
while (st < len && str.charAt(st) <= ' ')
{
st++;
}
if (st == 0)
{
return str;
}
return str.substring(st, len);
}
public static String trimRight(String str)
{
int len = str.length();
int end = len;
while (0 < end && str.charAt(end - 1) <= ' ')
{
end--;
}
if (end == len)
{
return str;
}
return str.substring(0, end);
}
public static String trimTrailingSlashes(String str)
{
int len = str.length();
int end = len;
while (end > 0)
{
char c = str.charAt(end - 1);
if (c != '/' && c != '\\')
{
break;
}
--end;
}
if (end == len)
{
return str;
}
return str.substring(0, end);
}
public static Pattern globPattern(String filter)
{
StringBuffer pattern = new StringBuffer("(\\Q"); //$NON-NLS-1$
Matcher matcher = WILDCARD_FILTER_PATTERN.matcher(filter);
while (matcher.find())
{
String separator = matcher.group(1);
if (separator.length() == 2)
{
matcher.appendReplacement(pattern, ""); //$NON-NLS-1$
if ("\\E".equals(separator)) //$NON-NLS-1$
{
pattern.append("\\E\\\\E\\Q"); //$NON-NLS-1$
}
else if ("\\\\".equals(separator)) //$NON-NLS-1$
{
pattern.append("\\E\\\\\\Q"); //$NON-NLS-1$
}
else
{
pattern.append(separator.charAt(1));
}
}
else
{
char separatorChar = separator.charAt(0);
String tail;
switch (separatorChar)
{
case '*':
tail = ".*?"; //$NON-NLS-1$
break;
case '?':
tail = "."; //$NON-NLS-1$
break;
default:
throw new IllegalStateException(NLS.bind(Messages.StringUtil_ShouldMatch_exception, WILDCARD_FILTER_PATTERN));
}
matcher.appendReplacement(pattern, "\\\\E)"); //$NON-NLS-1$
pattern.append(tail).append("(\\Q"); //$NON-NLS-1$
}
}
matcher.appendTail(pattern);
pattern.append("\\E)"); //$NON-NLS-1$
return Pattern.compile(pattern.toString(), Pattern.CASE_INSENSITIVE);
}
}