/*
 * このソースコードは blanco Frameworkによって自動生成されています。
 */
package blanco.nlpack.generator.csv.io;

import java.io.BufferedWriter;
import java.io.IOException;

import blanco.nlpack.generator.csv.record.BlancoNLpackGeneratorResultCsvRecord;
import blanco.nlpack.generator.csv.util.BlancoCsvRuntimeUtil;

/**
 * ファイル定義[BlancoNLpackGeneratorResult/blancoNLpackGenerator が内部的に利用するCSVファイル。]のライタクラス
 *
 * このクラスはblancoCsvファイル定義書から自動生成されたライタクラスです。<br>
 * 　1.文字列長チェックには、デフォルトエンコーディングを利用します。<br>
 * 　2.クラスの利用した後は必ず close()を呼び出してください。<br>
 */
public class BlancoNLpackGeneratorResultCsvWriter {
    /**
     * ライタオブジェクト
     *
     * 内部的に実際に出力を行うのライタを記憶します。
     */
    private BufferedWriter fWriter;

    /**
     * 処理中の行カウンタ
     *
     * 現在処理を行っている行の位置を記憶します。
     */
    private long fLineCounter = 0;

    /**
     * CSVライタクラスのコンストラクタ
     *
     * 与えられたライタと連結します。
     *
     * @param arg 連結するライタ
     */
    public BlancoNLpackGeneratorResultCsvWriter(final BufferedWriter arg) {
        fWriter = arg;
    }

    /**
     * CSVファイルのタイトル行をを書き出します
     *
     * タイトルはデリミタで区切られながらライタに出力され、最後に改行コードが付与されます。<br>
     * タイトルはダブルクオーテーションで囲まれます。
     *
     * @throws IOException 連結されたライター出力の際に例外が発生した場合。
     */
    public void writeTitle() throws IOException {
        fWriter.write("\"SymbolicName\"");
        fWriter.write(",\"URI\"");
        fWriter.write(",\"Action\"");
        fWriter.write(",\"Hit\"");
        fWriter.write(",\"Mnemon\"");
        fWriter.write(",\"Omit\"");
        fWriter.write(",\"Miss\"");
        fWriter.newLine();
    }

    /**
     * 与えられた一行を書き出します
     *
     * データはデリミタで区切られながらライタに出力され、最後に改行コードが付与されます。
     *
     * @param record レコードオブジェクト
     * @throws BlancoCsvIOException 与えられたレコード中の項目値が不正な場合など。
     * @throws IOException 連結されたライター出力の際に例外が発生した場合。
     */
    public void writeRecord(final BlancoNLpackGeneratorResultCsvRecord record) throws BlancoCsvIOException, IOException {
        String writeToken = null;

        // 項目番号[1] 項目名[BundleSymbolicName/SymbolicName]
        if (record.getBundleSymbolicName() == null) {
            throw new BlancoCsvIOException("出力" + (fLineCounter + 1) + "行目 1項目目。項目番号[1] 項目名[BundleSymbolicName/SymbolicName]の処理中において必須項目にnullが与えられていることを検知しました。");
        }
        if (record.getBundleSymbolicName().length() == 0) {
            throw new BlancoCsvIOException("出力" + (fLineCounter + 1) + "行目 1項目目。項目番号[1] 項目名[BundleSymbolicName/SymbolicName]の処理中において必須項目に長さ0の文字列が与えられていることを検知しました。");
        }
        writeToken = record.getBundleSymbolicName();
        if (writeToken == null) {
            throw new BlancoCsvIOException("出力" + (fLineCounter + 1) + "行目 1項目目。項目番号[1] 項目名[BundleSymbolicName/SymbolicName]の処理中において必須項目にnullが与えられていることを検知しました。");
        }
        // ダブルクオート処理付きで書き出しを行います。
        fWriter.write(BlancoCsvRuntimeUtil.getTokenWithQuote(writeToken));
        fWriter.write(',');

        // 項目番号[2] 項目名[BundleUri/URI]
        // 任意項目で文字列の項目に nullまたは長さ0の文字列が与えられた場合には、いずれも値が入っていないものとみなします。
        // この場合には長さチェックは行いません。
        writeToken = record.getBundleUri() == null ? "" : record.getBundleUri();
        if (writeToken.length() > 0) {
        }
        // ダブルクオート処理付きで書き出しを行います。
        fWriter.write(BlancoCsvRuntimeUtil.getTokenWithQuote(writeToken));
        fWriter.write(',');

        // 項目番号[3] 項目名[Action/Action]
        // 任意項目で文字列の項目に nullまたは長さ0の文字列が与えられた場合には、いずれも値が入っていないものとみなします。
        // この場合には長さチェックは行いません。
        writeToken = record.getAction() == null ? "" : record.getAction();
        if (writeToken.length() > 0) {
            if (writeToken.getBytes().length < 4) {
                throw new BlancoCsvIOException("出力" + (fLineCounter + 1) + "行目 3項目目。項目番号[3] 項目名[Action/Action]の処理中においてMIN長さ(4)よりも短い値[" + writeToken + "]を検知しました。");
            }
            if (writeToken.getBytes().length > 6) {
                throw new BlancoCsvIOException("出力" + (fLineCounter + 1) + "行目 3項目目。項目番号[3] 項目名[Action/Action]の処理中においてMAX長さ(6)よりも長い値[" + writeToken + "]を検知しました。");
            }
        }
        // ダブルクオート処理付きで書き出しを行います。
        fWriter.write(BlancoCsvRuntimeUtil.getTokenWithQuote(writeToken));
        fWriter.write(',');

        // 項目番号[4] 項目名[ReplaceHitCount/Hit]
        writeToken = String.valueOf(record.getReplaceHitCount());
        if (writeToken == null) {
            throw new BlancoCsvIOException("出力" + (fLineCounter + 1) + "行目 4項目目。項目番号[4] 項目名[ReplaceHitCount/Hit]の処理中において必須項目にnullが与えられていることを検知しました。");
        }
        fWriter.write(writeToken);
        fWriter.write(',');

        // 項目番号[5] 項目名[ReplaceMnemonicCount/Mnemon]
        writeToken = String.valueOf(record.getReplaceMnemonicCount());
        if (writeToken == null) {
            throw new BlancoCsvIOException("出力" + (fLineCounter + 1) + "行目 5項目目。項目番号[5] 項目名[ReplaceMnemonicCount/Mnemon]の処理中において必須項目にnullが与えられていることを検知しました。");
        }
        fWriter.write(writeToken);
        fWriter.write(',');

        // 項目番号[6] 項目名[ReplaceOmitCount/Omit]
        writeToken = String.valueOf(record.getReplaceOmitCount());
        if (writeToken == null) {
            throw new BlancoCsvIOException("出力" + (fLineCounter + 1) + "行目 6項目目。項目番号[6] 項目名[ReplaceOmitCount/Omit]の処理中において必須項目にnullが与えられていることを検知しました。");
        }
        fWriter.write(writeToken);
        fWriter.write(',');

        // 項目番号[7] 項目名[ReplaceMissCount/Miss]
        writeToken = String.valueOf(record.getReplaceMissCount());
        if (writeToken == null) {
            throw new BlancoCsvIOException("出力" + (fLineCounter + 1) + "行目 7項目目。項目番号[7] 項目名[ReplaceMissCount/Miss]の処理中において必須項目にnullが与えられていることを検知しました。");
        }
        fWriter.write(writeToken);

        // 最後に改行コードが付与されます。
        fWriter.newLine();
        fLineCounter++;
    }

    /**
     * 内部的に保持しているライタを返します。
     *
     * @return 内部的に保持しているライタ。
     */
    public BufferedWriter getWriter() {
        return fWriter;
    }

    /**
     * 現在処理中の行カウンタを返します。
     *
     * @return 現在処理中の行カウンタ。
     */
    public long getLineCounter() {
        return fLineCounter;
    }

    /**
     * このライタをフラッシュします。
     *
     * 関連づけられていたライタに対してもflush()を呼び出します。
     *
     * @throws IOException 関連づけられていたライタのflush()に失敗した場合。
     */
    public void flush() throws IOException {
        fWriter.flush();
    }

    /**
     * このライタを閉じます。
     *
     * 関連づけられていたライタに対してもclose()を呼び出します。
     *
     * @throws IOException 関連づけられていたライタのclose()に失敗した場合。
     */
    public void close() throws IOException {
        fWriter.close();
    }
}
