/*********************************************************************
*   All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JACejbAC0591DBABase
*   ソースファイル名：JACejbAC0591DBABase.java
*   作成者          ：富士通
*   日付            ：2011年04月21日
*＜機能概要＞
*   FTTH通信明細へのデータベースアクセスクラス
*＜修正履歴＞
*   バージョン  修正日      修正者      修正内容
*   v1.00.00    2011/04/21  富士通      新規作成
*   v24.00.00   2016/02/29  FJ)中原     ANK-2680-00-00_eoアクセスログ収集対応
*
**********************************************************************/

package eo.ejb.common.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import com.fujitsu.futurity.common.JCCWebAddTrnId;
import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.common.JCMTraceLog;
import com.fujitsu.futurity.common.JSYLogBase;
import com.fujitsu.futurity.model.base.CAANFinderException;
import com.fujitsu.futurity.model.base.CAANLog;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRemoveException;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.base.CAANSQLEntity;
import com.fujitsu.futurity.model.base.CAANSchemaInfo;

import eo.ejb.cbm.entity.AC0591ETMsg;

/**
 * <p>
 * FTTH通信明細へのデータベースアクセスクラス。
 * </p>
 * @author 富士通
 */
public class JACejbAC0591DBABase extends JPCejbDBABase
{
	// 新規追加のカラム名
	private static final String [] ADD_COLUMN_LIST = { "ADD_UNYO_YMD",
														  "ADD_TRN_ID",
														  "UPD_UNYO_YMD",
														  "UPD_TRN_ID",
														  "DEL_UNYO_YMD",
														  "DEL_TRN_ID",
																};

	/* 主キー以外で検索キーとして指定すべき項目 請求年月 */ 
	private static final String KEY_SEIKY_YM = "SEIKY_YM";

	/**
	 * <p>
	 * 新しいJACejbAC0591DBABaseを作成します。
	 * </p>
	 */
	public JACejbAC0591DBABase()
	{
		super(AC0591ETMsg.class.getName());
	}

	/**
	 * <p>
	 * 世代を管理するカラム名を取得します。
	 * </p>
	 * @return 世代を管理するカラム名
	 */
	protected String getGenerationColumn()
	{
		return null;
	}

	/**
	 * <p>
	 * 無効状態を管理するカラム名を取得します。
	 * </p>
	 * @return 無効状態を管理するカラム名
	 */
	protected String getInvalidColumn()
	{
		return AC0591ETMsg.MK_FLG;
	}

	/**
	 * <p>
	 * 予約管理エンティティか判定します。
	 * </p>
	 * @return 予約管理エンティティの場合はtrue
	 */
	protected boolean isReserveMgr()
	{
		return false;
	}

	/**
	 * <p>
	 * 予約適用基準日となるカラム名を取得します。
	 * </p>
	 * @return 予約適用基準日となるカラム名
	 */
	protected String getCurrentColumn()
	{
		return null;
	}

	/**
	 * <p>
	 * 予約の状態を管理するエンティティか判定します。
	 * </p>
	 * @return 予約の状態を管理するエンティティの場合はtrue
	 */
	protected boolean isReserveStateMgr()
	{
		return false;
	}

	/**
	 * <p>
	 * 予約の状態を管理するカラム名を取得します。
	 * </p>
	 * @return 予約の状態を管理するカラム名
	 */
	protected String getReserveStateColumn()
	{
		return null;
	}

	/**
	 * 既存のエンティティを更新します。<br>
	 * @param inMsg 更新するエンティティの情報を格納したメッセージキャリア
	 * @return 更新結果を格納したメッセージキャリア<br>
	 * @exception CAANFinderException 指定されたキーのデータが見つからない
	 */
	protected CAANMsg updateFtthTusinDtl(CAANMsg inMsg) throws CAANFinderException {
		
		CAANLog.println(CAANLog.LEVEL_FW, "CALL: JACejbAC0591DBABase#updateFtthTusinDtl");
		JCMTraceLog.logging("JACejbAC0591DBABase#updateFtthTusinDtl");
		
		Connection cnct = null;
		PreparedStatement pstmt = null;
		try {
			//FW改修対応 start
			// Connectionの取得。
			//cnct = getConnection();
			cnct = getConnection(getTableName());
			//FW改修対応 end
			
			//処理ID付与対応　2011/07/31 FST)fujita　start
			// 無効フラグの値で更新か論理削除か判定
			String mkFlg = inMsg.getString("MK_FLG");
			if("1".equals(mkFlg))
			{
				inMsg = setAddNewColumn(inMsg, 3);
			}
			else
			{
				inMsg = setAddNewColumn(inMsg, 2);
			}
			//処理ID付与対応　2011/07/31 FST)fujita　end
			
			String[][] updtList = getParameterList(getExceptedKeyColumnList2(), inMsg);
			String[][] keyList = getKeyColumnList2();
			
			StringBuffer sql = new StringBuffer();
			int clms = updtList[1].length;
			
			sql.append("update ").append(getTableName()).append(" set ");
			for (int i = 0; i < clms; i++) {
				sql.append(updtList[1][i]).append("=?,");
			}
			sql.setLength(sql.length() -1);
			sql.append(" where ").append(getWhereKeyColumnListString(keyList[1]));
			
			CAANLog.println(CAANLog.LEVEL_FW, "sql = [" + sql + "]");
			pstmt = cnct.prepareStatement(sql.toString());
			
			// 2016/02/29 ANK-2680-00-00_eoアクセスログ収集対応 UPDATE START
			// ログ出力タイミングを変更 2012/05/17 FST start
			//outputAccessLog(CAANSQLEntity.class, JSYLogBase.ACCESS_TYPE_UPDATE, sql.toString(), 0);
			outputAccessLog(CAANSQLEntity.class, JSYLogBase.ACCESS_TYPE_UPDATE, sql.toString(), 0, inMsg);
			// ログ出力タイミングを変更 2012/05/17 FST end
			// 2016/02/29 ANK-2680-00-00_eoアクセスログ収集対応 UPDATE END
			
			// update する値の設定
			setParameters(pstmt, 0,   updtList[0], inMsg);
			// where句の値設定
			setParameters(pstmt, clms, keyList[0], inMsg);
			
			int cnt = pstmt.executeUpdate();
			
// 2012/03/20 FST)arata アクセスログ引数の追加 start
			// ログ出力部品改修対応 2010/12/27 FST start
			//outputAccessLog(CAANSQLEntity.class, JSYLogBase.ACCESS_TYPE_UPDATE, sql.toString(), cnt, inMsg);
			// ログ出力部品改修対応 2010/12/27 FST end
// 2012/03/20 FST)arata アクセスログ引数の追加 end
			
			// update = ０件。
			if (cnt == 0) {
				throw new CAANFinderException("MSG00130", "Data is not updated");
			}

			// 正常終了。
			return inMsg;

		} catch (SQLException e) {
			CAANLog.printStackTrace(e);
			throw new CAANRuntimeException(e);
		} finally {
			// このメソッドで確保した資源の解放。
			try {
				if (pstmt != null) {
					pstmt.close();
				}
				if (cnct != null) {
					closeConnection(cnct);
				}
			} catch (SQLException e) {
				throw new CAANRuntimeException(e);
			}
		}
	}

	/**
	 * 指定したキーを持つエンティティを物理的に削除します。<br>
	 * @param inMsg 削除するエンティティのプライマリキー情報を格納したメッセージキャリア
	 * @return	引数のメッセージキャリアをそのまま返す
	 * @exception CAANRemoveException エンティティ削除時のエラーを通知
	 */
	protected CAANMsg removeFtthTusinDtl(CAANMsg inMsg) throws CAANRemoveException {
		
		CAANLog.println(CAANLog.LEVEL_FW, "CALL: JACejbAC0591DBABase#removeFtthTusinDtl");

		Connection cnct = null;
		PreparedStatement pstmt = null;
		try {
			//FW改修対応 start
			//cnct = getConnection();
			cnct = getConnection(getTableName());
			//FW改修対応 end
			
			String[][] keyList = getKeyColumnList2();
			
			StringBuffer sql = new StringBuffer();
			
			sql.append("delete from ").append(getTableName());
			sql.append(" where ").append(getWhereKeyColumnListString(keyList[1]));
			
			CAANLog.println(CAANLog.LEVEL_FW, "sql = [" + sql + "]");
			pstmt = cnct.prepareStatement(sql.toString());
			
			// 2016/02/29 ANK-2680-00-00_eoアクセスログ収集対応 UPDATE START
			// ログ出力タイミングを変更 2012/05/17 FST start
			//outputAccessLog(CAANSQLEntity.class, JSYLogBase.ACCESS_TYPE_DELETE, sql.toString(), 0);
			outputAccessLog(CAANSQLEntity.class, JSYLogBase.ACCESS_TYPE_DELETE, sql.toString(), 0, inMsg);
			// ログ出力タイミングを変更 2012/05/17 FST end
			// 2016/02/29 ANK-2680-00-00_eoアクセスログ収集対応 UPDATE END
			
			// 検索条件設定
			setParameters(pstmt, 0, keyList[0], inMsg);
			
			// SQLの実行。
			int cnt = pstmt.executeUpdate();
			
// 2012/03/20 FST)arata アクセスログ引数の追加 start
			// ログ出力部品改修対応 2010/12/27 FST start
			//outputAccessLog(CAANSQLEntity.class, JSYLogBase.ACCESS_TYPE_DELETE, sql.toString(), cnt, inMsg);
			// ログ出力部品改修対応 2010/12/27 FST end
// 2012/03/20 FST)arata アクセスログ引数の追加 end
			
			// delete = ０件。
			if (cnt == 0) {
				throw new CAANRemoveException("MSG00120", "Data is not deleted");
			}

			// 正常終了。
			return inMsg;

		} catch (SQLException e) {
			throw new CAANRuntimeException(e);
		} finally {
			// このメソッドで確保した資源の解放。
			try {
				if (pstmt != null) {
					pstmt.close();
				}
				if (cnct != null) {
					closeConnection(cnct);
				}
			} catch (SQLException e) {
				throw new CAANRuntimeException(e);
			}
		}
	}

	/**
	 * メッセージに新規カラムの情報を追加します。<br>
	 * @param  inMsg    追加対象のメッセージキャリア
	 * @param  dmlKind  1:登録　2:更新　3:論理削除 
	 * @return		     追加後のメッセージキャリア<br>
	 */
	private CAANMsg setAddNewColumn(CAANMsg inMsg, int dmlKind)
	{
//運用日付対応　2011/08/05 FST)fujita　start
		// スレッドローカルより依頼元IDを取得
		HashMap<String, Object> comMsg = JCCWebAddTrnId.get(JCMConstants.ADD_TRN_ID_MESSAGE_COMMON_MAP);
		// スレッドローカルより運用日付を取得
		HashMap<String, Object> unyoDateMap = JCCWebAddTrnId.get(JCMConstants.ADD_TRN_ID_UNYO_DATE_MAP);
		//HashMap<String, Object> comMsg = JCCWebAddTrnId.get();
//運用日付対応　2011/08/05 FST)fujita　end
		String trnId = (String)comMsg.get(JCMConstants.INVOKE_GAMEN_ID_KEY);
		String callType = (String)comMsg.get(JCMConstants.CALL_TYPE_KEY);
		if("2".equals(callType))  // API
		{
			trnId = trnId.substring(0, 6);  // 依頼元IDから不要な「0PJP」をカット
		}
		// バックヤード、フロント、モバイルの場合
		// 2012/02/15 量販タイプを追加 start
		else if("0".equals(callType) || "1".equals(callType) || "5".equals(callType) || "6".equals(callType))
		// 2012/02/15 量販タイプを追加 end
		{
			trnId = trnId.substring(0, 8);  // 依頼元IDから不要な「0PJP」をカット
		}
		else
		{
			// なにもしない
		}
		
//運用日付対応　2011/08/05 FST)fujita　start
		// 運用日付を取得
		String unyoYmd = null;
		if("4".equals(callType))  // バッチ
		{
			unyoYmd = (String)unyoDateMap.get("BDATE");
		}
		else                     //  バッチ以外
		{
			unyoYmd = (String)unyoDateMap.get("ODATE");
		}
		//String unyoYmd = "20990730"; 
//運用日付対応　2011/08/05 FST)fujita　end
		
		for(int i=0; i<ADD_COLUMN_LIST.length; i++)
		{
			// スキーマに新規カラムがあればCNNAMsgにデータをセットする。
			if(inMsg.containsKeyOfSchema(ADD_COLUMN_LIST[i]))
			{
				if(1 == dmlKind) // 登録
				{
					if(( -1 != ADD_COLUMN_LIST[i].indexOf("ADD")) || ( -1 != ADD_COLUMN_LIST[i].indexOf("UPD")))
					{
						if(-1 != ADD_COLUMN_LIST[i].indexOf("TRN_ID"))  // カラムが処理IDの場合
						{
							inMsg.set(ADD_COLUMN_LIST[i], trnId);
						}
						else  											// カラムが運用日付の場合
						{
							inMsg.set(ADD_COLUMN_LIST[i], unyoYmd);
						}
					}
				}
				if(2 == dmlKind) // 更新
				{
					if(( -1 != ADD_COLUMN_LIST[i].indexOf("UPD")))
					{
						if(-1 != ADD_COLUMN_LIST[i].indexOf("TRN_ID"))  // カラムが処理IDの場合
						{
							inMsg.set(ADD_COLUMN_LIST[i], trnId);
						}
						else  											// カラムが運用日付の場合
						{
							inMsg.set(ADD_COLUMN_LIST[i], unyoYmd);
						}
					}
				}
				if(3 == dmlKind) // 論理削除
				{
					if(( -1 != ADD_COLUMN_LIST[i].indexOf("DEL")) || ( -1 != ADD_COLUMN_LIST[i].indexOf("UPD")))
					{
						if(-1 != ADD_COLUMN_LIST[i].indexOf("TRN_ID"))  // カラムが処理IDの場合
						{
							inMsg.set(ADD_COLUMN_LIST[i], trnId);
						}
						else  											// カラムが運用日付の場合
						{
							inMsg.set(ADD_COLUMN_LIST[i], unyoYmd);
						}
					}
					
				}
			}
		}
		return inMsg;
	}

    /**
	 * 指定されたスキーマ項目名とＤＢカラム名のリストのスキーマ項目の値が、
	 * 指定されたメッセージに設定されていたら
	 * 取り出して新しいスキーマ項目名とＤＢカラム名のリストを構成します。
	 *
	 * @param clmList 元となるスキーマ項目名とＤＢカラム名のリスト
	 * @param inMsg メッセージ
     * @return 再構成されたスキーマ項目名とＤＢカラム名のリスト
	 */
	@SuppressWarnings("unchecked")
	protected String[][] getParameterList(String[][] clmList, CAANMsg inMsg) {
		
		ArrayList msgList = new ArrayList();
		ArrayList dbList = new ArrayList();
		
		int cnt = clmList[0].length;
		for (int i = 0; i < cnt; i++) {
			String key = clmList[0][i];
			if (inMsg.containsKeyOfMsgData(key)) {
				dbList.add(clmList[1][i]);
				msgList.add(key);
			}
		}
		String[] msgClm = (String[])msgList.toArray(new String[0]);
		String[] dbClm  = (String[])dbList.toArray(new String[0]);
		return new String[][] {msgClm, dbClm};
	}

    /**
     * このエンティティのスキーマから、プライマリキー項目以外のＤＢ項目の
     * スキーマ項目名とＤＢカラム名のリストを取得します。<br>
     * キャッシュして高速化を行なう場合は、業務レベルでオーバーライドしてください。
     * インデックス０にスキーマ項目名のリスト、
     * インデックス１にＤＢカラム名のリストが設定されます。
     * @return プライマリキー項目以外のＤＢ項目のスキーマ項目名とＤＢカラム名のリスト
     */
    @SuppressWarnings("unchecked")
	protected String[][] getExceptedKeyColumnList2() {
		
		Object[][] contents = getSchemaContents();
		
		ArrayList msgList = new ArrayList();
		ArrayList dbList = new ArrayList();
		
		int cnt = contents.length;
		for (int i = 0; i < cnt; i++) {
			if (contents[i][2] != null 
				&& !CAANSchemaInfo.PRIMARYKEY.equals(contents[i][3]) && !KEY_SEIKY_YM.equals(contents[i][2])) {
				dbList.add(contents[i][2]);
				msgList.add(contents[i][0]);
			}
		}
		
		String[] msgClm = (String[])msgList.toArray(new String[0]);
		String[] dbClm  = (String[])dbList.toArray(new String[0]);
		return new String[][] {msgClm, dbClm};
	}

    /**
     * このエンティティのスキーマから、プライマリキー項目の
     * スキーマ項目名とＤＢカラム名のリストを取得します。<br>
     * キャッシュして高速化を行なう場合は、業務レベルでオーバーライドしてください。
     * インデックス０にスキーマ項目名のリスト、
     * インデックス１にＤＢカラム名のリストが設定されます。
     * @return プライマリキー項目のスキーマ項目名とＤＢカラム名のリスト
     */
    @SuppressWarnings("unchecked")
	protected String[][] getKeyColumnList2() {
		
		Object[][] contents = getSchemaContents();
		
		ArrayList msgList = new ArrayList();
		ArrayList dbList = new ArrayList();
		
		int cnt = contents.length;
		for (int i = 0; i < cnt; i++) {
			if (CAANSchemaInfo.PRIMARYKEY.equals(contents[i][3]) || KEY_SEIKY_YM.equals(contents[i][2])) {
				dbList.add(contents[i][2]);
				msgList.add(contents[i][0]);
			}
		}
		
		String[] msgClm = (String[])msgList.toArray(new String[0]);
		String[] dbClm  = (String[])dbList.toArray(new String[0]);
		return new String[][] {msgClm, dbClm};
	}

}
