/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatKKMansRsvIfCheckSyk
*	ソースファイル名	：JBSbatKKMansRsvIfCheckSyk.java
*	作成者				：富士通　
*	作成日				：2012年05月31日
*＜機能概要＞
*　マンション受信情報チェック（集約）部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2012/05/31  富士通		新規作成
*	v56.00.00	2021/11/26  富士通)杉本	【ANK-4127-00-00】eSMエラー整合性チェック改善対応
*********************************************************************/
package eo.business.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.StringTokenizer;

import eo.business.common.JBSbatBusinessService;
import eo.business.util.file.JBSbatKKIFM204;
import eo.business.util.table.JBSbatZM_M_WORK_PARAM_KNRI;
import eo.framework.application.JBSbatBusinessError;
import eo.framework.application.JBSbatBusinessException;
import eo.framework.db.JBSbatSQLAccess;
import eo.framework.item.JBSbatCommonDBInterface;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.item.JBSbatServiceInterfaceMap;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/
public class JBSbatKKMansRsvIfCheckSyk extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/

	/** テーブルアクセスクラス(業務パラメータ)*/
	private JBSbatSQLAccess db_ZM_M_WORK_PARAM_KNRI = null;

	/** テーブル(業務パラメータ)*/ 
	private static final String D_TBL_NAME_ZM_M_WORK_PARAM_KNRI = "ZM_M_WORK_PARAM_KNRI";
	/** SQL定義キー(KK_SELECT_016)*/
	private static final String ZM_M_WORK_PARAM_KNRI_KK_SELECT_016 = "KK_SELECT_016";
	/** ファイル区分 */
	private String fileDiv = "";
	/** 運用日 */
	String unyo_ymd = null;
	/** オーナー情報エラー件数閾値 */
	private int ownrErrCnt = 0;
	/** 提供方式情報エラー件数閾値 */
	private int tkhkErrCnt = 0;
	/** 料金情報エラー件数閾値 */
	private int ryknErrCnt = 0;
	/** キャンペーン情報エラー件数閾値 */
	private int campErrCnt = 0;
	// ANK-4127-00-00 ADD START
	/** 判別文字列(マンションオーナーチェックエラーファイル) */
	private static final String KKIFM199_JDG_STR = "KKIFM199";
	/** 判別文字列(マンション提供方式情報エラーファイル) */
	private static final String KKIFM200_JDG_STR = "KKIFM200";
	/** 判別文字列(マンション料金情報エラーファイル) */
	private static final String KKIFM201_JDG_STR = "KKIFM201";
	/** 判別文字列(マンションキャンペーン情報エラーファイル) */
	private static final String KKIFM202_JDG_STR = "KKIFM202";
	/** エラー区分：1(オーナー) */
	private static final String ERR_KBN_1 = "1";
	/** エラー区分：2(オーナー以外) */
	private static final String ERR_KBN_2 = "2";
	// ANK-4127-00-00 ADD END
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);
		//運用年月日
		unyo_ymd = commonItem.getOpeDate();

		db_ZM_M_WORK_PARAM_KNRI = new JBSbatSQLAccess(commonItem, D_TBL_NAME_ZM_M_WORK_PARAM_KNRI);
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/
	/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 主処理
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		String fileList = this.commonItem.getFreeItem();
		String[] files = fileList.split("@");

		// 出力共通電文を生成する。
		JBSbatOutputItem outputBean = new JBSbatOutputItem();

		if(files != null && files.length != 0)
		{
			// ANK-4127-00-00 MOD START
//			HashSet<String> pidmap = new HashSet<String>();
			HashMap<String, ArrayList<String>> keyMap = new HashMap<String, ArrayList<String>>();
			// ANK-4127-00-00 MOD END
			//業パラ取得
			getGyouPrm();

			int fileCnt = 1;
			for(String file : files)
			{
				this.logPrint.printDebugLog("読込みファイル名：" + file);
				ArrayList<ArrayList<String>> result = convCsvFiletoList(file);

				for(ArrayList<String> linedata :result)
				{
					// ANK-4127-00-00 MOD START
//					String pid = linedata.get(1);
//					pidmap.add(pid);
//					this.logPrint.printDebugLog("エラー出力されたP-ID：" + pid);
					
					//必要情報の抽出
					//P-IDを抽出
					String pid = linedata.get(1);
					
					//エラー区分を設定
					String errKbn = getErrKbn(file);
					String tgtFileName = file.substring(file.indexOf("KKIFM"), file.indexOf("KKIFM")+8);
					
					//M-IDを抽出
					//CAT-ID,Cat-M管理番号を抽出
					String mid = "";
					String catid = "";
					//KKIFM199(マンションオーナーチェックエラーファイル)以外を抽出
					//KKIFM200(マンション提供方式情報エラーファイル)は3番目,12番目から抽出
					if(tgtFileName.equals(KKIFM200_JDG_STR))
					{
						mid = linedata.get(2);
						catid = linedata.get(11);
					}
					//KKIFM201(マンション料金情報エラーファイル),KKIFM202(マンションキャンペーン情報エラーファイル)は
					//4番目,6番目から抽出
					else if(tgtFileName.equals(KKIFM201_JDG_STR) || tgtFileName.equals(KKIFM202_JDG_STR))
					{
						mid = linedata.get(3);
						catid = linedata.get(5);
					}
					
					//必要情報を格納用ArrayListへ追加
					ArrayList<String> tgtData = new ArrayList<String>();
					tgtData.add(pid);
					tgtData.add(mid);
					tgtData.add(catid);
					tgtData.add(errKbn);
					
					//格納用ArrayListを出力用Mapへ追加
					keyMap.put(pid+mid+catid+errKbn, tgtData);
					
					//エラー情報のLog出力
					this.logPrint.printDebugLog("エラー出力されたP-ID：" + pid
							+ ",エラー出力されたM-ID：" + mid
							+ ",エラー出力されたCAT-M管理番号：" + catid + ",エラー区分：" + errKbn);
					// ANK-4127-00-00 MOD END
				}
				if(0 < result.size())
				{
					if(!checkErrCnt(fileCnt, result.size()))
					{
						// エラーフラグ設定
						super.commonItem.setErrFlg(true);
						//%1%の%2%に不正があります。（%3%）
						commonItem.getLogPrint().printBusinessErrorLog("EKKB0310JW",
								new String[]{"エラー", "件数", "閾値オーバー " + fileDiv});
						throw new JBSbatBusinessError();
					}
				}
				fileCnt++;
			}

			// ANK-4127-00-00 MOD START
//			Iterator<String> it = pidmap.iterator();
//
//			while(it.hasNext())
//			{
//				String pidout = it.next();
//				//入出力インターフェースオブジェクトを生成
//				JBSbatServiceInterfaceMap outmap = new JBSbatServiceInterfaceMap();
//				outmap.set(JBSbatKKIFM204.P_ID, pidout);
//				//出力フラグを設定
//				outmap.setOutFlg(true);
//				outputBean.addOutMapList(outmap);
//			}
			Iterator<ArrayList<String>> it = keyMap.values().iterator();
			
			while(it.hasNext())
			{
				ArrayList<String> outValue = it.next();
				//入出力インターフェースオブジェクトを生成
				JBSbatServiceInterfaceMap outmap = new JBSbatServiceInterfaceMap();
				outmap.set(JBSbatKKIFM204.P_ID, outValue.get(0));
				outmap.set(JBSbatKKIFM204.M_ID, outValue.get(1));
				outmap.set(JBSbatKKIFM204.CAT_M_KNRI_NO, outValue.get(2));
				outmap.set(JBSbatKKIFM204.ERR_KBN, outValue.get(3));

				//出力フラグを設定
				outmap.setOutFlg(true);
				outputBean.addOutMapList(outmap);
			}
			// ANK-4127-00-00 MOD END
		}

		return outputBean;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
		db_ZM_M_WORK_PARAM_KNRI.close();
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/

	/**
	 * 引数で指定されたCSVファイル名からファイルの内容を一行ずつ読取り、カンマ区切りの文字を
	 * List格納する。格納した行データのArrayListをArrayList配列に順番に格納し返却する。
	 * 引数で指定されたファイルパスを取得し、返却する。
	 * @param commonItem バッチ共通パラメータ電文
	 * @param fileName ファイル名(パスを含む)
	 * @return ArrayList ファイル内データを格納したリスト
	 * @throws Exception 例外
	 */
	private ArrayList<ArrayList<String>> convCsvFiletoList(String fileName) throws Exception
	{
		ArrayList<ArrayList<String>> csvFileList = new ArrayList<ArrayList<String>>();
		FileReader fr = null;
		BufferedReader br = null;

		// CSV指定ファイルパスチェック
		if(null == fileName || ("").equals(fileName))
		{
			throw new JBSbatBusinessException("EKKB0130CE", 
					new String[] { "読込ファイルパス未設定" });
		}

		try
		{
			// CSV指定ファイル読込み
			File file = new File(fileName);
			fr = new FileReader(file);
			br = new BufferedReader(fr);
			ArrayList<String> workList = null;
			String lineData = "";

			while (null != lineData)
			{
				// ワークリストを初期化
				workList = new ArrayList<String>();

				// CSVファイル一行読込み
				lineData = br.readLine();
				if(null != lineData && !("").equals(lineData))
				{
					// リストに格納された一行分のファイルデータを格納
					workList = convStringToList(lineData);
					csvFileList.add(workList);
				}
			}
		}
		catch (IOException e)
		{
			// 例外処理
			throw new JBSbatBusinessException("EKKB0020CE", new String[]{fileName});
		}
		finally
		{
	        // ストリームを閉じる
	        if(null != br )
	        {
	            br.close();
	        }
	        if(null != fr)
	        {
	        	fr.close();
	        }
		}
		return csvFileList;
	}

	/**
	 * 引数で指定されたCSVファイルの一行データを項目ごとにArrayList格納する。
	 * @param commonItem バッチ共通パラメータ電文
	 * @param lineData 一行分のCSVデータ
	 * @return ArrayList 項目ごとにCSVデータを格納したList
	 * @throws Exception 例外
	 **/
	private ArrayList<String> convStringToList(String lineData) throws Exception
	{
		// 戻り値格納用List
		ArrayList<String> resultList = new ArrayList<String>();

		// CSV指定ファイル読込み
		// 文字列リスト変換エスケープ処理に囲み文字の"を指定して呼出す。
		resultList = convEscapeStringToList(lineData, '"');

		return resultList;
	}

	/**
	 * 引数で指定されたCSVファイルの一行データを項目ごとに分割し、
	 * 引数の囲い文字を除外した状態でList格納する。
	 * @param  line 一行分のCSVデータ
	 * @param  kakoiMoji 囲み文字
	 * @return ArrayList 項目ごとにCSVデータを格納したList
	 * @throws Exception 例外
	 */
	private ArrayList<String> convEscapeStringToList(String line, char kakoiMoji) throws Exception
	{
		// 戻り値格納用List
		ArrayList<String> resultList = new ArrayList<String>();

		StringTokenizer st = new StringTokenizer(line, ",");
		StringBuffer bf = new StringBuffer();
		int len = 0;

		while (st.hasMoreElements())
		{
			String s = st.nextToken();
			bf = new StringBuffer();
			bf.append(s);
			len = bf.length();

			// 先頭文字が囲み文字の場合除去
			if(bf.charAt(0) == (kakoiMoji))
			{
				bf.delete(0, 1);
				len = len - 1;
			}

			// 終端文字が囲み文字の場合除去
			// ANK-4127-00-00 MOD START
//			if(len > 1 && bf.charAt(len - 1) == (kakoiMoji))
			if(len > 0 && bf.charAt(len - 1) == (kakoiMoji))
			// ANK-4127-00-00 MOD END
			{
				bf.delete(len - 1, len);
			}

			// 戻り値となるリストに1項目分のデータ格納
			resultList.add(bf.toString());
		}

		// 1行分のデータを格納したListを返却
		return resultList;
	}
	
	/**
	 * 業務パラメータから指定した値を取得します。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.DBアクセスを実行します。<br>
	 *
	 * </pre>
	 * <p>
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ
	 * @param Map				taknkiki_map　テーブルMap
	 *		param:バイント変数は以下に説明します。
	 *            業務パラメータＩＤ
	 * @return ArrayList<String> リスト
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private String executeZM_M_WORK_PARAM_KNRI_KK_SELECT_001(String paramId) throws Exception
	{
		ArrayList<String> resMap = new ArrayList<String>();

		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
		paramList.setValue(paramId);
		paramList.setValue(unyo_ymd);
		paramList.setValue(unyo_ymd);

		// DBアクセスを実行します
		db_ZM_M_WORK_PARAM_KNRI.selectBySqlDefine(paramList, ZM_M_WORK_PARAM_KNRI_KK_SELECT_016);

		JBSbatCommonDBInterface mapdata = new JBSbatCommonDBInterface();
		while((mapdata = db_ZM_M_WORK_PARAM_KNRI.selectNext()) != null)
		{
			resMap.add(mapdata.getString(JBSbatZM_M_WORK_PARAM_KNRI.WORK_PARAM_SETTE_VALUE));
		}
		//登録されていない場合
		if(0 == resMap.size()) return "2000";

		return resMap.get(0);
	}
	//業パラ取得
	private void getGyouPrm() throws Exception
	{
		ownrErrCnt = Integer.parseInt(
				executeZM_M_WORK_PARAM_KNRI_KK_SELECT_001("KK_MANS_OWNER_NUM"));

		tkhkErrCnt = Integer.parseInt(
				executeZM_M_WORK_PARAM_KNRI_KK_SELECT_001("KK_MANS_TKN_NUM"));

		ryknErrCnt = Integer.parseInt(
				executeZM_M_WORK_PARAM_KNRI_KK_SELECT_001("KK_MANS_PRC_NUM"));

		campErrCnt = Integer.parseInt(
				executeZM_M_WORK_PARAM_KNRI_KK_SELECT_001("KK_MANS_CAMP_NUM"));

		this.logPrint.printDebugLog("オーナー情報エラー件数閾値:"+ ownrErrCnt +
				" 提供方式情報エラー件数閾値:"+ tkhkErrCnt +
				" 料金情報エラー件数閾値:"+ ryknErrCnt +
				" キャンペーン情報エラー件数閾値:"+ campErrCnt);
	}

	// ANK-4127-00-00 ADD START
	/**
	 * エラー区分を作成する
	 * @param file 処理中のファイルパス
	 * @return エラー区分
	 */
	private String getErrKbn(String file)
	{
		//ファイル名の「KKIFM[0-9]{3}」を取得
		//KKIFMの位置を検索し、そこから8文字を取得
		int charPoint = file.indexOf("KKIFM");
		String tgtJdgStr = file.substring(charPoint, charPoint+8);
		String resultKbn = "";
		
		//ファイルによってエラー区分を設定する
		if (tgtJdgStr.equals(KKIFM199_JDG_STR))
		{
			resultKbn = ERR_KBN_1;
		}
		else
		{
			resultKbn = ERR_KBN_2;
		}
		
		return resultKbn;
	}
	// ANK-4127-00-00 ADD END
	//エラー件数チェック
	private boolean checkErrCnt(int fileCnt, int list)
	{
		boolean rslt = false;
		if(1 == fileCnt)
		{
			if(list >= ownrErrCnt)
			{
				fileDiv = "オーナー:" + list;
				this.logPrint.printDebugLog("マンションレプリカ受信チェック処理で" + ownrErrCnt +
						"件以上のエラーを検出しました。処理を終了します。(オーナー:"+ list +")");
				return rslt;
			}
		}
		else if(2 == fileCnt)
		{
			if(list >= tkhkErrCnt)
			{
				fileDiv = "提供方式:" + list;
				this.logPrint.printDebugLog("マンションレプリカ受信チェック処理で" + tkhkErrCnt +
						 "件以上のエラーを検出しました。処理を終了します。(提供方式:"+ list +")");
				return rslt;
			}
		}
		else if(3 == fileCnt)
		{
			if(list >= ryknErrCnt)
			{
				fileDiv = "料金:" + list;
				this.logPrint.printDebugLog("マンションレプリカ受信チェック処理で" + ryknErrCnt + 
						"件以上のエラーを検出しました。処理を終了します。(料金:"+ list +")");
				return rslt;
			}
		}
		else if(4 == fileCnt)
		{
			if(list >= campErrCnt)
			{
				fileDiv = "キャンペーン:" + list;
				this.logPrint.printDebugLog("マンションレプリカ受信チェック処理で" + campErrCnt +
						"件以上のエラーを検出しました。処理を終了します。(キャンペーン:"+ list +")");
				return rslt;
			}
		}
		return true;
	}
}
