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
49 if (expectedType == Types.DOUBLE) {
\r
50 return Double.parseDouble(value);
\r
52 else if (expectedType == Types.INTEGER) {
\r
53 return Integer.parseInt(value);
\r
55 else if (expectedType == Types.FLOAT) {
\r
56 return Float.parseFloat(value);
\r
58 else if (expectedType == Types.BYTE) {
\r
59 return Byte.parseByte(value);
\r
61 else if (expectedType == Types.SHORT) {
\r
62 return Short.parseShort(value);
\r
64 else if (expectedType == Types.LONG) {
\r
65 return Long.parseLong(value);
\r
67 else if (expectedType == Types.BOOLEAN) {
\r
68 return Boolean.parseBoolean(value);
\r
70 else if (expectedType == Types.CHARACTER && value.length() == 1) {
\r
71 return value.charAt(0);
\r
73 } catch(NumberFormatException e) {
\r
74 e.printStackTrace();
\r
80 public static Class<?> getNativeClass(Type expectedType) {
\r
81 if (expectedType == Types.STRING)
\r
82 return String.class;
\r
83 else if (expectedType == Types.DOUBLE)
\r
84 return Double.class;
\r
85 else if (expectedType == Types.INTEGER)
\r
86 return Integer.class;
\r
87 else if (expectedType == Types.FLOAT)
\r
89 else if (expectedType == Types.BYTE)
\r
91 else if (expectedType == Types.SHORT)
\r
93 else if (expectedType == Types.LONG)
\r
95 else if (expectedType == Types.BOOLEAN)
\r
96 return Boolean.class;
\r
97 else if (expectedType == Types.CHARACTER)
\r
98 return Character.class;
\r
100 return Object.class;
\r
103 public static Class<?> getNativePrimitiveClass(Type expectedType) {
\r
104 if (expectedType == Types.STRING)
\r
105 return String.class;
\r
106 else if (expectedType == Types.DOUBLE)
\r
107 return double.class;
\r
108 else if (expectedType == Types.INTEGER)
\r
110 else if (expectedType == Types.FLOAT)
\r
111 return float.class;
\r
112 else if (expectedType == Types.BYTE)
\r
114 else if (expectedType == Types.SHORT)
\r
115 return short.class;
\r
116 else if (expectedType == Types.LONG)
\r
118 else if (expectedType == Types.BOOLEAN)
\r
119 return boolean.class;
\r
120 else if (expectedType == Types.CHARACTER)
\r
123 return Object.class;
\r
126 @SuppressWarnings("unchecked")
\r
127 public static boolean needsConversion(Type expectedType, Object value) {
\r
128 if (!needsConversion(expectedType, value.getClass(), false))
\r
131 if (expectedType instanceof TApply) {
\r
132 TApply apply = (TApply)expectedType;
\r
133 if (apply.function == Types.LIST) {
\r
134 if (!(value instanceof List))
\r
137 for (Object item : (List<Object>)value) {
\r
138 if (needsConversion(apply.parameter, item))
\r
149 public static boolean needsConversion(Type expectedType, Class<?> clazz, boolean needPrimitive) {
\r
150 if (expectedType instanceof TCon) {
\r
151 if (needPrimitive && Types.isPrimitive(expectedType)) {
\r
152 Class<?> expectedClass = getNativePrimitiveClass(expectedType);
\r
153 if (expectedClass.isPrimitive())
\r
154 return clazz == expectedClass;
\r
156 return expectedClass.isAssignableFrom(clazz);
\r
158 else if (clazz.isPrimitive()) {
\r
162 return !getNativeClass(expectedType).isAssignableFrom(clazz);
\r
165 else if (expectedType instanceof TApply) {
\r
166 TApply apply = (TApply)expectedType;
\r
167 if (apply.function == Types.LIST) {
\r
170 else if (apply.function == Types.VECTOR || apply.function == Types.MVECTOR || apply.function == Types.ARRAY) {
\r
171 if (!clazz.isArray())
\r
174 boolean needPrimitive2 = apply.function != Types.ARRAY;
\r
175 return needsConversion(apply.parameter, clazz.getComponentType(), needPrimitive2);
\r
183 @SuppressWarnings({ "rawtypes", "unchecked" })
\r
184 public static Object fromDynamic(Type expectedType, Object value) {
\r
187 else if (value instanceof Variant)
\r
188 return fromDynamic(expectedType, ((Variant)value).getValue());
\r
189 else if (expectedType == Types.DYNAMIC)
\r
191 else if (!needsConversion(expectedType, value))
\r
194 if(expectedType instanceof TCon) {
\r
195 TCon con = (TCon)expectedType;
\r
196 if (con == Types.STRING)
\r
197 return value.toString();
\r
198 else if (value instanceof Number)
\r
199 return convertNumber(con, (Number)value);
\r
200 else if (value instanceof String && Types.isPrimitive(con))
\r
201 return parsePrimitive(con, (String)value);
\r
203 else if(expectedType instanceof TApply) {
\r
204 TApply apply = (TApply)expectedType;
\r
205 Type expectedComponentType = apply.parameter;
\r
207 if(apply.function == Types.LIST) {
\r
208 Class<?> valueClass = value.getClass();
\r
210 if(valueClass.isArray()) {
\r
211 Class<?> componentType = valueClass.getComponentType();
\r
212 if(needsConversion(expectedComponentType, componentType, false)) {
\r
213 int length = Array.getLength(value);
\r
214 ArrayList list = new ArrayList(length);
\r
215 for(int i=0;i<length;++i)
\r
216 list.add(fromDynamic(expectedComponentType, Array.get(value, i)));
\r
220 return Arrays.asList((Object[])value);
\r
222 else if (value instanceof Iterable) {
\r
223 Iterable iterable = (Iterable)value;
\r
224 ArrayList list = new ArrayList();
\r
225 for (Object element : iterable)
\r
226 list.add(fromDynamic(expectedComponentType, element));
\r
230 else if (apply.function == Types.VECTOR || apply.function == Types.MVECTOR || apply.function == Types.ARRAY) {
\r
231 Class<?> valueClass = value.getClass();
\r
232 Class<?> expectedComponentClass = apply.function != Types.ARRAY ?
\r
233 getNativePrimitiveClass(expectedComponentType) :
\r
234 getNativeClass(expectedComponentType);
\r
236 if(valueClass.isArray()) {
\r
237 Class<?> componentType = valueClass.getComponentType();
\r
238 int length = Array.getLength(value);
\r
239 Object array = Array.newInstance(expectedComponentClass, length);
\r
240 if (needsConversion(expectedComponentType, componentType, apply.function != Types.ARRAY)) {
\r
241 for(int i=0;i<length;++i)
\r
242 Array.set(array, i, fromDynamic(expectedComponentType, Array.get(value, i)));
\r
246 // This shouldn't really be happening...
\r
250 else if (value instanceof Iterable) {
\r
251 ArrayList<Object> list = new ArrayList<Object>();
\r
252 for (Object item : (Iterable)value) {
\r
253 list.add(fromDynamic(expectedComponentType, item));
\r
255 if (apply.function != Types.ARRAY && expectedComponentClass.isPrimitive()) {
\r
256 int length = list.size();
\r
257 Object array = Array.newInstance(expectedComponentClass, length);
\r
258 for (int i = 0; i < length; i++)
\r
259 Array.set(array, i, list.get(i));
\r
263 return list.toArray();
\r