/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKKCtrlMcafeeInfo
*	ソースファイル名：JKKCtrlMcafeeInfo.java
*	作成者			：FJ）原田
*	日付			：2017年04月18日
*＜機能概要＞
*	マカフィー社 外部連携（本番環境用）コマンド発行部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v32.00.00	2017/04/18  FJ)原田		【ANK-3149-00-00】新セキュリティパック
*	v32.01.00	2017/08/14  FJ)原田		【OM-2017-0000695】電文リトライ時のリクエスト重複エラー
*
**********************************************************************/
package eo.common.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.fujitsu.futurity.model.common.JCMAPLConstMgr;

import eo.common.constant.JKKStrConst;
import eo.common.constant.JWCStrConst;


/**
 *  マカフィー連携独自処理部品（本番環境用）です。<p>
 * <br>
 * @author 富士通
 */
public class JKKCtrlMcafeeInfoImpl extends JKKCtrlMcafeeInfo
{
	/** 通信方式SSL */
	private static final String S_HTTPS = "https";
	
	/**
	 * CRLF定数定義
	 */
	private static final String CRLF = "\r\n";
	
	
	// XML要素情報定数定義（結果コード取得電文）
	/**
	 * コマンド要求電文結果情報(RESPONSECONTEXT)
	 */
	private static final String CONTROL_RESULT_INFO = "RESPONSECONTEXT";
	
	/**
	 * カスタマーID（マカフィー会員ＩＤ）
	 */
	private static final String MCAFEE_MEMBER_ID = "mcafeeMemberId";
	
	/**
	 * トランザクション・コード
	 */
	private static final String RETURN_CODE = "returnCode";
	
	/**
	 *トランザクション・コード説明
	 */
	private static final String RETURN_CODE_SETMEI = "returnCodeSetmei";
	
	/**
	 * パートナー・オーダー照会番号（他事業者契約異動通知番号）
	 */
	private static final String TAJGS_KEI_IDT_NO = "tajgsKeiIdoNo";
	
	/**
	 * McAfeeオーダー照会番号（マカフィー購入ＩＤ）
	 */
	private static final String MCAFEE_BUY_ID = "mcafeeBuyId";
	
	/**
	 * e-mailアドレス（マカフィー用認証メールアドレス）
	 */
	private static final String MCAFEE_NINSHO_MLAD = "mcafeeNinshoMlad";
		
	/**
	 * 製品ダウンロードURL（マカフィー製品ダウンロードURL）
	 */
	private static final String MCAFEE_SEHN_DL_URL = "mcafeeSehnDlUrl";
	
	/**
	 * マカフィーリトライ回数
	 */
	protected static final String MCAFEE_RETRYCOUNT_KKIFE354 = "MCAFEE_RETRYCOUNT_KKIFE354";
	
	/**
	 * マカフィー連携タイムアウト値
	 */
	protected static final String MCAFEE_TIMEOUT_KKIFE354 = "MCAFEE_TIMEOUT_KKIFE354";
	
	/**
	 * 接続先URL
	 */
	protected static final String MCAFEE_URL_KKIFE354 = "MCAFEE_URL_KKIFE354";
	
	/**
	 * マカフィー用プロキシホスト
	 */
	protected static final String MCAFEE_HTTPS_PROXY_HOST = "MCAFEE_HTTPS_PROXY_HOST";
	
	/**
	 * マカフィー用プロキシポート
	 */
	protected static final String MCAFEE_HTTPS_PROXY_PORT = "MCAFEE_HTTPS_PROXY_PORT";
	
	/**
	 * 他事業者契約異動種別コード
	 */
	protected static final String TAJGS_KEI_IDO_SBT_CD = "tajgsKeiIdoSbtCd";
	
	// メッセージwriterから実装を移管
	/**
	 * XMLStreamWriterクラス
	 */
	private XMLStreamWriter writer = null;
	
	/**
	 * Writerクラス
	 */
	private Writer wt = null;
	
	// 文字化け対策
	/**
	 * StringWriterクラス
	 */
	private StringWriter sw = new StringWriter();
	
	/**
	 * エラーコード（ERR0001)
	 */
	private static final String ERR0001 = "ERR0001";
	
	/**
	 * エラーコード（ERR0002)
	 */
	private static final String ERR0002 = "ERR0002";
	
	/**
	 * エラーコード（ERR0003)
	 */
	private static final String ERR0003 = "ERR0003";
	
	/**
	 * エラーコード（ERR0004)
	 */
	private static final String ERR0004 = "ERR0004";
	
	/**
	 * エラーコード（ERR0005)
	 */
	private static final String ERR0005 = "ERR0005";
	
	/**
	 * エラーコード（ERR0006)
	 */
	private static final String ERR0006 = "ERR0006";
	
	/**
	 * エラーコード（ERR0007)
	 */
	private static final String ERR0007 = "ERR0007";
	
	/**
	 * エラーコード（ERR0008)
	 */
	private static final String ERR0008 = "ERR0008";
	
	/**
	 * エラーコード（ERR0009)
	 */
	private static final String ERR0009 = "ERR0009";
	
	/**
	 * レスポンス電文
	 */
	private static String responseXml = "";
	
	/**
	 * 結果明細一時格納用のMap
	 */
	private static final String TMP_RESULT_DETAIL = "TMP_RESULT_DETAIL";
	
	/**
	 * データ定義、XML要素変換テーブル（戻り電文）
	 */
	private static HashMap<String, String> mapToElement = new HashMap<String, String>() 
	{
		{
			// カスタマーID
			put("ID", MCAFEE_MEMBER_ID);
			// パートナー・オーダー照会番号
			put("PARTNERREF", TAJGS_KEI_IDT_NO);
			// McAfeeセールス・オーダーID
			put("REF", MCAFEE_BUY_ID);
			// e-mailアドレス
			put("EMAILADDRESS", MCAFEE_NINSHO_MLAD);
			// パスワード
			put("PASSWORD", PASSWORD);
			// 製品ダウンロードURL
			put("PRODUCTDOWNLOADURL", MCAFEE_SEHN_DL_URL);
			// トランザクション・コード
			put("RETURNCODE", RETURN_CODE);
			// トランザクション・コード説明
			put("RETURNDESC", RETURN_CODE_SETMEI);
		}
	};
	
	/**
	 *  マカフィー購入・キャンセル依頼処理を行います。
	 *  <br>
	 * @param serviceMap マカフィー購入・キャンセル依頼のインターフェイス情報
	 * @return 処理結果コード値　0：正常　1:異常
	 */
	public Map<String, Object> call_KKIFE354(Map<String, Object> serviceMap) throws Exception
	{
		// 電文送信処理の実行
		HashMap<String, Object> result = execute(serviceMap);
		
		return result;
	}
	
	/**
	 * SOAP電文送信処理を実行する。
	 * 
	 * @param serviceMap マカフィー購入・キャンセル依頼のインターフェイス情報
	 * @return 処理結果コード値　0：正常　1:異常
	 * @throws Exception 
	 */
	private HashMap<String, Object>  execute(Map<String, Object>serviceMap) throws Exception 
	{
		HashMap<String, Object> result = new HashMap<String, Object>();
		
		int retryCount = Integer.parseInt(JCMAPLConstMgr.getString(MCAFEE_RETRYCOUNT_KKIFE354));
		retryCount += 1;
		
		for(int i = 0 ; i < retryCount ; i++)
		{
			HttpURLConnection connection = null;
			InputStream is = null;
			InetAddress inetaddress = null;
			String responseContentType = null;
			OutputStream os = null;
			URL url = null;
			
			try
			{
				responseXml = new String();
				String urlString = JCMAPLConstMgr.getString(MCAFEE_URL_KKIFE354);
				String strPrxyHost = JCMAPLConstMgr.getString(MCAFEE_HTTPS_PROXY_HOST);
				String strPrxyPort = JCMAPLConstMgr.getString(MCAFEE_HTTPS_PROXY_PORT);
				
				url = new URL(urlString);
				
				// 電文を送信
				// 通信方式判定
				boolean bSslFlg = false;
				if(urlString.startsWith(S_HTTPS))
				{
					bSslFlg = true;
				}
				
				// プロキシの設定
				int intProxyPort = 0;
				if(strPrxyHost != null)
				{
					intProxyPort = Integer.parseInt(strPrxyPort);
				}
				
				// 電文を送信
				// SSLの場合、HttpsURLConnectionへキャスト
				if(bSslFlg)
				{
					// Proxy設定値がある場合はProxyをセットしてコネクションをオープン
					if(strPrxyHost != null && strPrxyPort != null)
					{
						Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(strPrxyHost, intProxyPort));
						connection = (HttpsURLConnection) url.openConnection(proxy);
					}
					else
					{
						connection = (HttpsURLConnection) url.openConnection();
					}
					
				}
				else
				{
					// Proxy設定値がある場合はProxyをセットしてコネクションをオープン
					if(strPrxyHost != null && strPrxyPort != null)
					{
						Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(strPrxyHost, intProxyPort));
						connection = (HttpURLConnection) url.openConnection(proxy);
					}
					else
					{
						connection = (HttpURLConnection) url.openConnection();
					}
				}
				
				connection.setDoInput(true);
				connection.setDoOutput(true);
				
				// マカフィー社との通信におけるタイムアウト値
				Integer mcafeeTimeout =(Integer.parseInt(JCMAPLConstMgr.getString(MCAFEE_TIMEOUT_KKIFE354) ));
				connection.setReadTimeout(mcafeeTimeout);
				connection.setConnectTimeout(mcafeeTimeout);
				
				os = connection.getOutputStream();
				
				// 送信用の電文を作成
				this.write(serviceMap, os);
				
				connection.connect();
				
				inetaddress =  InetAddress.getLocalHost();
				
				// 電文の戻りを取得
				is = connection.getInputStream();
				
				responseContentType = connection.getHeaderField("Content-Type");
					
				result = this.read(inetaddress.getHostName(), inetaddress.getHostAddress(), responseContentType, is);
			}
			catch(NullPointerException e)
			{
				result.put(JWCStrConst.CMD_RESULT_CD,"1");
				result.put(JWCStrConst.CMD_ERROR_CD, ERR0001);
				result.put(JWCStrConst.CMD_ERROR_MESSAGE,"XML電文処理でエラー（NullPointerException）が発生しました。" + e.getMessage());	
				continue;
			}
			catch(XMLStreamException e) 
			{
				result.put(JWCStrConst.CMD_RESULT_CD,"1");
				result.put(JWCStrConst.CMD_ERROR_CD, ERR0002);
				result.put(JWCStrConst.CMD_ERROR_MESSAGE,"XML電文処理でエラー（XMLStreamException）が発生しました。" + e.getMessage());	
				continue;
			}
			catch(MalformedURLException e) 
			{
				result.put(JWCStrConst.CMD_RESULT_CD,"1");
				result.put(JWCStrConst.CMD_ERROR_CD, ERR0003);
				result.put(JWCStrConst.CMD_ERROR_MESSAGE,"XML電文処理でエラー（MalformedURLException）が発生しました。" + e.getMessage());	
				continue;
			}
			catch (IOException e) 
			{
				
				result.put(JWCStrConst.CMD_RESULT_CD,"1");
				if(connection != null && inetaddress != null)
				{
					is = connection.getErrorStream();
					responseContentType = connection.getHeaderField("Content-Type");
					try 
					{
						if(is != null)
						{
							String msg = connection.getResponseMessage();
							result = this.read(inetaddress.getHostName(), inetaddress.getHostAddress(), responseContentType, is);
						}
						else 
						{
							result.put(JWCStrConst.CMD_RESULT_CD,"1");
							result.put(JWCStrConst.CMD_ERROR_CD, ERR0004);
							result.put(JWCStrConst.CMD_ERROR_MESSAGE,"XML電文処理でエラー（IOException）が発生しました。" + e.getMessage());
						}
					}
					catch(Exception ex) 
					{
						result.put(JWCStrConst.CMD_RESULT_CD,"1");
						result.put(JWCStrConst.CMD_ERROR_CD, ERR0005);
						result.put(JWCStrConst.CMD_ERROR_MESSAGE,"XML電文処理でエラー（IOException）が発生しました。" + ex.getMessage());	
						continue;
					}
				}
				if(result != null && result.get(JWCStrConst.CMD_ERROR_MESSAGE) != null )
				{
					result.put(JWCStrConst.CMD_RESULT_CD,"1");
				}
				else 
				{
					result.put(JWCStrConst.CMD_RESULT_CD,"1");
					result.put(JWCStrConst.CMD_ERROR_CD, ERR0006);
					result.put(JWCStrConst.CMD_ERROR_MESSAGE,"XML電文処理でエラー（IOException）が発生しました。" + e.getMessage());	
				}
				continue;
			}
			catch (ParserConfigurationException e) 
			{
				result.put(JWCStrConst.CMD_RESULT_CD,"1");
				result.put(JWCStrConst.CMD_ERROR_CD, ERR0007);
				result.put(JWCStrConst.CMD_ERROR_MESSAGE,"XML電文処理でエラー（ParserConfigurationException）が発生しました。" + e.getMessage());	
				continue;
			}
			catch (SAXException e) 
			{
				result.put(JWCStrConst.CMD_RESULT_CD,"1");
				result.put(JWCStrConst.CMD_ERROR_CD, ERR0008);
				result.put(JWCStrConst.CMD_ERROR_MESSAGE,"XML電文処理でエラー（SAXException）が発生しました。" + e.getMessage());	
				continue;
			}
			catch(Exception e) 
			{
				result.put(JWCStrConst.CMD_RESULT_CD,"1");
				result.put(JWCStrConst.CMD_ERROR_CD, ERR0009);
				result.put(JWCStrConst.CMD_ERROR_MESSAGE,"XML電文処理でエラー（Exception）が発生しました。" + e.getMessage());	
				continue;
			}
			finally
			{
				result.put("LOG_RESULT", "sendHttpRequestResponse"
											+ JKKCtrlMcafeeInfoImpl.CRLF
											+ "RequestText:"
											+ (os != null ? os : "RequestText == null")
											+ JKKCtrlMcafeeInfoImpl.CRLF
											+ "ResponseText:"
											+ (!("".equals(responseXml)) ? responseXml : "ResponseText == null")
											);
				
				if(os != null)
				{
					try {
						os.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if(is != null)
				{
					try {
						is.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			break;
		}
		
		return result;
	}
	
	/**
	 * 電文送信初期処理
	 * @param wt Writerオブジェクト
	 */
	private void init(Writer wt) 
	throws FactoryConfigurationError,XMLStreamException
	{
		// OM-2017-0000695 ADD START
		this.sw = new StringWriter();
		// OM-2017-0000695 ADD END
		this.wt = wt;
		
		XMLOutputFactory outfactory = XMLOutputFactory.newInstance();
		this.writer = outfactory.createXMLStreamWriter(this.sw);
	}
	
	/**
	 * クローズ処理
	 */
	private void close()
	throws XMLStreamException,IOException
	{
		
		writer.flush();
		writer.close();
		
		// 最後に全部出す。
		this.wt.write(sw.toString());
	}
	
	/**
	 * XML要素開始タグ出力処理
	 * 
	 * @param name
	 * @throws XMLStreamException
	 */
	private void writeStartElement(String name) 
	throws XMLStreamException
	{
		this.writer.writeStartElement(name);
	}
	
	/**
	 * XML要素終了タグ出力処理
	 * 
	 * @param name
	 * @throws XMLStreamException
	 */
	private void writeEndElement(String name) 
	throws XMLStreamException
	{
		this.writer.writeEndElement();
	}
	
	/**
	 * XML要素開始タグ出力処理
	 * 
	 * @param name
	 * @throws XMLStreamException
	 */
	private void writeAttribute(String name ,String value) 
	throws XMLStreamException
	{
		this.writer.writeAttribute(name, value);
	}
	
	/**
	 * XMLデータ出力処理
	 * 
	 * @param str
	 * @throws XMLStreamException
	 */
	private void writeCharacters(String str) 
	throws XMLStreamException
	{
		if(str == null)
		{
			this.writer.writeCharacters("");
		}
		else
		{
			this.writer.writeCharacters(str);
		}
	}
	
	/**
	 * XML出力処理
	 * 
	 * @param userData
	 * @param osw
	 * @throws XMLStreamException
	 */
	private int writeXML(Map<String, Object> userData,OutputStreamWriter osw) 
	throws XMLStreamException,IOException
	{
		
		int result = 0;
		this.init(osw);
		
		this.writeStartElement("PARTNERCONTEXT");
		this.writeStartElement("HEADER");
		this.writeStartElement("PARTNER");
		this.writeAttribute("PARTNER_ID","1060");
		this.writeEndElement("PARTNER");
		this.writeEndElement("HEADER");
		
		// 電文のBody部を作成
		result = this.writeUserData(userData);
		
		this.writeEndElement("PARTNERCONTEXT");
		
		this.close();
		
		return result;
	}
	
	/**
	 * 書き込み
	 * 
	 * @param userData 送信対象データ
	 * @param os os
	 * @return result
	 * @throws IOException IOException
	 * @throws XMLStreamException XMLStreamException
	 */
	public int write(Map<String, Object> userData,OutputStream os) 
	throws IOException,XMLStreamException
	{
		OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
		try 
		{
				
			// 本文
			int result = this.writeXML(userData,osw);
			osw.write(JKKCtrlMcafeeInfoImpl.CRLF);
			
			return result;
		}
		finally 
		{
			if(osw != null) {
				osw.flush();
				osw.close();
			}
			if(os != null) {
				os.flush();
				os.close();
			}
		}
	}
	
	/**
	 * ユーザデータ部分のメッセージ生成
	 * @param userData
	 * @throws XMLStreamException
	 */
	private int writeUserData(Map<String, Object> userData) 
	throws XMLStreamException
	{
		int result = 0;
		
		this.writeStartElement("DATA");
		
		result = this.trace(userData);
		
		this.writeEndElement("DATA");
		
		return result;
	}
	
	/**
	 * 引き渡された他事業者契約異動種別コードにしたがって電文作成メソッドを呼びだす
	 * @param serviceMap
	 * @throws XMLStreamException
	 */
	private int trace(Map<String, Object> serviceMap)
	throws XMLStreamException
	{
		String tajgsKeiIdoSbtCd = (String)serviceMap.get("tajgsKeiIdoSbtCd");
		String mcafeeMemberId = (String)serviceMap.get("mcafeeMemberId");
		
		if(JKKStrConst.TAJGS_KEI_IDO_SBT_CD_MCAFEE_BUY_REQ.equals(tajgsKeiIdoSbtCd))
		{
			this.writeStartElement("CUSTOMERCONTEXT");
			this.writeAttribute("ID", mcafeeMemberId);
			this.writeAttribute("REQUESTTYPE", "NEW");
			this.traceMskm(serviceMap);
			this.writeEndElement("CUSTOMERCONTEXT");
		}
		else if(JKKStrConst.TAJGS_KEI_IDO_SBT_CD_MCAFEE_DSL_REQ.equals(tajgsKeiIdoSbtCd))
		{
			this.writeStartElement("CUSTOMERCONTEXT");
			this.writeAttribute("ID", mcafeeMemberId);
			this.writeAttribute("REQUESTTYPE", "UPDATE");
			this.traceCancel(serviceMap);
			this.writeEndElement("CUSTOMERCONTEXT");
		}
		else
		{
			// エラーログ出力
			return -1;
		}
		return 0;
	}
	
	/**
	 * マカフィー購入申込の電文を組み立てます。
	 * 
	 * @param serviceMap
	 * @throws XMLStreamException
	 */
	private void traceMskm(Map<String, Object>serviceMap) throws XMLStreamException
	{
		String mcafeeNinshoMlad = (String)serviceMap.get("mcafeeNinshoMlad");
		String mcafeeNinshoPwd = (String)serviceMap.get("mcafeeNinshoPwd");
		String tajgsKeiIdoNo = (String)serviceMap.get("tajgsKeiIdoNo");
		
		
		// 電文イメージ
		//<ACCOUNT>
		//	<EMAILADDRESS>123456789012@dummy.k-opti.com</EMAILADDRESS>
		//	<FIRSTNAME>kopt</FIRSTNAME>
		//	<LASTNAME>kopt</LASTNAME>
		//	<PASSWORD>k1m23n4p5q</PASSWORD>
		//	<PREFERENCES>
		//		<PREFERENCE TYPE="LANG">ja</PREFERENCE>
		//	</PREFERENCES>
		//</ACCOUNT>
		this.writeStartElement("ACCOUNT");
		
			// e-mailアドレス
			this.writeStartElement("EMAILADDRESS");
			this.writeCharacters(convString(mcafeeNinshoMlad));
			this.writeEndElement("EMAILADDRESS");
			
			// ファーストネーム
			this.writeStartElement("FIRSTNAME");
			this.writeCharacters(convString("kopt"));
			this.writeEndElement("FIRSTNAME");
			
			// ラストネーム
			this.writeStartElement("LASTNAME");
			this.writeCharacters(convString("kopt"));
			this.writeEndElement("LASTNAME");
			
			// パスワード
			this.writeStartElement("PASSWORD");
			this.writeCharacters(convString(mcafeeNinshoPwd));
			this.writeEndElement("PASSWORD");
			
			this.writeStartElement("PREFERENCES");
			
				this.writeStartElement("PREFERENCE");
				this.writeAttribute("TYPE", "LANG");
				this.writeCharacters(convString("ja"));
				this.writeEndElement("PREFERENCE");
			
			this.writeEndElement("PREFERENCES");
		
		this.writeEndElement("ACCOUNT");
		
		// 電文イメージ
		//<ORDER PARTNERREF="123456789012345" REF="">
		//	<ITEMS>
		//		<ITEM SKU="1060-98318-5dmma" QTY="1" ACTION="PD" />
		//	</ITEMS>
		//</ORDER>
		this.writeStartElement("ORDER");
		this.writeAttribute("PARTNERREF", tajgsKeiIdoNo);
		this.writeAttribute("REF", "");
		
			this.writeStartElement("ITEMS");
			
				this.writeStartElement("ITEM");
				this.writeAttribute("SKU", "1060-98318-5dmma");
				this.writeAttribute("QTY", "1");
				this.writeAttribute("ACTION", "PD");
				this.writeEndElement("ITEM");
			
			this.writeEndElement("ITEMS");
		
		this.writeEndElement("ORDER");
	}
	
	/**
	 * マカフィーキャンセル申込の電文を組み立てます。
	 * 
	 * @param serviceMap
	 * @throws XMLStreamException
	 */
	private void traceCancel(Map<String, Object>serviceMap) throws XMLStreamException
	{
		String tajgsKeiIdoNo = (String)serviceMap.get("tajgsKeiIdoNo");
		String mcafeeBuyId = (String)serviceMap.get("mcafeeBuyId");
		
		// 電文イメージ
		//<ACCOUNT>
		//</ACCOUNT>
		//<ORDER PARTNERREF="123456789012345" REF="NCS1716493432">
		//	<ITEMS>
		//		<ITEM SKU="1060-98318-5dmma" QTY="1" ACTION="CN" />
		//	</ITEMS>
		//</ORDER>
		this.writeStartElement("ACCOUNT");
		this.writeEndElement("ACCOUNT");
		
		this.writeStartElement("ORDER");
		this.writeAttribute("PARTNERREF", tajgsKeiIdoNo);
		this.writeAttribute("REF", mcafeeBuyId);
		
			this.writeStartElement("ITEMS");
			
				this.writeStartElement("ITEM");
				this.writeAttribute("SKU", "1060-98318-5dmma");
				this.writeAttribute("QTY", "1");
				this.writeAttribute("ACTION", "CN");
				this.writeEndElement("ITEM");
			
			this.writeEndElement("ITEMS");
		
		this.writeEndElement("ORDER");
	}
	
	/**
	 *  オブジェクトを文字列に変換します。
	 *  
	 * @param obj 変換するオブジェクト
	 * @return 変換された文字列
	 */
	private String convString(Object obj)
	{
		if (obj == null) 
		{
			return "";
		}
		else if (obj instanceof Integer) 
		{
			return String.valueOf((Integer)obj);
		}
		else if (obj instanceof Long) 
		{
			return String.valueOf((Long)obj);
		}
		else if (obj instanceof Short) 
		{
			return String.valueOf((Short)obj);
		}
		else if (obj instanceof Double) 
		{
			return String.valueOf((Double)obj);
		}
		else if (obj instanceof Float) 
		{
			return String.valueOf((Float)obj);
		}
		else if (obj instanceof Byte) 
		{
			return String.valueOf((Byte)obj);
		}
		else if (obj instanceof Boolean) 
		{
			return String.valueOf((Boolean)obj);
		}
		else if (obj instanceof String) 
		{
			return (String)obj;
		}
		return obj.toString();
	}
	
	/**
	 * Soap項目名から項目名を取得します。
	 * 
	 * @param obj Soap項目名
	 * @return 項目名
	 */
	private String getMapName(String obj) 
	{
		return mapToElement.get(obj);
	}
	
	/**
	 * 電文読み込み処理
	 * 
	 * @param host
	 * @param ip
	 * @param contentType
	 * @param is
	 * @return XML電文解析結果
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 */
	private HashMap<String, Object> read(String host, String ip, String contentType, InputStream is) 
	throws IOException,ParserConfigurationException,SAXException
	{
		String charset = this.getEncoding(contentType);
		StringReader sr = readSingleResource(charset, is);
		HashMap<String, Object>result = new HashMap<String, Object>();
		
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setNamespaceAware(true);
		DocumentBuilder db = dbf.newDocumentBuilder();
		
		Document doc = db.parse(new InputSource(sr));
		
		Element elem = doc.getDocumentElement();
		
		// XMLの実行結果を取得する。
		analyzeXml(result, elem, true);

		// 結果明細一時格納用のMapを変換
		ArrayList<Map<String, Object>> nodelist = new ArrayList<Map<String, Object>>();
		nodelist.add((Map<String, Object>)result.get(TMP_RESULT_DETAIL));
		result.put(JWCStrConst.CMD_RESULT_DETAIL, nodelist);
		result.remove(TMP_RESULT_DETAIL);
		
		return result;
	}
	
	/**
	 * 電文読み取り処理（添付ファイルなし）
	 * 
	 * @param charSet
	 * @param is
	 * @return
	 * @throws IOException
	 */
	private StringReader readSingleResource(String charSet, InputStream is) 
	throws IOException
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		byte[] buf = new byte[1024*8];
		
		int length = readLine(is, buf, 0, buf.length);
		
		while(length != -1){
			// ボディ部
			baos.write(buf, 0, length);
			length = readLine(is, buf, 0, buf.length);
		}
		
		responseXml = baos.toString();
		
		byte[] contents = baos.toByteArray();
		
		
		// コンテントタイプから、encoding指定を得る。
		StringReader reader = new StringReader(new String(contents, charSet));
		
		return reader;
	}
	
	/**
	 * 行データ取得処理
	 * 
	 * @param is InputStream 
	 * @param abyte0 abyte0[]
	 * @param i i
	 * @param j j
	 * @return int 実行結果
	 * @throws IOException
	 */
	private int readLine(InputStream is, byte abyte0[], int i, int j) 
	throws IOException 
	{
		if (j <= 0) 
		{
			return 0;
		}
		int k = 0;
		int l;
		do 
		{
			if((l = is.read()) == -1) 
			{
				break;
			}
			abyte0[i++] = (byte)l;
			k++;
		}
		while(l != 10 && k != j);
		
		return k <= 0 ? -1 : k;
	}
	
	/**
	 * エンコーディングデータ取得処理
	 * 
	 * @param contentType HTTPContentType文字列
	 * @return エンコーディング
	 */
	private String getEncoding(String contentType)
	{
		
		if(contentType != null)
		{
			
			// 半角空白で切って、
			String[] contentTypes = contentType.split(" ");
			
			// 開始がcharsetで始まるものを探して、
			for(String ct : contentTypes){
				if(ct.startsWith("charset=")){
					ct = ct.trim();
					return ct.substring("charset=".length());
				}
			}
		}
		
		// 見つけられなかった場合
		return "UTF-8";
	}
	
	/**
	 * コマンド送信戻り電文解析処理
	 * 
	 * @param elem コマンド解析電文rootXML要素
	 */
	private void analyzeXml(HashMap<String, Object> resultMap, Node elem, boolean rootflag)
	{
		Node node = elem.getFirstChild();
		
		//電文の要素をすべて解析する。
		while(node != null)
		{
			if(node.getNodeType() == Node.ELEMENT_NODE) 
			{
				
				String nodename = node.getLocalName();
				
				// 取得する要素の親ノード名、または属性を取得するノード名
				if(JKKCtrlMcafeeInfoImpl.CONTROL_RESULT_INFO.equals(nodename)
					|| "ORDER".equals(nodename)
					|| "ITEM".equals(nodename)
					|| "ACCOUNT".equals(nodename)) 
				{
					Map<String, Object>resultinfo = analyzeResultXml(node);
					
					resultMap.put(JWCStrConst.CMD_RESULT_CD,"0");
					Map<String, Object> resultDetailMap = (Map<String, Object>)resultMap.get(TMP_RESULT_DETAIL);
					if (null == resultDetailMap)
					{
						resultDetailMap = new HashMap<String, Object>();
						resultMap.put(TMP_RESULT_DETAIL, resultDetailMap);
					}
					resultDetailMap.putAll(resultinfo);
				}
				
				// 子供のノードがある場合、さらに子供の要素をチェックする。
				if(node.hasChildNodes()) 
				{
					analyzeXml(resultMap, node,false);
				}
			}
				node = node.getNextSibling();
		}
		
		if(rootflag && resultMap == null)
		{
			resultMap.put(JWCStrConst.CMD_RESULT_CD,"0");
		}
	}
	
	/**
	 * コマンド結果発行戻り電文解析処理
	 * @param elem XMLコマンド発行電文戻りNode
	 * @return コマンド結果発行戻値
	 */
	private Map<String, Object>analyzeResultXml(Node elem) 
	{
		
		HashMap<String, Object>result = new HashMap<String, Object>();
		setAttributesItem(result, elem);
		Node node = elem.getFirstChild();
		
		while(node != null) {
			
			if(node.getNodeType() == Node.ELEMENT_NODE)
			{
				String nodename = node.getLocalName();
				setAttributesItem(result, elem);
				
				String elementString = this.getMapName(nodename);
				
				if(elementString != null) {
					result.put(elementString,node.getTextContent());
				}
			}
			node = node.getNextSibling();
		}
		return result;
	}
	
	/**
	 * コマンド結果発行戻り電文解析処理
	 * @param result 取得情報格納Map
	 * @param node XMLコマンド発行電文戻りNode
	 */
	private void setAttributesItem(HashMap<String, Object> result, Node node)
	{
		String nodeName = node.getLocalName();
		if("RESPONSECONTEXT".equals(nodeName) ||  "ORDER".equals(nodeName) || "ITEM".equals(nodeName))
		{
			if(node.getAttributes().getNamedItem("ID") != null)
			{
				result.put("mcafeeMemberId",node.getAttributes().getNamedItem("ID").getTextContent());
			}
			if(node.getAttributes().getNamedItem("PARTNERREF") != null)
			{
				result.put("tajgsKeiIdoNo",node.getAttributes().getNamedItem("PARTNERREF").getTextContent());
			}
			if(node.getAttributes().getNamedItem("REF") != null)
			{
				result.put("mcafeeBuyId",node.getAttributes().getNamedItem("REF").getTextContent());
			}
			if(node.getAttributes().getNamedItem("SKU") != null)
			{
				result.put("sku",node.getAttributes().getNamedItem("SKU").getTextContent());
			}
		}
	}
	
}
