/*
 * 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.util.method;

import blanco.db.collector.BlancoDbDatabaseConnectionDotNet;
import blanco.db.util.BlancoDbObjectStorageDotNet;
import blanco.ig.expander.Scope;
import blanco.ig.expander.Type;
import blanco.ig.expander.Value;
import blanco.ig.expander.implementor.Implementor;
import blanco.ig.expander.method.MethodExpander;

/**
 * @author tosiki iga
 */
public class ConvertToBlancoExceptionMethodDotNet extends MethodExpander {
    private static final boolean IS_DEBUG = false;

    protected Scope getScope() {
        return Scope.PUBLIC;
    }

    protected boolean isStatic() {
        return true;
    }

    public ConvertToBlancoExceptionMethodDotNet(
            final BlancoDbObjectStorageDotNet storage) {
        super("ConvertToBlancoException");

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

        final Type integrityConstraintException = new Type(runtimePackage
                + ".exception.IntegrityConstraintException");
        addUsingType(integrityConstraintException);

        final Type deadlockException = new Type(runtimePackage
                + ".exception.DeadlockException");
        addUsingType(deadlockException);

        final Type timeoutException = new Type(runtimePackage
                + ".exception.TimeoutException");
        addUsingType(timeoutException);

        addUsingType(new Type("System.Data.SqlClient.SqlException"));

        if (BlancoDbDatabaseConnectionDotNet.DRIVERNAME_SQLSERVER_2000
                .equals(storage.getSetting().getDriverName())
                || BlancoDbDatabaseConnectionDotNet.DRIVERNAME_SQLSERVER_2005
                        .equals(storage.getSetting().getDriverName())) {
            if (IS_DEBUG) {
                System.out.println("TRACE: SQL Serverです。");
            }
        } else {
            if (IS_DEBUG) {
                System.out.println("TRACE: 非SQL Serverです。ドライバ名["
                        + storage.getSetting().getDriverName() + "]");
            }
        }
    }

    public void setupSignature() {
        getJavaDoc().addLine(
                "SQL例外の内容をチェックし、必要に応じてblanco Framework例外オブジェクトに変換してスローします。");
        getJavaDoc().addLine("");
        getJavaDoc()
                .addLine(
                        "SQL例外のなかで、blanco Frameworkの例外オブジェクトに変換すべきものについてIntegrityConstraintException, DeadlockException, TimeoutExceptionに変換の上 throw します。");
        getJavaDoc().addLine("変換すべき先が無い場合には、そのまま元のオブジェクトを返却します。");
        getJavaDoc().addParameter("ex", "ADO.NETから返却された例外オブジェクト。");
        addArgument(new Value(new Type("System.Data.SqlClient.SqlException"),
                "ex"));
        getJavaDoc()
                .addReturn("もとのSQL例外オブジェクト。ここまで到達した場合には、変換の必要が無かったことを示します。");
        setReturnType(new Type("System.Data.SqlClient.SqlException"));
    }

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

        implementor.addLine("if (ex.Number == 2627) {");
        implementor
                .addLine("IntegrityConstraintException exBlanco = new IntegrityConstraintException(\"データベース制約違反により変更が失敗しました。\" + ex.ToString() + \"、Number=\" + ex.Number);");

        implementor.addLine("throw exBlanco;");
        implementor.addLine("} else if (ex.Number == 1205) {");
        implementor
                .addLine("// デッドロック発生をSQLServerが検知した際に発生する例外。デフォルトでは、デッドロック検知は5秒おき。");
        implementor
                .addLine("DeadlockException exBlanco = new DeadlockException(\"データベースデッドロックによりデータベース操作が失敗しました。\" + ex.ToString() + \"、Number=\" + ex.Number);");
        implementor.addLine("throw exBlanco;");
        implementor.addLine("} else if (ex.Number == 1222) {");
        implementor
                .addLine("// ロック待ちがロックタイムアウトの時間を越えて発生した場合のタイムアウト。デフォルトはタイムアウトなし。");
        implementor
                .addLine("TimeoutException exBlanco = new TimeoutException(\"データベースロック待ちのタイムアウトによりデータベース操作が失敗しました。\" + ex.ToString() + \"、Number=\" + ex.Number);");
        implementor.addLine("throw exBlanco;");
        implementor.addLine("} else if (ex.Number == -2) {");
        implementor
                .addLine("// コマンドのタイムアウト。SqlCommand.CommandTimeoutにて設定。デフォルトは30秒。");
        implementor
                .addLine("TimeoutException exBlanco = new TimeoutException(\"コマンドタイムアウトによりデータベース操作が失敗しました。\" + ex.ToString() + \"、Number=\" + ex.Number);");
        implementor.addLine("throw exBlanco;");
        implementor.addLine("}");
        implementor.addLine("return ex;");
    }
}