/** Copyright © 2003 by Jean-Hugues de Raigniac <jhraigniac@workingfrog.org>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

package org.workingfrog.i18n.util;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * Locate i18n resources in the file system.
 *
 * @author Jean-Hugues de Raigniac
 */
public class Loader {

    /** Current Locale. */
    private Locale locale = Locale.getDefault();

    /** Needed to dynamically refresh bundles when they are modified. */
    private HashMap resources = new HashMap();

    /** Store bundles for current Locale. */
    private HashMap bundles = new HashMap();

    /**
     * Empty constructor.
     */
    public Loader() {
    }

    /**
     * After instanciation, this method is needed to provide
     * application's bundles.
     * @param binding a key to retrieve the bundle
     * @param resource path to the bundle
     * @return the loaded bundle
     */
    public ResourceBundle loadResource (String binding, String resource) {

        ResourceBundle bundle = loadBundle(resource, locale);

        resources.put(binding, resource);
        bundles.put(binding, bundle);

        return bundle;
    }

    /**
     * Loading delegated to ResourceBundle.
     * @param resource bundle key
     * @param locale bundle Locale
     * @return expected bundle
     */
    private ResourceBundle loadBundle (String resource, Locale locale) {
        return ResourceBundle.getBundle(resource, locale, getLoader());
    }

    /**
     * Return a ResourceBundle.
     * @param binding a key to a bundle
     * @return the bundle tied to the binding
     */
    public ResourceBundle getBundle (String binding) {
        return (ResourceBundle) bundles.get(binding);
    }

    /**
     * Return all ResourceBundles for current Locale.
     * @return an HashMap of bundles
     */
    public HashMap getBundles () {
        return getBundles(locale);
    }

    /**
     * Return all ResourceBundles for a Locale.
     * @param locale bundles Locale
     * @return an HashMap of bundles
     */
    public HashMap getBundles (Locale locale) {
        return loadBundles(locale);
    }

    /**
     * Reload bundles for current Locale, useful after modification
     * will running.
     */
    public synchronized void reload () {
        locale = Locale.getDefault();
        bundles = loadBundles(locale);
    }

    /**
     * Load ResourceBundles for a Locale.
     * @param locale bundles Locale
     * @return an HashMap of bundles
     */
    private HashMap loadBundles (Locale locale) {

        HashMap result = new HashMap();
        Iterator iterator = resources.keySet().iterator();

        while (iterator.hasNext()) {
            String binding = (String) iterator.next();
            result.put(binding,
                       loadBundle((String) resources.get(binding), locale));
        }

        return result;
    }

    /**
     * Tool method.
     * @return a ClassLoader
     */
    private ClassLoader getLoader () {
        return Loader.class.getClassLoader();
    }
}
