package eo.web.webview.KKA06601SF;

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 javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MyXmlParser extends DefaultHandler {

	@SuppressWarnings("unchecked")
	private Map nowMapRef = null;

	@SuppressWarnings("unchecked")
	private Map dataMap = new HashMap();

	private List<String> elements = new ArrayList<String>();

	@SuppressWarnings("unchecked")
	public Map getDataMap(){
		return dataMap;
	}

	/**
	 * リクエストから取得したXMLを解析しMapに変換する
	 * @param servletRequest
	 * @return マップ
	 */
	@SuppressWarnings("unchecked")
	public static Map parseXml(ServletRequest servletRequest, String encoding){

		// 受信したXMLデータを解析
		ServletInputStream servletInputStream;
		MyXmlParser myXmlParser = new MyXmlParser();
		try {
			servletInputStream = servletRequest.getInputStream();
			SAXParserFactory spfactory = SAXParserFactory.newInstance();
			SAXParser parser = spfactory.newSAXParser();
			InputSource is = new InputSource(new InputStreamReader(servletInputStream,encoding));
			is.setEncoding(encoding);
			parser.parse(is, myXmlParser);
			
			parser.parse(servletInputStream, myXmlParser);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
		
		return myXmlParser.getDataMap();
	}

	/**
	 * リクエストから取得したXMLを解析しMapに変換する
	 * @param servletRequest
	 * @return マップ
	 */
	@SuppressWarnings("unchecked")
	public static Map parseXml(InputStream servletInputStream){

		// 受信したXMLデータを解析
		MyXmlParser myXmlParser = new MyXmlParser();
		try {
			SAXParserFactory spfactory = SAXParserFactory.newInstance();
			SAXParser parser = spfactory.newSAXParser();
			parser.parse(servletInputStream, myXmlParser);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
		
		return myXmlParser.getDataMap();
	}

	/**
	 * エレメントの開始時
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void startElement(String uri, String localName, String tagName,
			Attributes attr) throws SAXException {

		Object nowObj = dataMap;
		for (int i = 0; i < elements.size(); i++) {
			String elementName = elements.get(i);
			Map nowMap = null;
			if (nowObj instanceof Map) {
				nowMap = (Map)nowObj;
			} else if (nowObj instanceof List) {
				List nowList = (List)nowObj;
				nowMap = (Map)nowList.get(nowList.size() - 1);
			}
			nowObj = nowMap.get(elementName);
		}
		
		Map nowMap = null;
		if (nowObj instanceof Map) {
			nowMap = (Map)nowObj;
		} else if (nowObj instanceof List) {
			List nowList = (List)nowObj;
			nowMap = (Map)nowList.get(nowList.size() -1 );
		}
		
		if (!nowMap.containsKey(tagName)) {
			nowMap.put(tagName, new HashMap());
		} else {
			Object nowBase = nowMap.get(tagName);
			List nowList = null;
			if (nowBase instanceof List) {
				nowList = (List)nowBase;
			} else {
				nowList = new ArrayList();
				nowList.add((Map)nowBase);
			}
			nowList.add(new HashMap());
			nowMap.put(tagName, nowList);
		}
		nowMapRef = nowMap;
		elements.add(tagName);
	}

	/**
	 * エレメントのボディ部を取得
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void characters(char[] chars, int offset, int length) throws SAXException {

		String nodeData = new String(chars, offset, length);
		String checkData = nodeData;
		checkData = checkData.replaceAll("\r\n", "");
		checkData = checkData.replaceAll("\n", "");
		checkData = checkData.replaceAll("\t", "");
		checkData = checkData.replaceAll(" ", "");
		if (checkData.length() > 0) {
			String nowName = elements.get(elements.size() - 1);
			nowMapRef.put(nowName, nodeData);
		}
	}

	/**
	 * エレメントの終了時
	 */
	@Override
	public void endElement(String arg0, String arg1, String arg2)
			throws SAXException {
		elements.remove(elements.size() - 1);
	}

	/**
	 * ドキュメントの終了時
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void endDocument() throws SAXException {
		dataMap = (Map)replaceEmptyMap(dataMap);
	}

	/**
	 * 空のマップをnullに置き換える
	 * @param obj オブジェクト
	 * @return オブジェクト
	 */
	@SuppressWarnings("unchecked")
	private Object replaceEmptyMap(Object obj){
		
		if (obj instanceof Map) {
			Map nowMap = (Map)obj;
			if (nowMap.isEmpty()){
				return null;
			} else {
				Iterator iterator = nowMap.keySet().iterator();
				while (iterator.hasNext()){
					String mapKey = (String)iterator.next();
					Object recObj = replaceEmptyMap(nowMap.get(mapKey));
					nowMap.put(mapKey, recObj);
				}
			}
		} else if (obj instanceof List) {
			List nowList = (List)obj;
			for (int i = 0; i < nowList.size(); i++) {
				Object nowObj = nowList.get(i);
				nowObj = replaceEmptyMap(nowObj);
				nowList.set(i, nowObj);
			}
		}

		return obj;
	}
}
