/*********************************************************************
*	All Right reserved,Copyright (c) Fujitsu, 2011
**********************************************************************
*＜プログラム内容＞
*	システム名		：顧客契約
*	モジュール名	：KKA001SFLogic
*	ソースファイル名：KKA001SFLogic.java
*	作成者			：富士通
*	日付			：2011年06月24日
*＜機能概要＞
*	POP PW初期化連携のビューロジッククラスです。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/06/24	富士通		新規作成
*
**********************************************************************/
package eo.web.webview.KKA06601SF;

//import static com.fujitsu.futurity.web.x31.X31SWebLog.DEBUG_LOG;

//import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletRequest;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.fujitsu.futurity.common.JSYwebLog;
import com.fujitsu.futurity.web.x00.JCCBusinessException;
import com.fujitsu.futurity.web.x00.JCCWebServiceException;
import com.fujitsu.futurity.web.x31.X31BWebBusinessLogic;
import com.fujitsu.futurity.web.x31.X31CWebConst;
import com.fujitsu.futurity.web.x31.X31SDataBeanAccess;
import com.fujitsu.futurity.web.x33.HttpDispatchContext;
import com.fujitsu.futurity.web.x33.X33CUtil;
import com.fujitsu.futurity.web.x33.X33WSessionController;

import eo.common.constant.JPCOnlineMessageConstant;
import eo.web.webview.common.JCCWebCommon;
import eo.web.webview.common.JKKCommonConst;
import eo.web.webview.mapping.KKSV0566_KKSV0566OPDBMapper;

/**
 * <dd>クラス名：POP PW初期化連携ビューロジック
 * <dd>クラス説明：POP PW初期化連携時の処理を記述します。
 * <dd>備考：
 * @version  1.0 2011/06/24
 * @author   富士通
 */
@SuppressWarnings("serial")
public class KKA06601SFLogic extends X31BWebBusinessLogic
{
	
	/** 文字エンコーディング格納用キー */
	public static final String KEY_ENCODING = "ENCODING";

	/** 要素のタグ名格納用キー */
	public static final String KEY_ELEMENT = "ELEMENT";

	/** 要素の属性格納用キー */
	public static final String KEY_ATTRIBUTE = "ATTRIBUTE";

	/** 要素の値データ格納用キー */
	public static final String KEY_VALUE = "VALUE";

	/** 受信マップのルートタグ */
	private static final String RCV_ROOT_TAG = "LKA13010_RECEIVE";
	
	/** 返却用マップのルートタグ */
	private static final String SND_ROOT_TAG = "LKA13010_SEND";
	
	/** POP_IDタグ */
	private static final String RCV_POP_ID = "POP_ID";

	private static final String HTTP_PARAMETER_RECEIVE_XML = "receiveXml";

	private static final Object KKSV011501CC = "KKSV011501CC";


	/**
	 * APIリクエスト時
	 * @return 正常終了:true 異常終了:false
	 * @throws Exception 
	 */
	@SuppressWarnings("unchecked")
	public boolean actionInit() throws Exception
	{
		X31SDataBeanAccess bean = null;

		//返却用マップを追加
		HashMap<String, Object> retMap = new HashMap<String, Object>();
		retMap.put(SND_ROOT_TAG, new HashMap<String, Object>());

		try
		{
			// サービス結果格納用サービスフォームBean
			bean = getServiceFormBean();
			if (false)
			{
				return true;
			}

			if (false)
			{
				return true;
			}
			
			// XMLファイルを取得する。
			Map<?,?> dataMap = null;
			HashMap<String,Object> receiveMap = null;
			String encoding = "UTF-8";
			
			// 受信したXMLデータを解析し、Mapに変換
			ServletRequest request = getServletRequest();
			request.setCharacterEncoding(encoding);
			dataMap = parseXml(request, encoding);
			//2012-04-12Works
//			String sampleXML="<?xml version=\"1.0\" encoding=\"utf-8\" ?> <LKA13010_RECEIVE> <PROCESS_DIV>01</PROCESS_DIV> <SYS_ID>1000052897</SYS_ID> <EO_ID>510000524750</EO_ID> <POP_ID_LIST> <POP_ID>kgkk16650%ares.eonet.ne.jp</POP_ID> <POP_ID>sankaleia%zeus.eonet.ne.jp</POP_ID> </POP_ID_LIST> </LKA13010_RECEIVE>";
//			dataMap = JCCWebCommon.getParseXmlToMap(sampleXML);

			receiveMap = (HashMap<String,Object>)dataMap.get(RCV_ROOT_TAG);
			
//			// テスト用
//			HashMap<String, Object> receiveMap = new HashMap<String, Object>();
			
			 
//			receiveMap.put("PROCESS_DIV", "01");
//			receiveMap.put("SYS_ID", "C000000001");
//			receiveMap.put("EO_ID", "EO12345");
//			ArrayList<HashMap<String, Object>> popIdListTest = new ArrayList<HashMap<String, Object>>();
//			HashMap<String, Object> popId = null;
//			popId = new HashMap<String, Object>();
//			popId.put("POP_ID", "pop05");
//			popIdListTest.add(popId);
//			receiveMap.put("POP_ID_LIST", popIdListTest);
			
			
			// 受信データチェック
			String returnCode = checkRequest(receiveMap);
			if (returnCode != null)
			{
				// 返却値の設定
				// 返却値の設定(パラメータ不正エラー)
				setReturn((HashMap<String,Object>)retMap, KKA06601SFConst.RTN_PARAM_ERR);
				return true;
			}

			// サービス呼び出しの際の引数を生成
			HashMap paramMap = new HashMap();
			HashMap inputMap = new HashMap();
			HashMap outputMap = new HashMap();
			
			//---------- POPPW初期化連携登録 ----------//
			// サービスパラメタ設定
			paramMap.put(X31CWebConst.TELEGRAM_INFO_USECASE_ID, JKKCommonConst.UCID_KKSV0115);
			paramMap.put(X31CWebConst.TELEGRAM_INFO_OPERATION_ID, JKKCommonConst.OPID_KKSV0115OP);

			// 2012-05-11 ADD_START
			// 指示書からAxm連携時用ＳＹＳＩＤ
			String sysid = (String)receiveMap.get("SYS_ID");
			
			// 2012-05-11 ADD_END
			
			// 取得したパラメータを元に、inputMapを構築する。
			inputMap.put(KKSV011501CC, receiveMap);
			
			// サービスの呼出
			invokeService(paramMap, inputMap, outputMap);
			
			Integer retCode = getReturnCode(outputMap);
			if (null != retCode && 0 != retCode)
			{
				// 返却値の設定(パラメータ不正エラー)
				setReturn((HashMap<String,Object>)retMap, KKA06601SFConst.RTN_PARAM_ERR);
				return true;
			}
			else if (null == retCode || 0 != retCode)
			{
				throw new JCCBusinessException(JPCOnlineMessageConstant.EKB8370_KW, new String[]{"POPパスワード初期化連携"});
			}

			// 2012-05-11 ADD_START
			// Axm連携サービス呼出
			sjishoInvokeService(sysid);
			// 2012-05-11 ADD_END
				
			//---------- 処理結果の編集 ----------//
			// 返却値の設定(正常終了)
			setReturn((HashMap<String,Object>)retMap, KKA06601SFConst.RTN_NORMAL_DATA);
		}
		catch (JCCWebServiceException jwse)
		{
			// 返却値の設定(パラメータ不正エラー)
			setReturn((HashMap<String,Object>)retMap, KKA06601SFConst.RTN_PARAM_ERR);
			return true;
		}
		catch (Exception e) 
		{
			// システムエラー情報をMapに構築する
			HashMap errBaseMap = new HashMap();
			HashMap sysErrMap = new HashMap();
			List<Object> errList = new ArrayList<Object>();
			List<Object> valList = new ArrayList<Object>();
			sysErrMap.put(KEY_ENCODING, "UTF-8");
			sysErrMap.put(KEY_ELEMENT, "MESSAGE");
			valList.add(e.getMessage());
			sysErrMap.put("VALUE", valList);
			errList.add(sysErrMap);
			
			errBaseMap.put(KEY_ENCODING, "UTF-8");
			errBaseMap.put(KEY_ELEMENT, "ERRORS");
			errBaseMap.put("VALUE", errList);
			String errXml = JCCWebCommon.getParseMapToXml(errBaseMap);
			// 返却値の設定(システムエラー)
			bean.sendMessageString(KKA06601SFConst.RTN_DATA, X31CWebConst.DATABEAN_SET_VALUE, errXml);

			setReturn((HashMap<String,Object>)retMap, KKA06601SFConst.RTN_SYS_ERR);
			
			JSYwebLog.printStackTrace(JSYwebLog.ERROR, getClass(), e, null, null);
		}
		return true;
	}


	/**
	 * Axm連携サービス
	 * @param sysid
	 * 
	 */
	private void sjishoInvokeService(String sysid){
		
		// ユースケースID格納用のHashMap
		HashMap<String, Object> paramMap = new HashMap<String, Object>();
		// マッピングクラスの結果を格納するHashMap
		HashMap<String, Object> inputMap = new HashMap<String, Object>();
		// サービス呼出結果を格納するHashMap
		HashMap<String, Object> outputMap = new HashMap<String, Object>();

		// サービスパラメタ設定
		paramMap.put(X31CWebConst.TELEGRAM_INFO_USECASE_ID, "CKSV9001");
		paramMap.put(X31CWebConst.TELEGRAM_INFO_OPERATION_ID, "CKSV9001OP");
		
		// 上りマッピング(サービス項目-DataBean項目マッピング)
		KKSV0566_KKSV0566OPDBMapper mapper = new KKSV0566_KKSV0566OPDBMapper();
		mapper.setCKSV900101CC(inputMap, "1", sysid);
		invokeService(paramMap, inputMap, outputMap);
		
		// DataBeanログ出力
		JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), null, null, null);
	}
	/**
	 * 受信データのチェック
	 * @param receiveMap
	 * @return returnCode
	 */
	@SuppressWarnings("unchecked")
	private String checkRequest(HashMap<String,Object>receiveMap)
	{
		// 戻りコードの初期化
		String returnCode = null;

		// リクエスト元のチェック
		if (false)
		{
			returnCode = KKA06601SFConst.RTN_REMOTE_ERR;  // リモートアドレス不正エラー
		}
		else
		{
			// 処理コードのチェック
			String processDiv = (String)receiveMap.get("PROCESS_DIV");
			if ((processDiv == null) || (!"01".equals(processDiv)))
			{
				returnCode = KKA06601SFConst.RTN_PARAM_ERR;  //パラメータ不正エラー
			}
			// eoIDのチェック
			else if ((String)receiveMap.get("EO_ID") == null || ((String)receiveMap.get("EO_ID")).equals(""))
			{
				returnCode = KKA06601SFConst.RTN_PARAM_ERR;   //パラメータ不正エラー
			}
			// SYSIDのチェック
			else if ((String)receiveMap.get("SYS_ID") == null || ((String)receiveMap.get("SYS_ID")).equals(""))
			{
				returnCode = KKA06601SFConst.RTN_PARAM_ERR;   //パラメータ不正エラー
			}
			else
			{
//				// POP_IDのチェック
				HashMap<String, Object> popIdList = (HashMap<String, Object>)receiveMap.get("POP_ID_LIST");
				if (popIdList.size() == 0)
				{
					returnCode = KKA06601SFConst.RTN_PARAM_ERR;  //パラメータ不正エラー
				}
				else
				{
					String popID_Name = null;
					for(int i = 0; i < popIdList.size(); i++)
					{
						popID_Name="POPID_" + String.format("%02d", i);
						if ((String)popIdList.get(popID_Name) == null || ((String)popIdList.get(popID_Name)).equals("") )
						{
							returnCode = KKA06601SFConst.RTN_PARAM_ERR;   //パラメータ不正エラー
							break;
						}
					}
				}
			}
		}

		return returnCode;
	}

	/**
	 * 返却値の設定
	 * @param returnCode
	 * @return 正常終了:true 異常終了:false
	 */
	@SuppressWarnings("unchecked")
	private boolean setReturn(HashMap<String,Object> dataMap, String returnCode) throws IOException
	{
		// サービス結果格納用サービスフォームBean
		X31SDataBeanAccess bean = null;
		bean = getServiceFormBean();
		
		// 2012-03-13 ST1-2012-0000012 ADD_START
		
		// リターンコードを詰め替える
		setReturnCode(dataMap, returnCode);

		HashMap<String, Object> outputInfoMap = convMap((HashMap<String, Object>)dataMap.get(SND_ROOT_TAG), SND_ROOT_TAG);
		
		String ResultData = null;
		
		ResultData = JCCWebCommon.getParseMapToXml(outputInfoMap);
		bean.sendMessageString(KKA06601SFConst.RTN_DATA, X31CWebConst.DATABEAN_SET_VALUE, ResultData);

		
		// 2012-03-13 ST1-2012-0000012 ADD_END
		// DataBeanログ出力
		JSYwebLog.println(JSYwebLog.DataBean_Dump, getClass(), dumpDatabean(), null, null, null);
		
		return true;
	}
	
	// 2012-03-13 ST1-2012-0000012 ADD_START
	/**
	 * リターンコードを設定する
	 * @param dataMap
	 * @param returnCode
	 */
	@SuppressWarnings("unchecked")
	private void setReturnCode(HashMap<String,Object> dataMap, String returnCode)
	{
		HashMap<String,Object> lka11010 = (HashMap<String,Object>)dataMap.get(SND_ROOT_TAG);
		lka11010.put("RETURN_CODE", returnCode);
	}
	
	// 2012-03-13 ST1-2012-0000012 ADD_END

	/**
	 * requestを取得する
	 * @return リクエストオブジェクト
	 */
	private ServletRequest getServletRequest(){
		
		ServletRequest servletRequest = null;

		try {
			X33WSessionController controller = X33CUtil.getSession(getSessionId());
			HttpDispatchContext context = (HttpDispatchContext)controller.getContext();
			servletRequest = context.getServletRequest();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return servletRequest;
	}
	/**
	 * リクエストから取得したXMLを解析しMapに変換する
	 * @param servletRequest
	 * @return マップ
	 */
	@SuppressWarnings("unchecked")
	public static Map parseXml(ServletRequest servletRequest, String encoding){

		// 受信したXMLデータを解析
//		ServletInputStream servletInputStream;		//2012-04-23無効　ST1-2012-0000042対応
//		StringBuffer buf = new StringBuffer();
		MyXmlParser myXmlParser = new MyXmlParser();
		
		try {
			//↓↓↓2012-04-23更新　ST1-2012-0000042対応↓↓↓
			String tmpXmlData = servletRequest.getParameter(HTTP_PARAMETER_RECEIVE_XML);
			ByteArrayInputStream bais = new ByteArrayInputStream(tmpXmlData.getBytes());
//			servletInputStream = servletRequest.getInputStream();
			//↑↑↑2012-04-23更新　ST1-2012-0000042対応↑↑↑

			SAXParserFactory spfactory = SAXParserFactory.newInstance();
			SAXParser parser = spfactory.newSAXParser();

//			InputSource is = new InputSource(new InputStreamReader(servletInputStream,encoding));
			InputSource is = rewritePOP_ID_LIST(bais, encoding);
			bais.close();											//2012-04-23追加

			is.setEncoding(encoding);
			parser.parse(is, myXmlParser);
//			
//			parser.parse(servletInputStream, myXmlParser);

			is.getByteStream().close();

		} catch (IOException e) {
			e.printStackTrace();
		} 
		catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}

		return myXmlParser.getDataMap();
//		return JCCWebCommon.getParseXmlToMap(buf.toString());
	}


	/**
	 * リクエストXMLを読み込みつつ POP_ID 置換処理する
	 * 
	 * @param is
	 * @param encoding
	 * @return
	 * @throws IOException
	 */
	private static InputSource rewritePOP_ID_LIST(	InputStream is, String encoding)
		throws IOException
	{
		Integer cnt = new Integer(0);
		
		char[][] mem = new char[2][4098];
		InputStreamReader ir = new InputStreamReader(is, encoding);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		int sw = 0;
		int n = ir.read(mem[sw], 0, 4098);

		if (n > 0)
		{
			JSYwebLog.println(JSYwebLog.XML_Dump, KKA06601SFLogic.class, new String(mem[sw],0,n), null, null, null);
		}
		do
		{
			StringBuilder sb = new StringBuilder();
			int last_sw = sw;
			int last_n = n;
			if (0 < last_n)
			{
				sb.append(new String(mem[last_sw]).substring(0, last_n));

				sw = (0==sw ? 1 : 0);
				n = ir.read(mem[sw], 0, 4098);
				if (0 < n)
				{
					sb.append(new String(mem[sw]).substring(0, n));
				}
				else
				{
					n = 0;
				}
			}
			String newData = replacePOP_ID(sb, cnt);
			int newLen = newData.length();
			byte[] newBytes = newData.getBytes();
			if (null != newBytes && 0 < newBytes.length && newLen > n)
			{
				baos.write(newBytes, 0, (newLen - n));
			}
			if (0 < n)
			{
				newData.getChars((newLen-n), newLen, mem[sw], 0);
			}
		}
		while (0 < n);
		
		ir.close();
		byte[] ba = baos.toByteArray();
		baos.close();

		return new InputSource(new ByteArrayInputStream(ba));
	}


	/**
	 * POP_IDタグの置換
	 * 
	 * @param sb
	 * @param cnt
	 * @return
	 */
	private static String replacePOP_ID(StringBuilder sb, Integer cnt)
	{
		boolean sw = false;
		int pos = sb.indexOf("<POP_ID_LIST>") + "<POP_ID_LIST>".length();
		int end_pos = sb.indexOf("</POP_ID_LIST>");
		int p = 0;
		while (0 <= (p = sb.indexOf(RCV_POP_ID, pos)) && end_pos > p)
		{
			String newTag = "POPID_" + String.format("%02d", cnt);	//連番付きタグ
			sb.replace(p, (p+RCV_POP_ID.length()), newTag);				//タグを書き換え
			if (sw)													//POP_ID終了タグの置換をしたのでカウントアップ
			{
				cnt ++;
			}
			sw = (sw ? false : true);
			pos = p + newTag.length();		//次の検索位置
		}

		return sb.toString();
	}

	// 2012-03-13 ST1-2012-0000012 ADD_START
	/**
	 * Map をXML変換用に編集を行う
	 * @param src
	 * @param retKey
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private HashMap<String, Object> convMap(Map<String, Object> src, String retKey)
	{
		HashMap<String, Object> retMap = new HashMap<String, Object>();
		List<Object> valList = new ArrayList<Object>();
		Set<String> keySet = src.keySet();
		for (Iterator<String> iter = keySet.iterator(); iter.hasNext();)
		{
			Map<String, Object> childMap = new HashMap<String, Object>();
			List<Object> tmpList = new ArrayList<Object>();
			String key = iter.next();
			Object value = src.get(key);

			if (value instanceof ArrayList)
			{
				valList.addAll(convArrayToMap((List<Map<String, Object>>)value, key));
			}
			else if (value instanceof HashMap)
			{
				valList.addAll(convMapToMap((Map<String, Object>)value, key));
			}
			else
			{
				tmpList.add(value);
				childMap.put(KEY_ELEMENT, key);
				childMap.put(KEY_VALUE, tmpList);
				valList.add(childMap);
			}
		}

		retMap.put(KEY_ENCODING, "UTF-8");
		retMap.put(KEY_ELEMENT, retKey);
		retMap.put(KEY_VALUE, valList);
		return retMap;
	}

	/**
	 * ArrayList から Map へ変換する
	 * @param src
	 * @param retKey
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private List<Object> convArrayToMap(List<Map<String, Object>> src, String retKey)
	{
		List<Object> retList = new ArrayList<Object>();
		List<Object> valList = new ArrayList<Object>();
		for (Iterator<Map<String, Object>> iter = src.iterator(); iter.hasNext();)
		{
			Map<String, Object> map = iter.next();
			Set<String> keySet = map.keySet();
			for (Iterator<String> keyIter = keySet.iterator(); keyIter.hasNext();)
			{
				String key = keyIter.next();
				Map<String, Object> childMap = new HashMap<String, Object>();
				List<Object> tmpList = new ArrayList<Object>();
				Object value = map.get(key);

				if (value instanceof ArrayList)
				{
					valList.addAll(convArrayToMap((List<Map<String, Object>>)value, key));
				}
				else if (value instanceof HashMap)
				{
					valList.addAll(convMapToMap((Map<String, Object>)value, key));
				}
				else
				{
					tmpList.add(value);
					childMap.put(KEY_ELEMENT, key);
					childMap.put(KEY_VALUE, tmpList);
					valList.add(childMap);
				}
			}
		}
		Map<String, Object> childMap = new HashMap<String, Object>();
		childMap.put(KEY_ELEMENT, retKey);
		childMap.put(KEY_VALUE, valList);
		retList.add(childMap);
		return retList;
	}
	
	/**
	 * Map から Map へ編集する
	 * @param src
	 * @param retKey
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private List<Object> convMapToMap(Map<String, Object> src, String retKey)
	{
		List<Object> retList = new ArrayList<Object>();
		List<Object> valList = new ArrayList<Object>();
		Set<String> keySet = src.keySet();
		for (Iterator<String> iter = keySet.iterator(); iter.hasNext();)
		{
			Map<String, Object> childMap = new HashMap<String, Object>();
			List<Object> tmpList = new ArrayList<Object>();
			String key = iter.next();
			Object value = src.get(key);

			if (value instanceof ArrayList)
			{
				valList.addAll(convArrayToMap((List<Map<String, Object>>)value, key));
			}
			else if (value instanceof HashMap)
			{
				valList.addAll(convMapToMap((Map<String, Object>)value, key));
			}
			else
			{
				tmpList.add(value);
				childMap.put(KEY_ELEMENT, key);
				childMap.put(KEY_VALUE, tmpList);
				valList.add(childMap);
			}
		}
		Map<String, Object> childMap = new HashMap<String, Object>();
		childMap.put(KEY_ELEMENT, retKey);
		childMap.put(KEY_VALUE, valList);
		retList.add(childMap);
		return retList;
	}
	// 2012-03-13 ST1-2012-0000012 ADD_END


	/**
	 * リターンコードをチェックします
	 * 
	 * @param outputMap
	 * @return
	 * @since 2012-08-27 ST1-2012-0000418対応のついで（業務結果とFW処理結果の格納の切り分け）
	 */
	@SuppressWarnings("unchecked")
	private Integer getReturnCode(HashMap outputMap)
	{
		HashMap<?, ?> dataMap = (HashMap<?, ?>) outputMap.get(KKSV011501CC);
		
		Integer ret = null;
		String returnCode = (String)dataMap.get("return_code");
		if (null != returnCode)
		{
			ret = Integer.valueOf(returnCode);
		}

		return ret;
	}


}