/*
 * blancoDb Enterprise Edition
 * Copyright (C) 2004-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.invoker;

import blanco.db.definition.QueryInvoker;
import blanco.db.exception.NoRowModifiedExceptionClass;
import blanco.db.exception.TooManyRowsModifiedExceptionClass;
import blanco.db.util.BlancoDbObjectStorage;
import blanco.ig.expander.Type;
import blanco.ig.expander.Value;
import blanco.ig.expander.implementor.Call;
import blanco.ig.expander.implementor.Implementor;
import blanco.ig.expander.implementor.Statement;
import blanco.ig.expander.implementor.StringLiteral;
import blanco.ig.expander.method.MethodExpander;

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

    private String runtimePackage = null;

    public ExecuteSingleUpdateMethod(final BlancoDbObjectStorage storage,
            final QueryInvoker invoker) {
        super("executeSingleUpdate");
        this.storage = storage;

        runtimePackage = storage.getSetting().getRootNameSpace();
        if (storage.getSetting().getRuntimePackage() != null) {
            runtimePackage = storage.getSetting().getRuntimePackage();
        }
    }

    public void setupSignature() {
        // ランタイムパッケージの変化に対応。

        final Type noRowModifiedException = new Type(runtimePackage
                + ".exception.NoRowModifiedException");
        getJavaDoc().addException(noRowModifiedException,
                "データベースの処理の結果、1行もデータが変更されなかった場合。");
        addException(noRowModifiedException);
        final Type tooManyRowsModifiedException = new Type(runtimePackage
                + ".exception.TooManyRowsModifiedException");
        getJavaDoc().addException(tooManyRowsModifiedException,
                "データベースの処理の結果、1行を超えるデータが変更されてしまった場合。");
        addException(tooManyRowsModifiedException);

        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("SQL文を実行します。");
        getJavaDoc().addLine("");
        getJavaDoc().addLine(
                "SQL文の実行結果が1行であることを確認します。実行結果が1行以外である場合には例外を発生させます。<br>");
        getJavaDoc().addLine("シングル属性が有効となっているので生成されます。<br>");
    }

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

        final Value result = new Value(int.class, "result");

        implementor.declare(result, new Statement(int.class, "0"));

        implementor.addStatement("result = executeUpdate()");

        implementor.emptyLine();

        final Type noModified = new Type(runtimePackage + ".exception",
                NoRowModifiedExceptionClass.CLASS_NAME);
        final Type tooMeny = new Type(runtimePackage + ".exception",
                TooManyRowsModifiedExceptionClass.CLASS_NAME);

        Statement s = new Statement(result);
        s.join("==", new Statement(int.class, "0"));
        implementor.openIf(s);

        Call c = new Call(noModified);
        c.addArgument(new StringLiteral("データベースの処理の結果、1行もデータが変更されませんでした。"));
        implementor.addThrow(c);

        s = new Statement(result);
        s.join(">", new Statement(int.class, "1"));
        implementor.addElseIf(s);

        Value message = new Value(String.class, "message");
        s = new StringLiteral("データベースの処理の結果、1行を超えるデータが変更されました。変更件数:");
        s.join("+", new Statement(result));
        implementor.declare(message, s);

        c = new Call(tooMeny);
        c.addArgument(message);
        implementor.addThrow(c);

        implementor.closeIf();
    }
}