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