1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.common.utils;
\r
14 import java.math.BigDecimal;
\r
15 import java.math.MathContext;
\r
16 import java.math.RoundingMode;
\r
17 import java.util.Arrays;
\r
18 import java.util.regex.Pattern;
\r
21 * Common utility methods for handling and visualising literal values.
\r
23 * @author Tuukka Lehtonen
\r
26 * - ProCore does not support zero length vectors at the moment
\r
27 * - String[] literals could be parsed from a String assuming a StringMemento String serialization.
\r
29 public final class Literals {
\r
31 final private static Pattern comma = Pattern.compile(",");
\r
33 private static int precision = 8;
\r
35 // public static final boolean[] FALSE = { false };
\r
37 // public static final boolean[] TRUE = { true };
\r
39 public static int getPrecision() {
\r
43 public static void setPrecision(int precision) {
\r
44 Literals.precision = precision;
\r
47 private static String formattedDouble(double a) {
\r
49 BigDecimal dec = new BigDecimal(String.valueOf(a), new MathContext(precision, RoundingMode.HALF_UP));
\r
50 dec = dec.stripTrailingZeros();
\r
51 if(dec.scale() < 1) dec = dec.setScale(1);
\r
52 return dec.toString();
\r
53 } catch (NumberFormatException e) {
\r
54 return "Invalid Value";
\r
58 public static String toString(double[] a) {
\r
61 int iMax = a.length - 1;
\r
65 StringBuilder b = new StringBuilder();
\r
67 for (int i = 0; ; i++) {
\r
68 b.append(formattedDouble(a[i]));
\r
70 return b.append(']').toString();
\r
76 * Convert a literal object (of any allowed type) into to a String.
\r
80 * @throws IllegalArgumentException
\r
82 public static String literalToString(Object literal) throws IllegalArgumentException {
\r
83 Class<?> literalClass = literal.getClass();
\r
85 if (literalClass == String.class) {
\r
86 return (String)literal;
\r
87 } else if (literalClass == Double.class) {
\r
88 return literal.toString();
\r
89 } else if (literalClass == Float.class) {
\r
90 return literal.toString();
\r
91 } else if (literalClass == Long.class) {
\r
92 return literal.toString();
\r
93 } else if (literalClass == Integer.class) {
\r
94 return literal.toString();
\r
95 } else if (literalClass == Byte.class) {
\r
96 return literal.toString();
\r
97 } else if (literalClass == Boolean.class) {
\r
98 return literal.toString();
\r
99 } else if (literalClass == String[].class) {
\r
100 return literalToString((String[]) literal);
\r
101 } else if (literalClass == double[].class) {
\r
102 return literalToString((double[]) literal);
\r
103 } else if (literalClass == float[].class) {
\r
104 return literalToString((float[]) literal);
\r
105 } else if (literalClass == long[].class) {
\r
106 return literalToString((long[]) literal);
\r
107 } else if (literalClass == int[].class) {
\r
108 return literalToString((int[]) literal);
\r
109 } else if (literalClass == byte[].class) {
\r
110 return literalToString((byte[]) literal);
\r
111 } else if (literalClass == boolean[].class) {
\r
112 return literalToString((boolean[]) literal);
\r
115 throw new IllegalArgumentException(String.format("Literal object type not recognized: %s", literal.getClass().getName()));
\r
118 public static String shortString(Object original) {
\r
119 if(original.toString().length() > 100) return original.toString().substring(0, 99) + "...";
\r
120 else return original.toString();
\r
123 public static String literalToString(boolean[] l) throws IllegalArgumentException {
\r
124 return l.length == 1 ? String.valueOf(l[0]) : Arrays.toString(l);
\r
127 public static String literalToString(byte[] l) throws IllegalArgumentException {
\r
128 return l.length == 1 ? String.valueOf(l[0]) : Arrays.toString(l);
\r
131 public static String literalToString(int[] l) throws IllegalArgumentException {
\r
132 return l.length == 1 ? String.valueOf(l[0]) : Arrays.toString(l);
\r
135 public static String literalToString(long[] l) throws IllegalArgumentException {
\r
136 return l.length == 1 ? String.valueOf(l[0]) : Arrays.toString(l);
\r
139 public static String literalToString(float[] l) throws IllegalArgumentException {
\r
140 return l.length == 1 ? String.valueOf(l[0]) : Arrays.toString(l);
\r
143 public static String literalToString(double[] l) throws IllegalArgumentException {
\r
144 return l.length == 1 ? String.valueOf(l[0]) : Arrays.toString(l);
\r
147 public static String literalToString(String[] l) throws IllegalArgumentException {
\r
148 // FIXME BEWARE!!! THIS BREAKS UP WITH STRINGS CONTAINING ',' CHARACTERS
\r
149 return l.length == 1 ? String.valueOf(l[0]) : Arrays.toString(l);
\r
154 // * Convert a literal object (of any allowed type) into to a String.
\r
156 // * @param literal a literal as string
\r
157 // * @return the same literal as its native type
\r
158 // * @throws IllegalArgumentException
\r
160 // public static Object stringToLiteral(Graph g, Resource property, String literal) throws IllegalArgumentException, ResourceNotFoundException {
\r
161 // if (property == null)
\r
162 // throw new IllegalArgumentException("null property");
\r
163 // if (literal == null)
\r
164 // throw new IllegalArgumentException("null literal string");
\r
166 // // Attempt to parse the property value by its type.
\r
167 // if (g.isInstanceOf(property, g.getBuiltins().Double)) {
\r
168 // return parseDoubleLiteral(literal);
\r
169 // } else if (g.isInstanceOf(property, g.getBuiltins().Float)) {
\r
170 // return parseFloatLiteral(literal);
\r
171 // } else if (g.isInstanceOf(property, g.getBuiltins().Long)) {
\r
172 // return parseLongLiteral(literal);
\r
173 // } else if (g.isInstanceOf(property, g.getBuiltins().Integer)) {
\r
174 // return parseIntegerLiteral(literal);
\r
175 // } else if (g.isInstanceOf(property, g.getBuiltins().Byte)) {
\r
176 // return parseByteLiteral(literal);
\r
177 // } else if (g.isInstanceOf(property, g.getBuiltins().Boolean)) {
\r
178 // return parseBooleanLiteral(literal);
\r
179 // } else if (g.isInstanceOf(property, g.getBuiltins().String)) {
\r
180 // return parseStringLiteral(literal);
\r
183 // throw new IllegalArgumentException("unrecognized property type for resource");
\r
189 * @throws IllegalArgumentException if the parsing fails
\r
191 public static boolean[] parseBooleanLiteral(String literal) {
\r
192 literal = trimLiteralString(literal);
\r
194 String parts[] = comma.split(literal);
\r
195 boolean[] result = new boolean[parts.length];
\r
196 for (int i = 0; i < parts.length; i++)
\r
197 result[i] = Boolean.parseBoolean(parts[i]);
\r
199 } catch(NumberFormatException e) {
\r
200 throw new IllegalArgumentException("Invalid boolean value: " + literal, e);
\r
207 * @throws IllegalArgumentException if the parsing fails
\r
209 public static double[] parseDoubleLiteral(String literal) {
\r
210 literal = trimLiteralString(literal);
\r
212 String parts[] = comma.split(literal);
\r
213 // " " would be more common delimiter for primitive arrays since
\r
214 // it is also default delimiter in XML documents
\r
215 double result[] = new double[parts.length];
\r
216 for (int i = 0; i < parts.length; i++)
\r
217 result[i] = Double.parseDouble(parts[i]);
\r
219 } catch (NumberFormatException e) {
\r
220 throw new IllegalArgumentException("Invalid double value: " + literal, e);
\r
227 * @throws IllegalArgumentException if the parsing fails
\r
229 public static int[] parseIntegerLiteral(String literal) {
\r
230 literal = trimLiteralString(literal);
\r
232 String parts[] = comma.split(literal);
\r
233 int result[] = new int[parts.length];
\r
234 for (int i = 0; i < parts.length; i++)
\r
235 result[i] = Integer.parseInt(parts[i]);
\r
237 } catch (NumberFormatException e) {
\r
238 throw new IllegalArgumentException("Invalid integer value: " + literal, e);
\r
242 public static byte[] parseByteLiteral(String literal) {
\r
243 literal = trimLiteralString(literal);
\r
245 String parts[] = comma.split(literal);
\r
246 byte result[] = new byte[parts.length];
\r
247 for (int i = 0; i < parts.length; i++)
\r
248 result[i] = Byte.parseByte(parts[i]);
\r
250 } catch (NumberFormatException e) {
\r
251 throw new IllegalArgumentException("Invalid byte value: " + literal, e);
\r
255 public static long[] parseLongLiteral(String literal) {
\r
256 literal = trimLiteralString(literal);
\r
258 String parts[] = comma.split(literal);
\r
259 long result[] = new long[parts.length];
\r
260 for (int i = 0; i < parts.length; i++)
\r
261 result[i] = Long.parseLong(parts[i]);
\r
263 } catch (NumberFormatException e) {
\r
264 throw new IllegalArgumentException("Invalid long value: " + literal, e);
\r
268 public static float[] parseFloatLiteral(String literal) {
\r
269 literal = trimLiteralString(literal);
\r
271 String parts[] = comma.split(literal);
\r
272 float result[] = new float[parts.length];
\r
273 for (int i = 0; i < parts.length; i++)
\r
274 result[i] = Float.parseFloat(parts[i]);
\r
276 } catch (NumberFormatException e) {
\r
277 throw new IllegalArgumentException("Invalid float value: " + literal, e);
\r
281 private static String[] parseStringLiteral(String literal) {
\r
282 // TODO: support StringMemento serialized literals!
\r
283 return new String[] {literal};
\r
286 private static String trimLiteralString(String literal) {
\r
287 // First trim the literal to make the input more canonical.
\r
288 // Also remove possible '[' and ']' prefix and suffix.
\r
289 literal = literal.trim();
\r
290 if (literal.startsWith("["))
\r
291 literal = literal.substring(1);
\r
292 if (literal.endsWith("]"))
\r
293 literal = literal.substring(0, literal.length() - 1);
\r