/*
 * blancoDb
 * 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.db.expander.table.gateway;

import java.sql.SQLException;
import java.util.Iterator;

import blanco.db.conf.BlancoDbSetting;
import blanco.db.definition.TableField;
import blanco.db.definition.TableGateway;
import blanco.db.expander.implementor.BlancoDbImplementor;
import blanco.db.generator.TypeFactory;
import blanco.db.properties.GenerationProperties;
import blanco.db.util.BlancoDbObjectStorage;
import blanco.ig.expander.NameAdjuster;
import blanco.ig.expander.Type;
import blanco.ig.expander.Value;

/**
 * @author Yasuo Nakanishi
 */
public class UpdateMethod extends TableGatewayMethod {
    private Type _rowObjectType = null;

    private Value _row = null;

    private TypeFactory _typeFacotry = null;

    private BlancoDbSetting _setting = null;

    private String _query = "";

    private GenerationProperties _properties = null;

    public UpdateMethod(Type rowObjectType, TableGateway gateway, String query) {
        super("update", gateway);

        _rowObjectType = rowObjectType;
        _query = query;

        BlancoDbObjectStorage storage = BlancoDbObjectStorage.getInstance();
        _setting = storage.getSetting();
        _typeFacotry = storage.getTypeFactory();
        _properties = storage.getGenerationProperties();
    }

    public void setupSignature() {
        setReturnType(new Type(void.class));

        Value rowObjectValue = createRowObjectArgument();
        _row = rowObjectValue;
        addArgument(rowObjectValue);

        addException(new Type(SQLException.class));

        if (_properties.isGenerateJavaDoc()) {
            getJavaDoc().addLine("表の行を更新します。<br>");
            getJavaDoc().addLine("プライマリーキー列に該当する行を更新処理します。");

            String name = rowObjectValue.getName() + "Row";
            getJavaDoc().addParameter(name, "行オブジェクト");
        }
    }

    public void implement() {
        NameAdjuster adjuster = new NameAdjuster();
        BlancoDbImplementor implementor = getImplementor();

        String simpleClassName = "Simple" + getGateway().getClassName()
                + "UpdateInvoker";
        implementor.addUsingType(new Type(_setting.getRootNameSpace()
                + ".query." + simpleClassName));
        implementor.addStatement(simpleClassName + " invoker = new "
                + simpleClassName + "(_connection)");
        implementor.openTry();

        TableField field = null;
        Iterator i = getGateway().getFieldIterator();
        String strInputParameter = "";
        while (i.hasNext()) {
            field = (TableField) i.next();
            if (field.isPrimaryKey()) {
                continue;
            }
            if (strInputParameter.length() > 0) {
                strInputParameter += ", ";
            }
            strInputParameter += adjuster.toValueName(_rowObjectType.getName())
                    + ".get" + adjuster.toClassName(field.getName()) + "()";
            if (field.getTypeName().equals("InputStream")
                    || field.getTypeName().equals("Reader")) {
                strInputParameter += ", 10000";
            }
        }

        // 続いてプライマリキー
        i = getGateway().getFieldIterator();
        while (i.hasNext()) {
            field = (TableField) i.next();
            if (field.isPrimaryKey() == false) {
                continue;
            }
            if (strInputParameter.length() > 0) {
                strInputParameter += ", ";
            }
            strInputParameter += adjuster.toValueName(_rowObjectType.getName())
                    + ".get" + adjuster.toClassName(field.getName()) + "()";
            if (field.getTypeName().equals("InputStream")
                    || field.getTypeName().equals("Reader")) {
                strInputParameter += ", 10000";
            }
        }

        implementor.addStatement("invoker.setInputParameter("
                + strInputParameter + ")");
        implementor.addStatement("invoker.executeSingleUpdate()");

        implementor.addFinally();
        implementor.addStatement("invoker.close()");
        implementor.closeTry();
    }

    private Value createRowObjectArgument() {
        String name = getNameAdjuster().toValueName(
                getGateway().getClassName() + "Row");
        return new Value(_rowObjectType, name);
    }
}