Mercurial Hosting > luan
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 |