/*
 * blancoIg
 * Copyright (C) 2004-2005 Yasuo Nakanishi
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */
package blanco.struts.expander.form.base;

import java.util.Iterator;

import blanco.ig.expander.Type;
import blanco.ig.expander.Value;
import blanco.ig.expander.implementor.Call;
import blanco.ig.expander.method.MethodExpander;
import blanco.struts.definition.form.FieldValidation;
import blanco.struts.definition.form.Form;
import blanco.struts.definition.form.FormField;
import blanco.struts.definition.form.FormTable;
import blanco.struts.expander.StrutsImplementor;
import blanco.struts.expander.TypeFactory;
import blanco.struts.expander.form.ActionFormClass;
import blanco.struts.runtime.validator.Validator;
import blanco.struts.runtime.validator.message.ErrorMessageKey;

/**
 * @author Yasuo Nakanishi
 */
public abstract class BaseValidationMethod extends MethodExpander {

    private Form _form = null;

    private TypeFactory _typeFactory = null;

    private Value _mappintArgument = null;

    private Value _requestArgument = null;

    private StrutsImplementor _implementor = new StrutsImplementor(getData());

    public BaseValidationMethod(String method, Form form,
            TypeFactory typeFactory) {
        super(method);
        _form = form;
        _typeFactory = typeFactory;

    }

    protected StrutsImplementor getImplementor() {
        if (_implementor == null) {
            _implementor = new StrutsImplementor(getData());
        }
        return _implementor;
    }

    public void setupSignature() {
        _mappintArgument = new Value(new Type(
                "org.apache.struts.action.ActionMapping"), "mapping");
        _requestArgument = new Value(new Type(
                "javax.servlet.http.HttpServletRequest"), "request");

        addArgument(_mappintArgument);
        addArgument(_requestArgument);

        setReturnType(new Type("org.apache.struts.action.ActionErrors"));

        String name = "";
        name = _mappintArgument.getName();
        getJavaDoc().addParameter(name, name + " パラメータ。");

        name = _requestArgument.getName();
        getJavaDoc().addParameter(name, name + " パラメータ。");

        String doc = "";
        doc = "エラーがなかった場合、空のActionErrosが返されます。";
        getJavaDoc().addReturn(doc);
    }

    public void implement() {
        StrutsImplementor si = new StrutsImplementor(getData());
        Value errors = new Value(new Type(
                "org.apache.struts.action.ActionErrors"), "errors");
        si.declare(errors, new Call(new Type(
                "org.apache.struts.action.ActionErrors")));

        FormField f = null;
        FieldValidation validation = null;
        Iterator i = _form.getFieldIterator();

        Value fieldValue = null;
        while (i.hasNext()) {
            f = (FormField) i.next();
            implementFiledValidation(f, errors);
        }

        i = _form.getTableIterator();
        FormTable table = null;
        Type type = null;
        Value tableField = null;
        while (i.hasNext()) {
            table = (FormTable) i.next();
            type = table.getType();

            tableField = getField(ActionFormClass.createTableFieldName(table));
            String name = getNameAdjuster().toValueName(type.getName());

            if (table.existFormValidationField()
                    || table.existRequireValidationField()) {
                Value tableItem = new Value(type, name);
                si.declareByDefault(tableItem);

                Value counter = new Value(int.class, "i");
                si
                        .openFor(counter, si.getLoopEndStatement(tableField,
                                counter));

                si.assignTableItem(tableItem, type, tableField, counter);
                si.emptyLine();

                Iterator fieldIterator = table.getFieldIterator();

                while (fieldIterator.hasNext()) {
                    f = (FormField) fieldIterator.next();

                    implementTableValidation(tableItem, f, errors);
                }

                si.closeFor();
                si.emptyLine();
            }
        }
        si.addReturn(errors);
    }

    protected Type getRuntimeType(Class type) {
        return _typeFactory.createRuntime(type);
    }

    protected abstract void implementFiledValidation(FormField field,
            Value errors);

    protected abstract void implementTableValidation(Value item,
            FormField field, Value errors);

    protected abstract boolean existTableValidation(FormTable table);

}
