1 package org.simantics.scl.reflection;
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.Field;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Modifier;
8 import org.simantics.scl.compiler.types.TApply;
9 import org.simantics.scl.compiler.types.TCon;
10 import org.simantics.scl.compiler.types.TForAll;
11 import org.simantics.scl.compiler.types.TFun;
12 import org.simantics.scl.compiler.types.TMetaVar;
13 import org.simantics.scl.compiler.types.TPred;
14 import org.simantics.scl.compiler.types.TVar;
15 import org.simantics.scl.compiler.types.Type;
16 import org.simantics.scl.compiler.types.Types;
17 import org.simantics.scl.compiler.types.exceptions.MatchException;
18 import org.simantics.scl.compiler.types.util.MultiFunction;
19 import org.simantics.scl.reflection.internal.registry.BindingRegistry;
20 import org.simantics.scl.runtime.function.Function;
22 public class ReflectionUtils {
23 private static Class<?> toBoxedClass(Class<?> clazz) {
24 if(clazz == int.class) return Integer.class;
25 else if(clazz == boolean.class) return Boolean.class;
26 else if(clazz == double.class) return Double.class;
27 else if(clazz == byte.class) return Byte.class;
28 else if(clazz == long.class) return Long.class;
29 else if(clazz == float.class) return Float.class;
30 else if(clazz == short.class) return Short.class;
31 else if(clazz == char.class) return Character.class;
32 else throw new IllegalArgumentException("Expected a primitive type, got " + clazz + ".");
35 public static Class<?> getClass(TypeBindingScheme scheme, Type type) throws TypeNotFoundException {
37 if(type instanceof TCon) {
38 TCon con = (TCon)type;
39 return scheme.getClass(con);
41 else if(type instanceof TApply) {
42 TApply apply = (TApply)type;
43 type = apply.function;
45 else if(type instanceof TVar) {
48 else if(type instanceof TForAll) {
49 TForAll forAll = (TForAll)type;
52 else if(type instanceof TFun) {
53 return Function.class;
55 else if(type instanceof TPred) {
58 else if(type instanceof TMetaVar) {
59 type = Types.canonical(type);
60 if(type instanceof TMetaVar)
64 throw new IllegalArgumentException();
68 public static boolean isAssignableFrom(TypeBindingScheme scheme, Type to, Class<?> from) throws TypeNotFoundException {
69 if(from.isPrimitive()) {
70 if(from == void.class)
71 return Types.canonical(to) == Types.tupleConstructor(0);
72 from = toBoxedClass(from);
74 return getClass(scheme, to).isAssignableFrom(from);
77 public static boolean isAssignableFrom(TypeBindingScheme scheme, Class<?> to, Type from) throws TypeNotFoundException {
78 if(to.isPrimitive()) {
80 return Types.canonical(from) == Types.tupleConstructor(0);
81 to = toBoxedClass(to);
83 return to.isAssignableFrom(getClass(scheme, from));
86 public static boolean isCompatible(TypeBindingScheme scheme, Type type, Method method) throws TypeNotFoundException {
88 if(Modifier.isStatic(method.getModifiers())) {
89 Class<?>[] parameterTypes = method.getParameterTypes();
91 Types.matchFunction(Types.removeForAll(type), parameterTypes.length);
92 for(int i=0;i<parameterTypes.length;++i)
93 if(!isAssignableFrom(scheme, parameterTypes[i],
94 mfun.parameterTypes[i]))
96 return isAssignableFrom(scheme, mfun.returnType,
97 method.getReturnType());
100 Class<?>[] parameterTypes = method.getParameterTypes();
102 Types.matchFunction(Types.removeForAll(type), parameterTypes.length+1);
103 if(!isAssignableFrom(scheme, method.getDeclaringClass(), mfun.parameterTypes[0]))
105 for(int i=0;i<parameterTypes.length;++i)
106 if(!isAssignableFrom(scheme, parameterTypes[i], mfun.parameterTypes[i+1]))
108 return isAssignableFrom(scheme, mfun.returnType,
109 method.getReturnType());
111 } catch(MatchException e) {
116 public static boolean isCompatible(TypeBindingScheme scheme, Type type, Field field) throws TypeNotFoundException {
118 if(Modifier.isStatic(field.getModifiers())) {
119 return isAssignableFrom(scheme, type, field.getType());
122 MultiFunction mfun = Types.matchFunction(Types.removeForAll(type), 1);
123 if(!isAssignableFrom(scheme, mfun.returnType, field.getType()))
125 return isAssignableFrom(scheme, field.getDeclaringClass(), mfun.parameterTypes[0]);
127 } catch(MatchException e) {
132 public static boolean isCompatible(TypeBindingScheme scheme, Type type, Constructor<?> constructor) throws TypeNotFoundException {
134 Class<?>[] parameterTypes = constructor.getParameterTypes();
136 Types.matchFunction(Types.removeForAll(type), parameterTypes.length);
137 for(int i=0;i<parameterTypes.length;++i)
138 if(!isAssignableFrom(scheme, parameterTypes[i], mfun.parameterTypes[i]))
140 return isAssignableFrom(scheme, mfun.returnType,
141 constructor.getDeclaringClass());
142 } catch(MatchException e) {
147 public static TypedValue getValue(String uri) throws ValueNotFoundException {
148 int lp = uri.lastIndexOf('/');
150 throw new IllegalArgumentException("Invalid uri <" + uri + ">.");
151 return getValue(uri.substring(0, lp), uri.substring(lp+1));
154 public static TypedValue getValue(
156 String name) throws ValueNotFoundException {
157 return BindingRegistry.getValue(path, name);