/*********************************************************************
 *  All Rights reserved,Copyright (c) K-Opticom
 **********************************************************************
 *＜プログラム内容＞
 *	システム名			：eo顧客基幹システム
 *	モジュール名		：JBSbatFUEfoLogFileInput
 *	ソースファイル名	：JBSbatFUEfoLogFileInput.java
 *	作成者				：富士通
 *	作成日				：2012年04月03日
 *＜機能概要＞
 *　ＥＦＯログファイル取込部品です。
 *＜修正履歴＞
 *	バージョン	修正日		修正者		修正内容
 *	v1.00		2012/04/03	富士通		新規作成
 *	v4.00		2012/11/07	FJ)小林		【TAI-2012-0000XXX】date関数使用不可対応
 *	v4.01		2012/12/11	FJ)大塚		IT2-2012-0002009対応
 *	v4.02		2013/03/26	FJ)井上		入力時間半角数字7桁変換（"NaN"）
 *	v4.03		2013/04/02	FJ)井上		入力時間半角数字7桁変換（1時間以上）
 *	v8.00		2014/04/04	FJ)西川		【OM-2014-0001347 】EFOログファイルのヘッダー部複数対応
 *	v32.00		2017/05/24	FJ)鈴木		【OM-2017-0000419】画面URLが未設定の場合にスキップする対応
 *********************************************************************/
package eo.business.service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;

import eo.business.common.JBSbatBusinessService;
import eo.business.common.JFUBatCommon;
import eo.common.constant.JFUStrConst;
import eo.common.constant.JPCBatchMessageConstant;
import eo.common.util.JPCUtilCommon;
import eo.framework.application.JBSbatBusinessException;
import eo.framework.db.JBSbatSQLAccess;
import eo.framework.file.JBSbatInputFileUtil;
import eo.framework.item.JBSbatCommonDBInterface;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatOutputItem;

/**
 * (クラスの機能概要)
 * <p>
 *<BR>
 *
 * @author 富士通
 */
public class JBSbatFUEfoLogFileInput extends JBSbatBusinessService {
	/** ▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼ */
	/** テーブル(ＥＦＯログワーク) */
	private static final String D_TBL_NAME_FU_T_EFO_LOG_WK = "FU_T_EFO_LOG_WK";

	/** SQL定義キー(FU_DELETE_001) */
	private static final String FU_T_EFO_LOG_WK_FU_DELETE_001 = "FU_DELETE_001";

	/** SQL定義キー(FU_UPDATE_001) */
	private static final String FU_T_EFO_LOG_WK_FU_INSERT_001 = "FU_INSERT_001";

	/** SQL定義キー(FU_SELECT_003) */
	private static final String FU_T_EFO_LOG_WK_FU_SELECT_003 = "FU_SELECT_003";

	/** テーブルアクセスクラス(ＥＦＯログワーク) */
	private JBSbatSQLAccess db_FU_T_EFO_LOG_WK = null;
	/** ▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲ */

	/** メッセージキー */
	private static final String EFUB0030KE = JPCBatchMessageConstant.EFUB0030KE;

	/** メッセージキー */
	private static final String EFUB0060AI = JPCBatchMessageConstant.EFUB0060AI;

	/** メッセージキー */
	private static final String EFUB0070AI = JPCBatchMessageConstant.EFUB0070AI;

	/** メッセージキー */
	private static final String EFUB0140KE = JPCBatchMessageConstant.EFUB0140KE;

	/** メッセージキー */
	private static final String EFUB0210KE = JPCBatchMessageConstant.EFUB0210KE;

// 2017.05.24 OM-2017-0000419 ADD START
	/** メッセージキー */
	private static final String EFUB0230AW = JPCBatchMessageConstant.EFUB0230AW;
//2017.05.24 OM-2017-0000419 ADD END
	
	/** iNPUTファイル名の拡張子(ファイル名:日付+.csv) */
	private static final String STR_OUT_FILE_FORMAT = ".csv";

	/** 画面IDのメッセージ */
	private static final String STR_GAMID_MSG = "画面ID";

	/** ミリ秒埋め込み用 */
	private static final String S_MSEC = "000";

	/** core.jsエラー用 */
	private static final String NAN = "NaN";

	/** 入力時間（input_time）上限値 */
	private static final BigDecimal INPUT_TIME_MAX_VALUE = new BigDecimal(
			3600000);

	/**
	 * 初期処理
	 *
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	@Override
	public void initial(JBSbatCommonItem commonItem) throws Exception {
		/** ▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼ */
		/** ▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼ */
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);

		// DBアクセスクラスを生成します
		db_FU_T_EFO_LOG_WK = new JBSbatSQLAccess(commonItem,
				D_TBL_NAME_FU_T_EFO_LOG_WK);
		/** ▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲ */
		/** ▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲ */
	}

	/**
	 * 主処理
	 *
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute() throws Exception {
		/** ▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼ */

		String strFreeParam0 = JFUStrConst.EMPTY; // ディレクトリパス格納用変数初期化
		String strFreeParam1 = JFUStrConst.EMPTY; // 分割後の第一引数格納変数初期化
		String strFreeParam2 = JFUStrConst.EMPTY; // 分割後の第二引数格納変数初期化
		int iecUpdateNum = 0; // EFOログワークの登録件数

		// パラメータ読み出し
		String strFreeParam = commonItem.getFreeItem();

		// パラメータを区切り文字で分割する
		String[] lines = strFreeParam.split(JFUStrConst.S_PARAM_DELIM);

		if (lines.length == 3) {
			// ディレクトリpass取得
			strFreeParam0 = lines[0];

			// パラメータ個数が2個(ディレクトリpass + 日付2つ)の場合は第一引数と第二引数の期間を読込ファイル名とする
			strFreeParam1 = lines[1];
			strFreeParam2 = lines[2];

			// パラメータの妥当性チェック
			if (!JFUBatCommon.isDateFormat(strFreeParam1)) {
				throw new JBSbatBusinessException(EFUB0030KE);
			}
			if (!JFUBatCommon.isDateFormat(strFreeParam2)) {
				throw new JBSbatBusinessException(EFUB0030KE);
			}
		} else {
			// パラメータ個数が4個以上(ディレクトリpass + 日付3つ以上)の場合はエラーとする
			throw new JBSbatBusinessException(EFUB0030KE);
		}

		// 処理実行前にEFOログワークテーブルデータを全件削除
		JBSbatCommonDBInterface dbList1 = new JBSbatCommonDBInterface();
		executeFU_T_EFO_LOG_WK_FU_DELETE_001(dbList1.getList().toArray());

		// strFreeParam1からstrFreeParam2の日付までEFOlog連携ファイルを読込む
		for (String strAddDay = strFreeParam1; Integer.parseInt(strFreeParam2) >= Integer
				.parseInt(strAddDay); strAddDay = JPCUtilCommon.addDay(
				strAddDay, 1)) {
			int iFileReadNum = 0; // EFOログファイルの読込み件数

			ArrayList<String> efoLogFileList = null;
			try {
				efoLogFileList = readFile(strFreeParam0 + strAddDay
						+ STR_OUT_FILE_FORMAT);
			} catch (Exception e) {
				throw new JBSbatBusinessException(EFUB0210KE,
						new String[] { strFreeParam0 + strAddDay
								+ STR_OUT_FILE_FORMAT });
			}

			// ヘッダー部の2行中の1行目を判断するフラグ（ヘッダー部の2行中の1行目の場合に「true」）
			boolean isHeaderFirstFlg = false;

			for (int i = 0; i < efoLogFileList.size(); i++) {
				String line = efoLogFileList.get(i);
				if (!JFUBatCommon.isNotNullCheck(line)) {
					// 空白行の場合は読み飛ばす。
					continue;
				}

				// レコードを取得し、JFUStrConst.EMPTYを削除後、区切り文字で分割する
				String[] efoLogList = line.replace("\"", JFUStrConst.EMPTY)
						.split(JFUStrConst.S_SEP_CAM);

				if (efoLogList.length == 2) {
					// ヘッダー部の2行中の1行目をカンマ分割を行った場合のサイズは、2となる。

					isHeaderFirstFlg = true;

					// ヘッダー部の2行中の1行目の場合は読み飛ばす。
					continue;
				} else if (isHeaderFirstFlg) {

					isHeaderFirstFlg = false;

					// ヘッダー部の2行中の2行目の場合は読み飛ばす。
					continue;
				}

// 2017.05.24 OM-2017-0000419 ADD START
				if (!JFUBatCommon.isNotNullCheck(efoLogList[0])) {
					// 先頭項目の「画面URL」が未設定の場合は読み飛ばす(業務ログに出力する。アラームは出力しない。)
					super.logPrint.printBusinessErrorLog(EFUB0230AW, new String[] { line });
					continue;
				}
// 2017.05.24 OM-2017-0000419 ADD END

				// EFOログファイル番号を取得（+1加算）
				executeFU_T_EFO_LOG_WK_FU_SELECT_003();
				String strEfoLogileKNo = db_FU_T_EFO_LOG_WK.selectNext()
						.getString("SEQ_NEXTVAL");
				String strEfoLogileKNoSeq = JFUBatCommon.strZeroPad(
						strEfoLogileKNo, 10);

				// EFOログファイル(データ部)の読込み件数をカウントする
				iFileReadNum++;

				// EFOログワークテーブルへレコード登録
				JBSbatCommonDBInterface dbList = new JBSbatCommonDBInterface();
				dbList.setValue(strEfoLogileKNoSeq); // EFOログワーク番号
				dbList.setValue(JFUStrConst.S_SYSTEM_CD); // システムコード
				int iGamIdNum = efoLogList[0].indexOf(JFUStrConst.S_SYSTEM_CD); // システムコードの開始位置を取得
				if (iGamIdNum >= 0) {
					dbList.setValue(efoLogList[0].substring(iGamIdNum,
							iGamIdNum + 8)); // 画面IDの取得を行う。
				} else {
					throw new JBSbatBusinessException(EFUB0140KE, new String[] {
							strFreeParam0 + strAddDay + STR_OUT_FILE_FORMAT,
							String.valueOf(iFileReadNum), STR_GAMID_MSG }); // 画面IDが存在しない場合はエラー終了する
				}
				dbList.setValue(efoLogList[0]); // 画面URL
				dbList.setValue(efoLogList[1]); // フィールド名
				dbList.setValue(efoLogList[2]); // エラー理由ルール名
				dbList.setValue(efoLogList[3]); // 文字数

				// 入力時間が"NaN"または1時間を超える場合
				if (efoLogList[4] != null
						&& !JFUStrConst.EMPTY.equals(efoLogList[4])
						&& (NAN.equals(efoLogList[4]) || INPUT_TIME_MAX_VALUE
								.compareTo(new BigDecimal(efoLogList[4])) < 0))

				{
					// 入力時間に「3600000（ミリ秒＝1時間）」を設定
					dbList.setValue(3600000);
				} else {
					dbList.setValue(efoLogList[4]); // 入力時間
				}

				dbList.setValue(efoLogList[5]); // 必須入力項目有無
				dbList.setValue(efoLogList[6]); // 入力エラー有無
				dbList.setValue(efoLogList[7]); // ページ入力完了フラグ
				dbList.setValue(efoLogList[8]); // ページ読込完了フラグ
				dbList.setValue(efoLogList[9]); // 申込完了フラグ
				dbList.setValue(efoLogList[10]); // クッキーID
				dbList.setValue(efoLogList[11]); // セッションID
				dbList.setValue(efoLogList[12].replace("-", JFUStrConst.EMPTY)
						.replace(JFUStrConst.HALF_COLON, JFUStrConst.EMPTY)
						.replace(JFUStrConst.HALF_SPACE, JFUStrConst.EMPTY)
						+ S_MSEC); // 集計年月日時分秒
				dbList.setValue(efoLogList[13].replace("-", JFUStrConst.EMPTY)
						.replace(JFUStrConst.HALF_COLON, JFUStrConst.EMPTY)
						.replace(JFUStrConst.HALF_SPACE, JFUStrConst.EMPTY)
						+ S_MSEC); // EFO作成年月日時分秒
				dbList.setValue(efoLogList[14].replace("-", JFUStrConst.EMPTY)
						.replace(JFUStrConst.HALF_COLON, JFUStrConst.EMPTY)
						.replace(JFUStrConst.HALF_SPACE, JFUStrConst.EMPTY)
						+ S_MSEC); // EFO更新年月日時分秒
				dbList.setValue(efoLogList[15]); // ブラウザ名

				if (efoLogList.length < 17) {
					dbList.setValue(JFUStrConst.EMPTY); // OS名
				} else {
					dbList.setValue(efoLogList[16]); // OS名
				}

				executeFU_T_EFO_LOG_WK_FU_INSERT_001(dbList.getList().toArray());

				iecUpdateNum++;

			}
			super.logPrint.printBusinessErrorLog(EFUB0070AI, new String[] {
					strFreeParam0 + strAddDay + STR_OUT_FILE_FORMAT,
					String.valueOf(iFileReadNum) });
		}
		super.logPrint.printBusinessErrorLog(EFUB0060AI, new String[] {
				D_TBL_NAME_FU_T_EFO_LOG_WK, String.valueOf(iecUpdateNum) });

		return null;
		/** ▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲ */
	}

	/**
	 * 業務サービス終了処理
	 *
	 * @throws Exception
	 */
	@Override
	public void terminal() throws Exception {
		/** ▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼ */
		/** ▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼ */
		// DBアクセスクラスをクローズします
		db_FU_T_EFO_LOG_WK.close();
		/** ▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲ */
		/** ▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲ */
	}

	/** ▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼ */

	/**
	 * SQLKEY(FU_DELETE_001)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 *
	 * <pre>
	 * 1.引数でバイント変数を設定します。<br>
	 *
	 * 2.DBアクセスを実行します。<br>
	 *
	 * 3.メソッドの呼び出し方です。<br>
	 * 	引数:
	 * 	param:順にバイント変数の値をparam配列に入れます。バイント変数は以下に説明します。
	 * </pre>
	 * <p>
	 *
	 * @param param バイント変数の値配列。
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void executeFU_T_EFO_LOG_WK_FU_DELETE_001(Object[] param)
			throws Exception {
		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();

		// DBアクセスを実行します
		db_FU_T_EFO_LOG_WK.executeBySqlDefine(paramList,
				FU_T_EFO_LOG_WK_FU_DELETE_001);
	}

	/**
	 * SQLKEY(FU_INSERT_001)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 *
	 * <pre>
	 * 1.引数でバイント変数を設定します。<br>
	 *
	 * 2.DBアクセスを実行します。<br>
	 *
	 * 3.メソッドの呼び出し方です。<br>
	 * 	引数:
	 * 	param:順にバイント変数の値をparam配列に入れます。バイント変数は以下に説明します。
	 * 	 	EFOログワーク番号
	 * 	 	システムコード
	 * 	 	画面ID
	 * 	 	画面URL
	 * 	 	フィールド名
	 * 	 	エラー理由ルール名
	 * 	 	文字数
	 * 	 	入力時間
	 * 	 	必須入力項目有無
	 * 	 	入力エラー有無
	 * 	 	ページ入力完了フラグ
	 * 	 	ページ読込完了フラグ
	 * 	 	申込完了フラグ
	 * 	 	クッキーID
	 * 	 	セッションID
	 * 	 	集計年月日時分秒
	 * 	 	EFO作成年月日時分秒
	 * 	 	EFO更新年月日時分秒
	 * 	 	ブラウザ名
	 * 	 	OS名
	 * </pre>
	 * <p>
	 *
	 * @param param バイント変数の値配列。
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void executeFU_T_EFO_LOG_WK_FU_INSERT_001(Object[] param)
			throws Exception {
		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
		paramList.setValue(param[0].toString());
		paramList.setValue(param[1].toString());
		paramList.setValue(param[2].toString());
		paramList.setValue(param[3].toString());
		paramList.setValue(param[4].toString());
		paramList.setValue(param[5].toString());
		paramList.setValue(param[6].toString());
		paramList.setValue(param[7].toString());
		paramList.setValue(param[8].toString());
		paramList.setValue(param[9].toString());
		paramList.setValue(param[10].toString());
		paramList.setValue(param[11].toString());
		paramList.setValue(param[12].toString());
		paramList.setValue(param[13].toString());
		paramList.setValue(param[14].toString());
		paramList.setValue(param[15].toString());
		paramList.setValue(param[16].toString());
		paramList.setValue(param[17].toString());
		paramList.setValue(param[18].toString());
		paramList.setValue(param[19].toString());

		// DBアクセスを実行します
		db_FU_T_EFO_LOG_WK.executeBySqlDefine(paramList,
				FU_T_EFO_LOG_WK_FU_INSERT_001);
	}

	/**
	 * SQLKEY(FU_SELECT_003)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 *
	 * <pre>
	 * 1.引数でバイント変数を設定します。<br>
	 *
	 * 2.DBアクセスを実行します。<br>
	 *
	 * 3.メソッドの呼び出し方です。<br>
	 * 	引数:
	 * 	param:順にバイント変数の値をparam配列に入れます。バイント変数は以下に説明します。
	 * </pre>
	 * <p>
	 *
	 * @throws Exception
	 *             業務サービス内で発生した例外全般。
	 */
	private void executeFU_T_EFO_LOG_WK_FU_SELECT_003() throws Exception {
		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();

		// DBアクセスを実行します
		db_FU_T_EFO_LOG_WK.selectBySqlDefine(paramList,
				FU_T_EFO_LOG_WK_FU_SELECT_003);
	}

	/** ▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲ */

	/**
	 * ファイル読み込み処理を行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 *
	 * <pre>
	 * 1.引数で読込ファイルディレクトリ(フルパス)を設定します。<br>
	 *
	 * 2.引数を元にファイル読込を行い、行をListへ格納します。<br>
	 *
	 * </pre>
	 * <p>
	 *
	 * @param strFileDir
	 *            出力ディレクトリ(フルパス)。
	 * @return resultList 返却用List
	 * @throws Exception
	 *             業務サービス内で発生した例外全般。
	 */
	private static ArrayList<String> readFile(String strFileDir)
			throws Exception {
		ArrayList<String> resultList = new ArrayList<String>();

		// 外部出力ファイルパス
		JBSbatInputFileUtil inFile = new JBSbatInputFileUtil(strFileDir);
		inFile.setEncode(JFUStrConst.SJIS); // 文字コード
		inFile.setLine(JFUStrConst.S_LINE_SEPARAOR_LF); // 改行コード
		inFile.createReader();

		try {
			while (true) {
				String line = inFile.readLine();
				if (line == null) {
					break;
				}
				resultList.add(line);
			}

			return resultList;
		} catch (IOException e) {
			throw e;
		} finally {
			if (inFile != null) {
				inFile.close();
			}
		}
	}
}
