comparison 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
comparison
equal deleted inserted replaced
0:a89d06646ff3 1:2df768b926aa
1 package luan;
2
3 import java.lang.reflect.Method;
4 import java.lang.reflect.InvocationTargetException;
5
6
7 public final class LuaJavaFunction extends LuaFunction {
8 private final Method method;
9 private final Object obj;
10 private final RtnConverter rtnConverter;
11 private final ArgConverter[] argConverters;
12
13 public LuaJavaFunction(Method method,Object obj) {
14 this.method = method;
15 this.obj = obj;
16 rtnConverter = getRtnConverter(method);
17 argConverters = getArgConverters(method);
18 }
19
20 public Object[] call(Object... args) {
21 args = fixArgs(args);
22 Object rtn;
23 try {
24 rtn = method.invoke(obj,args);
25 } catch(IllegalAccessException e) {
26 throw new RuntimeException(e);
27 } catch(InvocationTargetException e) {
28 throw new RuntimeException(e);
29 }
30 return rtnConverter.convert(rtn);
31 }
32
33 private Object[] fixArgs(Object[] args) {
34 if( args.length != argConverters.length ) {
35 Object[] t = new Object[argConverters.length];
36 System.arraycopy(args,0,t,0,Math.min(args.length,t.length));
37 args = t;
38 }
39 for( int i=0; i<args.length; i++ ) {
40 args[i] = argConverters[i].convert(args[i]);
41 }
42 return args;
43 }
44
45
46 private interface RtnConverter {
47 public Object[] convert(Object obj);
48 }
49
50 private static final Object[] EMPTY = new Object[0];
51
52 private static final RtnConverter RTN_EMPTY = new RtnConverter() {
53 public Object[] convert(Object obj) {
54 return EMPTY;
55 }
56 };
57
58 private static final RtnConverter RTN_SAME = new RtnConverter() {
59 public Object[] convert(Object obj) {
60 return new Object[]{obj};
61 }
62 };
63
64 private static final RtnConverter RTN_NUMBER = new RtnConverter() {
65 public Object[] convert(Object obj) {
66 if( obj == null )
67 return new Object[1];
68 Number n = (Number)obj;
69 LuaNumber ln = new LuaNumber(n.doubleValue());
70 return new Object[]{ln};
71 }
72 };
73
74 private static RtnConverter getRtnConverter(Method m) {
75 Class<?> rtnType = m.getReturnType();
76 if( rtnType == Void.TYPE )
77 return RTN_EMPTY;
78 if( Number.class.isAssignableFrom(rtnType)
79 || rtnType == Short.TYPE
80 || rtnType == Integer.TYPE
81 || rtnType == Long.TYPE
82 || rtnType == Float.TYPE
83 || rtnType == Double.TYPE
84 )
85 return RTN_NUMBER;
86 return RTN_SAME;
87 }
88
89
90 private interface ArgConverter {
91 public Object convert(Object obj);
92 }
93
94 private static final ArgConverter ARG_SAME = new ArgConverter() {
95 public Object convert(Object obj) {
96 return obj;
97 }
98 };
99
100 private static final ArgConverter ARG_DOUBLE = new ArgConverter() {
101 public Object convert(Object obj) {
102 if( obj instanceof LuaNumber ) {
103 LuaNumber ln = (LuaNumber)obj;
104 return Double.valueOf(ln.n);
105 }
106 if( obj instanceof String ) {
107 String s = (String)obj;
108 try {
109 return Double.valueOf(s);
110 } catch(NumberFormatException e) {}
111 }
112 return obj;
113 }
114 };
115
116 private static final ArgConverter ARG_FLOAT = new ArgConverter() {
117 public Object convert(Object obj) {
118 if( obj instanceof LuaNumber ) {
119 LuaNumber ln = (LuaNumber)obj;
120 return Float.valueOf((float)ln.n);
121 }
122 if( obj instanceof String ) {
123 String s = (String)obj;
124 try {
125 return Float.valueOf(s);
126 } catch(NumberFormatException e) {}
127 }
128 return obj;
129 }
130 };
131
132 private static final ArgConverter ARG_LONG = new ArgConverter() {
133 public Object convert(Object obj) {
134 if( obj instanceof LuaNumber ) {
135 LuaNumber ln = (LuaNumber)obj;
136 long i = (long)ln.n;
137 if( i == ln.n )
138 return Long.valueOf(i);
139 }
140 else if( obj instanceof String ) {
141 String s = (String)obj;
142 try {
143 return Long.valueOf(s);
144 } catch(NumberFormatException e) {}
145 }
146 return obj;
147 }
148 };
149
150 private static final ArgConverter ARG_INTEGER = new ArgConverter() {
151 public Object convert(Object obj) {
152 if( obj instanceof LuaNumber ) {
153 LuaNumber ln = (LuaNumber)obj;
154 int i = (int)ln.n;
155 if( i == ln.n )
156 return Integer.valueOf(i);
157 }
158 else if( obj instanceof String ) {
159 String s = (String)obj;
160 try {
161 return Integer.valueOf(s);
162 } catch(NumberFormatException e) {}
163 }
164 return obj;
165 }
166 };
167
168 private static final ArgConverter ARG_SHORT = new ArgConverter() {
169 public Object convert(Object obj) {
170 if( obj instanceof LuaNumber ) {
171 LuaNumber ln = (LuaNumber)obj;
172 short i = (short)ln.n;
173 if( i == ln.n )
174 return Short.valueOf(i);
175 }
176 else if( obj instanceof String ) {
177 String s = (String)obj;
178 try {
179 return Short.valueOf(s);
180 } catch(NumberFormatException e) {}
181 }
182 return obj;
183 }
184 };
185
186 private static ArgConverter[] getArgConverters(Method m) {
187 Class<?>[] paramTypes = m.getParameterTypes();
188 ArgConverter[] a = new ArgConverter[paramTypes.length];
189 for( int i=0; i<a.length; i++ ) {
190 a[i] = getArgConverter(paramTypes[i]);
191 }
192 return a;
193 }
194
195 private static ArgConverter getArgConverter(Class<?> cls) {
196 if( cls == Double.TYPE || cls.equals(Double.class) )
197 return ARG_DOUBLE;
198 if( cls == Float.TYPE || cls.equals(Float.class) )
199 return ARG_FLOAT;
200 if( cls == Long.TYPE || cls.equals(Long.class) )
201 return ARG_LONG;
202 if( cls == Integer.TYPE || cls.equals(Integer.class) )
203 return ARG_INTEGER;
204 if( cls == Short.TYPE || cls.equals(Short.class) )
205 return ARG_SHORT;
206 return ARG_SAME;
207 }
208
209 }