package org.seasar.tapestry.listener;

import java.lang.reflect.Method;

import org.apache.tapestry.ApplicationRuntimeException;
import org.apache.tapestry.IActionListener;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.IRequestCycle;

/**
 * @author Masataka Kurihara (Gluegent, Inc.)
 */
public class ComponentMethodActionListener implements IActionListener {

    private static Class[] ARG_TYPES = new Class[] { IRequestCycle.class };
    
    private Object component;
    private String methodName;
    private Method method;
    
    public ComponentMethodActionListener(Object component, String methodName) {
        if((component == null) || (methodName == null)) {
            throw new IllegalArgumentException();
        }
        this.component = component;
        this.methodName = methodName;
    }
    
    private void handleException(Exception e) {
        if(e instanceof RuntimeException) {
            throw (RuntimeException)e;
        } else {
            throw new ApplicationRuntimeException(e); 
        }
    }
    
    private Method getSuitableMethod() {
        if(method == null) {
            Class clazz = component.getClass();
            try {
                method = clazz.getMethod(methodName, ARG_TYPES);
            } catch (Exception e) {
                handleException(e);
            }
        }
        return method;
    }
    
    private void invoke(Object[] args) {
        try {
            Method m = getSuitableMethod();
            m.invoke(component, args);
        } catch (Exception e) {
            handleException(e);
        } 
    }
    
    public void actionTriggered(IComponent component, IRequestCycle cycle) {
        invoke(new Object[] { cycle });
    }
    
}
