/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom						 *
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatACDnpUseChegDispatcher
*	ソースファイル名	：JBSbatACDnpUseChegDispatcher.java
*	作成者				：富士通　
*	作成日				：2013年10月09日
*＜機能概要＞
*　電報利用課金情報取得部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v5.00		2013/10/09   FJ) 北端	新規作成
*	v5.01		2013/11/19   FJ) 北端	【OM-2013-0004341】システムエラー時にステータス更新
*********************************************************************/
package eo.business.service;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import eo.business.common.JACBatCommon;
import eo.business.common.JBSbatBusinessService;
import eo.business.common.JCCbatShoriIraiUtil;
import eo.business.util.table.JBSbatZM_M_WORK_PARAM_KNRI;
import eo.common.constant.JACStrConst;
import eo.common.constant.JPCBatchMessageConstant;
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;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/
public class JBSbatACDnpUseChegDispatcher extends JBSbatBusinessService 
{
	
	/** ディレイド処理依頼情報オブジェクトファイル名 */
	public static final String BMP_ARI_MAP = "bmpAriMap";
	
	/** ディレイド処理依頼情報オブジェクトファイル名 */
	public static final String BMP_NASHI_MAP = "bmpNashiMap";
	
	/** テーブル(業務パラメータ管理)*/
	private static final String D_TBL_NAME_ZM_M_WORK_PARAM_KNRI = "ZM_M_WORK_PARAM_KNRI";
	
	/** テーブル(電子ファイル管理)*/
	private static final String D_TBL_NAME_CC_T_EFILE_KANRI = "CC_T_EFILE_KANRI";

	/** テーブル(ダウンロードファイル管理)*/
	private static final String D_TBL_NAME_ZM_T_DL_FILE_KANRI = "ZM_T_DL_FILE_KANRI";

	/** SQL定義キー(AC_SELECT_001)*/
	private static final String ZM_M_WORK_PARAM_KNRI_AC_SELECT_001 = "AC_SELECT_001";
	
	/** テーブルアクセスクラス(業務パラメータ管理)*/
	private JBSbatSQLAccess db_ZM_M_WORK_PARAM_KNRI = null;
	
	/** テーブルアクセスクラス(電子ファイル管理)*/
	private JBSbatSQLAccess db_CC_T_EFILE_KANRI = null;

	/** テーブルアクセスクラス(ダウンロードファイル管理)*/
	private JBSbatSQLAccess db_ZM_T_DL_FILE_KANRI = null;

	/** 番ポあり関連情報 */
	private HashMap<String, Object> bmpAriWorkMap = null;
	
	/** 番ポあり関連情報 */
	private HashMap<String, Object> bmpNashiWorkMap = null;
	
	/** 出力ファイルディレクトリ */
	private String outFileDir = "";
	
	/** 電報利用課金情報(番ポあり)一時ファイル */
	private String bmpAriTmpFile = "";
	
	/** 電報利用課金情報(番ポなし)一時ファイル */
	private String bmpNashiTmpFile = "";
	
	/** ディレイド処理依頼番号 */
	private String shoriIraiNo = null;
	
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception 
	{
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);
		
		// DBアクセスクラスを生成します
		db_ZM_M_WORK_PARAM_KNRI = new JBSbatSQLAccess(commonItem, D_TBL_NAME_ZM_M_WORK_PARAM_KNRI);
		db_CC_T_EFILE_KANRI = new JBSbatSQLAccess(commonItem, D_TBL_NAME_CC_T_EFILE_KANRI);
		db_ZM_T_DL_FILE_KANRI = new JBSbatSQLAccess(commonItem, D_TBL_NAME_ZM_T_DL_FILE_KANRI);
		
		/** (1) 業務パラメータ管理テーブル情報取得 */
		List<Object> searchList = new ArrayList<Object>();
		searchList.add(JACStrConst.WKPARA_AC_BNPARI_HDR_RCNT);
		searchList.add(JACStrConst.WKPARA_AC_BNPARI_FTR_RCNT);
		searchList.add(JACStrConst.WKPARA_AC_BNPARI_JDG_KMK);
		// 業務パラメータ管理から番ポあり関連情報を取得
		bmpAriWorkMap = new HashMap<String, Object>();
		for (int i = 0; i < searchList.size(); i++) 
		{
			executeZM_M_WORK_PARAM_KNRI_AC_SELECT_001(new Object[] {searchList.get(i), super.opeDate, super.opeDate});
			JBSbatCommonDBInterface workRecord = db_ZM_M_WORK_PARAM_KNRI.selectNext();
			if (workRecord != null) 
			{
				bmpAriWorkMap.put((String)searchList.get(i), workRecord.getString(JBSbatZM_M_WORK_PARAM_KNRI.WORK_PARAM_SETTE_VALUE));
				
			}
			else 
			{
				throw new JBSbatBusinessException(JPCBatchMessageConstant.EACB0440CE, new String[] { JBSbatZM_M_WORK_PARAM_KNRI.TABLE_NAME });
				
			}
		}

		/** (1) 業務パラメータ管理テーブル情報取得 */
		searchList = new ArrayList<Object>();
		searchList.add(JACStrConst.WKPARA_AC_BNPNASHI_HDR_RCNT);
		searchList.add(JACStrConst.WKPARA_AC_BNPNASHI_FTR_RCNT);
		searchList.add(JACStrConst.WKPARA_AC_BNPNASHI_JDG_KMK);
		// 業務パラメータ管理から番ポなし関連情報を取得
		bmpNashiWorkMap = new HashMap<String, Object>();
		for (int i = 0; i < searchList.size(); i++) 
		{
			executeZM_M_WORK_PARAM_KNRI_AC_SELECT_001(new Object[] {searchList.get(i), super.opeDate, super.opeDate});
			JBSbatCommonDBInterface workRecord = db_ZM_M_WORK_PARAM_KNRI.selectNext();
			if (workRecord != null) 
			{
				bmpNashiWorkMap.put((String)searchList.get(i), workRecord.getString(JBSbatZM_M_WORK_PARAM_KNRI.WORK_PARAM_SETTE_VALUE));
				
			} 
			else 
			{
				throw new JBSbatBusinessException(JPCBatchMessageConstant.EACB0440CE, new String[] { JBSbatZM_M_WORK_PARAM_KNRI.TABLE_NAME });
				
			}
		}
		
		/** (2) Free項目取得 */
		String[] freeItem = this.freeItem.split(JACStrConst.FREE_DIV);
		outFileDir = freeItem[0];
		bmpAriTmpFile = outFileDir + freeItem[1];
		bmpNashiTmpFile = outFileDir + freeItem[2];
	}

	/**
	 * 主処理
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute() throws Exception 
	{
		List<HashMap<String, Object>> infoDempoList = new ArrayList<HashMap<String, Object>>();
		HashMap<String, Object> fileMap = new HashMap<String, Object>();
		
		try 
		{
			infoDempoList = JCCbatShoriIraiUtil.getShoriIraiInfo(commonItem, "EO30E0110J0");
			if (infoDempoList == null) 	
			{
				// ディレイド処理依頼が無いので処理を終了
				return null;
			}
			
			// 番ポあり判断項目の取得
			String bmpAriJudgeItem = (String)bmpAriWorkMap.get(JACStrConst.WKPARA_AC_BNPARI_JDG_KMK);
			// 番ポなし判断項目の取得
			String bmpNashiJudgeItem = (String)bmpNashiWorkMap.get(JACStrConst.WKPARA_AC_BNPNASHI_JDG_KMK);
			
			// 先頭の1レコードのみ（DLYD_TRN_REQ_NOの最新)
			fileMap = (HashMap<String, Object>) infoDempoList.get(0);
			byte[] efile = (byte[]) fileMap.get("INPUT_EFILE"); // 実ファイル
			String s = new String(efile, JACStrConst.ENCODE_SJIS);
			s = s.substring(0, s.indexOf(JACBatCommon.chgKaigyo(JACStrConst.LINE_CRLF)));
			
			// ディレイド処理依頼番号
			shoriIraiNo = (String)fileMap.get("DLYD_TRN_REQ_NO");

			ArrayList<String> editList = this.splitRecord(s);
			String outfileName = null;
			String outMapName = null;
			// 番ポ識別判定
			for (int i = 0; i < editList.size(); i++) 
			{
				String workItem = editList.get(i);
				if (bmpAriJudgeItem.equals(workItem)) 
				{
					outfileName = bmpAriTmpFile;
					outMapName = BMP_ARI_MAP;
					break;
				}
				if (bmpNashiJudgeItem.equals(workItem)) 
				{
					outfileName = bmpNashiTmpFile;
					outMapName = BMP_NASHI_MAP;
					break;
				}
			}
			if (outfileName != null) 
			{
				// 電報利用課金情報（データ部）
				this.temporaryFileOutput(outfileName, efile);
			}
			if (outMapName != null) 
			{
				// ディレイド依頼情報
				this.fileMapOutput(outFileDir + outMapName, fileMap);
			}
		} 
		catch (IOException e) 
		{
			if(shoriIraiNo != null)
			{
				// ディレイド処理依頼への更新
				JCCbatShoriIraiUtil.updateShoriIraiResult(commonItem, shoriIraiNo, JACStrConst.DLYD_TRN_RSLT_CD_SYS_ERR , null);
			}
			throw new JBSbatBusinessException(JPCBatchMessageConstant.EACB0550AH);
		}
		
		return null;
	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception 
	{
		// DBアクセスクラスをクローズします
		db_ZM_M_WORK_PARAM_KNRI.close();
		db_CC_T_EFILE_KANRI.close();
		db_ZM_T_DL_FILE_KANRI.close();
	}

	/**
	 * SQLKEY(AC_SELECT_001)でDBアクセスを行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.引数でバイント変数を設定します。<br>
	 *
	 * 2.DBアクセスを実行します。<br>
	 * 
	 * 3.メソッドの呼び出し方です。<br>
	 *		引数:
	 *		param:順にバイント変数の値をparam配列に入れます。バイント変数は以下に説明します。
	 *		 	業務パラメータID
	 *		 	業務パラメータ適用開始年月日
	 *		 	業務パラメータ適用終了年月日
	 * </pre>
	 * <p>
	 * @param param バイント変数の値配列。
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void executeZM_M_WORK_PARAM_KNRI_AC_SELECT_001(Object[] param) throws Exception 
	{
		// バイント変数のリストを生成します
		JBSbatCommonDBInterface paramList = new JBSbatCommonDBInterface();
		paramList.setValue(param[0].toString());
		paramList.setValue(param[1].toString());
		paramList.setValue(param[2].toString());

		// DBアクセスを実行します
		db_ZM_M_WORK_PARAM_KNRI.selectBySqlDefine(paramList, ZM_M_WORK_PARAM_KNRI_AC_SELECT_001);
	}
	
	/**
	 * 一時ファイルの書き込みを行います。<br>
	 * <p>
	 * 電子ファイル管理より取得した電子ファイルを元にバイト変換を行い、
	 * 一時ファイルとしてファイル出力する。<br>
	 * <p>
	 * @param eFile 電子ファイル
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void temporaryFileOutput(String fileName, byte[] eFile) throws Exception 
	{
		FileOutputStream fStream = null;
		BufferedOutputStream bStream = null;
		if (eFile != null) 	
		{
			fStream = new FileOutputStream(fileName);
			bStream = new BufferedOutputStream(fStream);
			bStream.write(eFile);
		}
		
		// 出力ファイルを閉じる
		if (bStream != null) 
		{
			bStream.close();
		}
	}
	
	/**
	 *入力情報(電報利用課金情報(番ポあり))から抽出したデータ行(１行分)を<br>
	 *分割し、リストに格納する。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.引数で設定されているレコードに対して最初にレコード全体をカンマ分割し、分割した個々の文字列に「"」が存在する場合
	 * 　必要な連結やエスケープ処理を行い、個々のフィールドを確定する。<br>
	 * <p>
	 * 2.処理方法は以下のとおり<br>
	 * <p>
	 *   2-1.レコード全体をStringクラスのsplitメソッドを使ってカンマで分割し、分割した個々の文字列データの先頭から「"」を探す。
	 *   　　見つからなければその文字列は１フィールドとして確定する。
	 *       
	 *   2-2.「"」が見つかったら次の「"」を探す。次の「"」の直後に「"」があればエスケープされた「"」として処理し、
	 *   　　そうでなければフィールドの終わりとみなす。
	 *   
	 *   2-3.フィールで後ろの「"」が見つからなかった場合、フィールドに含まれるカンマでsplitメソッドが分割したものと見なして
	 *   　　フィールドの後ろに(splitメソッドが削除した)カンマと次のフィールドを連結する。
	 *   
	 *   2-4.フィールドの開始と終了の「"」は削除する。
	 * </pre>
	 * <p>
	 * @param lineRecord レコード(１行分)
	 * @return editList 「"」を取り除いたレコード
	 */
	private ArrayList<String> splitRecord(String lineRecord) 
	{
		// 変数宣言
		String column = "";										// フィールド
		StringBuffer sb = new StringBuffer(1024);				// 編集用
		int startPos = 0;										// 開始位置
		int endPos = 0;											// 終了位置
		int columnlen = 0;										// フィールドの長さ
		ArrayList<String> editList = new ArrayList<String>();	// 編集結果リスト
		
		// 設定された引数を分割
		String[] columns = lineRecord.split(",",-1);
		// 最大文字数の取得
		int maxlen = columns.length;
		
		// 文字列編集
		for (int i = 0; i < maxlen; i++) 
		{
			// フラグの初期化
			boolean flg = false;
			
			// １フィールドを取得
			column = columns[i];
			
			// 「"」を取得
			endPos = column.indexOf("\"");
			// フィールドに「"」が含まれていない場合
			if (endPos < 0) 
			{
				// 取得したフィールドをそのまま設定
				editList.add(column);
				
			}
			else 
			{
				// フィールドの長さを取得
				columnlen = column.length();
				
				// 終了位置が0の場合
				if (endPos == 0 && !flg) 
				{
					// 開始位置を設定
					startPos = 1;
					sb.setLength(0);
				}
				
				// 「"」の位置確認
				while (startPos < columnlen) 
				{
					// 「"」の終了位置を取得
					endPos = column.indexOf("\"", startPos);
					// 終了位置が0以上の場合
					if (endPos >= 0) 
					{
						// 終了位置が開始位置より大きい場合
						if (startPos <= endPos) 
						{
							// 編集用変数に「"」を除いた値を設定
							sb.append(column.substring(startPos, endPos));
							// 開始位置を加算
							startPos = ++endPos;
							
						}
					} 
					else 
					{
						// 編集用変数に1文字を設定
						sb.append(column.substring(startPos));
						// インデックスが「最大文字数 - 1」より小さい場合
						if (i < maxlen - 1) 
						{
							// 「,」を挿入
							sb.append(",");
							// 開始位置の初期化
							startPos = 0;
							
							flg = true;
							// 処理を抜ける
							break;
							
						}
					}
				}
				
				// 編集した文字列をリストに格納
				if (!flg) 
				{
					editList.add(sb.toString());
				}
			}
		}
		
		// 編集結果を返す
		return editList;
	}

	/**
	 * ディレイド処理情報の書き込みを行います。<br>
	 * <p>
	 * ディレイド処理情報を保持するMapをシリアライズしてファイル出力する。<br>
	 * <p>
	 * @param fileName ファイル名
	 * @param fileMap ディレイド処理情報
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void fileMapOutput(String fileName, HashMap<String, Object> fileMap) throws Exception 
	{
		if (fileMap != null) 	
		{
			FileOutputStream fos = new FileOutputStream(fileName);
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(fileMap);
			if (fos != null) 
			{
				fos.close();
			}
			if (oos != null) 
			{
				oos.close();
			}
		}
	}
}
