/*
 * $Id: ResourceManager.java,v 1.7 2005/12/25 23:36:16 sugimotokenichi Exp $
 * Copyright (C) 2005 SUGIMOTO Ken-ichi
 * 作成日: 2005/04/04
 */
package feat.v1;

import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Locale;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import feat.v1.config.BasicFileLocator;
import feat.v1.config.ClassLoaderFileLocator;
import feat.v1.config.FileLocator;
import feat.v1.config.ResourcesDeclaration;
import feat.v1.config.URLFileLocator;

/**
 * リソースを管理するクラス。
 * @author SUGIMOTO Ken-ichi
 */
public class ResourceManager {

    private static Log log = LogFactory.getLog(ResourceManager.class);
    private ResourcesDeclaration resources;
    private Locale locale;


    /**
     * デフォルトロケールのリソースマネージャを作成する。
     */
    public ResourceManager() {
        this(Locale.getDefault());
    }

    /**
     * 指定のロケールのリソースマネージャを作成する。
     */
    public ResourceManager(Locale locale) {
        resources = new ResourcesDeclaration();
        if ( locale == null )
            this.locale = Util.NULL_LOCALE;
        else
            this.locale = locale;
    }

    /**
     * リソースファイルの内容を追加する。
     * 重複するリソースは上書きされる。
     * @param file
     */
    public void addResourceFile(File file) {
        try {
            addResourceFile(new BasicFileLocator(file));
        }
        catch (IllegalArgumentException ex) {
            log.warn("IllegalArgumentException - "+ex.getMessage());
        }
    }

    /**
     * リソースファイルの内容を追加する。
     * 重複するリソースは上書きされる。
     * @param url
     */
    public void addResourceFile(URL url) {
        try {
            addResourceFile(new URLFileLocator(url));
        }
        catch (IllegalArgumentException ex) {
            log.warn("IllegalArgumentException - "+ex.getMessage());
        }
    }

    /**
     * リソースファイルの内容を追加する。
     * 重複するリソースは上書きされる。
     * @param resourceName
     * @param loader
     */
    public void addResourceFile(String resourceName, ClassLoader loader) {
        try {
            addResourceFile(new ClassLoaderFileLocator(resourceName, loader));
        }
        catch (IllegalArgumentException ex) {
            log.warn("IllegalArgumentException - "+ex.getMessage());
        }
        catch (URISyntaxException ex) {
            log.warn("URISyntaxException - "+ex.getMessage());
        }
    }

    /**
     * リソースファイルの内容を追加する。
     * @param file
     */
    public void addResourceFile(FileLocator file) {
        ResourcesDeclaration r = load(file);
        resources.addResources(r);
    }

    private ResourcesDeclaration load(FileLocator file) {
        List seq = Util.makeSequence(locale);
        seq.add(Util.NULL_LOCALE);

        // 言語名に、より詳細にマッチするファイルを探す
        ResourcesDeclaration ret = null;
        for(int i=0; i<seq.size(); i++) {

            Locale loc = (Locale)seq.get(i);

            // リソースファイルを読み込む
            try {
                // 言語別のファイル名を作る
                FileLocator fl = file;
                if ( !loc.equals(Util.NULL_LOCALE) ) {
    	            String filename = StringUtil.makeLocaleFilename(fl.getFilename(), loc);
    	            fl = file.newLocation(filename);
                }

                // 読み込み
                if ( fl.exists() ) {
	                ret = ConfigReader.parseResource(fl);
	                break;
	            }
            }
            catch (FeatException ex) {
                log.warn("FeatException", ex);
            }
        }
        return ret;
    }

    /**
     * 取得したリソース文字列をパラメータで置き換えるユーティリティメソッド。
     * パラメータ1〜3はそれぞれリソース文字列中の"${1}", "${2}", "${3}"と置き換えられる。
     * @param name
     * @return
     */
    public String getString(String name, String param1, String param2, String param3) {
        String ret = getString(name);
        if ( ret != null )
            return StringUtil.replaceParameters(ret, new String[] {param1, param2, param3});
        else
            return null;
    }

    /**
     * リソース文字列を返す。
     * @param name
     * @return
     */
    public String getString(String name) {
        return resources.getString(name, null);
    }

}
