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

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import blanco.commons.util.BlancoNameAdjuster;
import blanco.commons.util.BlancoStringUtil;
import blanco.db.common.stringgroup.BlancoDbSqlInfoTypeStringGroup;
import blanco.db.common.valueobject.BlancoDbSqlInfoStructure;
import blanco.jsf.db.BlancoJsfDbParser;
import blanco.jsf.message.BlancoJsfMessage;
import blanco.jsf.task.valueobject.BlancoJsfProcessInput;
import blanco.jsf.valueobject.BlancoJsfProcessSqlItemStructure;
import blanco.jsf.valueobject.BlancoJsfProcessStructure;
import blanco.jsf.valueobject.BlancoJsfStructure;

/**
 * 「バッチ処理定義書」Excel様式からバッチ処理を処理する抽象親クラス・ソースコードを生成。
 * 
 * このクラスは、中間XMLファイルからソースコードを自動生成する機能を担います。
 * 
 * @author IGA Tosiki
 */
public class BlancoJsfXml2SourceFile {
    /**
     * メッセージクラス。
     */
    protected final BlancoJsfMessage fMsg = new BlancoJsfMessage();

    /**
     * 中間XMLファイルをパースします。
     * 
     * @param argMetaXmlSourceFile
     *            メタ情報が含まれているXMLファイル。
     * @param argDirectoryTarget
     *            ソースコード生成先ディレクトリ (/mainを除く部分を指定します)。
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    public List<BlancoJsfStructure> parse(final File argMetaXmlSourceFile,
            final BlancoJsfProcessInput input) throws IOException {
        return new BlancoJsfXmlParser().parse(argMetaXmlSourceFile);
    }

    /**
     * 中間XMLファイルからソースコードを自動生成します。
     * 
     * @param argMetaXmlSourceFile
     *            メタ情報が含まれているXMLファイル。
     * @param argDirectoryTarget
     *            ソースコード生成先ディレクトリ (/mainを除く部分を指定します)。
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    public void process(final BlancoJsfStructure structure,
            final List<BlancoJsfStructure> listJsfStructure,
            final BlancoJsfProcessInput input) throws IOException {
        final List<BlancoDbSqlInfoStructure> sqlInfoList = new BlancoJsfDbParser()
                .process(input);

        // メタ情報の解析結果をもとにソースコード自動生成を実行します。
        structure2Source(structure, listJsfStructure, sqlInfoList, input);
    }

    /**
     * 与えられたクラス情報バリューオブジェクトから、Javaソースコードを自動生成します。
     * 
     * @param structure
     *            情報。
     * @param argDirectoryTarget
     *            ソースコードの出力先ディレクトリ
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    public void structure2Source(final BlancoJsfStructure structure,
            final List<BlancoJsfStructure> listJsfStructure,
            final List<BlancoDbSqlInfoStructure> sqlInfoList,
            final BlancoJsfProcessInput input) throws IOException {
        for (BlancoJsfProcessStructure processStructure : structure
                .getProcessList()) {
            final List<String> sqlClassNameList = getSqlClassNameList(
                    processStructure, sqlInfoList);

            final BlancoJsfExpandLogic expandLogic = new BlancoJsfExpandLogic();
            expandLogic.expandSourceFile(structure, listJsfStructure,
                    processStructure, sqlClassNameList, input);
        }

        final BlancoJsfExpandLogicProxy expandLogicProxy = new BlancoJsfExpandLogicProxy();
        expandLogicProxy.expandSourceFile(structure, listJsfStructure,
                sqlInfoList, input);
    }

    public static List<String> getSqlClassNameList(
            final BlancoJsfProcessStructure processStructure,
            final List<BlancoDbSqlInfoStructure> sqlInfoList) {
        final List<String> result = new ArrayList<String>();
        for (BlancoJsfProcessSqlItemStructure sqlItem : processStructure
                .getSqlList()) {
            boolean isFound = false;
            for (BlancoDbSqlInfoStructure sqlinfo : sqlInfoList) {
                if (sqlItem.getName().equals(sqlinfo.getName())) {
                    String basePackage = BlancoStringUtil.null2Blank(sqlinfo
                            .getPackage());
                    if (basePackage.length() == 0) {
                        basePackage = "noname";
                    }
                    final String sqlClassName = basePackage
                            + ".query."
                            + BlancoNameAdjuster.toClassName(sqlItem.getName())
                            + BlancoNameAdjuster
                                    .toUpperCaseTitle(new BlancoDbSqlInfoTypeStringGroup()
                                            .convertToString(sqlinfo.getType()));
                    result.add(sqlClassName);
                    isFound = true;
                    break;
                }
            }
            if (isFound == false) {
                throw new IllegalArgumentException("JSF処理定義書 ["
                        + processStructure.getName() + "]、["
                        + processStructure.getMethod() + "] の SQL定義ID ["
                        + sqlItem.getName() + "] が見つかりません。");
            }
        }

        return result;
    }
}
