package lemon.shared.message.parser;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

import com.thoughtworks.xstream.XStream;

import lemon.shared.MMTContext;
import lemon.shared.MmtException;
import lemon.shared.config.MMTCharset;
import lemon.shared.config.MMTConfig;
import lemon.shared.message.metadata.Message;
import lemon.shared.message.parser.MsgParser;
import lemon.shared.message.processor.MsgProcessor;
import lemon.shared.service.ServiceType;
import lemon.shared.toolkit.xstream.XStreamHelper;

/**
 * A message parser for WeiXin
 * @author lemon
 * @version 1.0
 *
 */
public abstract class AbstractMsgParser implements MsgParser {
	public static final String PREFIX = "MMT_";
	private static Log logger = LogFactory.getLog(AbstractMsgParser.class);
	protected XStream xStream = XStreamHelper.createXMLXStream();
	
	/**
	 * Get message parser
	 * @param service_type
	 * @param msg
	 * @return
	 */
	public static MsgParser getParser(ServiceType service_type, String msg){
		String msgType = getMsgType(msg);
		try{
			return (MsgParser) MMTContext.getApplicationContext().getBean(PREFIX + msgType);
		}catch(NoSuchBeanDefinitionException e){
			return (MsgParser) MMTContext.getApplicationContext().getBean(service_type + "_" + msgType);
		}
	}
	
	/**
	 * Generate replay message
	 * @param mmt_token
	 * @param msg
	 * @return
	 */
	public final String parseMessage(MMTConfig cfg, String msg){
		Message message = toMsg(msg);
		// process business
		String retMsg = process(cfg, message);
		// build replay message
		return retMsg;
	}
	
	/**
	 * Convert string to message 
	 * @param msg
	 * @return
	 */
	protected abstract Message toMsg(String msg);
	
	/**
	 * Convert WeiXin message to XML
	 * @param rMsg
	 * @return
	 */
	protected abstract String toXML(Message rMsg);
	
	
	/**
	 * Business process
	 * @param mmt_token
	 * @param msg
	 * @return an string message
	 */
	private String process(MMTConfig cfg, Message msg){
		if(null == cfg)
			throw new MmtException("No customer's configure find.");
		MsgProcessor processor = null;
		try {
			processor = (MsgProcessor) MMTContext.getApplicationContext().getBean(Class.forName(cfg.getBiz_class()));
			return processor.processMsg(cfg.getApi_url(), msg);
		} catch (ClassNotFoundException e) {
			logger.error("Can't find business implement class: " + cfg.getBiz_class());
			throw new MmtException("Can't find business implement class: " + cfg.getBiz_class());
		}
	}
	
	/**
	 * Get message type
	 * @param msg
	 * @return
	 */
	private static String getMsgType(String msg) {
		InputStream is = null;
		try {
			try {
				is = new ByteArrayInputStream(msg.getBytes(MMTCharset.LOCAL_CHARSET));
				Document doc = new SAXBuilder().build(is);
				Element e = doc.getRootElement().getChild("MsgType");
				return e.getValue();
			} finally {
				if (null != is)
					is.close();
			}
		} catch (IOException | JDOMException e) {
			logger.error("Can't get message type:" + e.getMessage());
		}
		return null;
	}
}

@@ -2974,16 +2974,20 @@
 g) %7B%0D%0A%09%09
+try(
 InputStr
@@ -2998,43 +2998,8 @@
 is =
- null;%0D%0A%09%09try %7B%0D%0A%09%09%09try %7B%0D%0A%09%09%09%09is =
  new
@@ -3059,20 +3059,21 @@
 HARSET))
-;
+) %7B
 %0D%0A
-%09
 %09%09%09Docum
@@ -3111,17 +3111,16 @@
 d(is);%0D%0A
-%09
 %09%09%09Eleme
@@ -3172,17 +3172,16 @@
 %22);%0D%0A%09%09%09
-%09
 return e
@@ -3198,69 +3198,8 @@
 );%0D%0A
-%09%09%09%7D finally %7B%0D%0A%09%09%09%09if (null != is)%0D%0A%09%09%09%09%09is.close();%0D%0A%09%09%09%7D%0D%0A
 %09%09%7D 

Use try with resource.