package jp.sourceforge.glad.reflect;

import java.lang.reflect.Method;

public class MethodAccessor<T> {

    final Object target;

    final MethodAdapter<T> method;

    public MethodAccessor(Object target, String name, Class<?>... paramTypes) {
        this(target, getMethod(target.getClass(), name, paramTypes));
    }

    public MethodAccessor(Object target, Method method) {
        this(target, new MethodAdapter<T>(method));
    }

    MethodAccessor(Object target, MethodAdapter<T> method) {
        this.target = target;
        this.method = method;
    }

    static Method getMethod(
            Class<?> clazz, String name, Class<?>... paramTypes) {
        for (Class<?> c = clazz; c != Object.class; c = c.getSuperclass()) {
            try {
                return clazz.getDeclaredMethod(name, paramTypes);
            } catch (NoSuchMethodException e) {}
        }
        throw new NoSuchMethodRuntimeException(
                ReflectionUtils.methodToSimpleString(clazz, name, paramTypes));
    }

    public T invoke(Object... args) {
        method.makeAccessible();
        return method.invoke(target, args);
    }

}
