Mercurial Hosting > luan
view src/luan/LuaJavaFunction.java @ 1:2df768b926aa
start Luan
git-svn-id: https://luan-java.googlecode.com/svn/trunk@2 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Tue, 13 Nov 2012 05:54:32 +0000 |
parents | |
children | 4da26b11d12a |
line wrap: on
line source
package luan; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; public final class LuaJavaFunction extends LuaFunction { private final Method method; private final Object obj; private final RtnConverter rtnConverter; private final ArgConverter[] argConverters; public LuaJavaFunction(Method method,Object obj) { this.method = method; this.obj = obj; rtnConverter = getRtnConverter(method); argConverters = getArgConverters(method); } public Object[] call(Object... args) { args = fixArgs(args); Object rtn; try { rtn = method.invoke(obj,args); } catch(IllegalAccessException e) { throw new RuntimeException(e); } catch(InvocationTargetException e) { throw new RuntimeException(e); } return rtnConverter.convert(rtn); } private Object[] fixArgs(Object[] args) { if( args.length != argConverters.length ) { Object[] t = new Object[argConverters.length]; System.arraycopy(args,0,t,0,Math.min(args.length,t.length)); args = t; } for( int i=0; i<args.length; i++ ) { args[i] = argConverters[i].convert(args[i]); } return args; } private interface RtnConverter { public Object[] convert(Object obj); } private static final Object[] EMPTY = new Object[0]; private static final RtnConverter RTN_EMPTY = new RtnConverter() { public Object[] convert(Object obj) { return EMPTY; } }; private static final RtnConverter RTN_SAME = new RtnConverter() { public Object[] convert(Object obj) { return new Object[]{obj}; } }; private static final RtnConverter RTN_NUMBER = new RtnConverter() { public Object[] convert(Object obj) { if( obj == null ) return new Object[1]; Number n = (Number)obj; LuaNumber ln = new LuaNumber(n.doubleValue()); return new Object[]{ln}; } }; private static RtnConverter getRtnConverter(Method m) { Class<?> rtnType = m.getReturnType(); if( rtnType == Void.TYPE ) return RTN_EMPTY; if( Number.class.isAssignableFrom(rtnType) || rtnType == Short.TYPE || rtnType == Integer.TYPE || rtnType == Long.TYPE || rtnType == Float.TYPE || rtnType == Double.TYPE ) return RTN_NUMBER; return RTN_SAME; } private interface ArgConverter { public Object convert(Object obj); } private static final ArgConverter ARG_SAME = new ArgConverter() { public Object convert(Object obj) { return obj; } }; private static final ArgConverter ARG_DOUBLE = new ArgConverter() { public Object convert(Object obj) { if( obj instanceof LuaNumber ) { LuaNumber ln = (LuaNumber)obj; return Double.valueOf(ln.n); } if( obj instanceof String ) { String s = (String)obj; try { return Double.valueOf(s); } catch(NumberFormatException e) {} } return obj; } }; private static final ArgConverter ARG_FLOAT = new ArgConverter() { public Object convert(Object obj) { if( obj instanceof LuaNumber ) { LuaNumber ln = (LuaNumber)obj; return Float.valueOf((float)ln.n); } if( obj instanceof String ) { String s = (String)obj; try { return Float.valueOf(s); } catch(NumberFormatException e) {} } return obj; } }; private static final ArgConverter ARG_LONG = new ArgConverter() { public Object convert(Object obj) { if( obj instanceof LuaNumber ) { LuaNumber ln = (LuaNumber)obj; long i = (long)ln.n; if( i == ln.n ) return Long.valueOf(i); } else if( obj instanceof String ) { String s = (String)obj; try { return Long.valueOf(s); } catch(NumberFormatException e) {} } return obj; } }; private static final ArgConverter ARG_INTEGER = new ArgConverter() { public Object convert(Object obj) { if( obj instanceof LuaNumber ) { LuaNumber ln = (LuaNumber)obj; int i = (int)ln.n; if( i == ln.n ) return Integer.valueOf(i); } else if( obj instanceof String ) { String s = (String)obj; try { return Integer.valueOf(s); } catch(NumberFormatException e) {} } return obj; } }; private static final ArgConverter ARG_SHORT = new ArgConverter() { public Object convert(Object obj) { if( obj instanceof LuaNumber ) { LuaNumber ln = (LuaNumber)obj; short i = (short)ln.n; if( i == ln.n ) return Short.valueOf(i); } else if( obj instanceof String ) { String s = (String)obj; try { return Short.valueOf(s); } catch(NumberFormatException e) {} } return obj; } }; private static ArgConverter[] getArgConverters(Method m) { Class<?>[] paramTypes = m.getParameterTypes(); ArgConverter[] a = new ArgConverter[paramTypes.length]; for( int i=0; i<a.length; i++ ) { a[i] = getArgConverter(paramTypes[i]); } return a; } private static ArgConverter getArgConverter(Class<?> cls) { if( cls == Double.TYPE || cls.equals(Double.class) ) return ARG_DOUBLE; if( cls == Float.TYPE || cls.equals(Float.class) ) return ARG_FLOAT; if( cls == Long.TYPE || cls.equals(Long.class) ) return ARG_LONG; if( cls == Integer.TYPE || cls.equals(Integer.class) ) return ARG_INTEGER; if( cls == Short.TYPE || cls.equals(Short.class) ) return ARG_SHORT; return ARG_SAME; } }