/*
 * blancoDb Enterprise Edition
 * 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.db.definition.QueryIterator;
import blanco.db.util.BlancoDbObjectStorage;
import blanco.ig.expander.Type;
import blanco.ig.expander.implementor.Implementor;
import blanco.ig.expander.method.MethodExpander;

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

    public UpdateRowMethod(final BlancoDbObjectStorage storage,
            final QueryIterator iterator) {
        super("updateRow");
        this.storage = storage;
    }

    public void setupSignature() {
        // ランタイムパッケージの変化に対応。
        String runtimePackage = storage.getSetting().getRootNameSpace();
        if (storage.getSetting().getRuntimePackage() != null) {
            runtimePackage = storage.getSetting().getRuntimePackage();
        }

        final Type integrityConstraintException = new Type(runtimePackage
                + ".exception.IntegrityConstraintException");
        getJavaDoc().addException(integrityConstraintException,
                "データベース制約違反が発生した場合。");
        addException(integrityConstraintException);

        final Type deadlockException = new Type(runtimePackage
                + ".exception.DeadlockException");
        getJavaDoc().addException(deadlockException, "データベースデッドロックが発生した場合。");
        addException(deadlockException);

        final Type timeoutException = new Type(runtimePackage
                + ".exception.TimeoutException");
        getJavaDoc().addException(timeoutException, "データベースタイムアウトが発生した場合。");
        addException(timeoutException);

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

        getJavaDoc().addLine("更新後の現在の行の値をもちいてデータベースを更新します。");
        getJavaDoc().addLine("");
        getJavaDoc().addLine("更新可能属性が有効となっているので生成されます。<br>");
    }

    /**
     * コメント <br>
     * 
     * PostgreSQLにおいて FOR UPDATEカーソルでupdateRowを呼び出した際に 制約違反の際には、SQLState[23505],
     * ErrorCode [0] が発生します。 <br>
     * java.sql.SQLException: ERROR: duplicate key violates unique constraint
     * "ract007_ketsugo_model_pkey" at
     * org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1471)
     */
    public void implement() {
        final Implementor implementor = new Implementor(getData());

        if (storage.getSetting().isLogging()) {
            implementor.addLine("if (fLog.isDebugEnabled()) {");
            implementor.addLine("fLog.debug(\"" + getName() + "\");");
            implementor.addLine("}");
            implementor.addLine("");
        }

        // べったりと展開します。
        implementor.addLine("try{");
        implementor.addLine("fResultSet.updateRow();");
        implementor.addLine("} catch (SQLException ex) {");
        implementor
                .addLine("if (ex.getSQLState() != null && ex.getSQLState().startsWith(\"23\")) {");
        implementor
                .addLine("final IntegrityConstraintException exBlanco = new IntegrityConstraintException(\"制約違反により変更に失敗しました。:\" + ex.toString(), ex.getSQLState(), ex.getErrorCode());");
        implementor.addLine("exBlanco.initCause(ex);");
        implementor.addLine("throw exBlanco;");
        implementor.addLine("}");
        implementor.addLine("throw ex;");
        implementor.addLine("}");
    }
}