/*
 * 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.FormField;
import blanco.struts.definition.form.FormTable;
import blanco.struts.expander.StrutsImplementor;
import blanco.struts.expander.TypeFactory;
import blanco.struts.expander.form.ActionFormClass;

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

    private String _event = "";

    private Iterator _eventFields = null;

    private Iterator _tableIterator = null;

    private TypeFactory _typeFactory = null;

    private Value _mappintArgument = null;

    private Value _requestArgument = null;

    private StrutsImplementor _implementor = null;

    public BaseEventValidationMethod(String method, String event,
            Iterator eventFields, Iterator tableIterator,
            TypeFactory typeFactory) {
        super(method);
        _event = event;
        _eventFields = eventFields;
        _tableIterator = tableIterator;
        _typeFactory = typeFactory;

    }

    protected final 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);
    }

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

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

    protected abstract boolean existTableValidation(String event,
            FormTable table);

    public final 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;
        Value fieldValue = null;

        while (_eventFields.hasNext()) {
            f = (FormField) _eventFields.next();
            implemntFieldValidation(f, errors);
        }

        FormTable table = null;
        Type type = null;
        Value tableField = null;
        FieldValidation validation = null;
        while (_tableIterator.hasNext()) {
            table = (FormTable) _tableIterator.next();
            type = getNameAdjuster().adjust(table.getType());

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

            if (existTableValidation(_event, table)) {
                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.getEventFieldIterator(_event);

                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);
    }
}
