/*
 * blanco Framework
 * Copyright (C) 2004-2006 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.odp;

import java.util.HashMap;
import java.util.List;

import blanco.cg.BlancoCgObjectFactory;
import blanco.cg.valueobject.BlancoCgClass;
import blanco.cg.valueobject.BlancoCgMethod;
import blanco.cg.valueobject.BlancoCgSourceFile;
import blanco.commons.util.BlancoNameAdjuster;
import blanco.db.common.expander.BlancoDbAbstractMethod;
import blanco.db.common.util.BlancoDbQueryParserUtil;
import blanco.db.common.valueobject.BlancoDbSetting;
import blanco.db.common.valueobject.BlancoDbSqlInfoStructure;
import blanco.db.util.BlancoDbCgUtilDotNet;
import blanco.db.util.BlancoDbMappingUtilDotNet;
import blanco.db.util.odp.BlancoDbMappingUtilOdpDotNet;
import blanco.dbmetadata.valueobject.BlancoDbMetaDataColumnStructure;

/**
 * 個別のメソッドを展開するためのクラス。
 * 
 * @author Tosiki Iga
 */
public class GetCallerOutputParameterMethodOdpDotNet extends
        BlancoDbAbstractMethod {
    private BlancoDbMetaDataColumnStructure fColumnStructure = null;

    public GetCallerOutputParameterMethodOdpDotNet(
            final BlancoDbSetting argDbSetting,
            final BlancoDbSqlInfoStructure argSqlInfo,
            final BlancoCgObjectFactory argCgFactory,
            final BlancoCgSourceFile argCgSourceFile,
            final BlancoCgClass argCgClass,
            final BlancoDbMetaDataColumnStructure columnStructure) {
        super(argDbSetting, argSqlInfo, argCgFactory, argCgSourceFile,
                argCgClass);
        this.fColumnStructure = columnStructure;
    }

    @SuppressWarnings("unchecked")
    public void expand() {
        final BlancoCgMethod cgMethod = fCgFactory.createMethod("Get"
                + BlancoNameAdjuster.toClassName(fColumnStructure.getName()),
                null);
        fCgClass.getMethodList().add(cgMethod);

        cgMethod.getLangDoc().getDescriptionList().add(
                "ストアドプロシージャの実行結果の出力パラメータを取得します。");
        cgMethod.getLangDoc().getDescriptionList().add(
                "※ストアドプロシージャの実行結果として戻すことができるのは値ひとつだけです。");
        cgMethod.getLangDoc().getDescriptionList()
                .add("クエリに与える入力パラメータをセットします。");

        BlancoDbCgUtilDotNet.addExceptionToMethodSqlException(fCgFactory,
                cgMethod);

        cgMethod.setReturn(fCgFactory.createReturn(BlancoDbMappingUtilDotNet
                .getFullClassName(fColumnStructure), ""));

        final List<String> listLine = cgMethod.getLineList();

        if (fDbSetting.getLogging()) {
            BlancoDbCgUtilDotNet.addBeginLogToMethod(cgMethod);
        }

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

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

        for (int indexParameter = 0; indexParameter < fSqlInfo
                .getOutParameterList().size(); indexParameter++) {
            final BlancoDbMetaDataColumnStructure columnStructure = (BlancoDbMetaDataColumnStructure) fSqlInfo
                    .getOutParameterList().get(indexParameter);

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

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

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

            if (BlancoDbMappingUtilDotNet
                    .getPrimitiveAndNullable(columnStructure)) {
                listLine
                        .add("// このバージョンのblancoDbDotNetではnullが格納されている場合の取得結果がADO.NETに依存します。");
            }
            listLine.add("return ("
                    + BlancoDbMappingUtilOdpDotNet
                            .getFullClassName(columnStructure)
                    + ") (("
                    + BlancoDbMappingUtilOdpDotNet
                            .getOracleType(columnStructure)
                    + ") fStatement.Parameters[\"" + columnStructure.getName()
                    + "\"].Value);");
        }

    }
}