/*
 * blancoDb Enterprise Edition
 * 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.expander.query.caller;

import blanco.commons.util.BlancoJavaSourceUtil;
import blanco.commons.util.BlancoNameAdjuster;
import blanco.db.definition.QueryCaller;
import blanco.db.mapping.BlancoDbMappingUtil;
import blanco.db.util.BlancoDbObjectStorage;
import blanco.db.util.BlancoDbQueryParserUtil;
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 GetCallerOutputParameterMethod extends MethodExpander {
    private BlancoDbObjectStorage storage = null;

    private QueryCaller _caller = null;

    private Value val = null;

    public GetCallerOutputParameterMethod(final BlancoDbObjectStorage storage,
            final QueryCaller caller, final Value val) {
        super("get" + BlancoNameAdjuster.toClassName(val.getName()));
        this._caller = caller;
        this.storage = storage;
        this.val = val;
    }

    public void setupSignature() {
        getJavaDoc().addLine("ストアドプロシージャの実行結果の出力パラメータを取得します。");

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

        getJavaDoc().addReturn(
                "ストアドプロシージャの["
                        + BlancoJavaSourceUtil.escapeStringAsJavaDoc(val
                                .getName()) + "]出力");
        setReturnType(val.getType());
    }

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

        if (storage.getSetting().isLogging()) {
            getData().addLine("if (fLog.isDebugEnabled()) {");
            getData().addLine("fLog.debug(\"" + getName() + "\");");
            getData().addLine("}");
            getData().addLine("");
        }

        getJavaDoc().addLine("SQL出力パラメータをゲットします。");
        getJavaDoc().addLine("");
        getJavaDoc().addLine("内部的には CallableStatementから出力パラメータをゲットします。");

        final BlancoDbQueryParserUtil query = new BlancoDbQueryParserUtil(
                _caller.getQuery());

        final int[] listCol = query.getSqlParameters(val.getName());
        if (listCol == null) {
            throw new IllegalArgumentException("SQL定義ID[" + _caller.getName()
                    + "]の SQL出力パラメータ[" + val.getName() + "]が結びついていません.");
        }
        for (int iteSame = 0; iteSame < listCol.length; iteSame++) {
            final int index = listCol[iteSame];
            final String type = BlancoDbMappingUtil
                    .getResultSetGetterMethodName(val.getType().getName());
            if (BlancoDbMappingUtil.isMapWrapperClassNecessity(val.getType()
                    .getName())) {
                getData().addLine(
                        val.getType().getName()
                                + " wrk = "
                                + BlancoDbMappingUtil
                                        .mapWrapperClassForPrimitive(
                                                "fStatement." + type + "("
                                                        + index + ")", val
                                                        .getType().getName())
                                + ";");
                getData().addLine("if (fStatement.wasNull()) {");
                getData().addLine("return null;");
                getData().addLine("}");
                getData().addLine("return wrk;");
            } else {
                getData().addLine(
                        "return fStatement." + type + "(" + index + ");");
            }
        }
    }
}