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