/*
 * blancoCsv 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.csv.expand;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;

import org.xml.sax.SAXException;

import blanco.commons.util.BlancoNameAdjuster;
import blanco.csv.valueobject.BlancoCsvFieldStructure;
import blanco.csv.valueobject.BlancoCsvStructure;
import blanco.test.valueobject.BlancoValueObjectXml2JUnit;
import blanco.valueobject.BlancoValueObjectXml2JavaClass;
import blanco.valueobject.concretesax.BlancoValueObjectSerializer;

public class BlancoCsvExpandRecord {
    /**
     * レコードを展開します。
     * 
     * @param processStructure
     * @param direcotryValueObjectWork
     * @param directoryTarget
     * @param isGenerateJUnit
     * @throws IOException
     * @throws TransformerException
     */
    public static void expand(final BlancoCsvStructure processStructure,
            final File direcotryValueObjectWork, final File directoryTarget,
            final boolean isGenerateJUnit) throws IOException,
            TransformerException {
        final String className = BlancoNameAdjuster
                .toClassName(processStructure.getFileDefinitionId())
                + "CsvRecord";
        final String packageName = processStructure.getPackageName()
                + ".record";
        final File filePojoWork = new File(direcotryValueObjectWork
                .getAbsolutePath()
                + "/" + className + ".xml");

        OutputStream outStream = null;
        try {
            outStream = new BufferedOutputStream(new FileOutputStream(
                    filePojoWork));
            final BlancoValueObjectSerializer serializer = new BlancoValueObjectSerializer(
                    outStream);
            serializer.startDocument();
            serializer.startElementWorkbook();
            serializer.characters("\n");
            serializer.startElementSheet("ValueObject");
            serializer.characters("\n");
            serializer.characters("  ");
            serializer.startElementBlancovalueobjectCommon();
            serializer.characters("\n");
            serializer.characters("    ");
            serializer.startElementName();
            // 名前
            serializer.characters(className);
            serializer.endElementName();
            serializer.characters("\n");
            serializer.characters("    ");
            serializer.startElementPackage();
            serializer.characters(packageName);
            serializer.endElementPackage();
            serializer.characters("\n");
            serializer.characters("    ");
            serializer.startElementDescription();
            serializer.characters("blancoCsvファイル定義書から作成されたレコードクラス");
            serializer.endElementDescription();
            serializer.characters("\n");
            serializer.characters("    ");
            serializer.startElementFileDescription();
            serializer.characters("ファイル定義["
                    + processStructure.getFileDefinitionId()
                    + (processStructure.getFileDescription() == null ? "" : "/"
                            + processStructure.getFileDescription())
                    + "]のレコードクラス\n");
            serializer.endElementFileDescription();
            serializer.characters("\n");
            serializer.characters("  ");
            serializer.endElementBlancovalueobjectCommon();
            serializer.characters("\n");
            serializer.characters("  ");
            serializer.startElementBlancovalueobjectList();
            serializer.characters("\n");

            for (int indexField = 0; indexField < processStructure
                    .getListField().size(); indexField++) {
                final BlancoCsvFieldStructure field = (BlancoCsvFieldStructure) processStructure
                        .getListField().get(indexField);

                try {
                    boolean isQuoted = false;
                    String actualType = field.getType();
                    if (field.getType().endsWith("(quote)")) {
                        // クオート指定がある場合には、型名称から(quote)を除去します。
                        actualType = field.getType().substring(0,
                                field.getType().length() - "(quote)".length());
                        isQuoted = true;
                    }
                    if (field.getRequired() == false) {
                        // 必要に応じてラッパー型に対応します。
                        if (actualType.equals("int")) {
                            actualType = "java.lang.Integer";
                        } else if (actualType.equals("long")) {
                            actualType = "java.lang.Long";
                        }
                    }

                    serializer.characters("    ");
                    serializer.startElementField();
                    serializer.characters("\n");
                    serializer.characters("      ");

                    if (field.getNo() != null) {
                        serializer.startElementNo();
                        serializer.characters(field.getNo());
                        serializer.endElementNo();
                    }

                    serializer.characters("\n");
                    serializer.characters("      ");
                    serializer.startElementName();
                    serializer.characters(field.getName());
                    serializer.endElementName();
                    serializer.characters("\n");
                    serializer.characters("      ");
                    serializer.startElementType();
                    serializer.characters(actualType);
                    serializer.endElementType();
                    serializer.characters("\n");

                    serializer.characters("      ");
                    serializer.startElementDescription();
                    if (field.getNo() != null) {
                        serializer.characters("項目番号: " + field.getNo() + "\n");
                    }
                    if (field.getDescription() != null) {
                        serializer.characters("項目の説明: "
                                + field.getDescription() + "\n");
                    }
                    if (isQuoted) {
                        serializer.characters("文字列はダブルクオート処理されて入出力されます。\n");
                    }

                    if (field.getMinLength() != null) {
                        serializer.characters("MIN長さ: " + field.getMinLength()
                                + "\n");
                    }
                    if (field.getMaxLength() != null) {
                        serializer.characters("MAX長さ: " + field.getMaxLength()
                                + "\n");
                    }
                    if (field.getRequired()) {
                        serializer.characters("必須項目\n");
                    }
                    serializer.endElementDescription();
                    serializer.characters("\n");

                    if (field.getDefault() != null) {
                        serializer.characters("      ");
                        serializer.startElementDefault();
                        serializer.characters(field.getDefault());
                        serializer.endElementDefault();
                        serializer.characters("\n");
                    }

                    serializer.characters("    ");
                    serializer.endElementField();
                    serializer.characters("\n");
                } catch (SAXException e) {
                    e.printStackTrace();
                }
            }

            serializer.characters("  ");
            serializer.endElementBlancovalueobjectList();
            serializer.characters("\n");
            serializer.endElementSheet();
            serializer.characters("\n");
            serializer.endElementWorkbook();
            serializer.endDocument();

            outStream.flush();
            outStream.close();
            outStream = null;

            new BlancoValueObjectXml2JavaClass().process(filePojoWork,
                    directoryTarget);
            if (isGenerateJUnit) {
                new BlancoValueObjectXml2JUnit().process(filePojoWork,
                        directoryTarget);
            }
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } finally {
            try {
                if (outStream != null) {
                    outStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
