--- /dev/null
+package org.simantics.scl.compiler.runtime;\r
+\r
+\r
+import java.lang.reflect.Array;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.scl.compiler.types.TApply;\r
+import org.simantics.scl.compiler.types.TCon;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+public class ValueConversion {\r
+\r
+ public static Number convertNumber(TCon expectedType, Number value) {\r
+ if (expectedType == Types.DOUBLE) {\r
+ if (value instanceof Double) return value;\r
+ else return new Double(value.doubleValue());\r
+ }\r
+ else if (expectedType == Types.INTEGER) {\r
+ if (value instanceof Integer) return value;\r
+ else return new Integer(value.intValue());\r
+ }\r
+ else if (expectedType == Types.FLOAT) {\r
+ if (value instanceof Float) return value;\r
+ else return new Float(value.floatValue());\r
+ }\r
+ else if (expectedType == Types.BYTE) {\r
+ if (value instanceof Byte) return value;\r
+ else return new Byte(value.byteValue());\r
+ }\r
+ else if (expectedType == Types.SHORT) {\r
+ if (value instanceof Short) return value;\r
+ else return new Short(value.shortValue());\r
+ }\r
+ else if (expectedType == Types.LONG) {\r
+ if (value instanceof Long) return value;\r
+ else return new Long(value.longValue());\r
+ }\r
+ \r
+ // Not expecting a number type\r
+ return value;\r
+ }\r
+ \r
+ public static Object parsePrimitive(TCon expectedType, String value) {\r
+ try {\r
+ if (expectedType == Types.DOUBLE) {\r
+ return Double.parseDouble(value);\r
+ }\r
+ else if (expectedType == Types.INTEGER) {\r
+ return Integer.parseInt(value);\r
+ }\r
+ else if (expectedType == Types.FLOAT) {\r
+ return Float.parseFloat(value);\r
+ }\r
+ else if (expectedType == Types.BYTE) {\r
+ return Byte.parseByte(value);\r
+ }\r
+ else if (expectedType == Types.SHORT) {\r
+ return Short.parseShort(value);\r
+ }\r
+ else if (expectedType == Types.LONG) {\r
+ return Long.parseLong(value);\r
+ }\r
+ else if (expectedType == Types.BOOLEAN) {\r
+ return Boolean.parseBoolean(value);\r
+ }\r
+ else if (expectedType == Types.CHARACTER && value.length() == 1) {\r
+ return value.charAt(0);\r
+ }\r
+ } catch(NumberFormatException e) {\r
+ e.printStackTrace();\r
+ }\r
+ \r
+ return value;\r
+ }\r
+ \r
+ public static Class<?> getNativeClass(Type expectedType) {\r
+ if (expectedType == Types.STRING)\r
+ return String.class;\r
+ else if (expectedType == Types.DOUBLE)\r
+ return Double.class;\r
+ else if (expectedType == Types.INTEGER)\r
+ return Integer.class;\r
+ else if (expectedType == Types.FLOAT)\r
+ return Float.class;\r
+ else if (expectedType == Types.BYTE)\r
+ return Byte.class;\r
+ else if (expectedType == Types.SHORT)\r
+ return Short.class;\r
+ else if (expectedType == Types.LONG)\r
+ return Long.class;\r
+ else if (expectedType == Types.BOOLEAN)\r
+ return Boolean.class;\r
+ else if (expectedType == Types.CHARACTER)\r
+ return Character.class;\r
+ else\r
+ return Object.class;\r
+ }\r
+ \r
+ public static Class<?> getNativePrimitiveClass(Type expectedType) {\r
+ if (expectedType == Types.STRING)\r
+ return String.class;\r
+ else if (expectedType == Types.DOUBLE)\r
+ return double.class;\r
+ else if (expectedType == Types.INTEGER)\r
+ return int.class;\r
+ else if (expectedType == Types.FLOAT)\r
+ return float.class;\r
+ else if (expectedType == Types.BYTE)\r
+ return byte.class;\r
+ else if (expectedType == Types.SHORT)\r
+ return short.class;\r
+ else if (expectedType == Types.LONG)\r
+ return long.class;\r
+ else if (expectedType == Types.BOOLEAN)\r
+ return boolean.class;\r
+ else if (expectedType == Types.CHARACTER)\r
+ return char.class;\r
+ else\r
+ return Object.class;\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public static boolean needsConversion(Type expectedType, Object value) {\r
+ if (!needsConversion(expectedType, value.getClass(), false))\r
+ return false;\r
+ \r
+ if (expectedType instanceof TApply) {\r
+ TApply apply = (TApply)expectedType;\r
+ if (apply.function == Types.LIST) {\r
+ if (!(value instanceof List))\r
+ return true;\r
+ else {\r
+ for (Object item : (List<Object>)value) {\r
+ if (needsConversion(apply.parameter, item))\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+ \r
+ return true;\r
+ }\r
+ \r
+ public static boolean needsConversion(Type expectedType, Class<?> clazz, boolean needPrimitive) {\r
+ if (expectedType instanceof TCon) {\r
+ if (needPrimitive && Types.isPrimitive(expectedType)) {\r
+ Class<?> expectedClass = getNativePrimitiveClass(expectedType);\r
+ if (expectedClass.isPrimitive())\r
+ return clazz == expectedClass;\r
+ else\r
+ return expectedClass.isAssignableFrom(clazz);\r
+ }\r
+ else if (clazz.isPrimitive()) {\r
+ return true;\r
+ }\r
+ else {\r
+ return !getNativeClass(expectedType).isAssignableFrom(clazz);\r
+ }\r
+ }\r
+ else if (expectedType instanceof TApply) {\r
+ TApply apply = (TApply)expectedType;\r
+ if (apply.function == Types.LIST) {\r
+ return true;\r
+ }\r
+ else if (apply.function == Types.VECTOR || apply.function == Types.MVECTOR || apply.function == Types.ARRAY) {\r
+ if (!clazz.isArray())\r
+ return true;\r
+ else {\r
+ boolean needPrimitive2 = apply.function != Types.ARRAY;\r
+ return needsConversion(apply.parameter, clazz.getComponentType(), needPrimitive2);\r
+ }\r
+ }\r
+ }\r
+ \r
+ return false;\r
+ }\r
+\r
+ @SuppressWarnings({ "rawtypes", "unchecked" })\r
+ public static Object fromDynamic(Type expectedType, Object value) {\r
+ if (value == null)\r
+ return null;\r
+ else if (value instanceof Variant)\r
+ return fromDynamic(expectedType, ((Variant)value).getValue());\r
+ else if (expectedType == Types.DYNAMIC)\r
+ return value;\r
+ else if (!needsConversion(expectedType, value))\r
+ return value;\r
+ \r
+ if(expectedType instanceof TCon) {\r
+ TCon con = (TCon)expectedType;\r
+ if (con == Types.STRING)\r
+ return value.toString();\r
+ else if (value instanceof Number)\r
+ return convertNumber(con, (Number)value);\r
+ else if (value instanceof String && Types.isPrimitive(con))\r
+ return parsePrimitive(con, (String)value);\r
+ }\r
+ else if(expectedType instanceof TApply) {\r
+ TApply apply = (TApply)expectedType;\r
+ Type expectedComponentType = apply.parameter;\r
+ \r
+ if(apply.function == Types.LIST) {\r
+ Class<?> valueClass = value.getClass();\r
+ \r
+ if(valueClass.isArray()) {\r
+ Class<?> componentType = valueClass.getComponentType();\r
+ if(needsConversion(expectedComponentType, componentType, false)) {\r
+ int length = Array.getLength(value);\r
+ ArrayList list = new ArrayList(length);\r
+ for(int i=0;i<length;++i)\r
+ list.add(fromDynamic(expectedComponentType, Array.get(value, i)));\r
+ return list;\r
+ }\r
+ else\r
+ return Arrays.asList((Object[])value);\r
+ }\r
+ else if (value instanceof Iterable) {\r
+ Iterable iterable = (Iterable)value;\r
+ ArrayList list = new ArrayList();\r
+ for (Object element : iterable)\r
+ list.add(fromDynamic(expectedComponentType, element));\r
+ return list;\r
+ }\r
+ }\r
+ else if (apply.function == Types.VECTOR || apply.function == Types.MVECTOR || apply.function == Types.ARRAY) {\r
+ Class<?> valueClass = value.getClass();\r
+ Class<?> expectedComponentClass = apply.function != Types.ARRAY ?\r
+ getNativePrimitiveClass(expectedComponentType) :\r
+ getNativeClass(expectedComponentType);\r
+ \r
+ if(valueClass.isArray()) {\r
+ Class<?> componentType = valueClass.getComponentType();\r
+ int length = Array.getLength(value);\r
+ Object array = Array.newInstance(expectedComponentClass, length);\r
+ if (needsConversion(expectedComponentType, componentType, apply.function != Types.ARRAY)) {\r
+ for(int i=0;i<length;++i)\r
+ Array.set(array, i, fromDynamic(expectedComponentType, Array.get(value, i)));\r
+ return array;\r
+ }\r
+ else {\r
+ // This shouldn't really be happening...\r
+ return value;\r
+ }\r
+ }\r
+ else if (value instanceof Iterable) {\r
+ ArrayList<Object> list = new ArrayList<Object>();\r
+ for (Object item : (Iterable)value) {\r
+ list.add(fromDynamic(expectedComponentType, item));\r
+ }\r
+ if (apply.function != Types.ARRAY && expectedComponentClass.isPrimitive()) {\r
+ int length = list.size();\r
+ Object array = Array.newInstance(expectedComponentClass, length);\r
+ for (int i = 0; i < length; i++)\r
+ Array.set(array, i, list.get(i));\r
+ return array;\r
+ }\r
+ else\r
+ return list.toArray();\r
+ }\r
+ }\r
+ }\r
+ return value;\r
+ } \r
+}\r