package com.n2bb.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import com.n2bb.util.N2bbException;
import com.n2bb.web.util.WebUtil;

/**
 * Abstract superclass struts actions that does exception handling.
 * <p>
 * On error, try forwarding to:
 * <ul>
 * <li>action's <code>input<code> page
 * <li>the <code>failure</code> forward
 * <li>the <code>message</code> forward
 * <li>the <code>home</code> forward
 * </ul>
 * in that order (if no <code>input<code> defined, try <code>failure</code>, etc.).
 *
 * @author kmatsuoka
 * @version $Id: AbstractAction.java,v 1.2 2006/08/28 20:57:24 rao Exp $
 */
public abstract class AbstractAction extends Action {
    protected static Logger log = Logger.getLogger(AbstractAction.class);

    /**
     * Performs error handling for subclasses.
     */
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        try {
            return executeAction(mapping, form, request, response);
        }
        catch (Exception ex) {
            ActionErrors errors = new ActionErrors();
            ActionError error;
            if (ex instanceof N2bbException) {
                N2bbException nex = (N2bbException) ex;
                error = nex.getMessage() == null ? new ActionError(nex.getErrorCode()) :
                                        new ActionError(nex.getErrorCode(), ex.getMessage());
            }
            else {
                String id = WebUtil.getExceptionID();
                log.error(id, ex);
                error = new ActionError("error.unexpected", id);
            }
            errors.add(ActionErrors.GLOBAL_ERROR, error);
            saveErrors(request, errors);
            ActionForward forward = mapping.getInputForward();
            if (forward == null || forward.getPath() == null) {
                forward = mapping.findForward("failure");
                if (forward == null || forward.getPath() == null) {
                    forward = mapping.findForward("message");
                    if (forward == null || forward.getPath() == null) {
                        forward = mapping.findForward("home");
                    }
                }
            }
            return forward;
        }
    }

    /**
     * Subclasses implement this method instead of <code>execute</code>.
     */
    protected abstract ActionForward executeAction(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception;

    /**
     * Saves a single global message.  This will replace any other messages in the queue!
     *
     * @param messageKey    key for localized message
     * @param request       http request
     */
    protected void saveGlobalMessage(String messageKey, HttpServletRequest request) {
        ActionMessages messages = new ActionMessages();
        messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(messageKey));
        saveMessages(request, messages);
    }

    /**
     * Saves a single global message with parameters.
     * This will replace any other messages in the queue!
     *
     * @param messageKey    key for localized message
     * @param parameters    parameters for message
     * @param request       http request
     */
    protected void saveGlobalMessage(String messageKey, String[] parameters,
            HttpServletRequest request) {
        ActionMessages messages = new ActionMessages();
        messages.add(ActionMessages.GLOBAL_MESSAGE,
                new ActionMessage(messageKey, parameters));
        saveMessages(request, messages);
    }

    /** Gets integer request parameter, or null if parameter is missing or not parseable. */ 
    protected Integer getInteger(HttpServletRequest request, String parameterName) {
        try {
            return new Integer(request.getParameter(parameterName));
        }
        catch (Exception ex) {
            return null;
        }
    }

}
