]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/ValueConversion.java
049799566818015cb8359d9e5bcd0714267811ce
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / runtime / ValueConversion.java
1 package org.simantics.scl.compiler.runtime;\r
2 \r
3 \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
8 \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
14 \r
15 public class ValueConversion {\r
16 \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
21                 }\r
22                 else if (expectedType == Types.INTEGER) {\r
23                         if (value instanceof Integer) return value;\r
24                         else return new Integer(value.intValue());\r
25                 }\r
26                 else if (expectedType == Types.FLOAT) {\r
27                         if (value instanceof Float) return value;\r
28                         else return new Float(value.floatValue());\r
29                 }\r
30                 else if (expectedType == Types.BYTE) {\r
31                         if (value instanceof Byte) return value;\r
32                         else return new Byte(value.byteValue());\r
33                 }\r
34                 else if (expectedType == Types.SHORT) {\r
35                         if (value instanceof Short) return value;\r
36                         else return new Short(value.shortValue());\r
37                 }\r
38                 else if (expectedType == Types.LONG) {\r
39                         if (value instanceof Long) return value;\r
40                         else return new Long(value.longValue());\r
41                 }\r
42                 \r
43                 // Not expecting a number type\r
44                 return value;\r
45         }\r
46         \r
47         public static Object parsePrimitive(TCon expectedType, String value) {\r
48                 try {\r
49                         if (expectedType == Types.DOUBLE) {\r
50                                 return Double.parseDouble(value);\r
51                         }\r
52                         else if (expectedType == Types.INTEGER) {\r
53                                 return Integer.parseInt(value);\r
54                         }\r
55                         else if (expectedType == Types.FLOAT) {\r
56                                 return Float.parseFloat(value);\r
57                         }\r
58                         else if (expectedType == Types.BYTE) {\r
59                                 return Byte.parseByte(value);\r
60                         }\r
61                         else if (expectedType == Types.SHORT) {\r
62                                 return Short.parseShort(value);\r
63                         }\r
64                         else if (expectedType == Types.LONG) {\r
65                                 return Long.parseLong(value);\r
66                         }\r
67                         else if (expectedType == Types.BOOLEAN) {\r
68                                 return Boolean.parseBoolean(value);\r
69                         }\r
70                         else if (expectedType == Types.CHARACTER && value.length() == 1) {\r
71                                 return value.charAt(0);\r
72                         }\r
73                 } catch(NumberFormatException e) {\r
74                         e.printStackTrace();\r
75                 }\r
76                 \r
77                 return value;\r
78         }\r
79         \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
88                         return Float.class;\r
89                 else if (expectedType == Types.BYTE)\r
90                         return Byte.class;\r
91                 else if (expectedType == Types.SHORT)\r
92                         return Short.class;\r
93                 else if (expectedType == Types.LONG)\r
94                         return Long.class;\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
99                 else\r
100                         return Object.class;\r
101         }\r
102         \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
109                         return int.class;\r
110                 else if (expectedType == Types.FLOAT)\r
111                         return float.class;\r
112                 else if (expectedType == Types.BYTE)\r
113                         return byte.class;\r
114                 else if (expectedType == Types.SHORT)\r
115                         return short.class;\r
116                 else if (expectedType == Types.LONG)\r
117                         return long.class;\r
118                 else if (expectedType == Types.BOOLEAN)\r
119                         return boolean.class;\r
120                 else if (expectedType == Types.CHARACTER)\r
121                         return char.class;\r
122                 else\r
123                         return Object.class;\r
124         }\r
125         \r
126         @SuppressWarnings("unchecked")\r
127         public static boolean needsConversion(Type expectedType, Object value) {\r
128                 if (!needsConversion(expectedType, value.getClass(), false))\r
129                         return false;\r
130                 \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
135                                         return true;\r
136                                 else {\r
137                                         for (Object item : (List<Object>)value) {\r
138                                                 if (needsConversion(apply.parameter, item))\r
139                                                         return true;\r
140                                         }\r
141                                         return false;\r
142                                 }\r
143                         }\r
144                 }\r
145                 \r
146                 return true;\r
147         }\r
148         \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
155                                 else\r
156                                         return expectedClass.isAssignableFrom(clazz);\r
157                         }\r
158                         else if (clazz.isPrimitive()) {\r
159                                 return true;\r
160                         }\r
161                         else {\r
162                                 return !getNativeClass(expectedType).isAssignableFrom(clazz);\r
163                         }\r
164                 }\r
165                 else if (expectedType instanceof TApply) {\r
166             TApply apply = (TApply)expectedType;\r
167             if (apply.function == Types.LIST) {\r
168                 return true;\r
169             }\r
170             else if (apply.function == Types.VECTOR || apply.function == Types.MVECTOR || apply.function == Types.ARRAY) {\r
171                 if (!clazz.isArray())\r
172                         return true;\r
173                 else {\r
174                         boolean needPrimitive2 = apply.function != Types.ARRAY;\r
175                         return needsConversion(apply.parameter, clazz.getComponentType(), needPrimitive2);\r
176                 }\r
177             }\r
178                 }\r
179                 \r
180                 return false;\r
181         }\r
182 \r
183     @SuppressWarnings({ "rawtypes", "unchecked" })\r
184     public static Object fromDynamic(Type expectedType, Object value) {\r
185         if (value == null)\r
186                 return null;\r
187         else if (value instanceof Variant)\r
188                         return fromDynamic(expectedType, ((Variant)value).getValue());\r
189                 else if (expectedType == Types.DYNAMIC)\r
190                         return value;\r
191                 else if (!needsConversion(expectedType, value))\r
192                 return value;\r
193         \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
202         }\r
203         else if(expectedType instanceof TApply) {\r
204             TApply apply = (TApply)expectedType;\r
205             Type expectedComponentType = apply.parameter;\r
206             \r
207             if(apply.function == Types.LIST) {\r
208                 Class<?> valueClass = value.getClass();\r
209                 \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
217                         return list;\r
218                     }\r
219                     else\r
220                         return Arrays.asList((Object[])value);\r
221                 }\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
227                         return list;\r
228                 }\r
229             }\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
235                 \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
243                         return array;\r
244                     }\r
245                     else {\r
246                         // This shouldn't really be happening...\r
247                         return value;\r
248                     }\r
249                 }\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
254                         }\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
260                         return array;\r
261                         }\r
262                         else\r
263                                 return list.toArray();\r
264                 }\r
265             }\r
266         }\r
267         return value;\r
268     }    \r
269 }\r