1 package org.simantics.scl.compiler.runtime;
\r
4 import java.lang.reflect.Array;
\r
5 import java.util.ArrayList;
\r
6 import java.util.Arrays;
\r
7 import java.util.List;
\r
9 import org.simantics.databoard.binding.mutable.Variant;
\r
10 import org.simantics.scl.compiler.types.TApply;
\r
11 import org.simantics.scl.compiler.types.TCon;
\r
12 import org.simantics.scl.compiler.types.Type;
\r
13 import org.simantics.scl.compiler.types.Types;
\r
15 public class ValueConversion {
\r
17 public static Number convertNumber(TCon expectedType, Number value) {
\r
18 if (expectedType == Types.DOUBLE) {
\r
19 if (value instanceof Double) return value;
\r
20 else return new Double(value.doubleValue());
\r
22 else if (expectedType == Types.INTEGER) {
\r
23 if (value instanceof Integer) return value;
\r
24 else return new Integer(value.intValue());
\r
26 else if (expectedType == Types.FLOAT) {
\r
27 if (value instanceof Float) return value;
\r
28 else return new Float(value.floatValue());
\r
30 else if (expectedType == Types.BYTE) {
\r
31 if (value instanceof Byte) return value;
\r
32 else return new Byte(value.byteValue());
\r
34 else if (expectedType == Types.SHORT) {
\r
35 if (value instanceof Short) return value;
\r
36 else return new Short(value.shortValue());
\r
38 else if (expectedType == Types.LONG) {
\r
39 if (value instanceof Long) return value;
\r
40 else return new Long(value.longValue());
\r
43 // Not expecting a number type
\r
47 public static Object parsePrimitive(TCon expectedType, String value) {
\r
48 if (expectedType == Types.DOUBLE) {
\r
49 return Double.parseDouble(value);
\r
51 else if (expectedType == Types.INTEGER) {
\r
52 return Integer.parseInt(value);
\r
54 else if (expectedType == Types.FLOAT) {
\r
55 return Float.parseFloat(value);
\r
57 else if (expectedType == Types.BYTE) {
\r
58 return Byte.parseByte(value);
\r
60 else if (expectedType == Types.SHORT) {
\r
61 return Short.parseShort(value);
\r
63 else if (expectedType == Types.LONG) {
\r
64 return Long.parseLong(value);
\r
66 else if (expectedType == Types.BOOLEAN) {
\r
67 return Boolean.parseBoolean(value);
\r
69 else if (expectedType == Types.CHARACTER && value.length() == 1) {
\r
70 return value.charAt(0);
\r
76 public static Class<?> getNativeClass(Type expectedType) {
\r
77 if (expectedType == Types.STRING)
\r
78 return String.class;
\r
79 else if (expectedType == Types.DOUBLE)
\r
80 return Double.class;
\r
81 else if (expectedType == Types.INTEGER)
\r
82 return Integer.class;
\r
83 else if (expectedType == Types.FLOAT)
\r
85 else if (expectedType == Types.BYTE)
\r
87 else if (expectedType == Types.SHORT)
\r
89 else if (expectedType == Types.LONG)
\r
91 else if (expectedType == Types.BOOLEAN)
\r
92 return Boolean.class;
\r
93 else if (expectedType == Types.CHARACTER)
\r
94 return Character.class;
\r
96 return Object.class;
\r
99 public static Class<?> getNativePrimitiveClass(Type expectedType) {
\r
100 if (expectedType == Types.STRING)
\r
101 return String.class;
\r
102 else if (expectedType == Types.DOUBLE)
\r
103 return double.class;
\r
104 else if (expectedType == Types.INTEGER)
\r
106 else if (expectedType == Types.FLOAT)
\r
107 return float.class;
\r
108 else if (expectedType == Types.BYTE)
\r
110 else if (expectedType == Types.SHORT)
\r
111 return short.class;
\r
112 else if (expectedType == Types.LONG)
\r
114 else if (expectedType == Types.BOOLEAN)
\r
115 return boolean.class;
\r
116 else if (expectedType == Types.CHARACTER)
\r
119 return Object.class;
\r
122 @SuppressWarnings("unchecked")
\r
123 public static boolean needsConversion(Type expectedType, Object value) {
\r
124 if (!needsConversion(expectedType, value.getClass(), false))
\r
127 if (expectedType instanceof TApply) {
\r
128 TApply apply = (TApply)expectedType;
\r
129 if (apply.function == Types.LIST) {
\r
130 if (!(value instanceof List))
\r
133 for (Object item : (List<Object>)value) {
\r
134 if (needsConversion(apply.parameter, item))
\r
145 public static boolean needsConversion(Type expectedType, Class<?> clazz, boolean needPrimitive) {
\r
146 if (expectedType instanceof TCon) {
\r
147 if (needPrimitive && Types.isPrimitive(expectedType)) {
\r
148 Class<?> expectedClass = getNativePrimitiveClass(expectedType);
\r
149 if (expectedClass.isPrimitive())
\r
150 return clazz == expectedClass;
\r
152 return expectedClass.isAssignableFrom(clazz);
\r
154 else if (clazz.isPrimitive()) {
\r
158 return !getNativeClass(expectedType).isAssignableFrom(clazz);
\r
161 else if (expectedType instanceof TApply) {
\r
162 TApply apply = (TApply)expectedType;
\r
163 if (apply.function == Types.LIST) {
\r
166 else if (apply.function == Types.VECTOR || apply.function == Types.MVECTOR || apply.function == Types.ARRAY) {
\r
167 if (!clazz.isArray())
\r
170 boolean needPrimitive2 = apply.function != Types.ARRAY;
\r
171 return needsConversion(apply.parameter, clazz.getComponentType(), needPrimitive2);
\r
179 @SuppressWarnings({ "rawtypes", "unchecked" })
\r
180 public static Object fromDynamic(Type expectedType, Object value) {
\r
183 else if (value instanceof Variant)
\r
184 return fromDynamic(expectedType, ((Variant)value).getValue());
\r
185 else if (expectedType == Types.DYNAMIC)
\r
187 else if (!needsConversion(expectedType, value))
\r
190 if(expectedType instanceof TCon) {
\r
191 TCon con = (TCon)expectedType;
\r
192 if (con == Types.STRING)
\r
193 return value.toString();
\r
194 else if (value instanceof Number)
\r
195 return convertNumber(con, (Number)value);
\r
196 else if (value instanceof String && Types.isPrimitive(con))
\r
197 return parsePrimitive(con, (String)value);
\r
199 else if(expectedType instanceof TApply) {
\r
200 TApply apply = (TApply)expectedType;
\r
201 Type expectedComponentType = apply.parameter;
\r
203 if(apply.function == Types.LIST) {
\r
204 Class<?> valueClass = value.getClass();
\r
206 if(valueClass.isArray()) {
\r
207 Class<?> componentType = valueClass.getComponentType();
\r
208 if(needsConversion(expectedComponentType, componentType, false)) {
\r
209 int length = Array.getLength(value);
\r
210 ArrayList list = new ArrayList(length);
\r
211 for(int i=0;i<length;++i)
\r
212 list.add(fromDynamic(expectedComponentType, Array.get(value, i)));
\r
216 return Arrays.asList((Object[])value);
\r
218 else if (value instanceof Iterable) {
\r
219 Iterable iterable = (Iterable)value;
\r
220 ArrayList list = new ArrayList();
\r
221 for (Object element : iterable)
\r
222 list.add(fromDynamic(expectedComponentType, element));
\r
226 else if (apply.function == Types.VECTOR || apply.function == Types.MVECTOR || apply.function == Types.ARRAY) {
\r
227 Class<?> valueClass = value.getClass();
\r
228 Class<?> expectedComponentClass = apply.function != Types.ARRAY ?
\r
229 getNativePrimitiveClass(expectedComponentType) :
\r
230 getNativeClass(expectedComponentType);
\r
232 if(valueClass.isArray()) {
\r
233 Class<?> componentType = valueClass.getComponentType();
\r
234 int length = Array.getLength(value);
\r
235 Object array = Array.newInstance(expectedComponentClass, length);
\r
236 if (needsConversion(expectedComponentType, componentType, apply.function != Types.ARRAY)) {
\r
237 for(int i=0;i<length;++i)
\r
238 Array.set(array, i, fromDynamic(expectedComponentType, Array.get(value, i)));
\r
242 // This shouldn't really be happening...
\r
246 else if (value instanceof Iterable) {
\r
247 ArrayList<Object> list = new ArrayList<Object>();
\r
248 for (Object item : (Iterable)value) {
\r
249 list.add(fromDynamic(expectedComponentType, item));
\r
251 if (apply.function != Types.ARRAY && expectedComponentClass.isPrimitive()) {
\r
252 int length = list.size();
\r
253 Object array = Array.newInstance(expectedComponentClass, length);
\r
254 for (int i = 0; i < length; i++)
\r
255 Array.set(array, i, list.get(i));
\r
259 return list.toArray();
\r