| /******************************************************************************* |
| * 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)]; |
| } |
| } |