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