/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatCHDelTgSknFix
*	ソースファイル名	：JBSbatCHDelTgSknFix.java
*	作成者				：富士通　
*	作成日				：2013年07月12日
*＜機能概要＞
*　削除対象債権確定部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v5.00.00	2013/07/12  富士通		新規作成
*	v6.00.00	2013/11/18  FJ)伊藤		【】入力変更に伴い処理変更
*********************************************************************/
package eo.business.service;

import java.util.ArrayList;
import java.util.HashMap;

import eo.business.common.JACbatDebugLogUtil;
import eo.business.common.JBSbatBusinessService;
import eo.business.util.file.JBSbatCHIFM191;
import eo.business.util.file.JBSbatCHIFM192;
import eo.business.util.file.JBSbatCHIFM205;
import eo.business.util.file.JBSbatCHIFM206;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatServiceInterfaceMap;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.util.JBSbatAplConst;
import eo.framework.file.JBSbatDefFileUtil;
import eo.framework.file.JBSbatInputFileUtil;
import eo.common.constant.JACStrConst;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/
public class JBSbatCHDelTgSknFix extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/
	
	/** 固定値：削除拒否「"0"」 */
	private final String DEL_NG = "0";
	
	/** 固定値：削除許可「"1"」 */
	private final String DEL_OK = "1";
	
	/** APLConstのプロパティ名：入力ファイル定義 */
	private final String IND = "IND";
	
	/** 債権削除可否情報マップ */
	private HashMap<String, String> saikenSakujoInfoMap = new HashMap<String, String>();

	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][initial]");
		
		//フリーからいろいろ分割
		String[] freeItems = commonItem.getFreeItem().split(";");
		
		//削除候補ファイル定義
		String delKouhoListDef = freeItems[0];
		
		//削除候補ファイルパス
		String delKouhoListPath = freeItems[1];
		
		//請求債権関連ファイル定義
		String delSaikenSeikyListDef = freeItems[2];
		
		//請求債権関連ファイルパス
		String delSaikenSeikyListPath = freeItems[3];
		
		//督促債権関連ファイル定義
		String delSaikenTokusokuListDef = freeItems[4];
		
		//督促債権関連ファイルパス
		String delSaikenTokusokuListPath = freeItems[5];
		
		//請求削除可否情報マップ
		HashMap<String, String> seikySakujoInfoMap = new HashMap<String, String>();
		
		//督促削除可否情報マップ
		HashMap<String, String> tokusokuSakujoInfoMap = new HashMap<String, String>();
		
		//請求関連情報リスト
		ArrayList<String[]> seikyRelationSaiken = new ArrayList<String[]>();
		
		//督促関連情報リスト
		ArrayList<String[]> tokusokuRelationSaiken = new ArrayList<String[]>();

		//ファイルを全て読み込み、全レコードをマップに代入
		for (JBSbatServiceInterfaceMap inMap : getMaps(delKouhoListDef, delKouhoListPath))
		{
			//削除債権番号取得
			String saikenNumber = inMap.getString(JBSbatCHIFM191.SAIKEN_NO);
			
			//削除許可でセット
			saikenSakujoInfoMap.put(saikenNumber, DEL_OK);
		}
		
		for (JBSbatServiceInterfaceMap inMap : getMaps(delSaikenSeikyListDef, delSaikenSeikyListPath))
		{
			//紐付けを作成
			String[] relation = {inMap.getString(JBSbatCHIFM205.SEIKY_NO), inMap.getString(JBSbatCHIFM205.SAIKEN_NO)};
			
			//紐付けを追加
			seikyRelationSaiken.add(relation);
			
			//請求チェック
			setDeleteNg(seikySakujoInfoMap, relation);
		}
		
		for (JBSbatServiceInterfaceMap inMap : getMaps(delSaikenTokusokuListDef, delSaikenTokusokuListPath))
		{
			//紐付けを作成
			String[] relation = {inMap.getString(JBSbatCHIFM206.TOKUSOKU_NO), inMap.getString(JBSbatCHIFM206.SAIKEN_NO)};
			
			//紐付けを追加
			tokusokuRelationSaiken.add(relation);
			
			//督促チェック
			setDeleteNg(tokusokuSakujoInfoMap, relation);
		}
		
		//相互反映により変更されたかどうかをみるフラグ（初回のためにtrue）
		boolean seikyChangeFlag = true;
		boolean tokusokuChangeFlag = true;
		
		//督促、請求の相互反映を行う。どちらも変更がなくなるまで繰り返す。
		while(seikyChangeFlag || tokusokuChangeFlag)
		{
			seikyChangeFlag = sougoHanei(seikySakujoInfoMap, seikyRelationSaiken);
			tokusokuChangeFlag = sougoHanei(tokusokuSakujoInfoMap, tokusokuRelationSaiken);
		}

		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][initial]");
	/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/**
	 * ファイルから全レコードを取得
	 * 
	 * @param id 定義ファイルID
	 * @return 全レコードマップ
	 * @throws Exception スローされる例外
	 */
	private ArrayList<JBSbatServiceInterfaceMap> getMaps(String id,String filePath) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getMaps]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getMaps][id=" + id + "]");
		
		//全レコードマップを格納するリスト配列を用意
		ArrayList<JBSbatServiceInterfaceMap> inMaps = new ArrayList<JBSbatServiceInterfaceMap>();
		
		//レコードの文字列を保管する変数
		String record = JACStrConst.KARA_MOJI;
		
		//各ファイルを取得
		JBSbatInputFileUtil readFile = new JBSbatInputFileUtil(filePath);
		readFile.setLine(JACStrConst.LINE_LF);
		readFile.setEncode(JACStrConst.ENCODE_SJIS);
		readFile.createReader();
		
		JBSbatDefFileUtil fileDef = getFileDefUtil(id, readFile);
		
		//ファイルのレコードを全て読む
		while (readFile.ready())
		{
			//一行読んで
			record = readFile.readLine();
			

			//マップとして配列に挿入
			inMaps.add(getRecMap(readFile, record, fileDef));
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getMaps]");
		
		return inMaps;
	}
	
	/**
	 * 定義ファイルIDから定義ファイルを取得
	 * 
	 * @param id 定義ファイルID
	 * @return 定義ファイル
	 * @throws Exception スローされる例外
	 */
	private JBSbatDefFileUtil getFileDefUtil(String fileId, JBSbatInputFileUtil inFileObj) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getFileDefUtil]");
		
		//定義ファイルフォルダ＋ID＋.defにする
		String filePath = JBSbatAplConst.getAplConstValue(IND) + fileId;
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getFileDefUtil][filePath=" + filePath + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getFileDefUtil]");
		
		//ファイル取得しながらリターン
		return new JBSbatDefFileUtil(filePath, inFileObj);
	}

	/**
	 * ファイルからレコードを取得
	 * 
	 * @param inFileObj 入力ファイルオブジェクト
	 * @param sLine 行文字列
	 * @param fileDef ファイル定義名
	 * @return レコードマップ
	 * @throws Exception スローされる例外
	 */
	private JBSbatServiceInterfaceMap getRecMap(JBSbatInputFileUtil inFileObj, String sLine, JBSbatDefFileUtil fileDefObj) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getRecMap][record=" + sLine + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getRecMap]");
		
		//レコードを取得
		return fileDefObj.lineToObject(sLine, inFileObj, 0);
	}
	
	/**
	 * 削除拒否対象番号を設定します。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.メソッドの呼び出し方です。<br>
	 *		引数:
	 *		filePath:請求債権関連情報のファイルパス
	 * </pre>
	 * <p>
	 * @param filePath 請求債権関連情報のファイルパス
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void setDeleteNg(HashMap<String, String> delNgMap, String[] relation) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][setDeleteNgSeiky]");

		//対象番号を取得
		String trgtNumber = relation[0];
		
		//債権番号を取得
		String saikenNumber = relation[1];
		
		//まだ可否が設定されていなかった場合
		if(delNgMap.get(trgtNumber) == null)
		{
			//まだ判断されていないため、ひとまず許可でセット
			delNgMap.put(trgtNumber, DEL_OK);
		}
		
		//すでに削除拒否対象番号かどうか
		if(delNgMap.get(trgtNumber).equals(DEL_NG))
		{
			assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][setDeleteNgSeiky][saikenNumber=" + saikenNumber + "]SET:NG");
			
			//債権番号を削除拒否にする
			saikenSakujoInfoMap.put(saikenNumber, DEL_NG);
		}
		else
		{
			//もし債権ナンバーが削除対象債権ではなければ
			if(saikenSakujoInfoMap.get(saikenNumber) == null || saikenSakujoInfoMap.get(saikenNumber).equals(DEL_NG))
			{
				//その対象番号を削除拒否にして
				delNgMap.put(trgtNumber, DEL_NG);
				
				//債権番号も削除拒否にする
				saikenSakujoInfoMap.put(saikenNumber, DEL_NG);
				assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][setDeleteNgSeiky][saikenNumber=" + saikenNumber + "]SET:NG");
			}
		}
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][setDeleteNgSeiky]");
	}
	
	/**
	 * 相互反映メソッド<br>
	 * @throws Exception 業務サービス内で発生した例外全般。
	 * @return retFlag 処理内で削除情報が変更されたか否かのフラグ
	 */
	private boolean sougoHanei(HashMap<String, String> delInfoMap, ArrayList<String[]> relarions) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][seikySougoHanei]");
		
		boolean retFlag = false;
		
		//全関連情報でループ
		for(String[] relation : relarions)
		{
			//請求番号とそのフラグを取得
			String trgtNumber =relation[0];
			String trgtFlag = delInfoMap.get(trgtNumber);
			
			//請求番号とそのフラグを取得
			String saikenNumber = relation[1];
			String saikenFlag = saikenSakujoInfoMap.get(saikenNumber);
			
			//どちらかがNULLの場合は処理を行わない(判断処理で対象番号は全て追加されているため)
			if(trgtFlag != null && saikenFlag != null)
			{
				//請求番号が削除拒否なら
				if(trgtFlag.equals(DEL_NG) && saikenFlag.equals(DEL_OK))
				{
					//債権番号を削除拒否にする
					saikenSakujoInfoMap.put(saikenNumber, DEL_NG);
					
					retFlag = true;
				}
				
				//債権番号が削除拒否なら
				if(saikenFlag.equals(DEL_NG) && trgtFlag.equals(DEL_OK))
				{
					//対象番号を削除拒否に
					delInfoMap.put(trgtNumber, DEL_NG);
					
					retFlag = true;
				}
			}
		}
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][seikySougoHanei]");
		
		return retFlag;
	}

	/**
	 * 主処理
	 * @param inMap　入力電文
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute(JBSbatServiceInterfaceMap inMap) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute]");

		//出力アイテムの設定
		JBSbatOutputItem outputItem = new JBSbatOutputItem();
		
		//債権番号取得
		String saikenNumber = inMap.getString(JBSbatCHIFM192.SAIKEN_NO);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][saikenNumber=" + saikenNumber + "]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][saikenNumber delFlag=" + saikenSakujoInfoMap.get(saikenNumber).equals(DEL_OK) + "]");
		
		//債権番号が削除OKなら
		if(saikenSakujoInfoMap.get(saikenNumber).equals(DEL_OK))
		{
			outputItem.addOutMapList(this.outPutDelDesideSaikenInfo(inMap));
		}
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][execute]");

		return outputItem;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/**
	 * 削除確定債権情報ファイル出力処理
	 * @param  inMap    入力電文
	 * @return outInfoMap 削除確定債権情報
	 * @throws Exception  業務サービス内で発生した例外全般。
	 */
	private JBSbatServiceInterfaceMap outPutDelDesideSaikenInfo(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][outPutDelDesideSaikenInfo]");

		JBSbatServiceInterfaceMap outInfoMap = new JBSbatServiceInterfaceMap();

		// 請求契約番号
		outInfoMap.set(JBSbatCHIFM192.SEIKY_KEI_NO,		inMap.get(JBSbatCHIFM192.SEIKY_KEI_NO));

		// 債権年月
		outInfoMap.set(JBSbatCHIFM192.SAIKEN_YM,		inMap.get(JBSbatCHIFM192.SAIKEN_YM));
		
		// 債権番号
		outInfoMap.set(JBSbatCHIFM192.SAIKEN_NO,		inMap.get(JBSbatCHIFM192.SAIKEN_NO));
		
		// 請求番号
		outInfoMap.set(JBSbatCHIFM192.SEIKY_NO,			inMap.get(JBSbatCHIFM192.SEIKY_NO));
		
		// 請求年月
		outInfoMap.set(JBSbatCHIFM192.SEIKY_YM,			inMap.get(JBSbatCHIFM192.SEIKY_YM));
		
		// 督促番号
		outInfoMap.set(JBSbatCHIFM192.TOKUSOKU_NO,		inMap.get(JBSbatCHIFM192.TOKUSOKU_NO));
		
		outInfoMap.setOutFlg(true);

		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][outPutDelDesideSaikenInfo]");

		return outInfoMap;
	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][terminal]");
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][terminal]");
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/
}
