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

import blanco.db.definition.QueryIterator;
import blanco.db.exception.NoRowFoundExceptionClass;
import blanco.db.exception.TooManyRowsFoundExceptionClass;
import blanco.db.util.BlancoDbObjectStorage;
import blanco.ig.expander.Type;
import blanco.ig.expander.Value;
import blanco.ig.expander.implementor.Implementor;
import blanco.ig.expander.method.MethodExpander;

/**
 * シングル属性がtrueの場合にのみ、このクラスは利用されます
 * 
 * @author Tosiki Iga
 */
public class GetSingleRowMethod extends MethodExpander {
    private BlancoDbObjectStorage storage = null;

    private Value _result = null;

    private String runtimePackage = null;

    public GetSingleRowMethod(final BlancoDbObjectStorage storage,
            final Type rowObjectType, final QueryIterator iterator) {
        super("getSingleRow");
        this.storage = storage;

        _result = new Value(rowObjectType, "result");

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

    public void setupSignature() {
        setReturnType(_result.getType());

        final Type noRowFoundException = new Type(runtimePackage
                + ".exception.NoRowFoundException");
        getJavaDoc().addException(noRowFoundException,
                "データベースの処理の結果、1行もデータが検索されなかった場合。");
        addException(noRowFoundException);
        final Type tooManyRowsFoundException = new Type(runtimePackage
                + ".exception.TooManyRowsFoundException");
        getJavaDoc().addException(tooManyRowsFoundException,
                "データベースの処理の結果、1行を超えるデータが検索されてしまった場合。");
        addException(tooManyRowsFoundException);

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

        getJavaDoc().addLine("現在の行のデータをオブジェクトとして取得します。");
        getJavaDoc().addLine("");
        getJavaDoc().addLine(
                "SQL文の実行結果が1行であることを確認します。実行結果が1行以外である場合には例外を発生させます。<br>");
        getJavaDoc().addLine("シングル属性が有効となっているので生成されます。<br>");

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

        addUsingType(new Type(runtimePackage + ".exception",
                NoRowFoundExceptionClass.CLASS_NAME));

        implementor.addLine("if (next() == false) {");
        implementor
                .addLine("throw new NoRowFoundException(\"データベースの処理の結果、1行もデータが検索されませんでした。\");");
        implementor.addLine("}");
        implementor.addLine("");

        implementor
                .addLine(_result.getType().getName() + " result = getRow();");
        implementor.addLine("");

        addUsingType(new Type(runtimePackage + ".exception",
                TooManyRowsFoundExceptionClass.CLASS_NAME));

        // 1行を超えて変更があったかどうかをチェック。
        implementor.addLine("if (next()) {");
        implementor
                .addLine("throw new TooManyRowsFoundException(\"データベースの処理の結果、1行を超えるデータが検索されました。\");");
        implementor.addLine("}");
        implementor.addLine("");

        implementor.addLine("return result;");
    }
}