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

import java.util.HashMap;
import java.util.Iterator;

import blanco.commons.util.BlancoNameAdjuster;
import blanco.db.definition.QueryCallerDotNet;
import blanco.db.mapping.BlancoDbMappingUtilDotNet;
import blanco.db.util.BlancoDbObjectStorageDotNet;
import blanco.db.util.BlancoDbQueryParserUtilDotNet;
import blanco.ig.expander.IgValue;
import blanco.ig.expander.implementor.Implementor;
import blanco.ig.expander.method.MethodExpander;

/**
 * @author Tosiki Iga
 */
public class GetCallerOutputParameterMethodDotNet extends MethodExpander {
    private BlancoDbObjectStorageDotNet storage = null;

    private QueryCallerDotNet _caller = null;

    private IgValue fVal = null;

    public GetCallerOutputParameterMethodDotNet(
            final BlancoDbObjectStorageDotNet storage,
            final QueryCallerDotNet caller, IgValue val) {
        super("Get" + BlancoNameAdjuster.toClassName(val.getName()));
        _caller = caller;
        this.storage = storage;
        this.fVal = val;
    }

    public void setupSignature() {
        getJavaDoc().addLine("ストアドプロシージャの実行結果の出力パラメータを取得します。");
        getJavaDoc().addLine("※ストアドプロシージャの実行結果として戻すことができるのは値ひとつだけです。");

        final Iterator ite = _caller.getOutParameterIterator();
        while (ite.hasNext()) {
            final IgValue val = (IgValue) ite.next();

            if (fVal.getName().equals(val.getName()) == false) {
                // ターゲットではないので処理をスキップします。
                continue;
            }

            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("クエリに与える入力パラメータをセットします。");

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

        // 既に処理をしたパラメータのマップ。
        final HashMap mapProcessedParam = new HashMap();

        final Iterator ite = _caller.getOutParameterIterator();
        while (ite.hasNext()) {
            // TODO: SQL文からパラメータを発見しなくてはなりません。
            // 現状、とりあえず与えられた順序で登場と仮定が加わっています。
            final IgValue val = (IgValue) ite.next();

            final int[] listCol = query.getSqlParameters(val.getName());
            if (listCol == null) {
                throw new IllegalArgumentException("SQL定義ID["
                        + _caller.getName() + "]の SQL出力パラメータ[" + val.getName()
                        + "]が結びついていません.");
            }

            if (fVal.getName().equals(val.getName()) == false) {
                // ターゲットではないので処理をスキップします。
                continue;
            }

            // 既に処理済のパラメータとして記憶します。
            mapProcessedParam.put(val.getName(), val);

            if (BlancoDbMappingUtilDotNet.isMapWrapperClassNecessity(val
                    .getType().getName())) {
                getData()
                        .addLine(
                                "// このバージョンのblancoDbDotNetではnullが格納されている場合の取得結果がADO.NETに依存します。");
            }
            getData().addLine(
                    "return (" + val.getType().getFullName()
                            + ") fStatement.Parameters[\"@" + val.getName()
                            + "\"].Value;");
        }
    }
}