/*
 * blanco Framework
 * Copyright (C) 2004-2005 IGA Tosiki
 * 
 * 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.QueryInvokerDotNet;
import blanco.db.util.BlancoDbObjectStorageDotNet;
import blanco.ig.expander.IgType;
import blanco.ig.expander.Scope;
import blanco.ig.expander.implementor.Implementor;
import blanco.ig.expander.method.MethodExpander;

/**
 * @author Yasuo Nakanishi
 */
public class ExecuteUpdateMethodDotNet extends MethodExpander {
    private BlancoDbObjectStorageDotNet storage = null;

    private QueryInvokerDotNet fInvoker = null;

    private String runtimePackage = null;

    public ExecuteUpdateMethodDotNet(final BlancoDbObjectStorageDotNet storage,
            final QueryInvokerDotNet invoker) {
        super("ExecuteUpdate");
        this.storage = storage;
        this.fInvoker = invoker;

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

        final IgType blancoDbUtil = new IgType(runtimePackage
                + ".util.BlancoDbUtil");
        addUsingType(blancoDbUtil);
    }

    /**
     * シングル属性が有効である場合には protectedとします。
     */
    protected Scope getScope() {
        if (fInvoker.isSingle()) {
            return Scope.PROTECTED;
        } else {
            return Scope.PUBLIC;
        }
    }

    public void setupSignature() {
        final IgType resultType = new IgType("int");
        setReturnType(resultType);

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

        getJavaDoc().addLine("実行型クエリを実行します。");
        getJavaDoc().addLine(
                "データベースの制約違反が発生した場合には IntegrityConstraintException 例外が発生します。");

        if (fInvoker.isSingle()) {
            getJavaDoc().addLine("");
            getJavaDoc().addLine("シングル属性が有効なのでスコープをprotectedとします。");
            getJavaDoc().addLine(
                    "このメソッドの代わりに ExecuteSingleUpdateメソッドを利用してください。");
        }

        getJavaDoc().addReturn("処理された行数");
    }

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

        // statementが未確保であるばあい、強制的にprepareStatementを呼び出します。
        implementor.addLine("if (fStatement == null) {");
        implementor
                .addLine("// PreparedStatementが未取得の状態なので、ExecuteNonQuery()実行に先立ちPrepareStatement()メソッドを呼び出して取得します。");
        implementor.addStatement("PrepareStatement()");
        implementor.addLine("}");

        implementor.emptyLine();

        // べったりと展開します。
        implementor.addLine("try {");
        implementor.addLine("return fStatement.ExecuteNonQuery();");
        implementor.addLine("} catch (SqlException ex) {");
        implementor.addLine("throw BlancoDbUtil.ConvertToBlancoException(ex);");
        implementor.addLine("}");
    }
}