/* Subtype.java Copyright 2003, Bil Lewis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.lambda.Debugger; // Subtype.java /* */ import java.io.*; import java.util.*; import java.lang.reflect.*; public class Subtype { public static void overload(Subtype s) {} public static void overload(Object o) {} public static Method getDeclaredMethod(Class objClass, String methodName, Class[] argClasses) throws NoSuchMethodException { Method[] methods = objClass.getMethods(); int len = methods.length; ArrayList possibleMethods = new ArrayList(); for (int i = 0; i < len; i++) { if (argsMatch(methods[i], methodName, argClasses)) possibleMethods.add(methods[i]); } if (possibleMethods.size() == 0) throw new NoSuchMethodException(); if (possibleMethods.size() > 1) {System.out.println("Multiple Matches: " + possibleMethods);} return((Method)possibleMethods.get(0)); } public static boolean argsMatch(Method method, String name, Class[] argClasses) { Class[] parameters = method.getParameterTypes(); int len = parameters.length; if (!name.equals(method.getName())) return false; if (parameters.length != argClasses.length) return false; for (int i = 0; i < len; i++) { if (!subtype(argClasses[i], parameters[i])) return false; } return true; } // Does not deal with sub == short, char, byte, long, float double, boolean public static boolean subtype(Class sub, Class sup) { if (sub == sup) return true; if (sub == null) { if ((sup != int.class) && (sup != short.class) && (sup != byte.class) && (sup != char.class) && (sup != long.class) && (sup != double.class) && (sup != boolean.class) && (sup != float.class)) return true; else return false; } if (sup == null) return false; Class[] interfaces = sub.getInterfaces(); int len = interfaces.length; for (int i = 0; i < len; i++) { if (subinterface(interfaces[i], sup)) return true; } return subclass(sub, sup); } private static boolean subinterface(Class sub, Class sup) { if (sub == sup) return true; if (sup == null) return false; Class[] interfaces = sub.getInterfaces(); int len = interfaces.length; for (int i = 0; i < len; i++) { if (subinterface(interfaces[i], sup)) return true; } return false; } private static boolean subclass(Class sub, Class sup) { if (sub == null) return false; Class directSup = sub.getSuperclass(); if (sup == directSup) return true; return subclass(directSup, sup); } private static Method test(Class objClass, String methodName, Class[] argClasses, Class[] argClassesSub) { Method method, methodActual = null; try {methodActual = objClass.getDeclaredMethod(methodName, argClasses);} catch (NoSuchMethodException e) { System.out.println("No such method: " + objClass + "." + methodName + "( " + argClasses + ")"); } try {method = Subtype.getDeclaredMethod(objClass, methodName, argClassesSub);} catch (NoSuchMethodException e) { System.out.println("Didn't find method: " + objClass + "." + methodName + "( " + argClassesSub + ")"); return null; } if (!method.equals(methodActual)) System.out.println("Different method: " +method + " " + methodActual); return method; } // C1 is-a C1, C1 is-a C2, C1 isn't-a C2, C1 is-a I1, C1 isn't-a I1, I1 is-a I2, I1 isn't-a I2 public static void main(String[] argv) { /* System.out.println("Subtype is-a Subtype (true): " + subtype(Subtype.class, Subtype.class)); System.out.println("Subtype is-a Object (true): " + subtype(Subtype.class, Object.class)); System.out.println("Object is-a Subtype (false): " + subtype(Object.class, Subtype.class)); System.out.println("Vector is-a Subtype (false): " + subtype(Vector.class, Subtype.class)); System.out.println("Subtype is-a Vector (false): " + subtype(Subtype.class, Vector.class)); System.out.println("Vector is-a Object (true): " + subtype(Vector.class, Object.class)); System.out.println("Vector is-a Collection (true): " + subtype(Vector.class, Collection.class)); System.out.println("Collection is-a Vector (false): " + subtype(Collection.class, Vector.class)); System.out.println("Collection is-a AbstractList (false): " + subtype(Collection.class, AbstractList.class)); System.out.println("AbstractList is-a Collection (true): " + subtype(AbstractList.class, Collection.class)); */ short s = 0; long l = 0; char c = 0; byte b = 0; ArrayList v = new ArrayList(); v.add(v); v.add(v); v.add(1, v); v.add(s, v); // v.add(l, v); v.add(c, v); v.add(b, v); Class[] classes; Class[] classesActual; Method method; classesActual = new Class[1]; classesActual[0] = Subtype.class; classes = new Class[1]; classes[0] = Object.class; method = test(ArrayList.class, "add", classes, classes); System.out.println("ArrayList.add(Object) \t=> <ArrayList_1>.add(<Object_1>): " + method); method = test(ArrayList.class, "add", classes, classesActual); System.out.println("ArrayList.add(Object) \t=> <ArrayList_1>.add(<Subtype_1>): " + method); classesActual[0] = Object.class; method = test(Subtype.class, "overload", classes, classesActual); System.out.println("Subtype.overload(Object) \t=> <Subtype_1>.overload(<Object_1>): " + method); classesActual[0] = Subtype.class; method = test(Subtype.class, "overload", classes, classesActual); System.out.println("Subtype.overload(Subtype) \t=> <Subtype_1>.overload(<Subtype_1>): " + method); classesActual = new Class[2]; classesActual[0] = int.class; classesActual[1] = Subtype.class; classes = new Class[2]; classes[0] = int.class; classes[1] = Object.class; method = test(ArrayList.class, "add", classes, classes); System.out.println("ArrayList.add(int, Object) \t=> <ArrayList_1>.add(1, <Object_1>): " + method); method = test(ArrayList.class, "add", classes, classesActual); System.out.println("ArrayList.add(int, Object) \t=> <ArrayList_1>.add(1, <Subtype_1>): " + method); /* classesActual[1] = short.class; method = test(ArrayList.class, "add", classes, classesActual); System.out.println("ArrayList.add(int, Object) \t=> <ArrayList_1>.add(1, (s)1)X: " + method); classesActual[1] = Object.class; classesActual[0] = short.class; method = test(ArrayList.class, "add", classes, classesActual); System.out.println("ArrayList.add(int, Object) \t=> <ArrayList_1>.add((s)1, <Object_1>): " + method); */ classesActual[1] = Object.class; classesActual[0] = null; method = test(ArrayList.class, "add", classes, classesActual); System.out.println("ArrayList.add(int, Object) \t=> <ArrayList_1>.add(null, <Object_1>) X: " + method); classesActual[1] = null; classesActual[0] = int.class; method = test(ArrayList.class, "add", classes, classesActual); System.out.println("ArrayList.add(int, Object) \t=> <ArrayList_1>.add(1, null): " + method); } }