blob: 5dffcc82c3be1117be0d28920604ebb490e6e409 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2015 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.utilities;
import java.math.BigInteger;
import java.util.List;
import org.eclipse.emf.ecore.ETypedElement;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.values.Unlimited;
import org.eclipse.osgi.util.NLS;
public class StringUtil
{
private static final String maxIntValue = Integer.toString(Integer.MAX_VALUE);
private static final int maxIntSize = maxIntValue.length();
private static final String maxLongValue = Long.toString(Long.MAX_VALUE);
private static final int maxLongSize = maxLongValue.length();
/**
* Copied from {@link java.util.Properties}
*/
private static final char[] hexDigit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/**
* Append a multiplicity string such as "[1..5]" to a StringBuilder.
* <br>
* Shortforms such as "[?]", "[+]", "[*]", "[1]", "[2..*]" are used if possible.
* <br>
* A -ve upper signals unlimited.
*/
public static void appendMultiplicity(@NonNull StringBuilder s, long lower, long upper, boolean isNullFree) {
s.append("[");
if (upper < 0) {
if (lower == 1) {
s.append("+");
}
else {
if (lower != 0) {
s.append(lower);
s.append("..");
}
s.append("*");
}
}
else if ((lower == 0) && (upper == 1)) {
s.append("?");
}
else {
s.append(lower);
if (lower != upper) {
s.append("..");
s.append(upper);
}
}
s.append("|");
s.append(isNullFree ? "1" : "?");
s.append("]");
}
/**
* @deprecated add isNullFree argument
*/
@Deprecated
public static void appendMultiplicity(@NonNull StringBuilder s, long lower, long upper) {
appendMultiplicity(s, lower, upper, false);
}
public static @NonNull String bind(String messageTemplate, Object... bindings) {
@SuppressWarnings("null") @NonNull String result = NLS.bind(messageTemplate, bindings);
return result;
}
/**
* Mostly copied from {@link java.util.Properties#loadConvert} via
* {@link org.eclipse.xtext.util.Strings#convertFromJavaString}
*/
public static@NonNull String convertFromOCLString(@NonNull String javaString) {
char[] in = javaString.toCharArray();
int off = 0;
int len = javaString.length();
char[] convtBuf = new char[len];
char aChar;
char[] out = convtBuf;
int outLen = 0;
int end = off + len;
while (off < end) {
aChar = in[off++];
if (aChar == '\\') {
aChar = in[off++];
if (aChar == 'u') {
// Read the xxxx
int value = 0;
if(off+4 > end)
throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
for (int i = 0; i < 4; i++) {
aChar = in[off++];
switch (aChar) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
value = (value << 4) + aChar - '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
value = (value << 4) + 10 + aChar - 'a';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
value = (value << 4) + 10 + aChar - 'A';
break;
default:
throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
}
}
out[outLen++] = (char) value;
} else {
if (aChar == 't')
aChar = '\t';
else if (aChar == 'r')
aChar = '\r';
else if (aChar == 'n')
aChar = '\n';
else if (aChar == 'f')
aChar = '\f';
else if (aChar == 'b')
aChar = '\b';
else if (aChar == '"')
aChar = '\"';
else if (aChar == '\'')
aChar = '\'';
else if (aChar == '\\')
aChar = '\\';
else
throw new IllegalArgumentException("Illegal escape character \\" + aChar);
out[outLen++] = aChar;
}
} else {
out[outLen++] = aChar;
}
}
return new String(out, 0, outLen);
}
/**
* Mostly copied from {@link java.util.Properties#saveConvert} via
* {@link org.eclipse.xtext.util.Strings#convertToJavaString}
*/
public static String convertToOCLString(String theString) {
if (theString == null) {
return null;
}
int len = theString.length();
int bufLen = len * 2;
if (bufLen < 0) {
bufLen = Integer.MAX_VALUE;
}
StringBuilder outBuffer = new StringBuilder(bufLen);
for (int x = 0; x < len; x++) {
char aChar = theString.charAt(x);
// Handle common case first, selecting largest block that
// avoids the specials below
if ((aChar > 61) && (aChar < 127)) {
if (aChar == '\\') {
outBuffer.append('\\');
outBuffer.append('\\');
continue;
}
outBuffer.append(aChar);
continue;
}
switch (aChar) {
case ' ':
outBuffer.append(' ');
break;
case '\t':
outBuffer.append('\\');
outBuffer.append('t');
break;
case '\n':
outBuffer.append('\\');
outBuffer.append('n');
break;
case '\r':
outBuffer.append('\\');
outBuffer.append('r');
break;
case '\f':
outBuffer.append('\\');
outBuffer.append('f');
break;
case '\b':
outBuffer.append('\\');
outBuffer.append('b');
break;
case '\'':
outBuffer.append('\\');
outBuffer.append('\'');
break;
case '\\':
outBuffer.append('\\');
outBuffer.append('\\');
break;
// case '"':
// outBuffer.append('\\');
// outBuffer.append('"');
// break;
default:
if (((aChar < 0x0020) || (aChar > 0x007e))) {
outBuffer.append('\\');
outBuffer.append('u');
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex(aChar & 0xF));
} else {
outBuffer.append(aChar);
}
}
}
return outBuffer.toString();
}
public static @NonNull Number createNumberFromString(@NonNull String aValue) throws NumberFormatException {
if ("*".equals(aValue)) {
return Unlimited.INSTANCE;
}
int len = aValue.length();
if ((len < maxIntSize) || ((len == maxIntSize) && (maxIntValue.compareTo(aValue) >= 0))) {
Integer result = Integer.valueOf(aValue);
assert result != null;
return result;
}
else if ((len < maxLongSize) || ((len == maxLongSize) && (maxLongValue.compareTo(aValue) >= 0))) {
Long result = Long.valueOf(aValue);
assert result != null;
return result;
}
else {
return new BigInteger(aValue);
}
}
public static @NonNull String formatMultiplicity(@Nullable ETypedElement typedElement) {
if (typedElement == null)
return "";
int lower = typedElement.getLowerBound();
int upper = typedElement.getUpperBound();
if (lower == upper)
return "" + Integer.toString(lower);
else if (lower == 0) {
if (upper < 0)
return "*";
else if (upper == 1)
return "?";
}
else if (lower == 1) {
if (upper < 0)
return "+";
}
return Integer.toString(lower) + ".." + (upper >= 0 ? Integer.toString(upper) : "*");
}
public static @NonNull String formatOrdered(@Nullable ETypedElement typedElement) {
boolean isOrdered = typedElement != null ? (typedElement.isOrdered() && typedElement.isMany()) : false;
return isOrdered ? "{ordered}" : "";
}
public static@NonNull String formatString(@Nullable String name) {
return name != null ? name : "<null>";
}
public static @NonNull String formatUnique(@Nullable ETypedElement typedElement) {
boolean isOrdered = typedElement != null ? (typedElement.isUnique() && typedElement.isMany()) : false;
return isOrdered ? "{unique}" : "";
}
public static String getIndentation(int depth, @NonNull String string) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < depth; i++) {
s.append(string);
}
return s.toString();
}
/**
* Return a composite string comprising each element od strings separated by separator.
* A null strings is returned as a null string. An empty strings as an empty string.
*
* @param strings strings to be spliced
* @param separator between elements
* @return spliced string
*/
public static String splice(List<String> strings, String separator) {
if (strings == null)
return null;
int iMax = strings.size();
if (iMax <= 0)
return "";
if (iMax == 1)
return strings.get(0);
StringBuilder s = new StringBuilder();
s.append(strings.get(0));
for (int i = 1; i < iMax; i++) {
s.append(separator);
s.append(strings.get(i));
}
return s.toString();
}
/**
* Copied from {@link java.util.Properties}
*/
public static char toHex(int nibble) {
return hexDigit[(nibble & 0xF)];
}
}