/*
 * blancoDb
 * Copyright (C) 2004-2005 Yasuo Nakanishi
 * 
 * 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 Yasuo Nakanishi
 */
public class ExecuteQueryMethod extends MethodExpander {
    private BlancoDbObjectStorage storage = null;

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

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

        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("検索型クエリを実行します。<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("");
        }

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

        // resultSetがあいた状態であれば、先にcloseを行います。
        implementor.addLine("if (fResultSet != null) {");
        implementor.addLine("// 前回の結果セット(ResultSet)が残っているので、これを一旦開放します。");
        implementor.addLine("fResultSet.close();");
        implementor.addLine("fResultSet = null;");
        implementor.addLine("}");

        implementor.addLine("");
        implementor.addLine("try {");
        implementor.addLine("fResultSet = fStatement.executeQuery();");
        implementor.addLine("} catch (SQLException ex) {");
        implementor.addLine("throw BlancoDbUtil.convertToBlancoException(ex);");
        implementor.addLine("}");
    }
}