package nodebox.function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import nodebox.graphics.Point;
import nodebox.node.Port;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public final class Functions {
private static final ImmutableMap<String, String> ARGUMENT_TYPE_MAPPING;
static {
ARGUMENT_TYPE_MAPPING = ImmutableMap.of(
"int", Port.TYPE_INT,
"float", Port.TYPE_FLOAT,
String.class.getName(), Port.TYPE_STRING,
Point.class.getName(), Port.TYPE_POINT
);
}
public static ImmutableList<Function.Argument> introspect(Method method) {
UniquePrefixMap prefixMap = new UniquePrefixMap();
// Find all parameters for this method.
ImmutableList.Builder<Function.Argument> builder = ImmutableList.builder();
for (Class parameter : method.getParameterTypes()) {
String type = MoreObjects.firstNonNull(ARGUMENT_TYPE_MAPPING.get(parameter.getName()), parameter.getName());
String name = prefixMap.nextWithPrefix(type);
builder.add(new Function.Argument(name, type));
}
return builder.build();
}
public static Method findMethod(Class c, String methodName) {
return findMethod(c, methodName, true);
}
public static Method findMethod(Class c, String methodName, boolean allowMultiple) {
Method[] methods = c.getMethods();
Method foundMethod = null;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
if (!allowMultiple && foundMethod != null)
throw new IllegalArgumentException("Class " + c + " has multiple methods named '" + methodName + "'.");
foundMethod = method;
if (allowMultiple)
break;
}
}
if (foundMethod != null)
return foundMethod;
throw new IllegalArgumentException("Class " + c + " does not have a method " + methodName);
}
private static class UniquePrefixMap {
final Map<String, Integer> prefixMap = new HashMap<String, Integer>();
public synchronized String nextWithPrefix(String prefix) {
int number = MoreObjects.firstNonNull(prefixMap.get(prefix), 0);
number++;
prefixMap.put(prefix, number);
return prefix + number;
}
}
}