/*
 * blancoDb
 * Copyright (C) 2005 Tosiki Iga
 * 
 * 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.query.iterator;

import blanco.commons.util.BlancoNameAdjuster;
import blanco.db.definition.QueryField;
import blanco.db.definition.QueryIterator;
import blanco.db.mapping.BlancoDbMappingUtil;
import blanco.db.util.BlancoDbObjectStorage;
import blanco.ig.expander.Type;
import blanco.ig.expander.Value;
import blanco.ig.expander.implementor.Implementor;
import blanco.ig.expander.implementor.StringLiteral;
import blanco.ig.expander.method.MethodExpander;

/**
 * @author Tosiki Iga
 */
public class UpdateObjectMethod extends MethodExpander {
    private BlancoDbObjectStorage storage = null;

    private QueryField _field = null;

    public UpdateObjectMethod(final BlancoDbObjectStorage storage,
            final QueryIterator iterator, final QueryField field) {
        super("update" + BlancoNameAdjuster.toClassName(field.getName()));
        _field = field;
        this.storage = storage;
    }

    public void setupSignature() {
        getJavaDoc().addException(new Type("java.sql.SQLException"),
                "SQL例外が発生した場合。");
        addException(new Type("java.sql.SQLException"));

        final Value value = new Value(_field.getJavaType(), "arg"
                + BlancoNameAdjuster.toClassName(_field.getName()));
        addArgument(value);

        if (_field.getTypeName().equals("InputStream")
                || _field.getTypeName().equals("Reader")) {
            addArgument(new Value(int.class, "sourceLength"));
        }

        getJavaDoc().addLine("現在カーソルがある行の'" + _field.getName() + "'列を更新します。");
        getJavaDoc().addLine("");
        getJavaDoc().addLine("実際の更新はupdateRowメソッドの呼び出し時におこなわれます。<br>");
        getJavaDoc().addLine("更新可能属性が有効となっているので生成されます。<br>");

        getJavaDoc().addParameter(
                "arg" + BlancoNameAdjuster.toClassName(_field.getName()),
                _field.getName() + "列にセットする値");
    }

    public void implement() {
        final Implementor implementor = new Implementor(getData());

        if (storage.getSetting().isLogging()) {
            implementor.addLine("if (fLog.isDebugEnabled()) {");
            implementor.addLine("fLog.debug(\"" + getName() + ": arg"
                    + BlancoNameAdjuster.toClassName(_field.getName())
                    + " = \" + arg"
                    + BlancoNameAdjuster.toClassName(_field.getName()) + ");");
            implementor.addLine("}");
            implementor.addLine("");
        }

        if (_field.getObjectMappingForPrimitiveNullSupport()) {
            implementor.addLine("if (arg"
                    + BlancoNameAdjuster.toClassName(_field.getName())
                    + " == null) {");
            implementor.addLine("fResultSet.updateNull("
                    + new StringLiteral(_field.getName()) + ");");
            implementor.addLine("} else {");
        }

        String optionParam = "";
        if (_field.getTypeName().equals("InputStream")
                || _field.getTypeName().equals("Reader")) {
            optionParam = ", sourceLength";
        }

        implementor.addLine("fResultSet."
                + BlancoDbMappingUtil.getResultSetUpdateMethodName(_field
                        .getTypeName())
                + "(\""
                + _field.getJdbcName()
                + "\", "
                + BlancoDbMappingUtil.mapWrapperClassIntoPrimitive("arg"
                        + BlancoNameAdjuster.toClassName(_field.getName()),
                        _field.getTypeName()) + optionParam + ");");

        if (_field.getTypeName().equals("Date")) {
            // BlancoDbMappingUtil.mapWrapperClassIntoPrimitiveメソッドでTimestamp型が必要です。
            addUsingType(new Type("java.sql.Timestamp"));
        }

        if (_field.getObjectMappingForPrimitiveNullSupport()) {
            implementor.addLine("}");
        }
    }
}