/*
 * DelimitedLineRecordWriterTest.java
 * Copyright (C) 2008 Cyber Beans Corporation. All rights reserved.
 */
package jp.co.cybec.cb3.accessor.fileaccess.flat.delimited;

import java.util.LinkedHashMap;
import java.util.Map;

import jp.co.cybec.cb3.accessor.fileaccess.flat.FlatFileRecord;
import jp.co.cybec.cb3.accessor.fileaccess.flat.delimited.DelimitedLineRecordWriter;
import jp.co.cybec.cb3.exception.AccessorNotOpenException;
import jp.co.cybec.cb3.exception.ConfigFileNotFoundException;
import jp.co.cybec.cb3.exception.DataFormatException;
import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * {@link DelimitedLineRecordWriter} のテストケース。
 * @author Juanjuan Wang
 */
public class DelimitedLineRecordWriterTest {

	private DelimitedLineRecordWriter delimitedWriter = null;
	private FlatFileRecord record = null;

	/** append："true"、separator：","、quotechar："&quot;"、lineSeparator："\r\n"、encode："Shift_JIS"の場合、書き込み用 正常ファイル */
	private static final String CONFIG_WRITE1 = "jp/co/cybec/cb3/accessor/fileaccess/flat/delimited/writer/writeConfig1.xml";

	/** append："false"、separator：""、quotechar：""、lineSeparator：""、encode：""の場合、書き込み用 正常ファイル  */
	private static final String CONFIG_WRITE2 = "jp/co/cybec/cb3/accessor/fileaccess/flat/delimited/writer/writeConfig2.xml";

	/** 可変長のライターのミニマムセットの場合、書き込み用 正常ファイル */
	private static final String CONFIG_WRITE3 = "jp/co/cybec/cb3/accessor/fileaccess/flat/delimited/writer/writeConfig3.xml";

	/** パターンクラスが設定された場合、書き込み用 正常ファイル */
	private static final String CONFIG_WRITE4 = "jp/co/cybec/cb3/accessor/fileaccess/flat/delimited/writer/writeConfig6.xml";

	/** ユーザー定義クラスが存在しない */
	private static final String CONFIG_WRITE5 = "jp/co/cybec/cb3/accessor/fileaccess/flat/delimited/writer/writeConfig7.xml";

	/** ファイルがオープンされていない */
	private static final String CONFIG_WRITE6 = "jp/co/cybec/cb3/accessor/fileaccess/flat/delimited/writer/writeConfig3.xml";

	/** パターンクラスの場合、文字列をフォーマットする時に、例外が発生する */
	private static final String CONFIG_WRITE7 = "jp/co/cybec/cb3/accessor/fileaccess/flat/delimited/writer/writeConfig8.xml";

	/** FlatFileRecordデータが作成用 正常ファイル */
	private static final String CONFIG_CREATE_RECORD1 = "jp/co/cybec/cb3/accessor/fileaccess/flat/delimited/writer/writeConfig4.xml";

	/** FlatFileRecordデータがNULL */
	private static final String CONFIG_CREATE_RECORD2 = "jp/co/cybec/cb3/accessor/fileaccess/flat/delimited/writer/writeConfig5.xml";

	/** 正常データファイル */
	private static final String FILE_NORMAL= "src/test/testdata/delimited/test_write.csv";

	/**
	 * @throws Exception
	 */
	@Before
	public void setUp() throws Exception {
		delimitedWriter = new DelimitedLineRecordWriter();
	}

	/**
	 * @throws Exception
	 */
	@After
	public void tearDown() throws Exception {
		delimitedWriter.release();
	}

	/**
	 * {@link DelimitedLineRecordWriter#initialize(String)} のためのテスト・メソッド。<br>
	 * 例外が発生しないことを確認する。
	 */
	@Test
	public void testInitialize() {
		delimitedWriter.initialize(CONFIG_WRITE1);
	}

	/**
	 * {@link DelimitedLineRecordWriter#initialize(String)} のためのテスト・メソッド。<br>
	 * 引数に存在しないキー（設定ファイル）を指定したときに例外が発生することを確認する。
	 */
	@Test(expected = ConfigFileNotFoundException.class)
	public void testInitializeConfigFileNotFoundException() {
		delimitedWriter.initialize("aaa");
	}

	/**
	 * {@link DelimitedLineRecordWriter#open(String)} のためのテスト・メソッド。
	 * 例外が発生しないことを確認する。
	 */
	@Test
	public void testOpenString() {
		delimitedWriter.initialize(CONFIG_WRITE1);
		delimitedWriter.open(FILE_NORMAL);
	}

	/**
	 * {@link DelimitedLineRecordWriter#write(FlatFileRecord)} のためのテスト・メソッド。
	 * 正しくレコードがファイルに書き込みできることをを確認する。
	 * append： "true"
	 * separator：","
	 * quotechar： "&quot;"
	 * encode   ： "Shift_JIS"
	 * lineSeparator："\r\n"
	 */
	@Test
	public void testWrite01() {
		// 予想データ
		LinkedHashMap<String, String> fileRecordMap = new LinkedHashMap<String, String>();
		fileRecordMap.put("intField", "1");
		fileRecordMap.put("strField1", "tests\"tring1");
		fileRecordMap.put("strField2", "test変数の１２３");
		fileRecordMap.put("dateField1", "2001/05/23 07:12:23");
		fileRecordMap.put("dateField2", "2002/02/23 00:00:00");
		fileRecordMap.put("dateField3", "2001/05/23 07:12:23");
		fileRecordMap.put("longField", "123456789120325");
		fileRecordMap.put("shortField", "1045852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("doubleField", "18975125355445852642.1022");
		fileRecordMap.put("floatField", "5125355445852642.2");

		// 設定ファイルを読み込む
		delimitedWriter.initialize(CONFIG_WRITE1);
		delimitedWriter.open();
		record = delimitedWriter.createFlatFileRecord(fileRecordMap);
		delimitedWriter.write(record);
		delimitedWriter.write(record);
		delimitedWriter.write(record);
	}

	/**
	 * {@link DelimitedLineRecordWriter#write(FlatFileRecord)} のためのテスト・メソッド。
	 * 正しくレコードがファイルに書き込みできることをを確認する。
	 * append： "false"
	 * separator：なし
	 * quotechar：なし
	 * encode   ：なし
	 * lineSeparator：なし
	 */
	@Test
	public void testWrite02() {
		// 予想データ
		LinkedHashMap<String, String> fileRecordMap = new LinkedHashMap<String, String>();
		fileRecordMap.put("intField", "1");
		fileRecordMap.put("strField1", "tests\"tring1");
		fileRecordMap.put("strField2", "test変数の１２３");
		fileRecordMap.put("dateField1", "2001/05/23 07:12:23");
		fileRecordMap.put("dateField2", "2002/02/23 00:00:00");
		fileRecordMap.put("dateField3", "2001/05/23 07:12:23");
		fileRecordMap.put("longField", "123456789120325");
		fileRecordMap.put("shortField", "1045852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("doubleField", "18975125355445852642.1022");
		fileRecordMap.put("floatField", "5125355445852642.2");

		// 設定ファイルを読み込む
		delimitedWriter.initialize(CONFIG_WRITE2);
		delimitedWriter.open();
		record = delimitedWriter.createFlatFileRecord(fileRecordMap);
		delimitedWriter.write(record);
		delimitedWriter.write(record);

	}

	/**
	 * {@link DelimitedLineRecordWriter#write(FlatFileRecord)} のためのテスト・メソッド。
	 * 可変長のライターのミニマムセットの場合、正しくレコードがファイルに書き込みできることをを確認する。
	 */
	@Test
	public void testWrite03() {
		// 予想データ
		LinkedHashMap<String, String> fileRecordMap = new LinkedHashMap<String, String>();
		fileRecordMap.put("intField", "1");
		fileRecordMap.put("strField1", "tests\"tring1");
		fileRecordMap.put("strField2", "test変数の１２３");
		fileRecordMap.put("dateField1", "2001/05/23 07:12:23");
		fileRecordMap.put("dateField2", "2002/02/23 00:00:00");
		fileRecordMap.put("dateField3", "2001/05/23 07:12:23");
		fileRecordMap.put("longField", "123456789120325");
		fileRecordMap.put("shortField", "1045852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("doubleField", "18975125355445852642.1022");
		fileRecordMap.put("floatField", "5125355445852642.2");

		// 設定ファイルを読み込む
		delimitedWriter.initialize(CONFIG_WRITE3);
		delimitedWriter.open();
		record = delimitedWriter.createFlatFileRecord(fileRecordMap);
		delimitedWriter.write(record);
		delimitedWriter.write(record);
		delimitedWriter.write(record);

	}

	/**
	 * {@link DelimitedLineRecordWriter#write(FlatFileRecord)} のためのテスト・メソッド。
	 * パターンクラスが設定された場合、正しくレコードがファイルに書き込みできることをを確認する。
	 */
	@Test
	public void testWrite04() {
		// 予想データ
		LinkedHashMap<String, String> fileRecordMap = new LinkedHashMap<String, String>();
		fileRecordMap.put("intField", "1");
		fileRecordMap.put("strField1", "tests\"tring1");
		fileRecordMap.put("strField2", "test変数の１２３");
		fileRecordMap.put("dateField1", "2001/05/23 07:12:23");
		fileRecordMap.put("dateField2", "2002/02/23 00:00:00");
		fileRecordMap.put("dateField3", "2001/05/23 07:12:23");
		fileRecordMap.put("longField", "123456789120325");
		fileRecordMap.put("shortField", "1045852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("doubleField", "18975125355445852642.1022");
		fileRecordMap.put("floatField", "5125355445852642.2");

		// 設定ファイルを読み込む
		delimitedWriter.initialize(CONFIG_WRITE4);
		delimitedWriter.open();
		record = delimitedWriter.createFlatFileRecord(fileRecordMap);
		delimitedWriter.write(record);
		delimitedWriter.write(record);
		delimitedWriter.write(record);
	}

	/**
	 * {@link DelimitedLineRecordWriter#write(FlatFileRecord)} のためのテスト・メソッド。
	 * パターンクラスが設定された場合、ユーザー定義クラスが存在しないで例外が発生することを確認する。
	 */
	@Test(expected = DataFormatException.class)
	public void testWrite05() {
		// 予想データ
		LinkedHashMap<String, String> fileRecordMap = new LinkedHashMap<String, String>();
		fileRecordMap.put("intField", "1");
		fileRecordMap.put("strField1", "tests\"tring1");
		fileRecordMap.put("strField2", "test変数の１２３");
		fileRecordMap.put("dateField1", "2001/05/23 07:12:23");
		fileRecordMap.put("dateField2", "2002/02/23 00:00:00");
		fileRecordMap.put("dateField3", "2001/05/23 07:12:23");
		fileRecordMap.put("longField", "123456789120325");
		fileRecordMap.put("shortField", "1045852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("doubleField", "18975125355445852642.1022");
		fileRecordMap.put("floatField", "5125355445852642.2");

		// 設定ファイルを読み込む
		delimitedWriter.initialize(CONFIG_WRITE5);
		delimitedWriter.open();
		record = delimitedWriter.createFlatFileRecord(fileRecordMap);
		delimitedWriter.write(record);

	}

	/**
	 * {@link DelimitedLineRecordWriter#write(FlatFileRecord)} のためのテスト・メソッド。
	 * ファイルがオープンされていない場合、例外が発生することを確認する。
	 */
	@Test(expected = AccessorNotOpenException.class)
	public void testWrite06() {
		// 予想データ
		LinkedHashMap<String, String> fileRecordMap = new LinkedHashMap<String, String>();
		fileRecordMap.put("intField", "1");
		fileRecordMap.put("strField1", "tests\"tring1");
		fileRecordMap.put("strField2", "test変数の１２３");
		fileRecordMap.put("dateField1", "2001/05/23 07:12:23");
		fileRecordMap.put("dateField2", "2002/02/23 00:00:00");
		fileRecordMap.put("dateField3", "2001/05/23 07:12:23");
		fileRecordMap.put("longField", "123456789120325");
		fileRecordMap.put("shortField", "1045852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("doubleField", "18975125355445852642.1022");
		fileRecordMap.put("floatField", "5125355445852642.2");

		// 設定ファイルを読み込む
		delimitedWriter.initialize(CONFIG_WRITE6);
		record = delimitedWriter.createFlatFileRecord(fileRecordMap);
		delimitedWriter.write(record);
	}

	/**
	 * {@link DelimitedLineRecordWriter#write(FlatFileRecord)} のためのテスト・メソッド。
	 * パターンクラスが設定された場合、文字列をフォーマットする時に、例外が発生することを確認する。
	 */
	@Test(expected = DataFormatException.class)
	public void testWrite07() {
		// 予想データ
		LinkedHashMap<String, String> fileRecordMap = new LinkedHashMap<String, String>();
		fileRecordMap.put("intField", "#1");
		fileRecordMap.put("strField1", "tests\"tring1");
		fileRecordMap.put("strField2", "test変数の１２３");
		fileRecordMap.put("dateField1", "2001/05/23 07:12:23");
		fileRecordMap.put("dateField2", "2002/02/23 00:00:00");
		fileRecordMap.put("dateField3", "2001/05/23 07:12:23");
		fileRecordMap.put("longField", "123456789120325");
		fileRecordMap.put("shortField", "1045852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("bigField", "18975125355445852642");
		fileRecordMap.put("doubleField", "18975125355445852642.1022");
		fileRecordMap.put("floatField", "5125355445852642.2");

		// 設定ファイルを読み込む
		delimitedWriter.initialize(CONFIG_WRITE7);
		delimitedWriter.open();
		record = delimitedWriter.createFlatFileRecord(fileRecordMap);
		delimitedWriter.write(record);
	}

	/**
	 * {@link DelimitedLineRecordWriter#createFlatFileRecord(Map)} のためのテスト・メソッド。
	 * 正しいFlatFileRecordデータが作成することを確認する。
	 */
	@Test
	public void testCreateFlatFileRecord01() {
		// 予想データ
		LinkedHashMap<String, String> fileRecordMap = new LinkedHashMap<String, String>();
		fileRecordMap.put("intField", "1");
		fileRecordMap.put("strField1", "teststring1");
		fileRecordMap.put("strField2", "teststring2");
		fileRecordMap.put("dateField1", "2001/05/23 07:12:23");

		// 設定ファイルを読み込む
		delimitedWriter.initialize(CONFIG_CREATE_RECORD1);
		delimitedWriter.open();
		record = delimitedWriter.createFlatFileRecord(fileRecordMap);
		delimitedWriter.write(record);

		// 結果をチェックする
		Assert.assertEquals("1", record.toMap().get("intField").toString());
		Assert.assertEquals("teststring1", record.toMap().get("strField1").toString());
		Assert.assertEquals("teststring2", record.toMap().get("strField2").toString());
		Assert.assertEquals("2001/05/23 07:12:23", record.toMap().get("dateField1").toString());
	}

	/**
	 * {@link DelimitedLineRecordWriter#createFlatFileRecord(Map)} のためのテスト・メソッド。
	 * FlatFileRecordデータがNULLを確認する。
	 */
	@Test
	public void testCreateFlatFileRecord02() {
		LinkedHashMap<String, String> fileRecordMap = null;

		// 設定ファイルを読み込む
		delimitedWriter.initialize(CONFIG_CREATE_RECORD2);
		delimitedWriter.open();
		record = delimitedWriter.createFlatFileRecord(fileRecordMap);
		delimitedWriter.write(record);
	}

}
