/*
 * 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.Catalog;
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.util.Map;

/**
 * <p>Look up a specified {@link Command} (which could also be a
 * {@link org.apache.commons.chain2.Chain})
 * in a {@link Catalog}, and delegate execution to it.  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>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> Context key type
 * @param <V> Context value type
 * @param <C> Type of the context associated with this command
 *
 * @version $Id$
 */
public class LookupCommand<K, V, C extends Map<K, V>> implements Filter<K, V, C> {

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

    /**
     * Create an instance, setting its <code>catalogFactory</code> property to the
     * value of <code>CatalogFactory.getInstance()</code>.
     *
     * @since Chain 1.1
     */
    public LookupCommand() {
        this(CatalogFactory.<K, V, C>getInstance());
    }

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

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

    private CatalogFactory<K, V, C> catalogFactory = null;

    /**
     * <p>Set the {@link CatalogFactory} from which lookups will be
     * performed.</p>
     *
     * @param catalogFactory The Catalog Factory.
     *
     * @since Chain 1.1
     */
    public void setCatalogFactory(CatalogFactory<K, V, C> catalogFactory) {
        this.catalogFactory = catalogFactory;
    }

    /**
     * Return the {@link CatalogFactory} from which lookups will be performed.
     * @return The Catalog factory.
     *
     * @since Chain 1.1
     */
    public CatalogFactory<K, V, C> getCatalogFactory() {
        return this.catalogFactory;
    }

    private String catalogName = null;

    /**
     * <p>Return the name of the {@link Catalog} to be searched, or
     * <code>null</code> to search the default {@link Catalog}.</p>
     * @return The Catalog name.
     */
    public String getCatalogName() {
        return this.catalogName;
    }

    /**
     * <p>Set the name of the {@link Catalog} to be searched, or
     * <code>null</code> to search the default {@link Catalog}.</p>
     *
     * @param catalogName The new {@link Catalog} name or <code>null</code>
     */
    public void setCatalogName(String catalogName) {
        this.catalogName = catalogName;
    }

    private String name = null;

    /**
     * <p>Return the name of the {@link Command} that we will look up and
     * delegate execution to.</p>
     * @return The name of the Command.
     */
    public String getName() {
        return this.name;
    }

    /**
     * <p>Set the name of the {@link Command} that we will look up and
     * delegate execution to.</p>
     *
     * @param name The new command name
     */
    public void setName(String name) {
        this.name = name;
    }

    private String nameKey = null;

    /**
     * <p>Return the context attribute key under which the {@link Command}
     * name is stored.</p>
     * @return The context key of the Command.
     */
    public String getNameKey() {
        return this.nameKey;
    }

    /**
     * <p>Set the context attribute key under which the {@link Command}
     * name is stored.</p>
     *
     * @param nameKey The new context attribute key
     */
    public void setNameKey(String nameKey) {
        this.nameKey = nameKey;
    }

    private boolean optional = false;

    /**
     * <p>Return <code>true</code> if locating the specified command
     * is optional.</p>
     * @return <code>true</code> if the Command is optional.
     */
    public boolean isOptional() {
        return this.optional;
    }

    /**
     * <p>Set the optional flag for finding the specified command.</p>
     *
     * @param optional The new optional flag
     */
    public void setOptional(boolean optional) {
        this.optional = optional;
    }

    private boolean ignoreExecuteResult = false;

    /**
     * <p>Return <code>true</code> if this command should ignore
     * the return value from executing the looked-up command.
     * Defaults to <code>false</code>, which means that the return result
     * of executing this lookup will be whatever is returned from that
     * command.</p>
     * @return <code>true</code> if result of the looked up Command
     * should be ignored.
     *
     * @since Chain 1.1
     */
    public boolean isIgnoreExecuteResult() {
        return ignoreExecuteResult;
    }

    /**
     * <p>Set the rules for whether or not this class will ignore or
     * pass through the value returned from executing the looked up
     * command.</p>
     * <p>If you are looking up a chain which may be "aborted" and
     * you do not want this class to stop chain processing, then this
     * value should be set to <code>true</code></p>
     * @param ignoreReturn <code>true</code> if result of the
     * looked up Command should be ignored.
     *
     * @since Chain 1.1
     */
    public void setIgnoreExecuteResult(boolean ignoreReturn) {
        this.ignoreExecuteResult = ignoreReturn;
    }

    private boolean ignorePostprocessResult = false;

    /**
     * <p>Return <code>true</code> if this command is a Filter and
     * should ignore the return value from executing the looked-up Filter's
     * <code>postprocess()</code> method.
     * Defaults to <code>false</code>, which means that the return result
     * of executing this lookup will be whatever is returned from that
     * Filter.</p>
     * @return <code>true</code> if result of the looked up Filter's
     * <code>postprocess()</code> method should be ignored.
     *
     * @since Chain 1.1
     */
    public boolean isIgnorePostprocessResult() {
        return ignorePostprocessResult;
    }

    /**
     * <p>Set the rules for whether or not this class will ignore or
     * pass through the value returned from executing the looked up
     * Filter's <code>postprocess()</code> method.</p>
     * <p>If you are looking up a Filter which may be "aborted" and
     * you do not want this class to stop chain processing, then this
     * value should be set to <code>true</code></p>
     * @param ignorePostprocessResult <code>true</code> if result of the
     * looked up Filter's <code>postprocess()</code> method should be ignored.
     *
     * @since Chain 1.1
     */
    public void setIgnorePostprocessResult(boolean ignorePostprocessResult) {
        this.ignorePostprocessResult = ignorePostprocessResult;
    }

    // ---------------------------------------------------------- Filter Methods

    /**
     * <p>Look up the specified command, and (if found) execute it.
     * Unless <code>ignoreExecuteResult</code> is set to <code>true</code>,
     * return the result of executing the found command.  If no command
     * is found, return {@link Processing#CONTINUE}, unless the <code>optional</code>
     * property is <code>false</code>, in which case an <code>IllegalArgumentException</code>
     * will be thrown.
     * </p>
     *
     * @param context The context for this request
     *
     * @exception IllegalArgumentException if no such {@link Command}
     *  can be found and the <code>optional</code> property is set
     *  to <code>false</code>
     * @return the result of executing the looked-up command, or
     * <code>CONTINUE</code> if no command is found or if the command
     * is found but the <code>ignoreExecuteResult</code> property of this
     * instance is <code>true</code>
     * @throws org.apache.commons.chain2.ChainException if and error occurs in the looked-up Command.
     */
    public Processing execute(C context) {
        Command<K, V, C> command = getCommand(context);
        if (command != null) {
            Processing result = command.execute(context);
            if (isIgnoreExecuteResult()) {
                return Processing.CONTINUE;
            }
            return result;
        }
        return Processing.CONTINUE;
    }


    /**
     * <p>If the executed command was itself a {@link Filter}, call the
     * <code>postprocess()</code> method of that {@link Filter} as well.</p>
     *
     * @param context The context for this request
     * @param exception Any <code>Exception</code> thrown by command execution
     *
     * @return the result of executing the <code>postprocess</code> method
     * of the looked-up command, unless <code>ignorePostprocessResult</code> is
     * <code>true</code>.  If no command is found, return <code>false</code>,
     * unless the <code>optional</code> property is <code>false</code>, in which
     * case <code>IllegalArgumentException</code> will be thrown.
     */
    public boolean postprocess(C context, Exception exception) {
        Command<K, V, C> command = getCommand(context);
        if (command != null) {
            if (command instanceof Filter) {
                boolean result = ((Filter<K, V, C>) command).postprocess(context, exception);
                return !isIgnorePostprocessResult() && result;
            }
        }
        return false;
    }

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

    /**
     * <p>Return the {@link Catalog} to look up the {@link Command} in.</p>
     *
     * @param context {@link Context} for this request
     * @return The catalog.
     * @exception IllegalArgumentException if no {@link Catalog}
     *  can be found
     *
     * @since Chain 1.2
     */
    protected Catalog<K, V, C> getCatalog(C context) {
        CatalogFactory<K, V, C> lookupFactory = this.catalogFactory;
        if (lookupFactory == null) {
            lookupFactory = CatalogFactory.getInstance();
        }

        String catalogName = getCatalogName();
        Catalog<K, V, C> catalog = null;
        if (catalogName == null) {
            // use default catalog
            catalog = lookupFactory.getCatalog();
        } else {
            catalog = lookupFactory.getCatalog(catalogName);
        }
        if (catalog == null) {
            if (catalogName == null) {
                throw new IllegalArgumentException
                    ("Cannot find default catalog");
            } else {
                throw new IllegalArgumentException
                    ("Cannot find catalog '" + catalogName + "'");
            }
        }

        return catalog;
    }

    /**
     * <p>Return the {@link Command} instance to be delegated to.</p>
     *
     * @param context {@link Context} for this request
     * @return The looked-up Command.
     * @exception IllegalArgumentException if no such {@link Command}
     *  can be found and the <code>optional</code> property is set
     *  to <code>false</code>
     */
    protected Command<K, V, C> getCommand(C context) {
        Catalog<K, V, C> catalog = getCatalog(context);

        Command<K, V, C> command;
        String name = getCommandName(context);
        if (name != null) {
            command = catalog.getCommand(name);
            if (command == null && !isOptional()) {
                if (catalogName == null) {
                    throw new IllegalArgumentException
                        ("Cannot find command '" + name
                         + "' in default catalog");
                } else {
                    throw new IllegalArgumentException
                        ("Cannot find command '" + name
                         + "' in catalog '" + catalogName + "'");
                }
            }
            return command;
        }
        throw new IllegalArgumentException("No command name");
    }

    /**
     * <p>Return the name of the {@link Command} instance to be delegated to.</p>
     *
     * @param context {@link Context} for this request
     * @return The name of the {@link Command} instance
     *
     * @since Chain 1.2
     */
    protected String getCommandName(C context) {
        String name = getName();
        if (name == null) {
            name = (String) context.get(getNameKey());
        }
        return name;
    }

}
