]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/ValueConversion.java
b9b4a3711a82c9f5dd503f22d057dafb8a47e428
[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                 if (expectedType == Types.DOUBLE) {\r
49                         return Double.parseDouble(value);\r
50                 }\r
51                 else if (expectedType == Types.INTEGER) {\r
52                         return Integer.parseInt(value);\r
53                 }\r
54                 else if (expectedType == Types.FLOAT) {\r
55                         return Float.parseFloat(value);\r
56                 }\r
57                 else if (expectedType == Types.BYTE) {\r
58                         return Byte.parseByte(value);\r
59                 }\r
60                 else if (expectedType == Types.SHORT) {\r
61                         return Short.parseShort(value);\r
62                 }\r
63                 else if (expectedType == Types.LONG) {\r
64                         return Long.parseLong(value);\r
65                 }\r
66                 else if (expectedType == Types.BOOLEAN) {\r
67                         return Boolean.parseBoolean(value);\r
68                 }\r
69                 else if (expectedType == Types.CHARACTER && value.length() == 1) {\r
70                         return value.charAt(0);\r
71                 }\r
72                 \r
73                 return value;\r
74         }\r
75         \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
84                         return Float.class;\r
85                 else if (expectedType == Types.BYTE)\r
86                         return Byte.class;\r
87                 else if (expectedType == Types.SHORT)\r
88                         return Short.class;\r
89                 else if (expectedType == Types.LONG)\r
90                         return Long.class;\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
95                 else\r
96                         return Object.class;\r
97         }\r
98         \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
105                         return int.class;\r
106                 else if (expectedType == Types.FLOAT)\r
107                         return float.class;\r
108                 else if (expectedType == Types.BYTE)\r
109                         return byte.class;\r
110                 else if (expectedType == Types.SHORT)\r
111                         return short.class;\r
112                 else if (expectedType == Types.LONG)\r
113                         return long.class;\r
114                 else if (expectedType == Types.BOOLEAN)\r
115                         return boolean.class;\r
116                 else if (expectedType == Types.CHARACTER)\r
117                         return char.class;\r
118                 else\r
119                         return Object.class;\r
120         }\r
121         \r
122         @SuppressWarnings("unchecked")\r
123         public static boolean needsConversion(Type expectedType, Object value) {\r
124                 if (!needsConversion(expectedType, value.getClass(), false))\r
125                         return false;\r
126                 \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
131                                         return true;\r
132                                 else {\r
133                                         for (Object item : (List<Object>)value) {\r
134                                                 if (needsConversion(apply.parameter, item))\r
135                                                         return true;\r
136                                         }\r
137                                         return false;\r
138                                 }\r
139                         }\r
140                 }\r
141                 \r
142                 return true;\r
143         }\r
144         \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
151                                 else\r
152                                         return expectedClass.isAssignableFrom(clazz);\r
153                         }\r
154                         else if (clazz.isPrimitive()) {\r
155                                 return true;\r
156                         }\r
157                         else {\r
158                                 return !getNativeClass(expectedType).isAssignableFrom(clazz);\r
159                         }\r
160                 }\r
161                 else if (expectedType instanceof TApply) {\r
162             TApply apply = (TApply)expectedType;\r
163             if (apply.function == Types.LIST) {\r
164                 return true;\r
165             }\r
166             else if (apply.function == Types.VECTOR || apply.function == Types.MVECTOR || apply.function == Types.ARRAY) {\r
167                 if (!clazz.isArray())\r
168                         return true;\r
169                 else {\r
170                         boolean needPrimitive2 = apply.function != Types.ARRAY;\r
171                         return needsConversion(apply.parameter, clazz.getComponentType(), needPrimitive2);\r
172                 }\r
173             }\r
174                 }\r
175                 \r
176                 return false;\r
177         }\r
178 \r
179     @SuppressWarnings({ "rawtypes", "unchecked" })\r
180     public static Object fromDynamic(Type expectedType, Object value) {\r
181         if (value == null)\r
182                 return null;\r
183         else if (value instanceof Variant)\r
184                         return fromDynamic(expectedType, ((Variant)value).getValue());\r
185                 else if (expectedType == Types.DYNAMIC)\r
186                         return value;\r
187                 else if (!needsConversion(expectedType, value))\r
188                 return value;\r
189         \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
198         }\r
199         else if(expectedType instanceof TApply) {\r
200             TApply apply = (TApply)expectedType;\r
201             Type expectedComponentType = apply.parameter;\r
202             \r
203             if(apply.function == Types.LIST) {\r
204                 Class<?> valueClass = value.getClass();\r
205                 \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
213                         return list;\r
214                     }\r
215                     else\r
216                         return Arrays.asList((Object[])value);\r
217                 }\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
223                         return list;\r
224                 }\r
225             }\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
231                 \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
239                         return array;\r
240                     }\r
241                     else {\r
242                         // This shouldn't really be happening...\r
243                         return value;\r
244                     }\r
245                 }\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
250                         }\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
256                         return array;\r
257                         }\r
258                         else\r
259                                 return list.toArray();\r
260                 }\r
261             }\r
262         }\r
263         return value;\r
264     }    \r
265 }\r