/*
 * $Id$ 
 *
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.struts.scaffold;


import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.scaffold.lang.Log;
import org.apache.commons.scaffold.lang.Tokens;
import org.apache.commons.scaffold.util.ProcessBean;
import org.apache.commons.scaffold.util.ProcessResult;
import org.apache.struts.action.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;


/**
 * Advanced framework class to instantiate and execute helper beans
 * and process the result.
 *
 * @version $Rev$ $Date$
 * @deprecated Use BizAction instead
 */
public class ProcessAction extends BaseHelperAction {


// --------------------------------------------------------- Public Methods


    /**
     * Exposes result in a servlet context.
     *
     * @param request the request being serviced
     * @param name The name to use in scope
     * @param scope The scope to set the attribute in
     * @param bean The attribute to be set
     */
    protected void exposeInScope(
            HttpServletRequest request,
            HttpServletResponse response,
            String name,
            String scope,
            Object bean) {

        if (null==scope) {
            //
        }
        else if (Tokens.REQUEST.equals(scope)) {
            request.setAttribute(name,bean);
        }
        else if (Tokens.SESSION.equals(scope)) {
            request.getSession().setAttribute(name,bean);
        }
        else if (Tokens.APPLICATION.equals(scope)) {
            servlet.getServletContext().setAttribute(name,bean);
        }
        else {
            StringBuffer sb = new StringBuffer("exposeInScope: ");
            sb.append(scope);
            sb.append(Tokens.INVALID_SCOPE);
            throw new IllegalArgumentException(sb.toString());
        }

    } // end exposeInScope


    /**
     * Save result object to servlet context.
     * <p>
     * <code>result.getData()</code> must return non-null.
     * If <code>result.getName()</code> is null, the mapping's attribute
     * (<code>mapping.getAttribute()</code>) is used instead.
     * By default, this is the <code>form-bean</code>'s name.
     * <p>
     * If data is a Collection, only the first element is stored.
     *
     * @param mapping The ActionMapping used to select this instance
     * @param request The HTTP request we are processing
     * @param result The ProcessResult we are handling
     */
    protected void checkDataSingle(
            ActionMapping mapping,
            HttpServletRequest request,
            HttpServletResponse response,
            ProcessResult result) {

        String name = result.getName();
        if (null==name) {
                // use form-bean or mapping name
            name = mapping.getAttribute();
            result.setName(name);
        }
        String scope = result.getScope();
        Object bean = result.getData();

            // if data is collection, use first element
        if (bean instanceof Collection) {
            Collection collection = (Collection) bean;
            if (collection.isEmpty()) {
                    // for lack of a better idea, get a fresh form-bean
                    // this will return null if there is not a form-bean
                    // associated with this mapping
                bean = createHelperBean(request,mapping.getName());
            }
            else {
                bean = collection.iterator().next();
            }
        }
        if (result.isExposed()) {
            exposeInScope(request,response,name,scope,bean);

        }

    } // end checkDataSingle


    /**
     * Save result object to servlet context.
     * <p>
     * <code>result.getData()</code> must return non-null.
     * If <code>result.getName()</code> is null, the mapping's attribute
     * (<code>mapping.getAttribute()</code>) is used instead.
     * By default, this is the <code>form-bean</code>'s name.
     *
     * @param mapping The ActionMapping used to select this instance
     * @param request The HTTP request we are processing
     * @param result The ProcessResult we are handling
     */
    protected void checkData(
            ActionMapping mapping,
            HttpServletRequest request,
            HttpServletResponse response,
            ProcessResult result) {

        if (result.isSingleForm()) {
            checkDataSingle(mapping,request,response,result);
        }
        else {

            String name = result.getName();
            if (null==name) {
                name = Tokens.LIST_KEY;
                result.setName(name);
            }
            String scope = result.getScope();
            Object bean = result.getData();

            if (result.isExposed()) {
                exposeInScope(request,response,name,scope,bean);
            }
        }

    } // end checkData


    /**
     * Stores informational messages for display.
     *
     * @param mapping The ActionMapping used to select this instance
     * @param request The HTTP request we are processing
     * @param processResult The ProcessResult we are handling
     */
    protected void checkMessages(
            ActionMapping mapping,
            HttpServletRequest request,
            HttpServletResponse response,
            ProcessResult processResult) {

        saveMessages(request,processResult.getMessages());

    } // end checkMessages


    /**
     * Process new dispatch advice passed by the business tier.
     * <p>
     * This is used to route control to another location besides
     * the default "success" forward registered with the controller.
     *
     * The business tier can pass back either a path or the name of
     * an ActionForward.
     * checkDispatch() will then create an ActionForward to return
     * and save it in the request under the SUCCESS token.
     * The <code>findSuccess()</code> will check for this attribute
     * before returning the controller's default.
     *
     * @param mapping The ActionMapping used to select this instance
     * @param request The HTTP request we are processing
     * @param processResult The ProcessResult we are handling
     */
    protected void checkDispatch(
            ActionMapping mapping,
            HttpServletRequest request,
            HttpServletResponse response,
            ProcessResult processResult) {

        String dispatch = processResult.getDispatch();
        ActionForward forward = null;

        if (processResult.isDispatchPath()) {
            forward = new ActionForward(dispatch);
        }
        else {
            forward = mapping.findForward(dispatch);
        }

            // Our findSuccess looks for this
        request.setAttribute(Tokens.SUCCESS,forward);

    } // end checkDispatch


// --------------------------------------------------------- Public Methods


     /**
      * Return the appropriate ActionForward for error or failure
      * conditions.
      * First checks for a FAILURE ActionForward stored in the request.
      * If an override is not found, returns the result of the
      * superclass method.
      *
      * @param mapping The ActionMapping used to select this instance
      * @param form The optional ActionForm bean for this request
      * @param request The HTTP request we are processing
      * @param response The resonse we are creating
      * @return The ActionForward representing FAILURE
      * or null if a FAILURE forward has not been specified.
      */
     protected ActionForward findFailure(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) {

            // Did someone leave us a forward?
        ActionForward forward = (ActionForward)
            request.getAttribute(Tokens.FAILURE);

        if (null==forward) {
                // No override, use default
            forward = super.findFailure(mapping,form,request,response);
        }
        else {
                // Clear advice from the request
            request.setAttribute(Tokens.FAILURE,null);
        }

        return forward;

    } // end findFailure


   /**
     * Optional extension point for pre-processing.
     * Default method does nothing.
     * To branch to another URI, return an non-null ActionForward.
     * If errors are logged (getErrors() et al),
     * default behaviour will branch to findFailure().
     *
     * @param mapping The ActionMapping used to select this instance
     * @param form The optional ActionForm bean for this request
     * @param request The HTTP request we are processing
     * @param response The resonse we are creating
     */
    protected void preProcess(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) {

            // Check for cancelled
        ActionForward forward = mapping.findForward(Tokens.CANCEL);
        if ((null!=forward) && (isCancelled(request))) {
            // Our findFailure looks for this
            request.setAttribute(Tokens.FAILURE,forward);
           // Post cancel error message
           ActionErrors errors = getErrors(request,true);
           errors.add(ActionErrors.GLOBAL_ERROR,
                new ActionError(Tokens.ERROR_CANCEL));
            return;
         }

            // Check for missing token
        forward = mapping.findForward(Tokens.GET_TOKEN);
        if ((null!=forward) && (!isTokenValid(request))) {
            // Our findFailure looks for this
            request.setAttribute(Tokens.FAILURE,forward);
           // Post token error message
           ActionErrors errors = getErrors(request,true);
           errors.add(ActionErrors.GLOBAL_ERROR,
                new ActionError(Tokens.ERROR_TOKEN));
            return;
        }
        if (null!=forward) {
            // reset to guard against duplicate request
            resetToken(request);
        }

          // Check for save token directive (do this last)
        forward = mapping.findForward(Tokens.SET_TOKEN);
        if (null!=forward) saveToken(request);


     } // end preProcess


    /**
     * Check outcome, if any; recurse if container for other outcomes.
     *
     * @param mapping The ActionMapping used to select this instance
     * @param request The HTTP request we are processing
     * @param result The ProcessResult we are handling
     */
    protected void checkOutcome(
            ActionMapping mapping,
            HttpServletRequest request,
            HttpServletResponse response,
            ProcessResult result) throws Exception {

        if (result!=null) {

            if (result.isAggregate()) {
                    // recurse for each ProcessResult in collection
                Collection collection = (Collection)
                    result.getData();
                Iterator iterator = collection.iterator();
                while (iterator.hasNext()) {
                    ProcessResult nextResult =
                        (ProcessResult) iterator.next();
                    checkOutcome(mapping,request,response,nextResult);
                }
            }

            else {
                    // call extension points for whatever is returned
                if (result.isData())
                    checkData(mapping,request,response,result);

                if (result.isMessages())
                    checkMessages(mapping,request,response,result);

                if (result.isDispatch())
                    checkDispatch(mapping,request,response,result);
            }
        }

        else {
            throw new Exception(Log.PROCESS_RESULT_NULL);
        }

    } // end checkOutcome


    /**
     * Return the appropriate ActionForward for the nominal,
     * non-error state.
     * First checks for a SUCCESS ActionForward stored in the request.
     * If an override is not found, returns the result of the
     * superclass method.
     *
     * @param mapping The ActionMapping used to select this instance
     * @param form The optional ActionForm bean for this request (if any)
     * @param request The HTTP request we are processing
     * @param response The response we are creating
     * @return The ActionForward representing SUCCESS
     * or null if a SUCCESS forward has not been specified.
     */
    protected ActionForward findSuccess(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) {

            // Did someone leave us a forward?
        ActionForward forward = (ActionForward)
            request.getAttribute(Tokens.SUCCESS);

        if (null==forward) {
                // No override, use default
            forward = super.findSuccess(mapping,form,request,response);
        }
        else {
                // Clear advice from the request
            request.setAttribute(Tokens.SUCCESS,null);
        }

        return forward;

    } // end findSuccess


    /**
     * Retrieve from session under known key
     * (<code>ProcessBean.USER_PROFILE_KEY</code>).
     * Override this approach to implement another method (e.g cookies).
     * Also revise UpdateProfile action-mapping to store changes.
     *
     * @param mapping The ActionMapping used to select this instance
     * @param form The ActionForm
     * @param request The HTTP request we are processing
     * @param response The HTTP response we are creating
     */
    protected BaseForm getUserProfile(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) {

        return(BaseForm)
            request.getSession().getAttribute(ProcessBean.USER_PROFILE_KEY);

    } // end getUserProfile


    /**
     * Assume that helpers are ProcessBeans, execute each, and
     * process outcome.
     *
     * @param mapping The ActionMapping used to select this instance
     * @param form The ActionForm
     * @param request The HTTP request we are processing
     * @param response The HTTP response we are creating
     * @param helpers The object instantiated from type given as parameter.
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet exception occurs
     */
    protected void executeLogic(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response,
            Object[] helpers) throws Exception {

            // Retrieve user profile, if any
        BaseForm userBean =
            getUserProfile(mapping,form,request,response);

        Map properties = null;
        for (int i = 0; i < helpers.length; i++) {

                // Get helper instantiated by ancestor
            ProcessBean dataBean = (ProcessBean) helpers[i];

            properties = null;
            if (null!=form) {
                if (form instanceof BaseForm) {

                    BaseForm formBean = (BaseForm) form;

                        // Merge user profile (if found)
                        // and our form into a single map
                    properties = formBean.merge(userBean);

                        // Pass up the Locale, RemoteNode, and RemoteServer (if any)
                    dataBean.setLocale(formBean.getSessionLocale());
                    dataBean.setRemoteNode(getRemoteNode(request));
                    dataBean.setRemoteServer(getRemoteServer());
                }
                else {
                    properties = PropertyUtils.describe(form);
                }
            } // end null form
            else if (null!=userBean) {
                    // if no form, but is profile, still use profile
                properties = PropertyUtils.describe(userBean);
            }

                // Execute business logic, using values from  map
            ProcessResult result = (ProcessResult)
                dataBean.execute(properties);

                // Analyze result of business logic
            checkOutcome(mapping,request,response,result);

        } // end for

    } // end executeLogic

} // end ProcessAction