KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > python > core > PyReflectedFunction


1 // Copyright (c) Corporation for National Research Initiatives
2
package org.python.core;
3
4 import java.lang.reflect.Method JavaDoc;
5 import java.lang.reflect.Modifier JavaDoc;
6 import java.util.Arrays JavaDoc;
7 import java.util.Hashtable JavaDoc;
8 import java.util.Enumeration JavaDoc;
9
10
11 public class PyReflectedFunction extends PyObject
12 {
13     public String JavaDoc __name__;
14     public PyObject __doc__ = Py.None;
15     public ReflectedArgs[] argslist;
16     public int nargs;
17
18     public PyReflectedFunction(String JavaDoc name) {
19         __name__ = name;
20         argslist = new ReflectedArgs[1];
21         nargs = 0;
22     }
23
24     public PyReflectedFunction(Method JavaDoc method) {
25         this(method.getName());
26         addMethod(method);
27     }
28
29     public PyObject _doget(PyObject container) {
30         return _doget(container, null);
31     }
32
33     public PyObject _doget(PyObject container, PyObject wherefound) {
34         if (container == null)
35             return this;
36         return new PyMethod(container, this, wherefound);
37     }
38
39     public boolean _doset(PyObject container) {
40         throw Py.TypeError("java function not settable: "+__name__);
41     }
42
43     private ReflectedArgs makeArgs(Method JavaDoc m) {
44         return new ReflectedArgs(m, m.getParameterTypes(),
45                                  m.getDeclaringClass(),
46                                  Modifier.isStatic(m.getModifiers()));
47     }
48
49     public PyReflectedFunction copy() {
50         PyReflectedFunction func = new PyReflectedFunction(__name__);
51         func.__doc__ = __doc__;
52         func.nargs = nargs;
53         func.argslist = new ReflectedArgs[nargs];
54         System.arraycopy(argslist, 0, func.argslist, 0, nargs);
55         return func;
56     }
57
58     public boolean handles(Method JavaDoc method) {
59         return handles(makeArgs(method));
60     }
61
62     protected boolean handles(ReflectedArgs args) {
63         ReflectedArgs[] argsl = argslist;
64         int n = nargs;
65         for(int i=0; i<n; i++) {
66             int cmp = args.compareTo(argsl[i]);
67             if (cmp == 0)
68                 return true;
69             if (cmp == +1)
70                 return false;
71         }
72         return false;
73     }
74
75     public void addMethod(Method JavaDoc m) {
76         int mods = m.getModifiers();
77         // Only add public methods unless we're overriding
78
if (!Modifier.isPublic(mods) && !JavaAccessibility.accessIsMutable())
79             return;
80         addArgs(makeArgs(m));
81     }
82
83     protected void addArgs(ReflectedArgs args) {
84         ReflectedArgs[] argsl = argslist;
85         int n = nargs;
86         int i;
87         for(i=0; i<n; i++) {
88             int cmp = args.compareTo(argsl[i]);
89             if (cmp == 0)
90                 return;
91             if (cmp == ReflectedArgs.REPLACE) {
92                 argsl[i] = args;
93                 return;
94             }
95             if (cmp == -1)
96                 break;
97         }
98
99         int nn = n+1;
100         if (nn > argsl.length) {
101             argsl = new ReflectedArgs[nn+2];
102             System.arraycopy(argslist, 0, argsl, 0, n);
103             argslist = argsl;
104         }
105
106         for(int j=n; j>i; j--) {
107             argsl[j] = argsl[j-1];
108         }
109
110         argsl[i] = args;
111         nargs = nn;
112     }
113
114     public PyObject __call__(PyObject self, PyObject[] args,
115                              String JavaDoc[] keywords)
116     {
117         ReflectedCallData callData = new ReflectedCallData();
118         Object JavaDoc method = null;
119
120         ReflectedArgs[] argsl = argslist;
121         int n = nargs;
122         for (int i=0; i<n; i++) {
123             ReflectedArgs rargs = argsl[i];
124             //System.err.println(rargs.toString());
125
if (rargs.matches(self, args, keywords, callData)) {
126                 method = rargs.data;
127                 break;
128             }
129         }
130         if (method == null) {
131             throwError(callData.errArg, args.length, self != null,
132                        keywords.length != 0);
133         }
134
135         Object JavaDoc cself = callData.self;
136         Method JavaDoc m = (Method JavaDoc)method;
137         // Check to see if we should be using a super__ method instead
138
// This is probably a bit inefficient...
139
if (self == null && cself != null && cself instanceof PyProxy &&
140                    !__name__.startsWith("super__")) {
141             PyInstance iself = ((PyProxy)cself)._getPyInstance();
142             if (argslist[0].declaringClass != iself.instclass.proxyClass) {
143                 String JavaDoc mname = ("super__"+__name__);
144                 // xxx experimental
145
Method JavaDoc[] super__methods = (Method JavaDoc[])iself.instclass.super__methods.get(mname);
146                 if (super__methods != null) {
147                     Class JavaDoc[] msig = m.getParameterTypes();
148                     for (int i=0; i<super__methods.length;i++) {
149                         if (java.util.Arrays.equals(msig,super__methods[i].getParameterTypes())) {
150                             m = super__methods[i];
151                             break;
152                         }
153                     }
154                 }
155                 /* xxx this way it is slow!
156                 Method super_method = null;
157                 try {
158                     super_method = cself.getClass().getMethod(mname,m.getParameterTypes());
159                 } catch(NoSuchMethodException e) { // ??? more stuff to ignore?
160                 }
161                 if (super_method != null) {
162                     m = super_method;
163                 }*/

164                 /* xxx original
165                 PyJavaClass jc = PyJavaClass.lookup(iself.__class__.proxyClass);
166                 PyObject super__ = jc.__findattr__(mname.intern());
167                 if (super__ != null) {
168                     return super__.__call__(self, args, keywords);
169                 }*/

170             }
171         }
172         try {
173
174             Object JavaDoc o = m.invoke(cself, callData.getArgsArray());
175             return Py.java2py(o);
176         } catch (Throwable JavaDoc t) {
177             throw Py.JavaError(t);
178         }
179     }
180
181     public PyObject __call__(PyObject[] args, String JavaDoc[] keywords) {
182         return __call__(null, args, keywords);
183     }
184
185     // A bunch of code to make error handling prettier
186

187
188     protected void throwError(String JavaDoc message) {
189         throw Py.TypeError(__name__+"(): "+message);
190     }
191
192     private static void addRange(StringBuffer JavaDoc buf, int min, int max,
193                                  String JavaDoc sep)
194     {
195         if (buf.length() > 0) {
196             buf.append(sep);
197         }
198         if (min < max) {
199             buf.append(Integer.toString(min)+"-"+max);
200         } else {
201             buf.append(min);
202         }
203     }
204
205
206     protected void throwArgCountError(int nArgs, boolean self) {
207         // Assume no argument lengths greater than 40...
208
boolean[] legalArgs = new boolean[40];
209         int maxArgs = -1;
210         int minArgs = 40;
211
212         ReflectedArgs[] argsl = argslist;
213         int n = nargs;
214         for (int i=0; i<n; i++) {
215             ReflectedArgs rargs = argsl[i];
216
217             int l = rargs.args.length;
218             if (!self && !rargs.isStatic) {
219                 l += 1;
220             }
221
222             legalArgs[l] = true;
223             if (l > maxArgs)
224                 maxArgs = l;
225             if (l < minArgs)
226                 minArgs = l;
227         }
228
229         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
230
231         int startRange = minArgs;
232         int a = minArgs+1;
233         while (a < maxArgs) {
234             if (legalArgs[a]) {
235                 a++;
236                 continue;
237             } else {
238                 addRange(buf, startRange, a-1, ", ");
239                 a++;
240                 while (a <= maxArgs) {
241                     if (legalArgs[a]) {
242                         startRange = a;
243                         break;
244                     }
245                     a++;
246                 }
247             }
248         }
249         addRange(buf, startRange, maxArgs, " or ");
250         throwError("expected "+buf+" args; got "+nArgs);
251     }
252
253     private static String JavaDoc ordinal(int n) {
254         switch(n+1) {
255         case 0:
256             return "self";
257         case 1:
258             return "1st";
259         case 2:
260             return "2nd";
261         case 3:
262             return "3rd";
263         default:
264             return Integer.toString(n+1)+"th";
265         }
266     }
267
268     private static String JavaDoc niceName(Class JavaDoc arg) {
269         if (arg == String JavaDoc.class || arg == PyString.class) {
270             return "String";
271         }
272         if (arg.isArray()) {
273             return niceName(arg.getComponentType())+"[]";
274         }
275         return arg.getName();
276     }
277
278     protected void throwBadArgError(int errArg, int nArgs, boolean self) {
279         Hashtable JavaDoc table = new Hashtable JavaDoc();
280         ReflectedArgs[] argsl = argslist;
281         int n = nargs;
282         for(int i=0; i<n; i++) {
283             ReflectedArgs rargs = argsl[i];
284             Class JavaDoc[] args = rargs.args;
285             int len = args.length;
286             /*if (!args.isStatic && !self) {
287               len = len-1;
288               }*/

289             // This check works almost all the time.
290
// I'm still a little worried about non-static methods
291
// called with an explict self...
292
if (len == nArgs) {
293                 if (errArg == -1) {
294                     table.put(rargs.declaringClass, rargs.declaringClass);
295                 } else {
296                     table.put(args[errArg], args[errArg]);
297                 }
298             }
299         }
300
301         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
302         Enumeration JavaDoc keys = table.keys();
303         while (keys.hasMoreElements()) {
304             Class JavaDoc arg = (Class JavaDoc)keys.nextElement();
305             String JavaDoc name = niceName(arg);
306             if (keys.hasMoreElements()) {
307                 buf.append(name);
308                 buf.append(", ");
309             } else {
310                 if (buf.length() > 2) {
311                     buf.setLength(buf.length()-2);
312                     buf.append(" or ");
313                 }
314                 buf.append(name);
315             }
316         }
317
318         throwError(ordinal(errArg)+" arg can't be coerced to "+buf);
319     }
320
321     protected void throwError(int errArg, int nArgs, boolean self,
322                               boolean keywords)
323     {
324         if (keywords) throwError("takes no keyword arguments");
325
326         if (errArg == -2) {
327             throwArgCountError(nArgs, self);
328         }
329
330         /*if (errArg == -1) {
331           throwBadArgError(-1);
332           throwError("bad self argument");
333           // Bad declared class
334           }*/

335
336         throwBadArgError(errArg, nArgs, self);
337     }
338
339     // Included only for debugging purposes...
340
public void printArgs() {
341         System.err.println("nargs: "+nargs);
342         for(int i=0; i<nargs; i++) {
343             ReflectedArgs args = argslist[i];
344             System.err.println(args.toString());
345         }
346     }
347
348
349     public String JavaDoc toString() {
350         //printArgs();
351
return "<java function "+__name__+" "+Py.idstr(this)+">";
352     }
353 }
354
Popular Tags