/*
 * $Id$
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.chain.commands;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.chain.Constants;
import org.apache.struts.chain.commands.util.ClassUtils;
import org.apache.struts.chain.contexts.ActionContext;
import org.apache.struts.config.ActionConfig;
import org.apache.struts.config.ForwardConfig;
import org.apache.struts.dispatcher.Dispatcher;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ExecuteDispatcher extends ActionCommandBase {

    private static final Log log = LogFactory.getLog(ExecuteDispatcher.class);

    /**
     * Creates the dispatcher of the specified type.
     * 
     * @param type the dispatcher class name
     * @param context the current action context
     * @return the dispatcher
     * @throws Exception if creation fails
     * @see ClassUtils#getApplicationInstance(String)
     */
    protected Dispatcher createDispatcher(String type, ActionContext context) throws Exception {
        log.info("Initializing dispatcher of type: " + type);
        return (Dispatcher) ClassUtils.getApplicationInstance(type);
    }

    public boolean execute(ActionContext context) throws Exception {
        // Skip processing if the current request is not valid
        Boolean valid = context.getFormValid();
        if ((valid == null) || !valid.booleanValue()) {
            return CONTINUE_PROCESSING;
        }

        // Skip processing if no dispatcher type specified
        String dispatcherType = getDispatcherType(context);
        if (dispatcherType == null) {
            return CONTINUE_PROCESSING;
        }

        // Obtain (or create) the dispatcher cache
        String cacheKey = Constants.DISPATCHERS_KEY + context.getModuleConfig().getPrefix();
        Map dispatchers = (Map) context.getApplicationScope().get(cacheKey);
        if (dispatchers == null) {
            dispatchers = new HashMap();
            context.getApplicationScope().put(cacheKey, dispatchers);
        }

        // Lookup (or create) the dispatch instance
        Dispatcher dispatcher = null;
        synchronized (dispatchers) {
            ActionConfig actionConfig = context.getActionConfig();
            String actionType = actionConfig.getType();
            dispatcher = (Dispatcher) dispatchers.get(actionType);
            if (dispatcher == null) {
                dispatcher = createDispatcher(dispatcherType, context);
                dispatchers.put(actionType, dispatcher);
            }
        }

        // Dispatch
        Object result = dispatcher.dispatch(context);
        processDispatchResult(result, context);

        return CONTINUE_PROCESSING;
    }

    protected String getDispatcherType(ActionContext context) {
        return (context != null) ? context.getActionConfig().getDispatcher() : null;
    }

    /**
     * Interprets the specified dispatch result. Subclasses should override this
     * method to provide custom result type handling. Four handlings are
     * automatically provided:
     * <ol>
     * <li><code>null</code> type means the response was handled directly,
     * and therefore no extra processing is perform</li>
     * <li>{@link ForwardConfig} type is the classical response, and will be
     * stored in the context</li>
     * <li>{@link String} type represents the name of a required forward to
     * lookup, and will be stored in the context</li>
     * <li>{@link Void} type means the method had no return signature, and
     * select the {@link Action#SUCCESS} action forward and store in the context</li>
     * </ol>
     * 
     * @param result the result value
     * @param context the current action context
     * @throws IllegalStateException if unknown result type or the forward
     *         cannot be found
     * @see ActionMapping#findRequiredForward(String)
     */
    protected void processDispatchResult(Object result, ActionContext context) {
        // Null means the response was handled directly
        if (result == null) {
            return;
        }

        // A forward is the classical response
        if (result instanceof ForwardConfig) {
            context.setForwardConfig((ForwardConfig) result);
            return;
        }

        // String represents the name of a forward
        ActionConfig actionConfig = context.getActionConfig();
        ActionMapping mapping = ((ActionMapping) actionConfig);
        if (result instanceof String) {
            context.setForwardConfig(mapping.findRequiredForward((String) result));
            return;
        }

        // Select success if no return signature
        if (result instanceof Void) {
            context.setForwardConfig(mapping.findRequiredForward(Action.SUCCESS));
            return;
        }

        // Unknown result type
        throw new IllegalStateException("Unknown dispatch return type: " + result.getClass().getName());
    }

}
