<commit_before>package com.sdw.soft.common.reply.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sdw.soft.common.bind.service.IBindService;
import com.sdw.soft.common.bind.vo.WechatUser;
import com.sdw.soft.common.config.WechatConfig;
import com.sdw.soft.common.reply.service.IReplyService;
import com.sdw.soft.common.reply.vo.MessageType;
import com.sdw.soft.common.reply.vo.WechatArticleMessage;
import com.sdw.soft.common.reply.vo.WechatBaseMessage;
import com.sdw.soft.common.reply.vo.WechatMusicMessage;
import com.sdw.soft.common.reply.vo.WechatTextMessage;
import com.sdw.soft.common.service.ICommonService;
import com.sdw.soft.common.vo.WechatUserSample;
import com.sdw.soft.core.utils.FreemarkerUtils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
/**
 * @author Sonicery_D
 * @date 2014年10月28日
 * @version 1.0.0
 **/
@Service
public class ReplyService implements IReplyService {

	private static final Logger logger = LoggerFactory.getLogger(ReplyService.class);
	
	private static final String REPLY_MESSAGE_TYPE_TEXT = "text";

	private static final String REPLY_MESSAGE_TYPE_MUSIC = "music";

	private static final String REPLY_MESSAGE_TYPE_NEWS = "news";

	private static final String DEFAULT_REPLY_MESSAGE = "抱歉，自动回复功能尚未开通 感谢您的关注！";
	
	private static final String DEFAULT_REPLY_ERROR = "系统异常,请稍后再试!";
	
	@Autowired
	private WechatConfig wechatConfig;
	
	@Autowired
	private ICommonService commonService;
	
	@Autowired
	private IBindService bindService;
	
	/* (non-Javadoc)
	 * @see com.sdw.soft.common.reply.service.impl.IReplyService#dealReceiveMessage(java.lang.String)
	 */
	public String dealReceiveMessage(String requestXml){
		String msgType = null;
		WechatBaseMessage baseMessage = this.fectchWechatMessage(requestXml, new Class[]{WechatBaseMessage.class});
		msgType = baseMessage.getMsgType();
		String responseMessage = "响应消息";
		logger.info("当前微信请求数据类型为:{}",msgType);
		String openId = baseMessage.getFromUserName();
		if(StringUtils.isBlank(openId)){//未获取到openid
			responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,assembleTextMessage(baseMessage,DEFAULT_REPLY_ERROR),new Class[]{WechatTextMessage.class});
		}else{
			logger.info("当前请求用户的OpenId为:{}",openId);
			WechatUser bindUser = bindService.fetchBindUser(openId);
			if(bindUser != null){//当前用户已经绑定
				responseMessage = replyMessage(msgType, baseMessage, responseMessage);
			}else{//当前用户尚未绑定
				Map<String,String> bindMap = new HashMap<String,String>();
				bindMap.put("url", "http://sydhappy.sinaapp.com/bind/user");
				bindMap.put("openId", openId);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,assembleTextMessage(baseMessage,FreemarkerUtils.data2Template(bindMap, "bind.ftl")),new Class[]{WechatTextMessage.class});
			}
		}
		logger.info("responseMessage finally:{}",responseMessage);
		return responseMessage;
	}
	
	/**
	 * 根据请求的报文 作出响应
	 * @param msgType
	 * @param baseMessage
	 * @param responseMessage
	 * @return
	 */
	private String replyMessage(String msgType, WechatBaseMessage baseMessage,
			String responseMessage) {
		if(msgType != null){
			if(msgType.equals(MessageType.MESSAGE_TYPE_TEXT)){//处理文本消息
				logger.info("dealReceiveMessage---处理文本消息");
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
				
			}else if(msgType.equals(MessageType.MESSAGE_TYPE_IMAGE)){//图片消息
				logger.info("dealReceiveMessage---图片消息");
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
			}else if(msgType.equals(MessageType.MESSAGE_TYPE_LOCATION)){//地理位置消息
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
				logger.info("dealReceiveMessage---地理位置消息");
			}else if(msgType.equals(MessageType.MESSAGE_TYPE_EVENT)){//事件消息
				logger.info("dealReceiveMessage---事件消息");
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
			}else if(msgType.equals(MessageType.MESSAGE_TYPE_LINK)){//链接消息
				logger.info("dealReceiveMessage---链接消息");
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
			}else if(msgType.equals(MessageType.MESSAGE_TYPE_VOICE)){//语言消息
				logger.info("dealReceiveMessage---语言消息");
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
			}
		}
		return responseMessage;
	}
	private String processReplyMessage(String replyMessageType,Object message,Class[] clazz) {
		XStream xstream = new XStream(new DomDriver("UTF-8",
				new XmlFriendlyNameCoder("-_", "_")));
		xstream.autodetectAnnotations(true);
		xstream.processAnnotations(clazz);
		if(REPLY_MESSAGE_TYPE_MUSIC.equals(replyMessageType)){//音乐消息
			WechatMusicMessage music = (WechatMusicMessage)message;
			return xstream.toXML(music);
		}else if(REPLY_MESSAGE_TYPE_NEWS.equals(replyMessageType)){//图文消息
			WechatArticleMessage article = (WechatArticleMessage)message;
			return xstream.toXML(article);
		}else{//文本消息
			WechatTextMessage text = (WechatTextMessage)message;
			return xstream.toXML(text);
		}
	}
	/**
	 * 拼装响应消息
	 * @param baseMessage<commit_msg>extend the xstream to make the content surrounded by the "<![CDATA[]]>"<commit_after>package com.sdw.soft.common.reply.service.impl;

import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sdw.soft.common.bind.service.IBindService;
import com.sdw.soft.common.bind.vo.WechatUser;
import com.sdw.soft.common.config.WechatConfig;
import com.sdw.soft.common.reply.service.IReplyService;
import com.sdw.soft.common.reply.vo.MessageType;
import com.sdw.soft.common.reply.vo.WechatArticleMessage;
import com.sdw.soft.common.reply.vo.WechatBaseMessage;
import com.sdw.soft.common.reply.vo.WechatMusicMessage;
import com.sdw.soft.common.reply.vo.WechatTextMessage;
import com.sdw.soft.common.service.ICommonService;
import com.sdw.soft.common.vo.WechatUserSample;
import com.sdw.soft.core.utils.FreemarkerUtils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
/**
 * @author Sonicery_D
 * @date 2014年10月28日
 * @version 1.0.0
 **/
@Service
public class ReplyService implements IReplyService {

	private static final Logger logger = LoggerFactory.getLogger(ReplyService.class);
	
	private static final String REPLY_MESSAGE_TYPE_TEXT = "text";

	private static final String REPLY_MESSAGE_TYPE_MUSIC = "music";

	private static final String REPLY_MESSAGE_TYPE_NEWS = "news";

	private static final String DEFAULT_REPLY_MESSAGE = "抱歉，自动回复功能尚未开通 感谢您的关注！";
	
	private static final String DEFAULT_REPLY_ERROR = "系统异常,请稍后再试!";
	
	@Autowired
	private WechatConfig wechatConfig;
	
	@Autowired
	private ICommonService commonService;
	
	@Autowired
	private IBindService bindService;
	
	/* (non-Javadoc)
	 * @see com.sdw.soft.common.reply.service.impl.IReplyService#dealReceiveMessage(java.lang.String)
	 */
	public String dealReceiveMessage(String requestXml){
		String msgType = null;
		WechatBaseMessage baseMessage = this.fectchWechatMessage(requestXml, new Class[]{WechatBaseMessage.class});
		msgType = baseMessage.getMsgType();
		String responseMessage = "响应消息";
		logger.info("当前微信请求数据类型为:{}",msgType);
		String openId = baseMessage.getFromUserName();
		if(StringUtils.isBlank(openId)){//未获取到openid
			responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,assembleTextMessage(baseMessage,DEFAULT_REPLY_ERROR),new Class[]{WechatTextMessage.class});
		}else{
			logger.info("当前请求用户的OpenId为:{}",openId);
			WechatUser bindUser = bindService.fetchBindUser(openId);
			if(bindUser != null){//当前用户已经绑定
				responseMessage = replyMessage(msgType, baseMessage, responseMessage);
			}else{//当前用户尚未绑定
				Map<String,String> bindMap = new HashMap<String,String>();
				bindMap.put("url", "http://sydhappy.sinaapp.com/bind/user");
				bindMap.put("openId", openId);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,assembleTextMessage(baseMessage,FreemarkerUtils.data2Template(bindMap, "bind.ftl")),new Class[]{WechatTextMessage.class});
			}
		}
		logger.info("responseMessage finally:{}",responseMessage);
		return responseMessage;
	}
	
	/**
	 * 根据请求的报文 作出响应
	 * @param msgType
	 * @param baseMessage
	 * @param responseMessage
	 * @return
	 */
	private String replyMessage(String msgType, WechatBaseMessage baseMessage,
			String responseMessage) {
		if(msgType != null){
			if(msgType.equals(MessageType.MESSAGE_TYPE_TEXT)){//处理文本消息
				logger.info("dealReceiveMessage---处理文本消息");
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
				
			}else if(msgType.equals(MessageType.MESSAGE_TYPE_IMAGE)){//图片消息
				logger.info("dealReceiveMessage---图片消息");
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
			}else if(msgType.equals(MessageType.MESSAGE_TYPE_LOCATION)){//地理位置消息
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
				logger.info("dealReceiveMessage---地理位置消息");
			}else if(msgType.equals(MessageType.MESSAGE_TYPE_EVENT)){//事件消息
				logger.info("dealReceiveMessage---事件消息");
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
			}else if(msgType.equals(MessageType.MESSAGE_TYPE_LINK)){//链接消息
				logger.info("dealReceiveMessage---链接消息");
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
			}else if(msgType.equals(MessageType.MESSAGE_TYPE_VOICE)){//语言消息
				logger.info("dealReceiveMessage---语言消息");
				Object message = assembleReplyMessage(baseMessage,REPLY_MESSAGE_TYPE_TEXT);
				responseMessage = processReplyMessage(REPLY_MESSAGE_TYPE_TEXT,message,new Class[]{WechatTextMessage.class});
			}
		}
		return responseMessage;
	}
	/**
	 * 将发生内容转回为XML
	 * @param replyMessageType
	 * @param message
	 * @param clazz
	 * @return
	 */
	private String processReplyMessage(String replyMessageType,Object message,Class[] clazz) {
		XStream xstream = new XStream(new DomDriver("UTF-8",
				new XmlFriendlyNameCoder("-_", "_")){
			@Override
			public HierarchicalStreamWriter createWriter(Writer out) {
				return new PrettyPrintWriter(out){
					//对所有xml节点的转换都增加CDATA标识
					boolean cdata = true;
					@Override
					public void startNode(String name, Class clazz) {
						super.startNode(name, clazz);
					}
					@Override
					protected void writeText(QuickWriter writer, String text) {
						if(cdata){
							writer.write("<![CDATA[");
							writer.write(text);
							writer.write("]]>");
						}else{
							writer.write(text);
						}
					}
				};
			}
		});
		xstream.autodetectAnnotations(true);
		xstream.processAnnotations(clazz);
		if(REPLY_MESSAGE_TYPE_MUSIC.equals(replyMessageType)){//音乐消息
			WechatMusicMessage music = (WechatMusicMessage)message;
			return xstream.toXML(music);
		}else if(REPLY_MESSAGE_TYPE_NEWS.equals(replyMessageType)){//图文消息
			WechatArticleMessage article = (WechatArticleMessage)message;
			return xstream.toXML(article);
		}else{//文本消息
			WechatTextMessage text = (WechatTextMessage)message;
			return xstream.toXML(text);
		}
	}
	/**
	 * 拼装响应消息
	 * @param baseMessage
{'fraction_non_alphanumeric': 0.11488230827638572, 'fraction_numerical': 0.0024297646165527716, 'mean_word_length': 5.895811518324607, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 7}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1466722', 'n_tokens_mistral': 4782, 'n_tokens_neox': 4438, 'n_words': 617}