/*
 * CB3JdbcTemplateTest.java
 * Copyright (C) 2008 Cyber Beans Corporation. All rights reserved.
 */
package jp.co.cybec.cb3.accessor.dbaccess;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;

import jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate;
import jp.co.cybec.cb3.accessor.dbaccess.DBAccessConfig;
import jp.co.cybec.cb3.accessor.dbaccess.DBQueryParameterMap;
import jp.co.cybec.cb3.util.ConfigurationLoader;
import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;

/**
 *
 * CB3JdbcTemplateクラスのテストケース
 * @author Lijuan Sun
 */
public class CB3JdbcTemplateTest {

	private ApplicationContext context = null;

	private CB3JdbcTemplate cb3JdbcTemplate = null;

	private static String[] CONTEXT_XML_PATH = new String[] {
			"jp/co/cybec/cb3/accessor/dbaccess/TestDBAccessConfig.xml",
			"datasourceContext.xml",
			"transactionContext.xml"
		};

	private DBQueryParameterMap parameter = null;
	//  SQL文をキャッシュする
	private Map<String, String> sqlCache = new HashMap<String,String>();

	@Before
	public void setup(){
		//インスタンスを作成する
		context = new ClassPathXmlApplicationContext(CONTEXT_XML_PATH);
		cb3JdbcTemplate = (CB3JdbcTemplate) context.getBean("CB3JdbcTemplate");

		// 設定ファイルを読み込む
		DBAccessConfig info = (DBAccessConfig) ConfigurationLoader
		.load("dbaccessConfigRule.xml","jp/co/cybec/cb3/accessor/dbaccess/dbaccessConfig.xml");

		// クエリー用SQL
		for (int i=0; i<info.getSelectSql().size(); i++) {
			sqlCache.put(info.getSelectSql().get(i).getId(),
			 info.getSelectSql().get(i).getSelect());
		}
		// 更新用SQL
		for (int i=0; i<info.getUpdateSql().size(); i++) {
			sqlCache.put(info.getUpdateSql().get(i).getId(),
			 info.getUpdateSql().get(i).getUpdate());
		}
		//インサート用SQL
		for (int i=0; i<info.getInsertSql().size(); i++) {
			sqlCache.put(info.getInsertSql().get(i).getId(),
			 info.getInsertSql().get(i).getInsert());
		}
		// 削除用SQL
		for (int i=0; i<info.getDeleteSql().size(); i++) {
			sqlCache.put(info.getDeleteSql().get(i).getId(),
			 info.getDeleteSql().get(i).getDelete());
		}

		// テーブルをクリアする
		cb3JdbcTemplate.update(sqlCache.get("delete1"));
		// パラメータを設定する
		parameter = new DBQueryParameterMap();
		parameter.put("EMP_NAME", "abcde");
		parameter.put("EMP_CELLULAR_PHONE", "123456789");
		parameter.put("EMP_BIRTH", "19800101");
		parameter.put("EMP_SEX", "1");

	}

	@After
	public void teardown(){
		cb3JdbcTemplate.close();
	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 *
	 */
	@Test
	public void testGetJdbcTemplate() {
		Assert.assertNotNull(cb3JdbcTemplate.getJdbcTemplate());

	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 * 正常クローズテスト
	 */
	@Test
	public void testClose() {
		try {
			// パラメータを設定する
			parameter.put("EMP_CODE", "tst01");

			// データをインサートする
			cb3JdbcTemplate.update(sqlCache.get("insert1"), parameter);
			// データを取得する
			ResultSet rs = cb3JdbcTemplate.query(sqlCache.get("select1"), parameter);
			// クローズする
			cb3JdbcTemplate.close();

			rs.next();
		} catch (Exception e) {
			// 結果チェック
			if (!(e instanceof SQLException)){
				Assert.fail("テスト失敗");
			}
		}
	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 * パラメータを付ける場合
	 * 正常クリアテスト
	 *
	 */
	@Test
	public void testQueryStringMapOfStringObject01() {
		try {

			// パラメータを設定する
			parameter.put("EMP_CODE", "tst01");

			// データをインサートする
			cb3JdbcTemplate.update(sqlCache.get("insert1"), parameter);
			// データを取得する
			ResultSet rs = cb3JdbcTemplate.query(sqlCache.get("select1"), parameter);
			// 結果チェック
			Assert.assertNotNull(rs);

			if(rs.next()){
				Assert.assertEquals("tst01", rs.getString("EMP_CODE"));
				Assert.assertEquals("abcde", rs.getString("EMP_NAME"));
				Assert.assertEquals(DateFormat.getDateInstance().parse("1980/01/01"), rs.getDate("EMP_BIRTH"));
			} else {
				Assert.fail("テスト失敗");
			}
		} catch (SQLException e) {
			e.printStackTrace();
			Assert.fail("テスト失敗");
		} catch (ParseException e) {
			e.printStackTrace();
			Assert.fail("テスト失敗");
		}
	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 * パラメータを付ける場合
	 * クエリー時エラー発生テスト
	 *
	 */
	@Test
	public void testQueryStringMapOfStringObject02() {
		try {
			// パラメータを設定する
			parameter.put("EMP_CODE", "tst01");
			// データをインサートする
			cb3JdbcTemplate.update(sqlCache.get("insert1"), parameter);
			// データを取得する
			cb3JdbcTemplate.query("select * from", parameter);

		} catch(Exception e){
			// 結果チェック
			if (!(e instanceof DataAccessException)){
				Assert.fail("テスト失敗");
			}
		}
	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 * パラメータを付けない場合
	 * 正常クエリーテスト
	 *
	 */
	@Test
	public void testQueryString01() {
		try {
		   	// パラメータを設定する
			parameter.put("EMP_CODE", "tst01");

			// データをインサートする
			cb3JdbcTemplate.update(sqlCache.get("insert1"), parameter);
			// 件数を取得する
			ResultSet rs = cb3JdbcTemplate.query(sqlCache.get("select2"));
			// 結果チェック
			Assert.assertNotNull(rs);
			if(rs.next()){
				Assert.assertEquals(1, rs.getInt("count"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
			Assert.fail("テスト失敗");
		}
	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 * パラメータを付けない場合
	 * クエリー時エラー発生テスト
	 *
	 */
	@Test
	public void testQueryString02() {
		try {
			// 件数を取得する
			cb3JdbcTemplate.query(sqlCache.get("select3"));

		} catch(Exception e){
			// 結果チェック
			if (!(e instanceof DataAccessException)){
				Assert.fail("テスト失敗");
			}
		}
	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 * パラメータを付ける場合
	 * 正常インサートテスト
	 */
	@Test
	public void testUpdateStringMapOfStringObject01() {

	   	// パラメータを設定する
		parameter.put("EMP_CODE", "tst01");

		// データをインサートする
		// 結果チェック
		Assert.assertEquals(1, cb3JdbcTemplate.update(sqlCache.get("insert1"), parameter));
	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 * パラメータを付ける場合
	 * インサート時エラー発生テスト
	 */
	@Test
	public void testUpdateStringMapOfStringObject02() {

		try{
		   	// パラメータを設定する
			parameter.put("EMP_CODE", "tst01");

			// データをインサートする
			cb3JdbcTemplate.update(sqlCache.get("insert1"), parameter);

		}catch(Exception e){
			// 結果チェック
			if (!(e instanceof DataAccessException)){
				Assert.fail("テスト失敗");
			}
		}
	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 * パラメータを付けない場合
	 * 正常削除テスト
	 */
	@Test
	public void testUpdateString01() {

		String code = null;
	   	// パラメータを設定する
		for(int i=0; i<5; i++){
			code = "tst0" + String.valueOf(i);
			parameter.put("EMP_CODE", code);
			Assert.assertEquals(1,cb3JdbcTemplate.update(sqlCache.get("insert1"), parameter));
		}
		// 結果チェック
		Assert.assertEquals(5,cb3JdbcTemplate.update(sqlCache.get("delete1")));
	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 * パラメータを付けない場合
	 * 削除時エラー発生テスト
	 *
	 */
	@Test
	public void testUpdateString02() {

		try{
		   	// パラメータを設定する
			Assert.assertEquals(1,cb3JdbcTemplate.update("delete * from"));
		}catch(Exception e){
			// 結果チェック
			if (!(e instanceof DataAccessException)){
				Assert.fail("テスト失敗");
			}
		}
	}

	/**
	 * {@link jp.co.cybec.cb3.accessor.dbaccess.CB3JdbcTemplate} のためのテスト・メソッド。
	 * 正常コミットテスト
	 *
	 */
	@Test
	public void testCommit01() {
		// key
		String code = null;
		try{

			for(int i=0; i<5; i++){
				if (i==4){
					// 五件目エラー発生
					code = "tst01";
				} else{
					code = "tst0" + String.valueOf(i);
				}
				parameter.put("EMP_CODE", code);
				Assert.assertEquals(1,cb3JdbcTemplate.update(sqlCache.get("insert1"), parameter));
				if (i==3){
					//４件をコミットする
					cb3JdbcTemplate.commit();
				}
			}
		}catch(Exception e){
			if (!(e instanceof DataAccessException)){
				Assert.fail("テスト失敗");
			}
		} finally{
			// 結果チェック
			Assert.assertEquals(4,cb3JdbcTemplate.update(sqlCache.get("delete1")));
		}
	}

}
