comparison src/luan/LuaJavaFunction.java @ 47:659c7139e903

better conversion git-svn-id: https://luan-java.googlecode.com/svn/trunk@48 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Thu, 27 Dec 2012 04:36:44 +0000
parents a443637829c1
children
comparison
equal deleted inserted replaced
46:a443637829c1 47:659c7139e903
2 2
3 import java.lang.reflect.Array; 3 import java.lang.reflect.Array;
4 import java.lang.reflect.Method; 4 import java.lang.reflect.Method;
5 import java.lang.reflect.Constructor; 5 import java.lang.reflect.Constructor;
6 import java.lang.reflect.InvocationTargetException; 6 import java.lang.reflect.InvocationTargetException;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
7 10
8 11
9 public final class LuaJavaFunction extends LuaFunction { 12 public final class LuaJavaFunction extends LuaFunction {
10 private final JavaMethod method; 13 private final JavaMethod method;
11 private final Object obj; 14 private final Object obj;
43 @Override public Object[] call(LuaState lua,Object[] args) throws LuaException { 46 @Override public Object[] call(LuaState lua,Object[] args) throws LuaException {
44 args = fixArgs(lua,args); 47 args = fixArgs(lua,args);
45 Object rtn; 48 Object rtn;
46 try { 49 try {
47 rtn = method.invoke(obj,args); 50 rtn = method.invoke(obj,args);
51 } catch(IllegalArgumentException e) {
52 checkArgs(lua,args);
53 throw e;
48 } catch(IllegalAccessException e) { 54 } catch(IllegalAccessException e) {
49 throw new RuntimeException(e); 55 throw new RuntimeException(e);
50 } catch(InvocationTargetException e) { 56 } catch(InvocationTargetException e) {
51 Throwable cause = e.getCause(); 57 Throwable cause = e.getCause();
52 if( cause instanceof Error ) 58 if( cause instanceof Error )
60 throw new RuntimeException(e); 66 throw new RuntimeException(e);
61 } 67 }
62 return rtnConverter.convert(rtn); 68 return rtnConverter.convert(rtn);
63 } 69 }
64 70
71 private void checkArgs(LuaState lua,Object[] args) throws LuaException {
72 Class<?>[] a = getParameterTypes();
73 for( int i=0; i<a.length; i++ ) {
74 if( !a[i].isInstance(args[i]) ) {
75 String got = args[i].getClass().getName();
76 String expected = a[i].getName();
77 if( !takesLuaState )
78 i++;
79 throw new LuaException(lua,LuaElement.JAVA,"bad argument #"+i+" ("+expected+" expected, got "+got+")");
80 }
81 }
82 }
83
65 private Object[] fixArgs(LuaState lua,Object[] args) { 84 private Object[] fixArgs(LuaState lua,Object[] args) {
66 int n = argConverters.length; 85 int n = argConverters.length;
67 Object[] rtn; 86 Object[] rtn;
68 int start = 0; 87 int start = 0;
69 if( !takesLuaState && varArgCls==null && args.length == n ) { 88 if( !takesLuaState && varArgCls==null && args.length == n ) {
123 } 142 }
124 }; 143 };
125 144
126 private static final Object[] NULL_RTN = new Object[1]; 145 private static final Object[] NULL_RTN = new Object[1];
127 146
147 private static final RtnConverter RTN_NUMBER_ARRAY = new RtnConverter() {
148 public Object[] convert(Object obj) {
149 if( obj == null )
150 return NULL_RTN;
151 Object[] rtn = new Object[Array.getLength(obj)];
152 for( int i=0; i<rtn.length; i++ ) {
153 rtn[i] = Array.get(obj,i);
154 }
155 return rtn;
156 }
157 };
158
128 private static RtnConverter getRtnConverter(JavaMethod m) { 159 private static RtnConverter getRtnConverter(JavaMethod m) {
129 Class<?> rtnType = m.getReturnType(); 160 Class<?> rtnType = m.getReturnType();
130 if( rtnType == Void.TYPE ) 161 if( rtnType == Void.TYPE )
131 return RTN_EMPTY; 162 return RTN_EMPTY;
132 if( rtnType.isArray() ) { 163 if( rtnType.isArray() ) {
164 rtnType = rtnType.getComponentType();
165 if( isNumber(rtnType) )
166 return RTN_NUMBER_ARRAY;
133 return RTN_ARRAY; 167 return RTN_ARRAY;
134 } 168 }
135 return RTN_ONE; 169 return RTN_ONE;
136 } 170 }
137 171
172 private static boolean isNumber(Class<?> rtnType) {
173 return rtnType == Byte.TYPE
174 || rtnType == Short.TYPE
175 || rtnType == Integer.TYPE
176 || rtnType == Long.TYPE
177 || rtnType == Float.TYPE
178 || rtnType == Double.TYPE
179 ;
180 }
138 181
139 private interface ArgConverter { 182 private interface ArgConverter {
140 public Object convert(Object obj); 183 public Object convert(Object obj);
141 } 184 }
142 185
143 private static final ArgConverter ARG_SAME = new ArgConverter() { 186 private static final ArgConverter ARG_SAME = new ArgConverter() {
144 public Object convert(Object obj) { 187 public Object convert(Object obj) {
188 return obj;
189 }
190 };
191
192 private static final ArgConverter ARG_DOUBLE = new ArgConverter() {
193 public Object convert(Object obj) {
194 if( obj instanceof Double )
195 return obj;
196 if( obj instanceof Number ) {
197 Number n = (Number)obj;
198 return n.doubleValue();
199 }
200 if( obj instanceof String ) {
201 String s = (String)obj;
202 try {
203 return Double.valueOf(s);
204 } catch(NumberFormatException e) {}
205 }
206 return obj;
207 }
208 };
209
210 private static final ArgConverter ARG_FLOAT = new ArgConverter() {
211 public Object convert(Object obj) {
212 if( obj instanceof Float )
213 return obj;
214 if( obj instanceof Number ) {
215 Number n = (Number)obj;
216 float r = n.floatValue();
217 if( r==n.doubleValue() )
218 return r;
219 }
220 if( obj instanceof String ) {
221 String s = (String)obj;
222 try {
223 return Float.valueOf(s);
224 } catch(NumberFormatException e) {}
225 }
226 return obj;
227 }
228 };
229
230 private static final ArgConverter ARG_LONG = new ArgConverter() {
231 public Object convert(Object obj) {
232 if( obj instanceof Long )
233 return obj;
234 if( obj instanceof Number ) {
235 Number n = (Number)obj;
236 long r = n.longValue();
237 if( r==n.doubleValue() )
238 return r;
239 }
240 else if( obj instanceof String ) {
241 String s = (String)obj;
242 try {
243 return Long.valueOf(s);
244 } catch(NumberFormatException e) {}
245 }
246 return obj;
247 }
248 };
249
250 private static final ArgConverter ARG_INTEGER = new ArgConverter() {
251 public Object convert(Object obj) {
252 if( obj instanceof Integer )
253 return obj;
254 if( obj instanceof Number ) {
255 Number n = (Number)obj;
256 int r = n.intValue();
257 if( r==n.doubleValue() )
258 return r;
259 }
260 else if( obj instanceof String ) {
261 String s = (String)obj;
262 try {
263 return Integer.valueOf(s);
264 } catch(NumberFormatException e) {}
265 }
266 return obj;
267 }
268 };
269
270 private static final ArgConverter ARG_SHORT = new ArgConverter() {
271 public Object convert(Object obj) {
272 if( obj instanceof Short )
273 return obj;
274 if( obj instanceof Number ) {
275 Number n = (Number)obj;
276 short r = n.shortValue();
277 if( r==n.doubleValue() )
278 return r;
279 }
280 else if( obj instanceof String ) {
281 String s = (String)obj;
282 try {
283 return Short.valueOf(s);
284 } catch(NumberFormatException e) {}
285 }
286 return obj;
287 }
288 };
289
290 private static final ArgConverter ARG_BYTE = new ArgConverter() {
291 public Object convert(Object obj) {
292 if( obj instanceof Byte )
293 return obj;
294 if( obj instanceof Number ) {
295 Number n = (Number)obj;
296 byte r = n.byteValue();
297 if( r==n.doubleValue() )
298 return r;
299 }
300 else if( obj instanceof String ) {
301 String s = (String)obj;
302 try {
303 return Byte.valueOf(s);
304 } catch(NumberFormatException e) {}
305 }
306 return obj;
307 }
308 };
309
310 private static final ArgConverter ARG_TABLE = new ArgConverter() {
311 public Object convert(Object obj) {
312 if( obj instanceof List ) {
313 @SuppressWarnings("unchecked")
314 List<Object> list = (List<Object>)obj;
315 return new LuaTable(list);
316 }
317 if( obj instanceof Map ) {
318 @SuppressWarnings("unchecked")
319 Map<Object,Object> map = (Map<Object,Object>)obj;
320 return new LuaTable(map);
321 }
322 if( obj instanceof Set ) {
323 @SuppressWarnings("unchecked")
324 Set<Object> set = (Set<Object>)obj;
325 return new LuaTable(set);
326 }
327 return obj;
328 }
329 };
330
331 private static final ArgConverter ARG_MAP = new ArgConverter() {
332 public Object convert(Object obj) {
333 if( obj instanceof LuaTable ) {
334 LuaTable t = (LuaTable)obj;
335 return t.asMap();
336 }
337 return obj;
338 }
339 };
340
341 private static final ArgConverter ARG_LIST = new ArgConverter() {
342 public Object convert(Object obj) {
343 if( obj instanceof LuaTable ) {
344 LuaTable t = (LuaTable)obj;
345 if( t.isList() )
346 return t.asList();
347 }
348 return obj;
349 }
350 };
351
352 private static final ArgConverter ARG_SET = new ArgConverter() {
353 public Object convert(Object obj) {
354 if( obj instanceof LuaTable ) {
355 LuaTable t = (LuaTable)obj;
356 if( t.isSet() )
357 return t.asSet();
358 }
145 return obj; 359 return obj;
146 } 360 }
147 }; 361 };
148 362
149 private static boolean takesLuaState(JavaMethod m) { 363 private static boolean takesLuaState(JavaMethod m) {
168 } 382 }
169 return a; 383 return a;
170 } 384 }
171 385
172 private static ArgConverter getArgConverter(Class<?> cls) { 386 private static ArgConverter getArgConverter(Class<?> cls) {
387 if( cls == Double.TYPE || cls.equals(Double.class) )
388 return ARG_DOUBLE;
389 if( cls == Float.TYPE || cls.equals(Float.class) )
390 return ARG_FLOAT;
391 if( cls == Long.TYPE || cls.equals(Long.class) )
392 return ARG_LONG;
393 if( cls == Integer.TYPE || cls.equals(Integer.class) )
394 return ARG_INTEGER;
395 if( cls == Short.TYPE || cls.equals(Short.class) )
396 return ARG_SHORT;
397 if( cls == Byte.TYPE || cls.equals(Byte.class) )
398 return ARG_BYTE;
399 if( cls.equals(LuaTable.class) )
400 return ARG_TABLE;
401 if( cls.equals(Map.class) )
402 return ARG_MAP;
403 if( cls.equals(List.class) )
404 return ARG_LIST;
405 if( cls.equals(Set.class) )
406 return ARG_SET;
173 return ARG_SAME; 407 return ARG_SAME;
174 } 408 }
175 409
176 410
177 411