]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/ValueConversion.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / runtime / ValueConversion.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/ValueConversion.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/ValueConversion.java
new file mode 100644 (file)
index 0000000..0497995
--- /dev/null
@@ -0,0 +1,269 @@
+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