Create callback

Et voilà, a method manager, to create method, add in a list of method and to call it with String name and check if this one already existe. I don’t if it’s really optimizing but that’s work :slight_smile:

/**
* Manage creator method
*/
void setup() {
  frameRate(1);
  create_method("my_method",this, String.class, int.class);
  create_method("my_method",this, String.class, int.class); // print: create_method(): this method my_method with those classes organisation already exist
  create_method("my_method",this, String.class, int.class, float.class);
  println("method size:",method_index.size());
  for(Method_Manager mm : method_index) {
    println(mm.get_name());
    printArray(mm.get_index());
  }
}

void draw() {
  surface.setTitle(Integer.toString((int)frameRate));
  background((int)random(#000000));
  method("my_method",this,"Frames:", frameCount);
  method("my_method",this,"Frames:", frameCount, 3.4);
  //method("my_method",this,"Frames:", frameCount);
}

void my_method(final String stuff, final int num) {
  println(stuff, num);
}








/**
* Method manager to call method if this one already exist
* v 0.0.1
* 2019-2019
*/
void method(String name, PApplet pa, Object... args) {
  Method method = method_exist(name, args);
  if(method != null) {
    invoke_method(method, pa, args);
  } else {
    println("method(): no method exist for this name:",name,"or this order of arguments:");
    for(int i = 0 ; i < args.length ; i++) {
      println("[",i,"]",args[i].getClass().getName());
    } 
  }
}

Method method_exist(String name, Object... args) {
  Method method = null;
  if(method_index != null && method_index.size() > 0) {
    for(Method_Manager mm : method_index) {
      if(mm.get_name().equals(name)) {
        boolean same_is = true;
        if(args.length == mm.get_index().length) {
          for(int i = 0 ; i < args.length; i++) {
            String arg_name = translate_class_to_type_name_if_necessary(args[i]);
            if(!arg_name.equals(mm.get_index()[i])) {
              same_is = false;
              break;
            }
          }
        } else {
          same_is = false;
        }       
        if(same_is) {
          method = mm.get_method();
        }
      }
    }
  }
  return method;
}

String translate_class_to_type_name_if_necessary(Object arg) {
  String name = arg.getClass().getName();
  if(name.equals("java.lang.Byte")) {
    name = "byte";
  } else if(name.equals("java.lang.Short")) {
    name = "short";
  } else if(name.equals("java.lang.Integer")) {
    name = "int";
  } else if(name.equals("java.lang.Long")) {
    name = "long";
  } else if(name.equals("java.lang.Float")) {
    name = "float";
  } else if(name.equals("java.lang.Double")) {
    name = "double";
  } else if(name.equals("java.lang.Boolean")) {
    name = "boolean";
  } else if(name.equals("java.lang.Character")) {
    name = "char";
  }
  return name;
}

void create_method(String name, PApplet pa, Class... classes) {
  if(method_index == null) {
    method_index = new ArrayList<Method_Manager>();
  } 
  init_method(name,pa,classes);
}

ArrayList<Method_Manager> method_index ;
void init_method(String name, PApplet pa, Class... classes) { 
  // check if method already exist
  boolean create_class_is = true; 
  for(Method_Manager mm : method_index) {
    if(mm.get_name().equals(name)) {
      if(mm.get_index().length == classes.length) {
        int count_same_classes = 0;
        for(int i = 0 ; i < classes.length ; i++) {
          if(mm.get_index()[i].equals(classes[i].getCanonicalName())) {
            count_same_classes++;
          }
        }
        if(count_same_classes == classes.length) {
          create_class_is = false;
          break;
        }
      }
    }
  }
  // instantiate if necessary
  if(create_class_is) {
    Method method = get_method(name,pa,classes);
    Method_Manager method_manager = new Method_Manager(method,name,classes);
    method_index.add(method_manager);
  } else {
    println("create_method(): this method",name,"with those classes organisation already exist");
  }
}


/**
* Method manger
*/
import java.lang.reflect.Method;
class Method_Manager {
  Method method;
  String name;
  String [] index;
  Method_Manager(Method method, String name, Class... classes) {
    index = new String[classes.length];
    for(int i = 0 ; i < index.length ; i++) {
      index[i] = classes[i].getName();
    }
    this.method = method;
    this.name = name;
  }

  String [] get_index() {
    return index;
  }


  String get_name() {
    return name;
  }

  Method get_method() {
    return method;
  }
}


/**
 * refactoring of Method Reflective Invocation (v4.0)
 * Stanlepunk (2019/Apr/03)
 * Mod GoToLoop
 * https://Discourse.Processing.org/t/create-callback/9831/16
 */
static final Method get_method(String name, Object instance, Class... classes) {
  final Class<?> c = instance.getClass();
  try {
    return c.getMethod(name, classes);
  } 
  catch (final NoSuchMethodException e) {
    try {
      final Method m = c.getDeclaredMethod(name, classes);
      m.setAccessible(true);
      return m;
    }   
    catch (final NoSuchMethodException ex) {
      ex.printStackTrace();
      return null;
    }
  }
}

static final Object invoke_method(Method funct, Object instance, Object... args) {
  try {
    return funct.invoke(instance, args);
  } 
  catch (final ReflectiveOperationException e) {
    throw new RuntimeException(e);
  }
}