]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/ValueConversion.java
(refs #7250) Merging master, minor CHR bugfixes
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / runtime / ValueConversion.java
1 package org.simantics.scl.compiler.runtime;
2
3
4 import java.lang.reflect.Array;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.List;
8
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;
14
15 public class ValueConversion {
16
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());
21                 }
22                 else if (expectedType == Types.INTEGER) {
23                         if (value instanceof Integer) return value;
24                         else return new Integer(value.intValue());
25                 }
26                 else if (expectedType == Types.FLOAT) {
27                         if (value instanceof Float) return value;
28                         else return new Float(value.floatValue());
29                 }
30                 else if (expectedType == Types.BYTE) {
31                         if (value instanceof Byte) return value;
32                         else return new Byte(value.byteValue());
33                 }
34                 else if (expectedType == Types.SHORT) {
35                         if (value instanceof Short) return value;
36                         else return new Short(value.shortValue());
37                 }
38                 else if (expectedType == Types.LONG) {
39                         if (value instanceof Long) return value;
40                         else return new Long(value.longValue());
41                 }
42                 
43                 // Not expecting a number type
44                 return value;
45         }
46         
47         public static Object parsePrimitive(TCon expectedType, String value) {
48                 if (expectedType == Types.DOUBLE) {
49                         return Double.parseDouble(value);
50                 }
51                 else if (expectedType == Types.INTEGER) {
52                         return Integer.parseInt(value);
53                 }
54                 else if (expectedType == Types.FLOAT) {
55                         return Float.parseFloat(value);
56                 }
57                 else if (expectedType == Types.BYTE) {
58                         return Byte.parseByte(value);
59                 }
60                 else if (expectedType == Types.SHORT) {
61                         return Short.parseShort(value);
62                 }
63                 else if (expectedType == Types.LONG) {
64                         return Long.parseLong(value);
65                 }
66                 else if (expectedType == Types.BOOLEAN) {
67                         return Boolean.parseBoolean(value);
68                 }
69                 else if (expectedType == Types.CHARACTER && value.length() == 1) {
70                         return value.charAt(0);
71                 }
72                 
73                 return value;
74         }
75         
76         public static Class<?> getNativeClass(Type expectedType) {
77                 if (expectedType == Types.STRING)
78                         return String.class;
79                 else if (expectedType == Types.DOUBLE)
80                         return Double.class;
81                 else if (expectedType == Types.INTEGER)
82                         return Integer.class;
83                 else if (expectedType == Types.FLOAT)
84                         return Float.class;
85                 else if (expectedType == Types.BYTE)
86                         return Byte.class;
87                 else if (expectedType == Types.SHORT)
88                         return Short.class;
89                 else if (expectedType == Types.LONG)
90                         return Long.class;
91                 else if (expectedType == Types.BOOLEAN)
92                         return Boolean.class;
93                 else if (expectedType == Types.CHARACTER)
94                         return Character.class;
95                 else
96                         return Object.class;
97         }
98         
99         public static Class<?> getNativePrimitiveClass(Type expectedType) {
100                 if (expectedType == Types.STRING)
101                         return String.class;
102                 else if (expectedType == Types.DOUBLE)
103                         return double.class;
104                 else if (expectedType == Types.INTEGER)
105                         return int.class;
106                 else if (expectedType == Types.FLOAT)
107                         return float.class;
108                 else if (expectedType == Types.BYTE)
109                         return byte.class;
110                 else if (expectedType == Types.SHORT)
111                         return short.class;
112                 else if (expectedType == Types.LONG)
113                         return long.class;
114                 else if (expectedType == Types.BOOLEAN)
115                         return boolean.class;
116                 else if (expectedType == Types.CHARACTER)
117                         return char.class;
118                 else
119                         return Object.class;
120         }
121         
122         @SuppressWarnings("unchecked")
123         public static boolean needsConversion(Type expectedType, Object value) {
124                 if (!needsConversion(expectedType, value.getClass(), false))
125                         return false;
126                 
127                 if (expectedType instanceof TApply) {
128             TApply apply = (TApply)expectedType;
129                         if (apply.function == Types.LIST) {
130                                 if (!(value instanceof List))
131                                         return true;
132                                 else {
133                                         for (Object item : (List<Object>)value) {
134                                                 if (needsConversion(apply.parameter, item))
135                                                         return true;
136                                         }
137                                         return false;
138                                 }
139                         }
140                 }
141                 
142                 return true;
143         }
144         
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;
151                                 else
152                                         return expectedClass.isAssignableFrom(clazz);
153                         }
154                         else if (clazz.isPrimitive()) {
155                                 return true;
156                         }
157                         else {
158                                 return !getNativeClass(expectedType).isAssignableFrom(clazz);
159                         }
160                 }
161                 else if (expectedType instanceof TApply) {
162             TApply apply = (TApply)expectedType;
163             if (apply.function == Types.LIST) {
164                 return true;
165             }
166             else if (apply.function == Types.VECTOR || apply.function == Types.MVECTOR || apply.function == Types.ARRAY) {
167                 if (!clazz.isArray())
168                         return true;
169                 else {
170                         boolean needPrimitive2 = apply.function != Types.ARRAY;
171                         return needsConversion(apply.parameter, clazz.getComponentType(), needPrimitive2);
172                 }
173             }
174                 }
175                 
176                 return false;
177         }
178
179     @SuppressWarnings({ "rawtypes", "unchecked" })
180     public static Object fromDynamic(Type expectedType, Object value) {
181         if (value == null)
182                 return null;
183         else if (value instanceof Variant)
184                         return fromDynamic(expectedType, ((Variant)value).getValue());
185                 else if (expectedType == Types.DYNAMIC)
186                         return value;
187                 else if (!needsConversion(expectedType, value))
188                 return value;
189         
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);
198         }
199         else if(expectedType instanceof TApply) {
200             TApply apply = (TApply)expectedType;
201             Type expectedComponentType = apply.parameter;
202             
203             if(apply.function == Types.LIST) {
204                 Class<?> valueClass = value.getClass();
205                 
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)));
213                         return list;
214                     }
215                     else
216                         return Arrays.asList((Object[])value);
217                 }
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));
223                         return list;
224                 }
225             }
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);
231                 
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)));
239                         return array;
240                     }
241                     else {
242                         // This shouldn't really be happening...
243                         return value;
244                     }
245                 }
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));
250                         }
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));
256                         return array;
257                         }
258                         else
259                                 return list.toArray();
260                 }
261             }
262         }
263         return value;
264     }    
265 }