1 package org.simantics.scl.reflection;
\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
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
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
35 public static Class<?> getClass(TypeBindingScheme scheme, Type type) throws TypeNotFoundException {
\r
37 if(type instanceof TCon) {
\r
38 TCon con = (TCon)type;
\r
39 return scheme.getClass(con);
\r
41 else if(type instanceof TApply) {
\r
42 TApply apply = (TApply)type;
\r
43 type = apply.function;
\r
45 else if(type instanceof TVar) {
\r
46 return Object.class;
\r
48 else if(type instanceof TForAll) {
\r
49 TForAll forAll = (TForAll)type;
\r
52 else if(type instanceof TFun) {
\r
53 return Function.class;
\r
55 else if(type instanceof TPred) {
\r
56 return Object.class;
\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
64 throw new IllegalArgumentException();
\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
74 return getClass(scheme, to).isAssignableFrom(from);
\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
83 return to.isAssignableFrom(getClass(scheme, from));
\r
86 public static boolean isCompatible(TypeBindingScheme scheme, Type type, Method method) throws TypeNotFoundException {
\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
96 return isAssignableFrom(scheme, mfun.returnType,
\r
97 method.getReturnType());
\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
105 for(int i=0;i<parameterTypes.length;++i)
\r
106 if(!isAssignableFrom(scheme, parameterTypes[i], mfun.parameterTypes[i+1]))
\r
108 return isAssignableFrom(scheme, mfun.returnType,
\r
109 method.getReturnType());
\r
111 } catch(MatchException e) {
\r
116 public static boolean isCompatible(TypeBindingScheme scheme, Type type, Field field) throws TypeNotFoundException {
\r
118 if(Modifier.isStatic(field.getModifiers())) {
\r
119 return isAssignableFrom(scheme, type, field.getType());
\r
122 MultiFunction mfun = Types.matchFunction(Types.removeForAll(type), 1);
\r
123 if(!isAssignableFrom(scheme, mfun.returnType, field.getType()))
\r
125 return isAssignableFrom(scheme, field.getDeclaringClass(), mfun.parameterTypes[0]);
\r
127 } catch(MatchException e) {
\r
132 public static boolean isCompatible(TypeBindingScheme scheme, Type type, Constructor<?> constructor) throws TypeNotFoundException {
\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
140 return isAssignableFrom(scheme, mfun.returnType,
\r
141 constructor.getDeclaringClass());
\r
142 } catch(MatchException e) {
\r
147 public static TypedValue getValue(String uri) throws ValueNotFoundException {
\r
148 int lp = uri.lastIndexOf('/');
\r
150 throw new IllegalArgumentException("Invalid uri <" + uri + ">.");
\r
151 return getValue(uri.substring(0, lp), uri.substring(lp+1));
\r
154 public static TypedValue getValue(
\r
156 String name) throws ValueNotFoundException {
\r
157 return BindingRegistry.getValue(path, name);
\r