How to search for Java API methods by type signature? -


are there open-source tools available support searching java methods set of parameter types , return type?

as example, i'm looking method generate hash code array of ints. search method takes int[] parameter , returns int:

int[] -> int 

yielding

java.util.arrays#hashcode(int[]) ... 

or may want find method takes string, , character replace, , character replace with. search matching method:

string, char, char -> string 

yielding

java.lang.string#replace(char, char) ... 

ideally i'd java equivalent haskell's hoogle, supports searching functions type signature.

i'd expect tool to:

  • ignore order of parameters
  • include methods accept 'wider' types parameters (e.g. superclasses)
  • include methods return 'narrower' types return values (e.g. subclasses)
  • treat 'self' value parameter instance methods (e.g. 'string -> int' include string#hashcode)

i'm aware many ides support searching methods take or return given type, haven't yet seen tool narrow search combination of parameter types and return type.

solution comments:

  1. ignoring order, permutation of parameters tested till match of given function found
  2. primitive types interchangeable (eg integer.class = integer.type)
  3. checks wider parameters
  4. return types can narrower
  5. self treated first of arguments findmethod method

this output of program:

int[] -> integer     public native int java.lang.object.hashcode()     public static native int java.lang.reflect.array.getlength(java.lang.object) throws java.lang.illegalargumentexception     public static int java.util.arrays.hashcode(int[])     public static native int java.lang.system.identityhashcode(java.lang.object)  string, character, character -> string     public java.lang.string java.lang.string.replace(char,char)  string -> integer     public int java.lang.string.hashcode()     public int java.lang.string.length()     public static native int java.lang.reflect.array.getlength(java.lang.object) throws java.lang.illegalargumentexception     public static java.lang.integer java.lang.integer.decode(java.lang.string) throws java.lang.numberformatexception     public static java.lang.integer java.lang.integer.valueof(java.lang.string) throws java.lang.numberformatexception     public static int java.lang.integer.parseint(java.lang.string) throws java.lang.numberformatexception     public static java.lang.integer java.lang.integer.getinteger(java.lang.string)     public static native int java.lang.system.identityhashcode(java.lang.object)  list -> void     public abstract void java.util.list.clear()     public static void java.util.concurrent.locks.locksupport.park(java.lang.object)     public static void java.util.collections.reverse(java.util.list)     public static void java.util.collections.shuffle(java.util.list)     public static void java.util.collections.sort(java.util.list) 

the code:

public class methodmatcher {      public static void main(string... args) throws exception {          // load classes (could list of classes          // search from)..         //        string pathtojar = "/usr/lib/jvm/java-6-sun-1.6.0.22/jre/lib/rt.jar";         string pathtojar = "c:\\program files\\java\\jdk1.6.0_20\\jre\\lib\\rt.jar";          methodmatcher m = new methodmatcher(pathtojar,                  "java.io", "java.lang", "java.math", "java.net",                  "java.nio", "java.text", "java.util");          // print examples         m.printexamplesearch(integer.class, new int[0].getclass());         m.printexamplesearch(string.class, string.class, character.class, character.class);         m.printexamplesearch(integer.class, string.class);         m.printexamplesearch(void.class, list.class);     }      public void printexamplesearch(class<?> returntype, class<?>... arguments) {          (int = 0; < arguments.length; i++)             system.out.print((i == 0 ? "":", ") + arguments[i].getsimplename());          system.out.println(" -> " + returntype.getsimplename());          set<method> methods = findmethods(returntype, arguments);          (method method : methods)             system.out.println("\t" + method);          system.out.println();     }        private final list<methodfinder> klasses;      public methodmatcher(string jarfile, string... allowedpackages)      throws ioexception, classnotfoundexception {          klasses = loadclasses(jarfile, allowedpackages);     }      /**      * finds set of methods      * @param returntype return type      * @param arguments arguments (in order)      * @return set of methods      */     public set<method> findmethods(class<?> returntype,             class<?>... arguments) {          set<method> methods = new linkedhashset<method>();          if (arguments.length > 0) {             methodfinder instance = new methodfinder(arguments[0]);              class<?>[] rest = new class<?>[arguments.length - 1];             system.arraycopy(arguments, 1, rest, 0, rest.length);              methods.addall(instance.findinstancemethods(returntype, rest));         }         else {             (methodfinder k : klasses)                 methods.addall(k.findinstancemethods(returntype, arguments));         }          (methodfinder k : klasses)             methods.addall(k.findstaticmethods(returntype, arguments));          return methods;     }      /**      * method finder class      */     static class methodfinder {          public final class<?> klass;          /**          * constructs method finder (doh)          * @param klass class          */         public methodfinder(class<?> klass) {             this.klass = klass;         }          /**          * finds instance method matches          * @param returntype return type          * @param arguments arguments (in order)          * @return          */         public list<method> findinstancemethods(class<?> returntype,                  class<?>... arguments) {              list<method> matches = new linkedlist<method>();              (method method : klass.getmethods()) {                 if ((method.getmodifiers() & modifier.static) == 0)                      if (testmethod(method, returntype, arguments))                         matches.add(method);             }              return matches;                 }          /**          * finds static method matches          * @param returntype return type          * @param arguments arguments (in order)          * @return          */         public list<method> findstaticmethods(class<?> returntype,                 class<?>... arguments) {              list<method> matches = new linkedlist<method>();              (method method : klass.getmethods())                  if ((method.getmodifiers() & modifier.static) != 0)                      if (testmethod(method, returntype, arguments))                         matches.add(method);              return matches;                 }          /**          * tests method if match          * @param method method test          * @param returntype return type          * @param arguments arguments (in order)          * @return true if matches          */         private boolean testmethod(method method,                  class<?> returntype,                  class<?>... arguments) {              boolean returntypeisok = false;             (class<?> ic : getinterchangable(returntype))                 if (ic.isassignablefrom(method.getreturntype()))                     returntypeisok = true;              if (!returntypeisok)                 return false;              class<?>[] methodarguments = method.getparametertypes();              if (methodarguments.length != arguments.length)                 return false;              if (methodarguments.length == 0) {                 return true;             }             else {                 permutations permutations = new permutations(arguments);                  outer: (class<?>[] permutation : permutations) {                     (int = 0; < methodarguments.length; i++) {                          boolean canassign = false;                         (class<?> ic : getinterchangable(permutation[i]))                              if (methodarguments[i].isassignablefrom(ic))                                 canassign = true;                          if (!canassign)                             continue outer;                     }                     return true;                 }                  return false;             }         }          /**          * returns autoboxing types          * @param type type autobox :)          * @return list of types          */         private static class<?>[] getinterchangable(class<?> type) {              if (type == boolean.class || type == boolean.type)                 return new class<?>[] { boolean.class, boolean.type };             if (type == character.class || type == character.type)                 return new class<?>[] { character.class, character.type };             if (type == short.class || type == short.type)                 return new class<?>[] { short.class, short.type };             if (type == integer.class || type == integer.type)                 return new class<?>[] { integer.class, integer.type };             if (type == float.class || type == float.type)                 return new class<?>[] { float.class, float.type };             if (type == double.class || type == double.type)                 return new class<?>[] { double.class, double.type };             if (type == void.class || type == void.type)                 return new class<?>[] { void.class, void.type };              return new class<?>[] { type };         }           /**          * creates permutation list of different combinations          */         @suppresswarnings("serial")         private class permutations extends linkedlist<class<?>[]> {              /**              * creates permutation list              * @param list list permutated              */             public permutations(class<?>[] list) {                 permutate(new linkedlist<class<?>>(arrays.aslist(list)),                         new linkedlist<class<?>>());             }              // ugly, there better ways of doing this...             private void permutate(list<class<?>> tail, list<class<?>> choosen) {                  if (tail.isempty()) {                     add(choosen.toarray(new class<?>[0]));                     return;                 }                  listiterator<class<?>> = tail.listiterator();                  while (it.hasnext()) {                      class<?> current = it.next();                      choosen.add(current);                     it.remove();                      permutate(new linkedlist<class<?>>(tail), choosen);                      choosen.remove(current);                     it.add(current);                 }             }         }     }      /**      * hack read classes allowed packages      * @param jarfile jar file read      * @param allowedpackages allowed packages      * @return list of methodfinders      * @throws ioexception      * @throws classnotfoundexception      */     private static list<methodfinder> loadclasses(             string jarfile,              string... allowedpackages) throws ioexception, classnotfoundexception {          list<methodfinder> klasses = new linkedlist<methodfinder>();          jarfile file = new jarfile(jarfile);         try {             enumeration<jarentry> enumerator = file.entries();              while (enumerator.hasmoreelements()) {                  string name = enumerator.nextelement().getname();                  if (!name.endswith(".class"))                      continue;                  name = name.substring(0, name.length() - 6).replace('/', '.');                  boolean allowed = false;                 (string pkg : allowedpackages)                     allowed |= name.startswith(pkg);                  if (allowed)                     klasses.add(new methodfinder(class.forname(name)));             }         }          {             if (file != null)                 file.close();         }          return klasses;     } } 

Comments

Popular posts from this blog

android - Spacing between the stars of a rating bar? -

html - Instapaper-like algorithm -

c# - How to execute a particular part of code asynchronously in a class -