/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatKKCreateMcafeeUrlJizenSyutoku
*	ソースファイル名	：JBSbatKKCreateMcafeeUrlJizenSyutoku.java
*	作成者				：富士通　
*	作成日				：2017年05月10日
*＜機能概要＞
*	マカフィーURL情報事前取得用ファイル作成
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*  v32.00.00	2017/05/10  FJ)三宅隆	新規作成(【ANK-3149-00-00】新セキュリティパック導入)
*   
*********************************************************************/
package eo.business.service;

import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import eo.business.common.JBSbatBusinessService;
import eo.business.util.file.JBSbatKKIFM730;

import eo.business.common.JCCBatCommon;
import eo.business.common.JKKBatCommon;
import eo.business.common.JKKBatConst;
import eo.common.constant.JPCBatchMessageConstant;
import eo.common.util.JKKCtrlMcafeeInfo;
import eo.framework.application.JBSbatBusinessException;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.item.JBSbatServiceInterfaceMap;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/
public class JBSbatKKCreateMcafeeUrlJizenSyutoku extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/
	
	/** フリー項目[処理件数] */
	private String free = null;
	
	/** シーケンス定義名(マカフィー会員ID) */
	private static final String SEQ_MCAFEE_MEMBER_ID = "SEQ_MCAFEE_MEMBER_ID";

	/** 接頭語(マカフィー会員ID) */
	private static final String PREFIX_MCAFEE_MEMBER_ID = "";

	/** シーケンス補正桁数(マカフィー会員ID) */
	private static final int SEQ_MCAFEE_MEMBER_ID_LENGTH = 12;
	
	/** シーケンス定義名(マカフィー用認証パスワード) */
	private static final String SEQ_MCAFEE_NINSHO_PWD = "SEQ_MCAFEE_NINSHO_PWD";

	/** 接頭語(マカフィー用認証パスワード) */
	private static final String PREFIX_MCAFEE_NINSHO_PWD = "";

	/** シーケンス補正桁数(マカフィー用認証パスワード) */
	private static final int SEQ_MCAFEE_NINSHO_PWD_LENGTH = 10;
	
	/** シーケンス定義名(他事業者契約異動通知番号) */
	private static final String SEQ_TAJGS_KEI_IDT_NO = "SEQ_TAJGS_KEI_IDT_NO";

	/** 接頭語(他事業者契約異動通知番号) */
	private static final String PREFIX_TAJGS_KEI_IDT_NO = "";

	/** 桁数(他事業者契約異動通知番号) */
	private static final int SEQ_TAJGS_KEI_IDT_NO_LENGTH = 15;
	
	/** 業務パラメータ（マカフィー用認証メールアドレスドメイン） */
//	private static final String WORK_PARAM_KK_MACFEE_DOMAIN = "KK_MACFEE_DOMAIN";
	
	/** 乱数(フェムトセル用認証ID) */
	public static final int RANDOM_LENGTH_FMTCEL_NINSHO_ID = 10;
	
	/** 変換配列 */
	private static final HashMap<String, String> CHANGE_DATA = new HashMap<String, String>();
	
	/** 他事業者契約異動通知結果コード（エラー） */
	private String TAJGS_KEI_IDT_RSLT_CD_ERR = "1";

	/**
	 * 英字・記号のマッピング配列
	 */
	private static final HashMap<String, String> MAPPING = new HashMap<String, String>();
	
	static
	{
		// 英字・記号のマッピング配列設定
		MAPPING.put("@", "0");
		MAPPING.put("a", "1");
		MAPPING.put("b", "2");
		MAPPING.put("c", "3");
		MAPPING.put("d", "4");
		MAPPING.put("e", "5");
		MAPPING.put("f", "6");
		MAPPING.put("g", "7");
		MAPPING.put("h", "8");
		MAPPING.put("i", "9");
		MAPPING.put("j", "0");
		MAPPING.put("k", "1");
		MAPPING.put("l", "2");
		MAPPING.put("m", "3");
		MAPPING.put("n", "4");
		MAPPING.put("o", "5");
		MAPPING.put("p", "0");
		MAPPING.put("q", "1");
		MAPPING.put("r", "2");
		MAPPING.put("s", "3");
		MAPPING.put("t", "4");
		MAPPING.put("u", "5");
		MAPPING.put("v", "6");
		MAPPING.put("w", "7");
		MAPPING.put("x", "8");
		MAPPING.put("y", "9");
		MAPPING.put("z", "0");
		MAPPING.put("A", "1");
		MAPPING.put("B", "2");
		MAPPING.put("C", "3");
		MAPPING.put("D", "4");
		MAPPING.put("E", "5");
		MAPPING.put("F", "6");
		MAPPING.put("G", "7");
		MAPPING.put("H", "8");
		MAPPING.put("I", "9");
		MAPPING.put("J", "0");
		MAPPING.put("K", "1");
		MAPPING.put("L", "2");
		MAPPING.put("M", "3");
		MAPPING.put("N", "4");
		MAPPING.put("O", "5");
		MAPPING.put("P", "0");
		MAPPING.put("Q", "1");
		MAPPING.put("R", "2");
		MAPPING.put("S", "3");
		MAPPING.put("T", "4");
		MAPPING.put("U", "5");
		MAPPING.put("V", "6");
		MAPPING.put("W", "7");
		MAPPING.put("X", "8");
		MAPPING.put("Y", "9");
		MAPPING.put("Z", "0");
		// 変換配列設定
		CHANGE_DATA.put("0", "KMNPQRSTUV");
		CHANGE_DATA.put("1", "PQRSTUVWXY");
		CHANGE_DATA.put("2", "TUVWXYZABC");
		CHANGE_DATA.put("3", "IJKMNPQRST");
		CHANGE_DATA.put("4", "CDEFGHIJKM");
		CHANGE_DATA.put("5", "MNPQRSTUVW");
		CHANGE_DATA.put("6", "ABCDEFGHIJ");
		CHANGE_DATA.put("7", "STUVWXYZAB");
		CHANGE_DATA.put("8", "HIJKMNPQRS");
		CHANGE_DATA.put("9", "NPQRSTUVWX");
	}
	
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/
	/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 主処理
	 * @param inMap 入力電文
	 * @throws Exception
	 */
	public JBSbatOutputItem execute() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		JBSbatOutputItem outputBean = new JBSbatOutputItem();
		
		// シェルから渡されたfreeの値を取得
		free = commonItem.getFreeItem();
		String[] lines = free.split(JKKBatConst.S_PARAM_DELIM);
		
		// 処理件数を取得
		int cnt = 0;
		if (null != lines[0]) {
			cnt = Integer.parseInt(lines[0]);
		}
		
		// 出力ファイルを取得
		String outputFile = lines[1] + lines[2];
		
		// システム日付の取得
		String sysDate = JCCBatCommon.getSysDateTimeStamp();

		// マカフィーURL情報事前取得用ファイルを作成する
		try
		{
			
			// 受け取った処理件数の値分、以下の処理を繰り返す
			for (int roop = 0; cnt > roop; roop++) {
				
				// 入出力インターフェースオブジェクトを生成
				JBSbatServiceInterfaceMap outmap = new JBSbatServiceInterfaceMap();
			
				//マカフィー会員IDを採番する
				String mcfMemID = JCCBatCommon.getFormatedNextSeq(
						super.commonItem, SEQ_MCAFEE_MEMBER_ID, PREFIX_MCAFEE_MEMBER_ID, SEQ_MCAFEE_MEMBER_ID_LENGTH);
				
				// マカフィー会員IDを設定する
				outmap.set(JBSbatKKIFM730.MCAFEE_MEMBER_ID, mcfMemID);
				
				// 業務パラメータよりマカフィー用認証メールアドレスドメインを取得する
//				String mcfDom = paramUtil.getGyoumuParameter(WORK_PARAM_KK_MACFEE_DOMAIN);
				
				// マカフィー用認証メールアドレスを採番する
//				String mcfNisMlad = mcfMemID.concat("@").concat(mcfDom);
				String mcfNisMlad = mcfMemID.concat("@").concat("dummy.k-opti.com");
				
				// マカフィー用認証メールアドレスを設定する
				outmap.set(JBSbatKKIFM730.MCAFEE_NINSHO_MLAD, mcfNisMlad);
				
				// マカフィー用認証パスワードを採番する
				// シーケンス取得
				Long seq = Long.parseLong(JCCBatCommon.getFormatedNextSeq(
						super.commonItem, SEQ_MCAFEE_NINSHO_PWD, PREFIX_MCAFEE_NINSHO_PWD, SEQ_MCAFEE_NINSHO_PWD_LENGTH));
				
				// パスワードを採番する
				String mcfNisPwd = getCreateMcfNinPwd(RANDOM_LENGTH_FMTCEL_NINSHO_ID, seq);
				
				// マカフィー用認証パスワードを設定する
				outmap.set(JBSbatKKIFM730.MCAFEE_NINSHO_PWD, mcfNisPwd);
				
				// 他事業者契約異動通知番号を採番する
				String tajgsKeiIdtNo = JCCBatCommon.getFormatedNextSeq(
						super.commonItem, SEQ_TAJGS_KEI_IDT_NO, PREFIX_TAJGS_KEI_IDT_NO, SEQ_TAJGS_KEI_IDT_NO_LENGTH);
				
				// 他事業者契約異動通知番号を設定する
				outmap.set(JBSbatKKIFM730.TAJGS_KEI_IDT_NO, tajgsKeiIdtNo);

				// 他事業者契約異動種別コードを設定する
				String tajgsKeiIdoSbtCd = "0101";
				outmap.set(JBSbatKKIFM730.TAJGS_KEI_IDO_SBT_CD, tajgsKeiIdoSbtCd);
				
				// マカフィー購入依頼のパラメータ設定マップ
				HashMap<String, Object> serviceMap = new HashMap<String, Object>();
				
				// serviceMapに電文の作成に必要なデータを格納
				// 他事業者契約異動通知番号
				serviceMap.put("tajgsKeiIdoNo", tajgsKeiIdtNo);
				
				// 他事業者契約異動種別コード
				serviceMap.put("tajgsKeiIdoSbtCd", tajgsKeiIdoSbtCd);
				
				// マカフィー会員ID
				serviceMap.put("mcafeeMemberId", mcfMemID);
				
				// マカフィー用認証メールアドレス
				serviceMap.put("mcafeeNinshoMlad", mcfNisMlad);
				
				// マカフィー用認証パスワード
				serviceMap.put("mcafeeNinshoPwd", mcfNisPwd);
				
				// コマンド発行部品のインスタンスを取得
				JKKCtrlMcafeeInfo instance = JKKCtrlMcafeeInfo.getInstance();
				
				// マカフィー連携処理呼出
				Map<String, Object> ret = instance.call_KKIFE354(serviceMap);
				
				if ("0".equals(ret.get("CMD_RESULT_CD")))
				{
					ArrayList<Map<String, Object>> nodelist = new ArrayList<Map<String, Object>>();
					HashMap<String, Object> resultinfo = new HashMap<String, Object>();
					
					nodelist = (ArrayList<Map<String, Object>>)ret.get("CMD_RESULT_DETAIL");
					resultinfo = (HashMap<String, Object>)nodelist.get(0);
					
					// リターンコードから他事業者契約異動結果コードを判定
					String returnCode = (String)resultinfo.get("returnCode");
					String tajgsKeiIdtRsltCd = analyzeResult(returnCode);
					
					if(TAJGS_KEI_IDT_RSLT_CD_ERR.equals(tajgsKeiIdtRsltCd))
					{
						super.logPrint.printDebugLog("マカフィー申込依頼処理にて返却値の異常が発生しています。");
						
						// ログを出力
						StringBuilder msg = new StringBuilder();
						
						msg.append("他事業者契約異動通知番号[").append((String)serviceMap.get("tajgsKeiIdoNo")).append("]")
							.append("トランザクション・コード[").append((String)resultinfo.get("returnCode")).append("]")
							.append("トランザクション・コード説明[").append((String)resultinfo.get("returnCodeSetmei")).append("]")
							;
						
						commonItem.getLogPrint().printBusinessErrorLog("EKKB1370AE",  new String[] {msg.toString()});
						
						continue;
					}
					// マカフィー製品ダウンロードURLの設定
					outmap.set(JBSbatKKIFM730.MCAFEE_SEHN_DL_URL, resultinfo.get("mcafeeSehnDlUrl"));
					
					// マカフィー購入IDの設定
					outmap.set(JBSbatKKIFM730.MCAFEE_BUY_ID, resultinfo.get("mcafeeBuyId"));
				}
				else
				{
					super.logPrint.printDebugLog("マカフィー申込依頼処理中に通信異常が発生しました。");
					
					// ログを出力
					StringBuilder msg = new StringBuilder();
					
					String log = (String)ret.get("LOG_RESULT");
					
					msg.append("他事業者契約異動通知番号[").append((String)serviceMap.get("tajgsKeiIdoNo")).append("]")
						.append("CMD_ERROR_CD[").append((String)ret.get("CMD_ERROR_CD")).append("]")
						.append("CMD_ERROR_MESSAGE[").append((String)ret.get("CMD_ERROR_MESSAGE")).append("]")
						;
					
					commonItem.getLogPrint().printBusinessErrorLog("EKKB0990CE", new String[] {msg.toString()});
					commonItem.getLogPrint().printBusinessErrorLog("EKKB1200AI", new String[] {log});
					
					continue;
				}

				outmap.setOutFlg(true);
				outputBean.addOutMapList(outmap);
			}
		
		}
		catch(IOException e)
		{
			// ファイルを出力します。
			JKKBatCommon.outFile(super.commonItem, outputBean, "KKIFM730", lines[1], lines[2] + sysDate);
			
			throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0250CE, new String[]{outputFile, e.getMessage()});
		}
		catch(Exception e)
		{
			// ファイルを出力します。
			JKKBatCommon.outFile(super.commonItem, outputBean, "KKIFM730", lines[1], lines[2] + sysDate);
			
			throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0250CE, new String[]{outputFile, e.getMessage()});
		}
		// ファイルを出力します。
		JKKBatCommon.outFile(super.commonItem, outputBean, "KKIFM730", lines[1], lines[2] + sysDate);
		
		return null;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/
	
	/**
	 * マカフィー認証用パスワードを採番します
	 * <br>
	 * @param arg0 生成する文字数
	 * @param arg1 シード値
	 * @return String 変換後の文字列
	 */
	private String getCreateMcfNinPwd(int arg0, long arg1) 
	{

		SecureRandom random = new SecureRandom();

		StringBuffer ret = new StringBuffer();

		random.setSeed(arg1);

		// ランダムな文字列を生成する
		for (int i = 0; i < arg0; i++) 
		{
			ret.append((char)(48 + random.nextInt(10)));
		}
		
		String randomValue = ret.toString();
		
		// 変換処理
		StringBuffer pwd = new StringBuffer();
		
		// (1)乱数の9桁目,10桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabet(randomValue.substring(8, 9), randomValue.substring(9, 10)));
		// (2)乱数の1桁目,10桁目の加算値の下1桁目を設定する
		pwd.append(toAlphabet(randomValue.substring(0, 1), randomValue.substring(9, 10)));
		// (3)乱数の3桁目,4桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabet(randomValue.substring(2, 3), randomValue.substring(3, 4)));
		// (4)乱数の9桁目を設定する
		pwd.append(randomValue.substring(8, 9));
		// (5)乱数の8桁目を設定する
		pwd.append(randomValue.substring(7, 8));
		// (6)乱数の5桁目,6桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabet(randomValue.substring(4, 5), randomValue.substring(5, 6)));
		// (7)乱数の2桁目,4桁目の加算値の下1桁目を設定する
		pwd.append(toAlphabet(randomValue.substring(1, 2), randomValue.substring(3, 4)));
		// (8)乱数の7桁目,8桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabet(randomValue.substring(6, 7), randomValue.substring(7, 8)));
		// (9)乱数の5桁目を設定する
		pwd.append(randomValue.substring(4, 5));
		// (10)乱数の1桁目,2桁目を元に英小文字変換処理を呼び出す
		pwd.append(toAlphabet(randomValue.substring(0, 1), randomValue.substring(1, 2)));

		return pwd.toString();
	}
	
	/**
	 * <p>
	 * 英字変換処理。<br>
	 * </p>
	 * @param str1 変換元データの１桁目
	 * @param str2 変換元データの２桁目
	 * @param mode 変換モード
	 * @return 変換した英字
	 */
	private String toAlphabet(String str1, String str2)
	{
		// 変換元データの１桁目から、英字変換対象行を取得
		String chgStr = CHANGE_DATA.get(str1);
		// 変換元データの２桁目から、変換した英字を取得
		chgStr = chgStr.substring(Integer.valueOf(str2), Integer.valueOf(str2) + 1);

		// 英字を小文字に変換して返却
		return chgStr.toLowerCase();
	}
	
	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/
	/**
	 * 電文の返却値から他事業者契約異動通知に登録する値を編集します
	 * <br>
	 * @param returnCode リターンコード
	 * @return HashMap 他事業者契約異動通知に登録する値（他事業者契約異動通知結果コード、他事業者契約異動通知結果詳細コード）
	 */
	public String analyzeResult(String returnCode)
	{
		String tajgsKeiIdtRsltCd = "";
		
		if("1000".equals(returnCode) || "5001".equals(returnCode) || "5002".equals(returnCode))
		{
			tajgsKeiIdtRsltCd = "0";
		}
		else
		{
			tajgsKeiIdtRsltCd = "1";
		}
		
		return tajgsKeiIdtRsltCd;
	}

}
