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

import feat2.FeatError;
import feat2.FeatErrors;
import feat2.FeatRuntimeException;
import feat2.StringUtil;
import feat2.config.type.Identifier;
import feat2.config.type.JavaIdentifier;
import feat2.validation.ByteValidator;
import feat2.validation.CreditCardValidator;
import feat2.validation.DateValidator;
import feat2.validation.DoubleValidator;
import feat2.validation.FileTypeValidator;
import feat2.validation.FloatValidator;
import feat2.validation.IntValidator;
import feat2.validation.LengthValidator;
import feat2.validation.LongValidator;
import feat2.validation.MailAddressValidator;
import feat2.validation.NumberRangeValidator;
import feat2.validation.PostalCodeValidator;
import feat2.validation.RequiredValidator;
import feat2.validation.ShortValidator;
import feat2.validation.SimpleDateValidator;
import feat2.validation.StringValidator;
import feat2.validation.Validator;

/**
 * 検証の設定。
 * @author SUGIMOTO Ken-ichi
 */
public class ValidationConfig extends Config implements DIComponentConfig {

    private Identifier name;
    private String propertyList;
    private String type;
    private JavaIdentifier className;
    private String dependList;
    private String messageId;
    private InputSupport inputs;

    // validateメソッドで有効になる変数

    private Class validatorClass;
    private ValidationConfig[] depends;
    private JavaIdentifier[] properties;

    public ValidationConfig() {
        inputs = new InputSupport(this);
    }


    // プロパティ -------------------------------------------------------------

    public JavaIdentifier getClassName() {
        return className;
    }
    public void setClassName(JavaIdentifier className) {
        this.className = className;
    }

    /**
     * このバリデーションが依存するバリデーションのリストを返す。未設定のときは長さ0の配列を返す。
     */
    public ValidationConfig[] getDepends() {
        return depends;
    }

    public void setDependList(String dependList) {
        this.dependList = dependList;
    }

    public String getMessageId() {
        return messageId;
    }
    public void setMessageId(String messageId) {
        this.messageId = messageId;
    }

    public Identifier getName() {
        return name;
    }
    public void setName(Identifier name) {
        this.name = name;
    }

    public JavaIdentifier[] getProperties() {
        return properties;
    }
    public void setProperties(JavaIdentifier[] properties) {
        this.properties = properties;
    }

    public void setPropertyList(String propertyList) {
        this.propertyList = propertyList;
    }

    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }


    // インスタンスメソッド ---------------------------------------------------

    public Validator getValidatorInstance() {

        Validator validator = null;

        try {
            validator = (Validator)validatorClass.newInstance();
        }
        catch (InstantiationException ex) {
            throw new FeatRuntimeException(ex);
        }
        catch (IllegalAccessException ex) {
            throw new FeatRuntimeException(ex);
        }

        return validator;
    }


    // DIComponentのメソッド --------------------------------------------------

    public void addInput(InputConfigBase input) {
        inputs.addInput(input);
    }

    public InputConfigBase[] getInputs() {
        return inputs.getInputs();
    }

    public InputConfigBase getInputConfig(String propertyName) {
        return inputs.getInputConfig(propertyName);
    }


    // Configのメソッド -------------------------------------------------------

    public String getElementName() {
        return "validation";
    }


    // Validatableのメソッド --------------------------------------------------

    public boolean validate(FeatErrors errs) {

        boolean ret = true;
        FeatureConfig featureConf = getFeatureConfig();

        // プロパティの検証

        ret = ret && ConfigUtil.validateRequired(name, "name", this, errs);
        ret = ret && ConfigUtil.validateRequired(propertyList, "properties", this, errs);
        ret = ret && ConfigUtil.validateRequired(type, "type", this, errs);


        // プロパティの準備


        // properties

        if ( propertyList != null ) {

            String[] nameList = StringUtil.split(propertyList);
            properties = new JavaIdentifier[nameList.length];
            for (int i = 0; i < nameList.length; i++) {
                properties[i] = new JavaIdentifier(nameList[i]);
            }

        }


        // class

        if ( getType().equalsIgnoreCase("class") ) {

            validatorClass = ConfigUtil.validateClass(className, "class", this, errs);
            if ( validatorClass == null ) {
                ret = false;
            }

        }

        // 規定のバリデータのクラスを作成

        else if ( type.equalsIgnoreCase("byte") ) {
            validatorClass = ByteValidator.class;
        }

        else if ( type.equalsIgnoreCase("short") ) {
            validatorClass = ShortValidator.class;
        }

        else if ( type.equalsIgnoreCase("int") ) {
            validatorClass = IntValidator.class;
        }

        else if ( type.equalsIgnoreCase("long") ) {
            validatorClass = LongValidator.class;
        }

        else if ( type.equalsIgnoreCase("float") ) {
            validatorClass = FloatValidator.class;
        }

        else if ( type.equalsIgnoreCase("double") ) {
            validatorClass = DoubleValidator.class;
        }

        else if ( type.equalsIgnoreCase("string") ) {
            validatorClass = StringValidator.class;
        }

        else if ( type.equalsIgnoreCase("required") ) {
            validatorClass = RequiredValidator.class;
        }

        else if ( type.equalsIgnoreCase("range") ) {
            validatorClass = NumberRangeValidator.class;
        }

        else if ( type.equalsIgnoreCase("length") ) {
            validatorClass = LengthValidator.class;
        }

        else if ( type.equalsIgnoreCase("date") ) {
            validatorClass = DateValidator.class;
        }

        else if ( type.equalsIgnoreCase("simple-date") ) {
            validatorClass = SimpleDateValidator.class;
        }

        else if ( type.equalsIgnoreCase("mail-address") ) {
            validatorClass = MailAddressValidator.class;
        }

        else if ( type.equalsIgnoreCase("postal-code") ) {
            validatorClass = PostalCodeValidator.class;
        }

        else if ( type.equalsIgnoreCase("credit-card") ) {
            validatorClass = CreditCardValidator.class;
        }

        else if ( type.equalsIgnoreCase("filetype") ) {
            validatorClass = FileTypeValidator.class;
        }

        else {
            errs.add(new ConfigError(type, "error.config.validation.type", FeatError.ERROR, this));
        }


        // depends

        ValidatableComponentConfig parent = (ValidatableComponentConfig)getParent();

        if ( dependList != null ) {

            String[] elements = StringUtil.split(dependList);
            depends = new ValidationConfig[elements.length];

            for (int i = 0; i < elements.length; i++) {

                depends[i] = parent.getValidationConfig(elements[i]);
                if ( depends[i] == null )
                    errs.add(new ConfigError(elements[i], "depends", ConfigError.TYPE_REFERRENCE_VALIDATION, FeatError.ERROR, this));

            }

        }

        else {
            depends = new ValidationConfig[0];
        }


        // messageId

        /*if ( messageId != null ) {

            Resources featureResources = featureConf.getResources();
            Resources featResources = getFeatConfig().getResources();

            if ( !featureResources.exists(messageId) && !featResources.exists(messageId) )
                errs.add( new ConfigError(messageId, "name", ConfigError.TYPE_RESOURCE, FeatError.ERROR, this) );

        }*/


        // 子要素の検証

        ret = ret && inputs.validate(errs);

        return true;

    }



}
