/*
 * 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.commons.chain2.base;

import org.apache.commons.chain2.CatalogFactory;
import org.apache.commons.chain2.Command;
import org.apache.commons.chain2.Context;
import org.apache.commons.chain2.Filter;
import org.apache.commons.chain2.Processing;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.WeakHashMap;

/**
 * <p>This command combines elements of the {@link LookupCommand} with the
 * {@link DispatchCommand}.  Look up a specified {@link Command} (which could
 * also be a {@link org.apache.commons.chain2.Chain}) in a
 * {@link org.apache.commons.chain2.Catalog}, and delegate execution to
 * it.  Introspection is used to lookup the appropriate method to delegate
 * execution to.  If the delegated-to {@link Command} is also a
 * {@link Filter}, its <code>postprocess()</code> method will also be invoked
 * at the appropriate time.</p>
 *
 * <p>The name of the {@link Command} can be specified either directly (via
 * the <code>name</code> property) or indirectly (via the <code>nameKey</code>
 * property).  Exactly one of these must be set.</p>
 *
 * <p>The name of the method to be called can be specified either directly
 * (via the <code>method</code> property) or indirectly (via the <code>
 * methodKey</code> property).  Exactly one of these must be set.</p>
 *
 * <p>If the <code>optional</code> property is set to <code>true</code>,
 * failure to find the specified command in the specified catalog will be
 * silently ignored.  Otherwise, a lookup failure will trigger an
 * <code>IllegalArgumentException</code>.</p>
 *
 * @param <K> the type of keys maintained by the context associated with this catalog
 * @param <V> the type of mapped values
 * @param <C> Type of the context associated with this command
 *
 * @version $Id$
 * @since Chain 1.1
 */
public class DispatchLookupCommand<K, V, C extends Context<K, V>>
    extends LookupCommand<K, V, C> implements Filter<K, V, C> {

    // -------------------------------------------------------------- Constructors

    /**
     * Create an instance with an unspecified <code>catalogFactory</code> property.
     * This property can be set later using <code>setProperty</code>, or if it is not set,
     * the static singleton instance from <code>CatalogFactory.getInstance()</code> will be used.
     */
    public DispatchLookupCommand() {  super();  }

    /**
     * Create an instance and initialize the <code>catalogFactory</code> property
     * to given <code>factory</code>.
     * @param factory The Catalog Factory.
     */
    public DispatchLookupCommand(CatalogFactory<K, V, C> factory) {
        super(factory);
    }

    // ------------------------------------------------------- Static Variables

    /**
     * The base implementation expects dispatch methods to take a <code>
     * Context</code> as their only argument.
     */
    private static final Class<?>[] DEFAULT_SIGNATURE = new Class<?>[] {Context.class};

    // ----------------------------------------------------- Instance Variables

    private final WeakHashMap<String, Method> methods = new WeakHashMap<String, Method>();

    // ------------------------------------------------------------- Properties

    private String method = null;

    private String methodKey = null;

    /**
     * Return the method name.
     * @return The method name.
     */
    public String getMethod() {
        return method;
    }

    /**
     * Return the Context key for the method name.
     * @return The Context key for the method name.
     */
    public String getMethodKey() {
        return methodKey;
    }

    /**
     * Set the method name.
     * @param method The method name.
     */
    public void setMethod(String method) {
        this.method = method;
    }

    /**
     * Set the Context key for the method name.
     * @param methodKey The Context key for the method name.
     */
    public void setMethodKey(String methodKey) {
        this.methodKey = methodKey;
    }

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

    /**
     * <p>Look up the specified command, and (if found) execute it.</p>
     *
     * @param context The context for this request
     * @return the result of executing the looked-up command's method, or
     * {@link Processing#CONTINUE} if no command is found.
     *
     * @throws DispatchException if no such {@link Command} can be found and the
     *  <code>optional</code> property is set to <code>false</code>
     */
    @Override
    public Processing execute(C context) {
        if (this.getMethod() == null && this.getMethodKey() == null) {
            throw new IllegalStateException("Neither 'method' nor 'methodKey' properties are defined");
        }

        Command<K, V, C> command = getCommand(context);

        if (command != null) {
            try {
                Method methodObject = extractMethod(command, context);
                Object obj = methodObject.invoke(command, getArguments(context));
                
                if(obj instanceof Processing) {
                    Processing result = (Processing) obj;
                    return result;
                } else {
                    return Processing.CONTINUE;
                }
            } catch (NoSuchMethodException e) {
                throw new DispatchException("Error extracting method from context", e, context, this);
            } catch (IllegalAccessException e) {
                throw new DispatchException("Error accessing method", e, context, this);
            } catch (InvocationTargetException e) {
                Throwable cause = e.getTargetException();
                throw new DispatchException("Error in reflected dispatched command", cause, context, this);
            }
        }
        return Processing.CONTINUE;
    }

    // ------------------------------------------------------ Protected Methods

    /**
     * <p>Return a <code>Class[]</code> describing the expected signature of
     * the method.  The default is a signature that just accepts the command's
     * {@link Context}.  The method can be overidden to provide a different
     * method signature.<p>
     *
     * @return the expected method signature
     */
    protected Class<?>[] getSignature() {
        return DEFAULT_SIGNATURE;
    }

    /**
     * Get the arguments to be passed into the dispatch method.
     * Default implementation simply returns the context which was passed in,
     * but subclasses could use this to wrap the context in some other type,
     * or extract key values from the context to pass in.  The length and types
     * of values returned by this must coordinate with the return value of
     * <code>getSignature()</code>
     *
     * @param context The context associated with the request
     * @return the method arguments to be used
     */
    protected Object[] getArguments(C context) {
        return new Object[] {context};
    }

    // -------------------------------------------------------- Private Methods

    /**
     * Extract the dispatch method.  The base implementation uses the
     * command's <code>method</code> property at the name of a method
     * to look up, or, if that is not defined, uses the <code>
     * methodKey</code> to lookup the method name in the context.
     *
     * @param command The commmand that contains the method to be
     *    executed.
     * @param context The context associated with this request
     * @return the dispatch method
     *
     * @throws NoSuchMethodException if no method can be found under the
     *    specified name.
     * @throws NullPointerException if no methodName can be determined
     */
    private Method extractMethod(Command<K, V, C> command, C context) throws NoSuchMethodException {
        String methodName = this.getMethod();

        if (methodName == null) {
            Object methodContextObj = context.get(getMethodKey());
            if (methodContextObj == null) {
                throw new NullPointerException("No value found in context under " + getMethodKey());
            }
            methodName = methodContextObj.toString();
        }

        Method theMethod = null;

        synchronized (methods) {
            theMethod = methods.get(methodName);

            if (theMethod == null) {
                theMethod = command.getClass().getMethod(methodName,
                                                         getSignature());
                methods.put(methodName, theMethod);
            }
        }

        return theMethod;
    }

}
