]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/ReflectionUtils.java
Several Wiki documentation view improvements.
[simantics/platform.git] / bundles / org.simantics.scl.reflection / src / org / simantics / scl / reflection / ReflectionUtils.java
1 package org.simantics.scl.reflection;\r
2 \r
3 import java.lang.reflect.Constructor;\r
4 import java.lang.reflect.Field;\r
5 import java.lang.reflect.Method;\r
6 import java.lang.reflect.Modifier;\r
7 \r
8 import org.simantics.scl.compiler.types.TApply;\r
9 import org.simantics.scl.compiler.types.TCon;\r
10 import org.simantics.scl.compiler.types.TForAll;\r
11 import org.simantics.scl.compiler.types.TFun;\r
12 import org.simantics.scl.compiler.types.TMetaVar;\r
13 import org.simantics.scl.compiler.types.TPred;\r
14 import org.simantics.scl.compiler.types.TVar;\r
15 import org.simantics.scl.compiler.types.Type;\r
16 import org.simantics.scl.compiler.types.Types;\r
17 import org.simantics.scl.compiler.types.exceptions.MatchException;\r
18 import org.simantics.scl.compiler.types.util.MultiFunction;\r
19 import org.simantics.scl.reflection.internal.registry.BindingRegistry;\r
20 import org.simantics.scl.runtime.function.Function;\r
21 \r
22 public class ReflectionUtils {\r
23     private static Class<?> toBoxedClass(Class<?> clazz) {\r
24         if(clazz == int.class) return Integer.class;\r
25         else if(clazz == boolean.class) return Boolean.class;\r
26         else if(clazz == double.class) return Double.class;\r
27         else if(clazz == byte.class) return Byte.class;\r
28         else if(clazz == long.class) return Long.class;\r
29         else if(clazz == float.class) return Float.class;\r
30         else if(clazz == short.class) return Short.class;\r
31         else if(clazz == char.class) return Character.class;\r
32         else throw new IllegalArgumentException("Expected a primitive type, got " + clazz + "."); \r
33     }\r
34     \r
35     public static Class<?> getClass(TypeBindingScheme scheme, Type type) throws TypeNotFoundException {\r
36         while(true) {\r
37             if(type instanceof TCon) {\r
38                 TCon con = (TCon)type;\r
39                 return scheme.getClass(con);\r
40             }\r
41             else if(type instanceof TApply) {\r
42                 TApply apply = (TApply)type;\r
43                 type = apply.function;\r
44             }\r
45             else if(type instanceof TVar) {\r
46                 return Object.class;\r
47             }\r
48             else if(type instanceof TForAll) {\r
49                 TForAll forAll = (TForAll)type;\r
50                 type = forAll.type;\r
51             }\r
52             else if(type instanceof TFun) {\r
53                 return Function.class;\r
54             }\r
55             else if(type instanceof TPred) {\r
56                 return Object.class;\r
57             }\r
58             else if(type instanceof TMetaVar) {\r
59                 type = Types.canonical(type);\r
60                 if(type instanceof TMetaVar)\r
61                     return Object.class;\r
62             }\r
63             else\r
64                 throw new IllegalArgumentException();\r
65         }\r
66     }\r
67     \r
68     public static boolean isAssignableFrom(TypeBindingScheme scheme, Type to, Class<?> from) throws TypeNotFoundException {\r
69         if(from.isPrimitive()) {\r
70             if(from == void.class)\r
71                 return Types.canonical(to) == Types.tupleConstructor(0);\r
72             from = toBoxedClass(from);\r
73         }\r
74         return getClass(scheme, to).isAssignableFrom(from);   \r
75     }\r
76     \r
77     public static boolean isAssignableFrom(TypeBindingScheme scheme, Class<?> to, Type from) throws TypeNotFoundException {\r
78         if(to.isPrimitive()) {\r
79             if(to == void.class)\r
80                 return Types.canonical(from) == Types.tupleConstructor(0);\r
81             to = toBoxedClass(to);\r
82         }\r
83         return to.isAssignableFrom(getClass(scheme, from));   \r
84     }\r
85     \r
86     public static boolean isCompatible(TypeBindingScheme scheme, Type type, Method method) throws TypeNotFoundException {\r
87         try {\r
88             if(Modifier.isStatic(method.getModifiers())) {\r
89                 Class<?>[] parameterTypes = method.getParameterTypes();\r
90                 MultiFunction mfun = \r
91                         Types.matchFunction(Types.removeForAll(type), parameterTypes.length);\r
92                 for(int i=0;i<parameterTypes.length;++i)\r
93                     if(!isAssignableFrom(scheme, parameterTypes[i], \r
94                             mfun.parameterTypes[i]))\r
95                         return false;\r
96                 return isAssignableFrom(scheme, mfun.returnType,\r
97                         method.getReturnType());\r
98             }\r
99             else {\r
100                 Class<?>[] parameterTypes = method.getParameterTypes();\r
101                 MultiFunction mfun = \r
102                         Types.matchFunction(Types.removeForAll(type), parameterTypes.length+1);\r
103                 if(!isAssignableFrom(scheme, method.getDeclaringClass(), mfun.parameterTypes[0]))\r
104                     return false;\r
105                 for(int i=0;i<parameterTypes.length;++i)\r
106                     if(!isAssignableFrom(scheme, parameterTypes[i], mfun.parameterTypes[i+1]))\r
107                         return false;\r
108                 return isAssignableFrom(scheme, mfun.returnType,\r
109                         method.getReturnType());\r
110             }\r
111         } catch(MatchException e) {\r
112             return false;\r
113         }\r
114     }\r
115     \r
116     public static boolean isCompatible(TypeBindingScheme scheme, Type type, Field field) throws TypeNotFoundException {\r
117         try {\r
118             if(Modifier.isStatic(field.getModifiers())) {\r
119                 return isAssignableFrom(scheme, type, field.getType());\r
120             }\r
121             else {\r
122                 MultiFunction mfun = Types.matchFunction(Types.removeForAll(type), 1);\r
123                 if(!isAssignableFrom(scheme, mfun.returnType, field.getType()))\r
124                     return false;\r
125                 return isAssignableFrom(scheme, field.getDeclaringClass(), mfun.parameterTypes[0]);\r
126             }\r
127         } catch(MatchException e) {\r
128             return false;\r
129         }\r
130     }\r
131     \r
132     public static boolean isCompatible(TypeBindingScheme scheme, Type type, Constructor<?> constructor) throws TypeNotFoundException {\r
133         try {\r
134             Class<?>[] parameterTypes = constructor.getParameterTypes();\r
135             MultiFunction mfun = \r
136                     Types.matchFunction(Types.removeForAll(type), parameterTypes.length);\r
137             for(int i=0;i<parameterTypes.length;++i)\r
138                 if(!isAssignableFrom(scheme, parameterTypes[i], mfun.parameterTypes[i]))\r
139                     return false;\r
140             return isAssignableFrom(scheme, mfun.returnType,\r
141                     constructor.getDeclaringClass());           \r
142         } catch(MatchException e) {\r
143             return false;\r
144         }\r
145     }\r
146     \r
147     public static TypedValue getValue(String uri) throws ValueNotFoundException {\r
148         int lp = uri.lastIndexOf('/');\r
149         if(lp < -1)\r
150             throw new IllegalArgumentException("Invalid uri <" + uri + ">.");\r
151         return getValue(uri.substring(0, lp), uri.substring(lp+1));\r
152     }\r
153             \r
154     public static TypedValue getValue(\r
155             String path, \r
156             String name) throws ValueNotFoundException {\r
157         return BindingRegistry.getValue(path, name);\r
158     }\r
159 }\r