/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：CNA00801SFLogic
*   ソースファイル名：CNA00801SFLogic.java
*   作成者          ：富士通
*   日付            ：2013年02月21日
*＜機能概要＞
*   ０５０番号発行を行います。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v5.00.00    2013/02/21   FJ          新規作成
*   v8.00.00	2014/01/16   FJ         【ANK-1585-00-00】リクエストパラメータ追加
*   v70.00.00	2024/02/14	FJ張	    【ANK-4538-00-00】LaLaCall契約時の本人確認必須化
**********************************************************************/
package eo.web.webview.CNA00601SF;

import static com.fujitsu.futurity.web.x31.X31SWebLog.DEBUG_LOG;
import static eo.common.constant.JCNStrConst.*;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.fujitsu.futurity.common.JSYLogBase;
import com.fujitsu.futurity.common.JSYwebLog;
import com.fujitsu.futurity.web.x31.X31BWebBusinessLogic;
import com.fujitsu.futurity.web.x31.X31CMessageResult;
import com.fujitsu.futurity.web.x31.X31CWebConst;
import com.fujitsu.futurity.web.x31.X31SDataBeanAccess;

import eo.common.constant.JCNStrConst;
import eo.web.webview.CNA00601SF.CNA00601SFConst;

/**
 * ０５０番号発行処理を行います。
 * <BR>
 * @author FJ
 *
 */
@SuppressWarnings("serial")
public class CNA00601SFLogic extends X31BWebBusinessLogic
{
	
	/** 空文字 */
	private static final String STR_BLANK = "";
	
	/** ０５０番号発行ID */
	private static final String SERVICE_ID = "CNSV0045";
	
	/** サービスコンポーネント名 */
	private static final String CC_NAME = "JCN050HakkoCC";	

	// ------------------------------------------
	// マップ項目
	// ------------------------------------------
	// リクエスト
	/** リクエストマップ項目名：SYSID */
	private static final String REQMAP_SYSID = "SYSID";

	/** リクエストマップ項目名：コンテンツ契約番号 */
	private static final String REQMAP_CONT_KEI_NO = "CONT_KEI_NO";

	/** リクエストマップ項目名：050電話番号払出種別コード */
	private static final String REQMAP_TELNO_HRADSI_SBT_CD = "TELNO_HRADSI_SBT_CD";
	
	/** リクエストマップ項目名：050電話番号 */
	private static final String REQMAP_TELNO = "TELNO";
	
	//ANK-4538-00-00 ADD START
	/** リクエストマップ項目名：身元確認ID */
	private static final String REQMAP_MIMOTCFM_ID = "MIMOTCFM_ID";
	//ANK-4538-00-00 ADD END
	
	
	// レスポンス
	/** レスポンスマップ項目名：戻りコード */
	private static final String RESMAP_RETURN_CODE = "RETURN_CODE";
	
	/** レスポンスマップ項目名：050電話番号 */
	private static final String RESMAP_050_TELNO = "TELNO";
	
	// ------------------------------------------
	// 入力チェック用
	// ------------------------------------------
	/** 半角英数字の範囲の最初 */
	private static final char HALF_DIGIT_AND_ALPHABET_START = '\u0021';

	/** 半角英数字の範囲の最後を示します */
	private static final char HALF_DIGIT_AND_ALPHABET_END = '\u007E';

	/** 半角スペース */
	private static final char HALF_SPACE = '\u0020';

	/** 桁数：SYSID */
	private static final int LEN_SYSID = 10;
	
	/** 桁数：コンテンツ契約番号 */
	private static final int LEN_CONT_KEI_NO = 12;

	/** 桁数：050電話番号払出種別コード */
	private static final int LEN_TELNO_HRADSI_SBT_CD = 1;
	
	/** 桁数：050電話番号 */
	private static final int LEN_TELNO = 11;
	
	//ANK-4538-00-00 ADD START
	/** 桁数：身元確認ID */
	private static final int MAX_MIMOTCFM_ID = 36;
	//ANK-4538-00-00 ADD END
	/**
	 * APIリクエスト時の処理を行います。
	 * <BR>
	 * @return boolean 処理結果
	 * @throws Exception 処理中に発生した例外をスロー
	 */
	@SuppressWarnings("unchecked")
	public boolean action_Init() throws Exception
	{

		DEBUG_LOG.info("action_Init Start!");

		X31SDataBeanAccess bean = getServiceFormBean();

		// 出力用Map
		HashMap outMap = new HashMap();

		// エラー出力用
		HashMap<String, Object> mapCc = new HashMap<String, Object>();
		String returnCd = S_API_RTN_CD_OK;

		try
		{
			// リクエストパラメータを取得・格納
			Map<String, String> requestMap = super.getRequestParams();
			
			DEBUG_LOG.info("テスト reqestMap= " + requestMap.toString());
			DEBUG_LOG.info("テスト(UTF-8) reqestMap= " + new String(requestMap.toString().getBytes(), "UTF-8"));
			DEBUG_LOG.info("テスト(Shift-JIS) reqestMap= " + new String(requestMap.toString().getBytes(), "Shift-JIS"));
			JSYwebLog.println(JSYLogBase.EXECUTION, this.getClass(), null, "BPCON0I002",  new String[]{"CNA006_050番号発行_reqestMap= " + requestMap.toString()}, "");
			
			// ******************************************************
			// パラメータチェック処理
			// ******************************************************
			String sysId = (String)requestMap.get(REQMAP_SYSID);
			String contKeiNo = (String)requestMap.get(REQMAP_CONT_KEI_NO);
			String telHrSbtCd = (String)requestMap.get(REQMAP_TELNO_HRADSI_SBT_CD);
			String telNo = (String)requestMap.get(REQMAP_TELNO);
			//ANK-4538-00-00 ADD START
			String mimotcfmID = (String)requestMap.get(REQMAP_MIMOTCFM_ID);
			//ANK-4538-00-00 ADD END
			// ----------------------------------
			// SYSID
			// ----------------------------------
			if ("".equals(nullOrBlankWithTrim(sysId)))
			{
				// 未入力
				returnCd = JCNStrConst.API_RETURN_CD_10;
			}
			else if (sysId.length() != LEN_SYSID)
			{
				// 桁数不備
				returnCd = JCNStrConst.API_RETURN_CD_11;
			}
			else if (!isNarrowEiSuji(sysId))
			{
				// 形式エラー
				returnCd = JCNStrConst.API_RETURN_CD_12;
			}
			
			// エラーの場合は終了
			if (!JCNStrConst.API_RETURN_CD_00.equals(returnCd))
			{
				DEBUG_LOG.info("０５０番号発行サービスにてエラーが発生しました。(SYSID=" + sysId + ")");
				mapCc.put(RESMAP_RETURN_CODE, returnCd);
				outMap.put(CC_NAME, mapCc);
				createResultParam(bean, outMap);
				return true;
			}

			// ----------------------------------
			// コンテンツ契約番号
			// ----------------------------------
			if ("".equals(nullOrBlankWithTrim(contKeiNo)))
			{
				// 未入力
				returnCd = JCNStrConst.API_RETURN_CD_13;
			}
			else if (contKeiNo.length() != LEN_CONT_KEI_NO)
			{
				// 桁数不備
				returnCd = JCNStrConst.API_RETURN_CD_14;
			}
			else if (!isNarrowEiSuji(contKeiNo))
			{
				// 形式エラー
				returnCd = JCNStrConst.API_RETURN_CD_15;
			}
			
			// エラーの場合は終了
			if (!JCNStrConst.API_RETURN_CD_00.equals(returnCd))
			{
				DEBUG_LOG.info("０５０番号発行サービスにてエラーが発生しました。(CONT_KEI_NO=" + contKeiNo + ")");
				mapCc.put(RESMAP_RETURN_CODE, returnCd);
				outMap.put(CC_NAME, mapCc);
				createResultParam(bean, outMap);
				return true;
			}

			// ----------------------------------
			// 050電話番号払出種別コード
			// ----------------------------------
			if ("".equals(nullOrBlankWithTrim(telHrSbtCd)))
			{
				// 未入力
				returnCd = JCNStrConst.API_RETURN_CD_16;
			}
			else if (telHrSbtCd.length() != LEN_TELNO_HRADSI_SBT_CD)
			{
				// 桁数不備
				returnCd = JCNStrConst.API_RETURN_CD_17;
			}
			else if (!isNarrowEiSuji(telHrSbtCd))
			{
				// 形式エラー
				returnCd = JCNStrConst.API_RETURN_CD_18;
			}
			
			// エラーの場合は終了
			if (!JCNStrConst.API_RETURN_CD_00.equals(returnCd))
			{
				DEBUG_LOG.info("０５０番号発行サービスにてエラーが発生しました。(TELNO_HRADSI_SBT_CD=" + telHrSbtCd + ")");
				mapCc.put(RESMAP_RETURN_CODE, returnCd);
				outMap.put(CC_NAME, mapCc);
				createResultParam(bean, outMap);
				return true;
			}
			
			// ----------------------------------
			// 050電話番号
			// ----------------------------------
			if ("".equals(nullOrBlankWithTrim(telNo)))
			{
				// 未入力
				returnCd = JCNStrConst.API_RETURN_CD_19;
			}
			else if (telNo.length() != LEN_TELNO)
			{
				// 桁数不備
				returnCd = JCNStrConst.API_RETURN_CD_20;
			}
			// 形式チェックはECNA0070001(コンテンツ契約050番号発行)内で実施
			
			// エラーの場合は終了
			if (!JCNStrConst.API_RETURN_CD_00.equals(returnCd))
			{
				DEBUG_LOG.info("０５０番号発行サービスにてエラーが発生しました。(TELNO=" + telNo + ")");
				mapCc.put(RESMAP_RETURN_CODE, returnCd);
				outMap.put(CC_NAME, mapCc);
				createResultParam(bean, outMap);
				return true;
			}
			
			//ANK-4538-00-00 ADD START
			// ----------------------------------
			// 身元確認ID
			// ----------------------------------
			if ("".equals(nullOrBlankWithTrim(mimotcfmID)))
			{
				// 未入力
				returnCd = JCNStrConst.API_RETURN_CD_22;
			}
			else if (mimotcfmID.length() > MAX_MIMOTCFM_ID || mimotcfmID.length() < 1 )
			{
				// 桁数不備
				returnCd = JCNStrConst.API_RETURN_CD_23;
			}
			else if (!isNarrowEiSuji(mimotcfmID))
			{
				// 形式エラー
				returnCd = JCNStrConst.API_RETURN_CD_24;
			}
			
			// エラーの場合は終了
			if (!JCNStrConst.API_RETURN_CD_00.equals(returnCd))
			{
				DEBUG_LOG.info("０５０番号発行サービスにてエラーが発生しました。(MIMOTCFM_ID=" + mimotcfmID + ")");
				mapCc.put(RESMAP_RETURN_CODE, returnCd);
				outMap.put(CC_NAME, mapCc);
				createResultParam(bean, outMap);
				return true;
			}
			//ANK-4538-00-00 ADD END
			
			// ******************************************************
			// ０５０番号発行CC呼出
			// ******************************************************
			// サービス呼び出しの際の引数を生成
			HashMap paramMap = new HashMap();
			HashMap inputMap = new HashMap();
			
			// サービスへのデータセット
			paramMap.put(X31CWebConst.TELEGRAM_INFO_USECASE_ID, SERVICE_ID);
			paramMap.put(X31CWebConst.TELEGRAM_INFO_OPERATION_ID, SERVICE_ID + "OP");
			
			createServiceMap(requestMap, inputMap);

			// サービスの呼出(０５０番号発行)
			X31CMessageResult msgResult = invokeService(paramMap, inputMap, outMap);
			
			// エラー処理 
			//String errFlgAuth = (String)getParamFromMap(outMap, CC_NAME, RESMAP_RETURN_CODE);
			returnCd = (String)getParamFromMap(outMap, CC_NAME, RESMAP_RETURN_CODE);
			if (msgResult != null)
			{
				DEBUG_LOG.info("０５０番号発行サービスにてエラーが発生しました。");
				returnCd = JCNStrConst.API_RETURN_CD_99;

				outMap.put(RESMAP_RETURN_CODE, JCNStrConst.API_RETURN_CD_99);
				createResultParam(bean, outMap);
				return true;
			}
			else if (!S_API_RTN_CD_OK.equals(returnCd))
			{
				DEBUG_LOG.info("０５０番号発行サービスにてエラーが発生しました。");
				createResultParam(bean, outMap);
				return true;
			}
			
			// 返却パラメータ設定
			createResultParam(bean, outMap);
			
		}
		catch (Exception e)
		{
			StringBuilder sb = new StringBuilder();
			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw);
			
			e.printStackTrace(pw);
			sb.append("\n" + sw.toString());
			DEBUG_LOG.info("０５０番号発行サービスにてエラー(Exception)発生" + sb.toString());

			if (S_API_RTN_CD_OK.equals(returnCd))
			{
				returnCd = JCNStrConst.API_RETURN_CD_99;
			}
			if (outMap.get(CC_NAME) != null)
			{
				mapCc = (HashMap<String, Object>)outMap.get(CC_NAME);
			}
			mapCc.put(RESMAP_RETURN_CODE, returnCd);
			outMap.put(CC_NAME, mapCc);
			createResultParam(bean, outMap);
		}
		DEBUG_LOG.info("action_Init End!");
		return true;
	}

	/**
	 * 返却パラメータ編集処理を行います。
	 * <BR>
	 * @param bean データBeanアクセスクラス
	 * @param outMap 出力用Map
	 */
	private void createResultParam(X31SDataBeanAccess bean, Map<?, ?> outMap) throws Exception
	{
		
		String returnCd = (String)getParamFromMap(outMap, CC_NAME, RESMAP_RETURN_CODE);
		String telNo = (String)getParamFromMap(outMap, CC_NAME, RESMAP_050_TELNO);
		
		String setValue = X31CWebConst.DATABEAN_SET_VALUE;
		bean.sendMessageString(CNA00601SFConst.RETURN_CODE, setValue, returnCd);
		bean.sendMessageString(CNA00601SFConst.N_050_TELNO, setValue, telNo);
		
		JSYwebLog.println(JSYLogBase.EXECUTION, this.getClass(), null, "BPCON0I002",  new String[]{"CNA005_050番号発行_returnCd= " + returnCd.toString()}, "");
	}
	
	/**
	 * サービスへのパラメータを作成します。
	 * <BR>
	 * @param requestMap リクエストパラメータMap
	 * @param inputMap 入力Map
	 * @throws Exception 処理中に発生した例外をスロー
	 */
	private void createServiceMap(Map<String, String> requestMap, Map<String, Object> inputMap) throws Exception
	{
		
		HashMap<String, Object> mapCc = new HashMap<String, Object>();
		
		mapCc.put(REQMAP_SYSID, getParameterToString(requestMap, REQMAP_SYSID));
		mapCc.put(REQMAP_CONT_KEI_NO, getParameterToString(requestMap, REQMAP_CONT_KEI_NO));
		mapCc.put(REQMAP_TELNO_HRADSI_SBT_CD, getParameterToString(requestMap, REQMAP_TELNO_HRADSI_SBT_CD));
		mapCc.put("IN_TELNO", getParameterToString(requestMap, REQMAP_TELNO));
		//ANK-4538-00-00 ADD START
		mapCc.put(REQMAP_MIMOTCFM_ID, getParameterToString(requestMap, REQMAP_MIMOTCFM_ID));
		//ANK-4538-00-00 ADD END

		inputMap.put(CC_NAME, mapCc);
	}

	/**
	 * パラメータマップを解析し、キーに一致する値を返却します。
	 * <BR>
	 * @param requestMap リクエストMap
	 * @param keyName キー名
	 * @return String キー値
	 * @throws 処理中に発生した例外をスロー
	 */
	private static String getParameterToString(Map<String, String> requestMap, String keyName) throws Exception
	{
		
		String value = "";
		Iterator<?> keyIterator = requestMap.keySet().iterator();
		
		while (keyIterator.hasNext())
		{
			String key = (String)keyIterator.next();
			
			if (key.equals(keyName) ||  key.matches(keyName + "\\[[0-9]*\\]"))
			{
				value = requestMap.get(key);
			}
			
		}
		return new String(value.getBytes());
	}
	
	/**
	 * マップから指定されたキーの値を取得します。<BR>
	 * (使用例） getParamFromXml("LKA11020_RECEIVE", "PROCESS_DIV");
	 * <BR>
	 * @param map マップ
	 * @param allKeys キー名
	 * @return 値
	 */
	@SuppressWarnings("unchecked")
	public static Object getParamFromMap(Map map, String...allKeys)
	{

		Map nowMap = map;
		Object returnVal = null;
		for (int i = 0; i < allKeys.length; i++)
		{
			String key = allKeys[i]; 
			int idx = -1; 
			if (key.matches("[a-zA-Z0-9_\\-]+\\[[0-9]+\\]"))
			{
				idx = new Integer(key.replaceFirst("^[a-zA-Z0-9_\\-]+\\[", "").replace("]", "")); 
				key = key.replaceFirst("\\[[0-9]+\\]", ""); 
			}
			if (nowMap.containsKey(key))
			{
				Object val = nowMap.get(key); 
				if ((val instanceof List) && (idx >= 0))
				{
					List nowList = (List)val; 
					val = nowList.get(idx); 
				}
				if (val instanceof Map)
				{
					nowMap = (Map)val; 
				}
				if (i == allKeys.length - 1)
				{
					returnVal = val; 
				}
			}
			else
			{
				return null; 
			}
		}

		return returnVal;
	}
	
	/**
	 * 対象文字列がnull以外の場合trimして返し、nullの場合は空白を返します。
	 * <BR>
	 * @param base 対象文字列
	 * @return 変換後文字列
	 */
	private static String nullOrBlankWithTrim(String base)
	{	
		
    	// 引数の対象文字列がnull以外の場合
        if (!isNullOrBlanks(base))
        {
        	// TRIMした値を返す
            return base.trim();
        }
        
        // 引数の対象文字列がnullの場合、空文字を返す
        return STR_BLANK;
    }
	/**
	 * null、空文字、空白文字（半角空白、全角空白）の判定を行います。
	 * <BR>
	 * @param strCheck　対象文字列
	 * @return true:対象文字列がnullもしくは空白文字（半角空白、全角空白）のみ、false:それ以外
	 */
    private static boolean isNullOrBlanks(String strCheck)
    {
    	
		// 対象文字列が対象文字列がnullもしくは空文字の場合
    	if (strCheck == null || STR_BLANK.equals(strCheck))
    	{
    		// trueを返す
        	return true;
        }
    	
    	// 全半角空白を空文字に置換
        String strRep = strCheck.replaceAll(" ", STR_BLANK).replaceAll("　", STR_BLANK);
        
        // 空文字以外が存在する場合
        if (strRep.length() > 0)
        {
        	// falseを返す
        	return false;
        }
        
        // 空文字のみの場合、trueを返す
        return true;
	}

	/**
	 * 文字列がすべて半角英数で構成されているか判定します。
	 * 備考：<br>
	 *           <p>半角文字の範囲：<br>
	 *           　半角英数字 &#92;u0021〜&#92;u007E 、半角空白とISO制御文字も許容されます。<br>
	 *           　半角空白 &#92;u0020<br>
	 *           　ISO制御文字 &#92;u0000 〜 &#92;u001F または &#92;u007F 〜 &#92;u009F
	 *           
	 * @param str 判定対象の文字列<br>
	 * @return boolean 文字列がすべて半角文字ならば true そうでないなら false
	 * @exception IllegalArgumentException 引数が空文字列またはnullの場合にスローされます
	 */
	private static boolean isNarrowEiSuji(String str) throws IllegalArgumentException {

		// 引数がnullか空文字の場合はfalse。
		if(str == null || "".equals(str)) 
		{
			return false;
		}

		// 引数の文字列を文字に分解します。
		char[] chars = str.toCharArray( );
		int length = chars.length;

		// 文字列を構成する文字が半角文字の範囲に入っているか調べます。
		for(int i = 0; i < length; i++) 
		{
			// 範囲に入っていない場合は false を返します。
			if(!(HALF_DIGIT_AND_ALPHABET_START <= chars[i] && chars[i] <= HALF_DIGIT_AND_ALPHABET_END 
					|| chars[i] == HALF_SPACE || Character.isISOControl(chars[i]))) 
			{
				return false;
			}
		}
		return true;
	}

}
