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

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

import feat2.FeatErrors;
import feat2.config.type.Identifier;

/**
 * Validation要素をサポートするためのクラス。
 * @author SUGIMOTO Ken-ichi
 */
public class ValidationSupport implements
        ValidatableComponentConfig {

    private Config parent;
    private ArrayList validations;
    private boolean sorted;

    public ValidationSupport(Config parent) {
        this.parent = parent;

        validations = new ArrayList();
        sorted = false;
    }

    public void addValidation(ValidationConfig validation) {
        validations.add(validation);
        validation.setParent(parent);
        sorted = false;
    }

    public ValidationConfig[] getValidations() throws ConfigurationException {
        if ( !sorted ) {
            validations = sortValidation(validations);
            sorted = true;
        }
        return (ValidationConfig[])validations.toArray(new ValidationConfig[0]);
    }

    public ValidationConfig getValidationConfig(String name) {
        for (Iterator iter = validations.iterator(); iter.hasNext();) {
            ValidationConfig cfg = (ValidationConfig) iter.next();
            if ( cfg.getName().getValue().equals(name) )
                return cfg;
        }
        return null;
    }

    /**
     * 登録されているバリデーション設定オブジェクトの数を返す。
     */
    public int count() {
        return validations.size();
    }

    public boolean validate(FeatErrors errs) {
        return ConfigUtil.validate(validations.iterator(), errs);
    }


    /**
     * 検証の設定を依存関係の順にソートする。
     * @param validations
     * @return
     * @throws ConfigurationException バリデーションの依存関係に循環参照があるとき
     */
    private ArrayList 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;
    }

    /**
     * このメソッドはこのクラスではサポートしない。
     * @return 常にnullを返す。
     */
    public String getPropertyNameId(String propertyName) {
        return null;
    }

    /**
     * このメソッドはこのクラスではサポートしない。
     * @return 常にnullを返す。
     */
    public Identifier getErrorResponse() {
        return null;
    }

}
