package org.simantics.scl.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import org.simantics.scl.compiler.types.TApply; import org.simantics.scl.compiler.types.TCon; import org.simantics.scl.compiler.types.TForAll; import org.simantics.scl.compiler.types.TFun; import org.simantics.scl.compiler.types.TMetaVar; import org.simantics.scl.compiler.types.TPred; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.MatchException; import org.simantics.scl.compiler.types.util.MultiFunction; import org.simantics.scl.reflection.internal.registry.BindingRegistry; import org.simantics.scl.runtime.function.Function; public class ReflectionUtils { private static Class toBoxedClass(Class clazz) { if(clazz == int.class) return Integer.class; else if(clazz == boolean.class) return Boolean.class; else if(clazz == double.class) return Double.class; else if(clazz == byte.class) return Byte.class; else if(clazz == long.class) return Long.class; else if(clazz == float.class) return Float.class; else if(clazz == short.class) return Short.class; else if(clazz == char.class) return Character.class; else throw new IllegalArgumentException("Expected a primitive type, got " + clazz + "."); } public static Class getClass(TypeBindingScheme scheme, Type type) throws TypeNotFoundException { while(true) { if(type instanceof TCon) { TCon con = (TCon)type; return scheme.getClass(con); } else if(type instanceof TApply) { TApply apply = (TApply)type; type = apply.function; } else if(type instanceof TVar) { return Object.class; } else if(type instanceof TForAll) { TForAll forAll = (TForAll)type; type = forAll.type; } else if(type instanceof TFun) { return Function.class; } else if(type instanceof TPred) { return Object.class; } else if(type instanceof TMetaVar) { type = Types.canonical(type); if(type instanceof TMetaVar) return Object.class; } else throw new IllegalArgumentException(); } } public static boolean isAssignableFrom(TypeBindingScheme scheme, Type to, Class from) throws TypeNotFoundException { if(from.isPrimitive()) { if(from == void.class) return Types.canonical(to) == Types.tupleConstructor(0); from = toBoxedClass(from); } return getClass(scheme, to).isAssignableFrom(from); } public static boolean isAssignableFrom(TypeBindingScheme scheme, Class to, Type from) throws TypeNotFoundException { if(to.isPrimitive()) { if(to == void.class) return Types.canonical(from) == Types.tupleConstructor(0); to = toBoxedClass(to); } return to.isAssignableFrom(getClass(scheme, from)); } public static boolean isCompatible(TypeBindingScheme scheme, Type type, Method method) throws TypeNotFoundException { try { if(Modifier.isStatic(method.getModifiers())) { Class[] parameterTypes = method.getParameterTypes(); MultiFunction mfun = Types.matchFunction(Types.removeForAll(type), parameterTypes.length); for(int i=0;i[] parameterTypes = method.getParameterTypes(); MultiFunction mfun = Types.matchFunction(Types.removeForAll(type), parameterTypes.length+1); if(!isAssignableFrom(scheme, method.getDeclaringClass(), mfun.parameterTypes[0])) return false; for(int i=0;i constructor) throws TypeNotFoundException { try { Class[] parameterTypes = constructor.getParameterTypes(); MultiFunction mfun = Types.matchFunction(Types.removeForAll(type), parameterTypes.length); for(int i=0;i."); return getValue(uri.substring(0, lp), uri.substring(lp+1)); } public static TypedValue getValue( String path, String name) throws ValueNotFoundException { return BindingRegistry.getValue(path, name); } }