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

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

import javax.xml.transform.TransformerException;

import blanco.jsf.BlancoJsfConstants;
import blanco.jsf.BlancoJsfMeta2Xml;
import blanco.jsf.BlancoJsfXml2ConfigFile;
import blanco.jsf.BlancoJsfXml2SourceFile;
import blanco.jsf.message.BlancoJsfMessage;
import blanco.jsf.task.valueobject.BlancoJsfProcessInput;
import blanco.jsf.valueobject.BlancoJsfStructure;

/**
 * バッチ処理生成処理の実際の処理内容。
 */
public class BlancoJsfProcessImpl implements BlancoJsfProcess {
    /**
     * メッセージクラス。
     */
    protected final BlancoJsfMessage fMsg = new BlancoJsfMessage();

    protected BlancoJsfProcessInput fInput;

    /**
     * 具体的なバッチ処理内容を記述するためのメソッドです。
     * 
     * このメソッドに実際の処理内容を記述します。
     * 
     * @param input
     *            バッチ処理の入力パラメータ。
     * @return バッチ処理の終了コード。正常終了の場合には、BlancoJsfJsf.END_SUCCESS。
     * @throws IOException
     *             入出力例外が発生した場合。
     * @throws IllegalArgumentException
     *             入力値に不正が見つかった場合。
     */
    public int execute(final BlancoJsfProcessInput input) throws IOException,
            IllegalArgumentException {
        fInput = input;
        System.out.println("- " + BlancoJsfConstants.PRODUCT_NAME + " ("
                + BlancoJsfConstants.VERSION + ")");

        try {
            final File fileMetadir = new File(input.getMetadir());
            if (fileMetadir.exists() == false) {
                throw new IllegalArgumentException(fMsg.getMbjfa001(input
                        .getMetadir()));
            }

            final List<BlancoJsfStructure> structureList = new ArrayList<BlancoJsfStructure>();

            // テンポラリディレクトリを作成。
            new File(input.getTmpdir() + BlancoJsfConstants.TARGET_SUBDIRECTORY)
                    .mkdirs();

            // 指定されたメタディレクトリを処理します。
            new BlancoJsfMeta2Xml().processDirectory(fileMetadir, input
                    .getTmpdir()
                    + BlancoJsfConstants.TARGET_SUBDIRECTORY);

            // XML化された中間ファイルからソースコードを生成
            final File[] fileMeta2 = new File(input.getTmpdir()
                    + BlancoJsfConstants.TARGET_SUBDIRECTORY).listFiles();
            for (int index = 0; index < fileMeta2.length; index++) {
                if (fileMeta2[index].getName().endsWith(".xml") == false) {
                    continue;
                }

                if (progress("Processing [" + fileMeta2[index].getName()
                        + "] ...")) {
                    return BlancoJsfBatchProcess.END_ERROR;
                }

                final BlancoJsfXml2SourceFile xml2source = new BlancoJsfXml2SourceFile();
                structureList.addAll(xml2source.parse(fileMeta2[index], input));
            }

            for (BlancoJsfStructure structure : structureList) {
                new BlancoJsfXml2SourceFile().process(structure, structureList,
                        input);
            }

            new BlancoJsfXml2ConfigFile().structure2Xml(structureList, input);

            return BlancoJsfBatchProcess.END_SUCCESS;
        } catch (TransformerException ex) {
            throw new IOException("XML変換の過程で例外が発生しました: " + ex.toString());
        }
    }

    /**
     * 処理の中でアイテムが処理されるたびに進捗報告としてコールバックします。
     * 
     * @param argProgressMessage
     *            現在処理しているアイテムに関するメッセージ。
     * @return 処理をそのまま継続する場合は false。処理中断をリクエストしたい場合は true。
     */
    public boolean progress(final String argProgressMessage) {
        if (fInput.getVerbose()) {
            System.out.println(" " + argProgressMessage);
        }
        return false;
    }
}
