package org.apache.velocity.tools;

/*
 * 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.
 */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.config.ConfigurationUtils;

/**
 * {@link Context} implementation that keeps a list of {@link Toolbox}es
 * and returns them as requested, using its internal context Map as the
 * dynamic properties passed to the requested tools when they are first
 * created.
 *
 * @author Nathan Bubna
 * @version $Id: ToolContext.java 511959 2007-02-26 19:24:39Z nbubna $
 */
public class ToolContext implements Context
{
    public static final String PATH_KEY = "requestPath";
    public static final String CONTEXT_KEY = "velocityContext";
    public static final String ENGINE_KEY = "velocityEngine";
    public static final String LOCALE_KEY = "locale";
    public static final String LOG_KEY = "log";
    public static final String TOOLKEY_KEY = "key";
    public static final String CATCH_EXCEPTIONS_KEY = "catchExceptions";

    private List<Toolbox> toolboxes = new ArrayList<Toolbox>();
    // this is meant solely for tool setup,
    // values in here are not part of the Context
    private Map<String,Object> toolProps = new HashMap<String,Object>(12);
    // this is only for values added during use of this context
    private Map<String,Object> localContext = new HashMap<String,Object>();
    private boolean userOverwrite = true;

    public ToolContext()
    {
        // add this as a common tool property
        putToolProperty(CONTEXT_KEY, this);
    }

    /**
     * Creates an instance that automatically has the specified
     * VelocityEngine and related tool properties set.
     * @param engine VelocityEngine instance
     */
    public ToolContext(VelocityEngine engine)
    {
        this();

        putVelocityEngine(engine);
    }

    /**
     * Creates an instance starting with the specified tool properties.
     * @param toolProps tools properties
     */
    public ToolContext(Map<String,Object> toolProps)
    {
        this();

        if (toolProps != null)
        {
            this.toolProps.putAll(toolProps);
        }
    }

    /**
     * Set whether or not tool references can be overwritten within a template.
     * The default value is {@code true}.  Set this to false if you want to
     * ensure that your tool references are never replaced within the course
     * of a template.
     * @param overwrite flag value
     */
    public void setUserCanOverwriteTools(boolean overwrite)
    {
        this.userOverwrite = overwrite;
    }

    /**
     * Default is {@code true}.
     * @return flag value
     * @see #setUserCanOverwriteTools
     */
    public boolean getUserCanOverwriteTools()
    {
        return this.userOverwrite;
    }

    public void addToolbox(Toolbox toolbox)
    {
        toolboxes.add(toolbox);
    }

    /**
     * Returns a {@link Map} of all tools available to this
     * context. NOTE: this is not a cheap operation as it will
     * request and initialize an instance of every available tool.
     * @return aggregated toolbox of all available tools
     */
    public Map<String,Object> getToolbox()
    {
        Map<String,Object> aggregate = new HashMap<String,Object>();
        Map<String,Object> toolProps = getToolProperties();
        for (Toolbox toolbox : getToolboxes())
        {
            aggregate.putAll(toolbox.getAll(toolProps));
        }
        return aggregate;
    }

    /**
     * Gets a map of keys to classes for all available tools.
     * This does not include any data nor any local context values.
     * @return aggregated map of all available tools classes
     */
    public Map<String,Class> getToolClassMap()
    {
        Map<String,Class> toolClasses = new HashMap<String,Class>();
        // go thru toolboxes backwards so final map matches
        // what would be found in lookups
        int n = getToolboxes().size();
        for (int i = n - 1; i >= 0; i--)
        {
            Toolbox toolbox = getToolboxes().get(i);
            toolClasses.putAll(toolbox.getToolClassMap());
        }
        return toolClasses;
    }

    protected List<Toolbox> getToolboxes()
    {
        return this.toolboxes;
    }

    protected Map<String,Object> getToolProperties()
    {
        return this.toolProps;
    }

    /**
     * Puts the specified VelocityEngine in the tool properties,
     * as well as the Log for that engine.  Last, if the specified
     * engine has a MethodExceptionEventHandler configured, then
     * this will automatically set {@link #CATCH_EXCEPTIONS_KEY}
     * to false in the tool properties.
     * @param engine VelocityEngine instance
     */
    public void putVelocityEngine(VelocityEngine engine)
    {
        // add the engine and log as common tool properties
        putToolProperty(ENGINE_KEY, engine);
        putToolProperty(LOG_KEY, ConfigurationUtils.getLog(engine, "tools"));

        // tell interested tools not to catch exceptions whenever there's a
        // method exception event handler configured for the engine
        Object ehme =
            engine.getProperty(VelocityEngine.EVENTHANDLER_METHODEXCEPTION);
        if (ehme != null)
        {
            putToolProperty(CATCH_EXCEPTIONS_KEY, Boolean.FALSE);
        }
    }

    public Object putToolProperty(String key, Object value)
    {
        return toolProps.put(key, value);
    }

    public void putToolProperties(Map<String,Object> props)
    {
        if (props != null)
        {
            for (Map.Entry<String,Object> prop : props.entrySet())
            {
                putToolProperty(prop.getKey(), prop.getValue());
            }
        }
    }

    public Object put(String key, Object value)
    {
        return localContext.put(key, value);
    }

    public Object get(String key)
    {
        // for user overwriting, it's all a matter of which we check first
        Object value = userOverwrite ? internalGet(key) : findTool(key);
        if (value == null)
        {
            value = userOverwrite ? findTool(key) : internalGet(key);
        }
        return value;
    }

    protected Object internalGet(String key)
    {
        return localContext.get(key);
    }

    protected Object findTool(String key)
    {
        String path = (String)toolProps.get(PATH_KEY);
        for (Toolbox toolbox : getToolboxes())
        {
            Object tool = toolbox.get(key, path, toolProps);
            if (tool != null)
            {
                return tool;
            }
        }
        return null;
    }
        

    public Set<String> keySet()
    {
        Set<String> keys = new HashSet<String>();
        for (Toolbox toolbox : getToolboxes())
        {
            keys.addAll(toolbox.getKeys());
        }
        keys.addAll(localContext.keySet());
        return keys;
    }

    public boolean containsKey(String key)
    {
        return keySet().contains(key);
    }

    public String[] getKeys()
    {
        Set<String> keys = keySet();
        return keys.toArray(new String[keys.size()]);
    }

    public Object remove(String key)
    {
        //tools and their props cannot be removed
        return localContext.remove(key);
    }

    public void putAll(Map context)
    {
        localContext.putAll(context);
    }
}
