001: // Copyright (c) Corporation for National Research Initiatives
002: package org.python.core;
003:
004: import java.lang.reflect.Method;
005: import java.lang.reflect.Modifier;
006: import java.util.Enumeration;
007: import java.util.Hashtable;
008:
009: public class PyReflectedFunction extends PyObject {
010: public String __name__;
011: public PyObject __doc__ = Py.None;
012: public ReflectedArgs[] argslist;
013: public int nargs;
014:
015: public PyReflectedFunction(String name) {
016: __name__ = name;
017: argslist = new ReflectedArgs[1];
018: nargs = 0;
019: }
020:
021: public PyReflectedFunction(Method method) {
022: this (method.getName());
023: addMethod(method);
024: }
025:
026: public PyObject _doget(PyObject container) {
027: return _doget(container, null);
028: }
029:
030: public PyObject _doget(PyObject container, PyObject wherefound) {
031: if (container == null)
032: return this ;
033: return new PyMethod(container, this , wherefound);
034: }
035:
036: public boolean _doset(PyObject container) {
037: throw Py.TypeError("java function not settable: " + __name__);
038: }
039:
040: private ReflectedArgs makeArgs(Method m) {
041: return new ReflectedArgs(m, m.getParameterTypes(), m
042: .getDeclaringClass(), Modifier.isStatic(m
043: .getModifiers()));
044: }
045:
046: public PyReflectedFunction copy() {
047: PyReflectedFunction func = new PyReflectedFunction(__name__);
048: func.__doc__ = __doc__;
049: func.nargs = nargs;
050: func.argslist = new ReflectedArgs[nargs];
051: System.arraycopy(argslist, 0, func.argslist, 0, nargs);
052: return func;
053: }
054:
055: public boolean handles(Method method) {
056: return handles(makeArgs(method));
057: }
058:
059: protected boolean handles(ReflectedArgs args) {
060: ReflectedArgs[] argsl = argslist;
061: int n = nargs;
062: for (int i = 0; i < n; i++) {
063: int cmp = args.compareTo(argsl[i]);
064: if (cmp == 0)
065: return true;
066: if (cmp == +1)
067: return false;
068: }
069: return false;
070: }
071:
072: public void addMethod(Method m) {
073: int mods = m.getModifiers();
074: // Only add public methods unless we're overriding
075: if (!Modifier.isPublic(mods)
076: && !JavaAccessibility.accessIsMutable())
077: return;
078: addArgs(makeArgs(m));
079: }
080:
081: protected void addArgs(ReflectedArgs args) {
082: ReflectedArgs[] argsl = argslist;
083: int n = nargs;
084: int i;
085: for (i = 0; i < n; i++) {
086: int cmp = args.compareTo(argsl[i]);
087: if (cmp == 0)
088: return;
089: if (cmp == ReflectedArgs.REPLACE) {
090: argsl[i] = args;
091: return;
092: }
093: if (cmp == -1)
094: break;
095: }
096:
097: int nn = n + 1;
098: if (nn > argsl.length) {
099: argsl = new ReflectedArgs[nn + 2];
100: System.arraycopy(argslist, 0, argsl, 0, n);
101: argslist = argsl;
102: }
103:
104: for (int j = n; j > i; j--) {
105: argsl[j] = argsl[j - 1];
106: }
107:
108: argsl[i] = args;
109: nargs = nn;
110: }
111:
112: public PyObject __call__(PyObject self, PyObject[] args,
113: String[] keywords) {
114: ReflectedCallData callData = new ReflectedCallData();
115: Object method = null;
116:
117: ReflectedArgs[] argsl = argslist;
118: int n = nargs;
119: for (int i = 0; i < n; i++) {
120: ReflectedArgs rargs = argsl[i];
121: //System.err.println(rargs.toString());
122: if (rargs.matches(self, args, keywords, callData)) {
123: method = rargs.data;
124: break;
125: }
126: }
127: if (method == null) {
128: throwError(callData.errArg, args.length, self != null,
129: keywords.length != 0);
130: }
131:
132: Object cself = callData.self;
133: Method m = (Method) method;
134: // Check to see if we should be using a super__ method instead
135: // This is probably a bit inefficient...
136: if (self == null && cself != null && cself instanceof PyProxy
137: && !__name__.startsWith("super__")) {
138: PyInstance iself = ((PyProxy) cself)._getPyInstance();
139: if (argslist[0].declaringClass != iself.instclass.proxyClass) {
140: String mname = ("super__" + __name__);
141: // xxx experimental
142: Method[] super __methods = (Method[]) iself.instclass.super __methods
143: .get(mname);
144: if (super __methods != null) {
145: Class[] msig = m.getParameterTypes();
146: for (int i = 0; i < super __methods.length; i++) {
147: if (java.util.Arrays.equals(msig,
148: super __methods[i].getParameterTypes())) {
149: m = super __methods[i];
150: break;
151: }
152: }
153: }
154: /* xxx this way it is slow!
155: Method super_method = null;
156: try {
157: super_method = cself.getClass().getMethod(mname,m.getParameterTypes());
158: } catch(NoSuchMethodException e) { // ??? more stuff to ignore?
159: }
160: if (super_method != null) {
161: m = super_method;
162: }*/
163: /* xxx original
164: PyJavaClass jc = PyJavaClass.lookup(iself.__class__.proxyClass);
165: PyObject super__ = jc.__findattr__(mname.intern());
166: if (super__ != null) {
167: return super__.__call__(self, args, keywords);
168: }*/
169: }
170: }
171: try {
172:
173: Object o = m.invoke(cself, callData.getArgsArray());
174: return Py.java2py(o);
175: } catch (Throwable t) {
176: throw Py.JavaError(t);
177: }
178: }
179:
180: public PyObject __call__(PyObject[] args, String[] keywords) {
181: return __call__(null, args, keywords);
182: }
183:
184: // A bunch of code to make error handling prettier
185:
186: protected void throwError(String message) {
187: throw Py.TypeError(__name__ + "(): " + message);
188: }
189:
190: private static void addRange(StringBuffer buf, int min, int max,
191: String sep) {
192: if (buf.length() > 0) {
193: buf.append(sep);
194: }
195: if (min < max) {
196: buf.append(Integer.toString(min) + "-" + max);
197: } else {
198: buf.append(min);
199: }
200: }
201:
202: protected void throwArgCountError(int nArgs, boolean self) {
203: // Assume no argument lengths greater than 40...
204: boolean[] legalArgs = new boolean[40];
205: int maxArgs = -1;
206: int minArgs = 40;
207:
208: ReflectedArgs[] argsl = argslist;
209: int n = nargs;
210: for (int i = 0; i < n; i++) {
211: ReflectedArgs rargs = argsl[i];
212:
213: int l = rargs.args.length;
214: if (!self && !rargs.isStatic) {
215: l += 1;
216: }
217:
218: legalArgs[l] = true;
219: if (l > maxArgs)
220: maxArgs = l;
221: if (l < minArgs)
222: minArgs = l;
223: }
224:
225: StringBuffer buf = new StringBuffer();
226:
227: int startRange = minArgs;
228: int a = minArgs + 1;
229: while (a < maxArgs) {
230: if (legalArgs[a]) {
231: a++;
232: continue;
233: } else {
234: addRange(buf, startRange, a - 1, ", ");
235: a++;
236: while (a <= maxArgs) {
237: if (legalArgs[a]) {
238: startRange = a;
239: break;
240: }
241: a++;
242: }
243: }
244: }
245: addRange(buf, startRange, maxArgs, " or ");
246: throwError("expected " + buf + " args; got " + nArgs);
247: }
248:
249: private static String ordinal(int n) {
250: switch (n + 1) {
251: case 0:
252: return "self";
253: case 1:
254: return "1st";
255: case 2:
256: return "2nd";
257: case 3:
258: return "3rd";
259: default:
260: return Integer.toString(n + 1) + "th";
261: }
262: }
263:
264: private static String niceName(Class arg) {
265: if (arg == String.class || arg == PyString.class) {
266: return "String";
267: }
268: if (arg.isArray()) {
269: return niceName(arg.getComponentType()) + "[]";
270: }
271: return arg.getName();
272: }
273:
274: protected void throwBadArgError(int errArg, int nArgs, boolean self) {
275: Hashtable table = new Hashtable();
276: ReflectedArgs[] argsl = argslist;
277: int n = nargs;
278: for (int i = 0; i < n; i++) {
279: ReflectedArgs rargs = argsl[i];
280: Class[] args = rargs.args;
281: int len = args.length;
282: /*if (!args.isStatic && !self) {
283: len = len-1;
284: }*/
285: // This check works almost all the time.
286: // I'm still a little worried about non-static methods
287: // called with an explict self...
288: if (len == nArgs) {
289: if (errArg == -1) {
290: table.put(rargs.declaringClass,
291: rargs.declaringClass);
292: } else {
293: table.put(args[errArg], args[errArg]);
294: }
295: }
296: }
297:
298: StringBuffer buf = new StringBuffer();
299: Enumeration keys = table.keys();
300: while (keys.hasMoreElements()) {
301: Class arg = (Class) keys.nextElement();
302: String name = niceName(arg);
303: if (keys.hasMoreElements()) {
304: buf.append(name);
305: buf.append(", ");
306: } else {
307: if (buf.length() > 2) {
308: buf.setLength(buf.length() - 2);
309: buf.append(" or ");
310: }
311: buf.append(name);
312: }
313: }
314:
315: throwError(ordinal(errArg) + " arg can't be coerced to " + buf);
316: }
317:
318: protected void throwError(int errArg, int nArgs, boolean self,
319: boolean keywords) {
320: if (keywords)
321: throwError("takes no keyword arguments");
322:
323: if (errArg == -2) {
324: throwArgCountError(nArgs, self);
325: }
326:
327: /*if (errArg == -1) {
328: throwBadArgError(-1);
329: throwError("bad self argument");
330: // Bad declared class
331: }*/
332:
333: throwBadArgError(errArg, nArgs, self);
334: }
335:
336: // Included only for debugging purposes...
337: public void printArgs() {
338: System.err.println("nargs: " + nargs);
339: for (int i = 0; i < nargs; i++) {
340: ReflectedArgs args = argslist[i];
341: System.err.println(args.toString());
342: }
343: }
344:
345: public String toString() {
346: //printArgs();
347: return "<java function " + __name__ + " " + Py.idstr(this )
348: + ">";
349: }
350: }
|