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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * <p>Instances of this class are typically created by a {@link ToolboxFactory}
 * on a one-per-scope basis.  So, for each application, there would be one
 * application-scoped Toolbox from which you would retrieve tool instances,
 * and for each request, there would be one request-scoped Toolbox.
 * Of course, none of the above is enforced.  There's no reason that you can't
 * manually create a Toolbox or have multiple Toolboxes for each scope.
 * </p><p>
 * When a Toolbox creates a tool instance asked of it (see {@link #get}),
 * it will cache that instance for future requests.
 * </p>
 *
 * @author Nathan Bubna
 * @version $Id: Toolbox.java 511959 2007-02-26 19:24:39Z nbubna $
 */
public class Toolbox implements java.io.Serializable
{
    /**
     * The key used to place instances in various scopes.
     */
    public static final String KEY = Toolbox.class.getName();

    private static final long serialVersionUID = 888081253188664649L;

    private Map<String,ToolInfo> infoMap;
    private Map<String,Object> properties;
    private Map<String,Object> cache;

    public Toolbox(Map<String,ToolInfo> toolInfo)
    {
        this(toolInfo, null);
    }

    public Toolbox(Map<String,ToolInfo> toolInfo, Map<String,Object> properties)
    {
        if (toolInfo == null)
        {
            this.infoMap = Collections.emptyMap();
        }
        else
        {
            this.infoMap = toolInfo;
        }
        this.properties = properties;
    }

    protected void cacheData(Map<String,Object> data)
    {
        if (data != null && !data.isEmpty())
        {
            cache = new HashMap<String,Object>(data);
        }
    }


    public Map<String,Object> getProperties()
    {
        return properties;
    }

    public Object get(String key)
    {
        return get(key, null, null);
    }

    public Object get(String key, String path)
    {
        return get(key, path, null);
    }

    public Object get(String key, Map<String,Object> context)
    {
        return get(key, null, context);
    }

    public Object get(String key, String path, Map<String,Object> context)
    {
        /* try the cache */
        Object tool = getFromCache(key, path);

        if (tool == null)
        {
            /* synchronize and try again */
            synchronized (this)
            {
                tool = getFromCache(key, path);
                if (tool == null)
                {
                    tool = getFromInfo(key, path, context);
                }
            }
        }
        return tool;
    }


    protected Object getFromCache(String key, String path)
    {
        if (cache == null)
        {
            return null;
        }
        else
        {
            Object tool = cache.get(key);
            if (tool == null)
            {
                return null;
            }
            else if (path == null)
            {
                return tool;
            }
            else if (hasPermission(infoMap.get(key), path))
            {
                return tool;
            }
            else
            {
                return null;
            }
        }
    }

    protected Object getFromInfo(String key, String path,
                                 Map<String,Object> context)
    {
        ToolInfo info = infoMap.get(key);
        if (info != null && (path == null || hasPermission(info, path)))
        {
            Object tool = info.create(context);
            if (cache == null)
            {
                cache = new HashMap<String,Object>();
            }
            cache.put(key, tool);
            return tool;
        }
        return null;
    }

    protected boolean hasPermission(ToolInfo info, String path)
    {
        if (info == null || path == null)
        {
            return true;
        }
        return info.hasPermission(path);
    }

    public Set<String> getKeys()
    {
        // add keys for all available tools
        Set<String> keys = new HashSet<String>(infoMap.keySet());
        // be sure to add cache, which holds data keys
        if (cache != null)
        {
            keys.addAll(cache.keySet());
        }
        return keys;
    }

    /**
     * Return a new {@link Map} link tools' keys to their {@link Class}es.
     * This will not instantiate any tools, it is merely informational.
     * This will not include the keys for any cached data. Note that inclusion
     * in this map does NOT mean that all these tools will be available for
     * all requests, as this map ignores all path restrictions on the tools.
     * @return a map of tools classes indexed by key
     */
    public Map<String,Class> getToolClassMap()
    {
        Map<String,Class> classMap = new HashMap<String,Class>(infoMap.size());
        for (Map.Entry<String,ToolInfo> entry : infoMap.entrySet())
        {
            classMap.put(entry.getKey(), entry.getValue().getToolClass());
        }
        return classMap;
    }

    public Map<String,Object> getAll(Map<String,Object> context)
    {
        // request all tools we have info for
        for (ToolInfo info : infoMap.values())
        {
            get(info.getKey(), context);
        }
        // then return a copy of the cache
        return new HashMap<String,Object>(this.cache);
    }

    /**
     * Returns a new {@link Toolbox} that is a combination of
     * this Toolbox with one or more specified {@link Toolbox}es.
     * Neither this instance nor those specified are modified.
     * @param toolboxes Toolboxes to combine
     * @return the combined toolbox
     */
    public Toolbox combine(Toolbox... toolboxes)
    {
        Map<String,ToolInfo> info = new HashMap<String,ToolInfo>(this.infoMap);
        Map<String,Object> props = new HashMap<String,Object>(this.properties);
        Map<String,Object> data = new HashMap<String,Object>(this.cache);
        for (Toolbox toolbox : toolboxes)
        {
            info.putAll(toolbox.infoMap);
            props.putAll(toolbox.properties);
            data.putAll(toolbox.cache);
        }
        Toolbox combination = new Toolbox(info, props);
        combination.cacheData(data);
        return combination;
    }

}
