/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JFUDbConnectionUtil
*   ソースファイル名：JFUDbConnectionUtil.java
*   作成者          ：富士通
*   日付            ：2011年09月13日
*＜機能概要＞
*   DBアクセス部品です。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v1.00.00    2011/09/13   FJ）和田    新規作成
*
**********************************************************************/
package eo.web.webview.common;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fujitsu.futurity.web.x31.X31SWebLog;

import eo.common.util.JCCFrameworkException;

/**
 * DBアクセス部品です。
 * <br>
 * @author 富士通
 */
public class JFUDbConnectionUtil
{

	/** DBコネクション */
	private Connection connection = null;

	/**
	 * DBアクセス部品を生成します。
	 * <br>
	 * @param driver JDBCドライバ名
	 * @param url 接続URL情報
	 * @param user 接続ユーザ
	 * @param password 接続パスワード
	 */
	public JFUDbConnectionUtil(String driver, String url, String user, String password)
	{
		this.setConnection(this.getConnection(driver, url, user, password));
	}

	/**
	 * DBアクセス部品を生成します。
	 * <br>
	 */
	public JFUDbConnectionUtil()
	{

	}

	/**
	 * データベースコネクションを取得します。
	 * <br>
	 * @param driver JDBCドライバ名
	 * @param url 接続URL情報
	 * @param user 接続ユーザ
	 * @param password 接続パスワード
	 * @return データベースコネクション
	 */
	public Connection getConnection(String driver, String url, String user, String password)
	{
		Connection conn = null;

		try
		{
			Class.forName(driver);
			conn = DriverManager.getConnection(url, user, password);
		}
		catch (ClassNotFoundException e)
		{
			throw new JCCFrameworkException("DB接続でエラーが発生しました。:" + e.getMessage());
		}
		catch (SQLException e)
		{
			throw new JCCFrameworkException("DB接続でエラーが発生しました。:" + e.getMessage());
		}

		return conn;
	}

	/**
	 * データベースコネクションを設定します。
	 * <br>
	 * @param conn データベースコネクション
	 */
	public void setConnection(Connection conn)
	{
		this.connection = conn;
	}

	/**
	 * データベースコネクションをクローズします。
	 * <br>
	 */
	public void close()
	{
		try
		{
			if (this.connection != null && !this.connection.isClosed())
			{
				this.connection.close();
			}
		}
		catch (SQLException e)
		{
			throw new JCCFrameworkException("DBクローズ処理でエラーが発生しました。:" + e.getMessage());
		}
	}

	/**
	 * SQLを実行します。
	 * 引数（param）はSQLをバインドするパラメータとなります。
	 * <br>
	 * @param sql SQL文
	 * @param param バインドパラメータ
	 * @return SQL取得結果
	 */
	public List<Map<String, Object>> executeQuery(String sql, List<Object> param)
	{
		if (sql == null || "".equals(sql))
		{
			return null;
		}

		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		PreparedStatement statement = null;
		ResultSet resultSet = null;
		ResultSetMetaData resultSetMetaData = null;
		List<String> columnNames = new ArrayList<String>();
		
		//ログ出力(SQL文の出力)
		X31SWebLog.DEBUG_LOG.info("【" + this.getClass() + "】SQL:" + sql);
		X31SWebLog.DEBUG_LOG.info("【" + this.getClass() + "】SQL param:" + (param != null ? param.toString() : ""));

		try
		{

			statement = this.connection.prepareStatement(sql);

			if (param != null)
			{
				for (int i = 0; i < param.size(); i++)
				{
					if (param.get(i) == null)
					{
						statement.setString(i + 1, null);
						continue;
					}

					String clsName = param.get(i).getClass().getName();
					if ("java.lang.String".equals(clsName))
					{
						statement.setString(i + 1, (String)param.get(i));
					}
					else if ("java.math.BigDecimal".equals(clsName))
					{
						statement.setBigDecimal(i + 1, (BigDecimal)param.get(i));
					}
					else if ("java.sql.Timestamp".equals(clsName))
					{
						statement.setTimestamp(i + 1, (Timestamp)param.get(i));
					}
					else
					{
						throw new JCCFrameworkException("対応していないデータ型です。");
					}
				}
			}

			resultSet = statement.executeQuery();

			resultSetMetaData = resultSet.getMetaData();

			for (int i = 0; i < resultSetMetaData.getColumnCount(); i++)
			{
				columnNames.add(resultSetMetaData.getColumnName(i + 1));
			}

			while (resultSet.next())
			{
				Map<String, Object> resultMap = new HashMap<String, Object>();
				String strColumnName = null;

				for (int i = 0; i < columnNames.size(); i++)
				{
					strColumnName = columnNames.get(i);
					if (strColumnName != null && !"".equals(strColumnName))
					{
						resultMap.put(strColumnName, resultSet.getObject(strColumnName));
					}
				}
				resultList.add(resultMap);
			}
		}
		catch (SQLException e)
		{
			throw new JCCFrameworkException("SQL実行でエラーが発生しました。");
		}
		finally
		{
			try{
				if(statement != null){
					statement.close();
				}
				if(resultSet != null){
					resultSet.close();
				}
			}catch(SQLException e){
				throw new JCCFrameworkException("CLOSE処理でエラーが発生しました。");
			}
		}
		return resultList;
	}
}
