/*
 * $Id: ConfigUtil.java 220 2007-07-16 10:32:15Z sugimotokenichi $
 * Copyright (C) 2006 SUGIMOTO Ken-ichi
 * 作成日: 2006/03/06
 */
package feat2.config;

import java.util.Iterator;
import java.util.List;

import feat2.FeatError;
import feat2.FeatErrors;
import feat2.ObjectUtil;
import feat2.ResourceManager;
import feat2.config.type.JavaIdentifier;

/**
 * 設定のユーティリティクラス。
 * @author SUGIMOTO Ken-ichi
 */
public class ConfigUtil {

    /**
     * 検証の設定を依存関係の順にソートする。
     * @param validations
     * @return
     * @throws ConfigurationException バリデーションの依存関係に循環参照があるとき
     * @deprecated
     */
    /*public static List sortValidation(List validations) throws ConfigurationException {
        ArrayList ret = new ArrayList();
        Dependencies dep = new Dependencies();

        // 依存関係を作る

        for(int i=0; i<validations.size(); i++) {

            ValidationConfig config = (ValidationConfig)validations.get(i);
            dep.addDependency(config, null);

            // 依存先をすべて依存関係に追加する

            ValidationConfig[] depends = config.getDepends();
            for(int ii=0; ii<depends.length; ii++) {

                dep.addDependency(config, depends[ii]);

            }

        }

        // 実行順の決定

        while( dep.count() > 0 ) {

            Object o = dep.getIndependentObject();
            if ( o == null ) {

                // すべてのオブジェクトがどこかに依存しているので、循環参照
                throw new ConfigurationException("error.config.ValidationConfig.recurrence");

            }

            dep.removeDependencies(o);
            ret.add(o);
        }

        return ret;
    }*/


    /**
     * イテレータで繰り返されるすべての設定オブジェクトのバリデーションを行う。
     * @param configIterator
     * @return
     */
    public static boolean validate(Iterator configIterator, FeatErrors errs) {

        boolean ret = true;

        while (configIterator.hasNext()) {
            Config conf = (Config) configIterator.next();
            ret = (ret && conf.validate(errs));
        }

        return ret;

    }

    /**
     * 配列のすべての設定オブジェクトのバリデーションを行う。
     * @param configArray
     * @return
     */
    public static boolean validate(Config[] configArray, FeatErrors errs) {

        boolean ret = true;

        for (int i = 0; i < configArray.length; i++) {
            ret = (ret && configArray[i].validate(errs));
        }

        return ret;

    }


    /**
     * クラスがロードできるかチェックする。
     * @return ロードされたクラス。ロードにまたはインスタンスの作成に失敗したらnull。
     */
    public static Class validateClassLoading(JavaIdentifier className, String attrName, Config config, FeatErrors errs) {

        FeatureConfig featureConf = config.getFeatureConfig();
        if ( featureConf == null )
            return null;

        Class ret = null;

        if ( className == null ) {
            errs.add(new ConfigError(null, attrName, ConfigError.TYPE_NULL, FeatError.ERROR, config));
        }

        else {

            try {

                ret = ObjectUtil.loadClass(className.getValue(), featureConf.getPackageName().getValue());

            }
            catch (ClassNotFoundException ex) {
                errs.add(new ConfigError(className.getValue(), attrName, ConfigError.TYPE_CLASS_NOT_FOUND_EXCEPTION, FeatError.ERROR, config));
                ret = null;
            }

        }

        return ret;

    }


    /**
     * クラスが存在して、引数なしのコンストラクタでインスタンスを作成できるかチェックする。
     * @param className クラス名。完全修飾名かフィーチャーで指定されたパッケージからの相対名
     * @param config このクラス名が定義されている設定要素
     * @param errs エラーの出力先
     * @return ロードされたクラス。ロードにまたはインスタンスの作成に失敗したらnull。
     */
    public static Class validateClass(JavaIdentifier className, String attrName, Config config, FeatErrors errs) {

        FeatureConfig featureConf = config.getFeatureConfig();
        if ( featureConf == null )
            return null;

        Class ret = validateClassLoading(className, attrName, config, errs);

        if ( ret == null ) {
            return null;
        }

        else {

            try {

                ret.newInstance();

            }
            catch (InstantiationException ex) {
                errs.add(new ConfigError(className.getValue(), attrName, ConfigError.TYPE_INSTANTIATION_EXCEPTION, FeatError.ERROR, config));
                ret = null;
            }
            catch (IllegalAccessException ex) {
                errs.add(new ConfigError(className.getValue(), attrName, ConfigError.TYPE_ILLEGAL_ACCESS_EXCEPTION, FeatError.ERROR, config));
                ret = null;
            }

        }

        return ret;

    }

    /**
     * 必須項目のチェック。
     */
    public static boolean validateRequired(Object value, String attrName, Config config, FeatErrors errs) {

        if ( value == null ) {
            errs.add( new ConfigError(null, attrName, ConfigError.TYPE_NULL, FeatError.ERROR, config) );
            return false;
        }

        return true;

    }

    public static boolean validateResource(String resourceId, Config config, ResourceManager rm, FeatErrors errs) {

        if ( rm.getStringResource(resourceId) == null ) {

            errs.add( new ConfigError(resourceId, "", ConfigError.TYPE_RESOURCE, FeatError.ERROR, config) );
            return false;

        }

        return true;

    }

    public static Config getConfig(List list, String name) {

        for (Iterator iter = list.iterator(); iter.hasNext();) {
            Config conf = (Config) iter.next();
            if ( name.equals(conf.getName().getValue()) ) {
                return conf;
            }
        }

        return null;
    }

}
