package cn.songxinqiang.weixin4j.util;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import cn.songxinqiang.weixin4j.request.EventBaseMessage;
import cn.songxinqiang.weixin4j.request.RequestBaseMessage;
import cn.songxinqiang.weixin4j.request.RequestImageMessage;
import cn.songxinqiang.weixin4j.request.RequestLinkMessage;
import cn.songxinqiang.weixin4j.request.RequestLocationMessage;
import cn.songxinqiang.weixin4j.request.RequestTextMessage;
import cn.songxinqiang.weixin4j.request.RequestType;
import cn.songxinqiang.weixin4j.request.RequestVideoMessage;
import cn.songxinqiang.weixin4j.request.RequestVoiceMessage;
import cn.songxinqiang.weixin4j.request.SubscribeUnsubscribeEvent;
import cn.songxinqiang.weixin4j.response.ResponseNewsMessage;
import cn.songxinqiang.weixin4j.response.ResponseTextMessage;
import cn.songxinqiang.weixin4j.response.model.Article;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
/**
* 消息工具类
*
*/
public class WeixinMessageUtil {
/**
* 解析微信发来的请求(XML)<br>
* 将消息按照【节点-节点值】的形式封装返回,以待后续处理
*
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
public Map<String, String> parseXml(InputStream inputStream)
throws Exception {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>();
// 读取输入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements();
// 遍历所有子节点
for (Element e : elementList)
map.put(e.getName(), e.getText());
// 释放资源
inputStream.close();
inputStream = null;
return map;
}
/**
* 解析请求类型,对于空字符串或者去掉空格后长度小于2的字符串返回null
*
* @param type
* @return
*/
public RequestType parseRequestType(String type) {
if (type == null || type.trim().length() < 2) {
return null;
} else {
return RequestType.valueOf(type.trim());
}
}
/**
* 请求消息共有属性的设置,包括了:ToUserName,FromUserName,CreateTime,MsgId
*
* @param message
* @param map
*/
private void _setCommonMessageField(RequestBaseMessage message,
Map<String, String> map) {
message.setToUserName(map.get(RequestBaseMessage.MSG_FIELD_ToUserName));
message.setFromUserName(map
.get(RequestBaseMessage.MSG_FIELD_FromUserName));
message.setCreateTime(Long.valueOf(map
.get(RequestBaseMessage.MSG_FIELD_CreateTime)));
message.setMsgId(Long.valueOf(map
.get(RequestBaseMessage.MSG_FIELD_MsgId)));
}
/**
* 将以键值对形式保存的文本消息转换成文本消息类型的对象
*
* @param map
* @return
*/
public RequestTextMessage parseTextMessage(Map<String, String> map) {
RequestTextMessage message = new RequestTextMessage();
_setCommonMessageField(message, map);
message.setMsgType(RequestType.text);
message.setContent(map.get(RequestTextMessage.MSG_FIELD_Content));
return message;
}
/**
* 将以键值对形式保存的图片消息转换成图片消息类型的对象
*
* @param map
* @return
*/
public RequestImageMessage parseImageMessage(Map<String, String> map) {
RequestImageMessage message = new RequestImageMessage();
_setCommonMessageField(message, map);
message.setMsgType(RequestType.image);
message.setPicUrl(map.get(RequestImageMessage.MSG_FIELD_PicUrl));
message.setMediaId(map.get(RequestImageMessage.MSG_FIELD_MediaId));
return message;
}
/**
* 将以键值对形式保存的语音消息转换成语音消息类型的对象
*
* @param map
* @return
*/
public RequestVoiceMessage parseVoiceMessage(Map<String, String> map) {
RequestVoiceMessage message = new RequestVoiceMessage();
_setCommonMessageField(message, map);
message.setMsgType(RequestType.voice);
message.setMediaId(map.get(RequestVoiceMessage.MSG_FIELD_MediaId));
message.setFormat(map.get(RequestVoiceMessage.MSG_FIELD_Format));
return message;
}
/**
* 将以键值对形式保存的视频消息转换成视频消息类型的对象
*
* @param map
* @return
*/
public RequestVideoMessage parseVideoMessage(Map<String, String> map) {
RequestVideoMessage message = new RequestVideoMessage();
_setCommonMessageField(message, map);
message.setMsgType(RequestType.video);
message.setMediaId(map.get(RequestVideoMessage.MSG_FIELD_MediaId));
message.setThumbMediaId(map
.get(RequestVideoMessage.MSG_FIELD_ThumbMediaId));
return message;
}
/**
* 将以键值对形式保存的地理位置消息转换成地理位置消息类型的对象
*
* @param map
* @return
*/
public RequestLocationMessage parseLocationMessage(Map<String, String> map) {
RequestLocationMessage message = new RequestLocationMessage();
_setCommonMessageField(message, map);
message.setMsgType(RequestType.location);
message.setLocation_X(map
.get(RequestLocationMessage.MSG_FIELD_Location_X));
message.setLocation_Y(map
.get(RequestLocationMessage.MSG_FIELD_Location_Y));
message.setScale(map.get(RequestLocationMessage.MSG_FIELD_Scale));
message.setLabel(map.get(RequestLocationMessage.MSG_FIELD_Label));
return message;
}
/**
* 将以键值对形式保存的链接消息转换成链接消息类型的对象
*
* @param map
* @return
*/
public RequestLinkMessage parseLinkMessage(Map<String, String> map) {
RequestLinkMessage message = new RequestLinkMessage();
_setCommonMessageField(message, map);
message.setMsgType(RequestType.link);
message.setTitle(map.get(RequestLinkMessage.MSG_FIELD_Title));
message.setDescription(map
.get(RequestLinkMessage.MSG_FIELD_Description));
message.setUrl(map.get(RequestLinkMessage.MSG_FIELD_Url));
return message;
}
/**
* 事件消息的属性设置
*
* @param message
* @param map
*/
private void _setCommonEventMessageField(EventBaseMessage message,
Map<String, String> map) {
_setCommonMessageField(message, map);
message.setMsgType(RequestType.event);
message.setEvent(map.get(EventBaseMessage.MSG_FIELD_Event));
}
/**
* 关注、取消关注事件的消息转换
*
* @param map
* @return
*/
public SubscribeUnsubscribeEvent parseSubscribeUnsubscribeEventMessage(
Map<String, String> map) {
SubscribeUnsubscribeEvent message = new SubscribeUnsubscribeEvent();
_setCommonEventMessageField(message, map);
return message;
}
/**
* 文本消息对象转换成xml
*
* @param textMessage
* 文本消息对象
* @return xml
*/
public String textMessageToXml(ResponseTextMessage textMessage) {
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
/**
* 图文消息对象转换成xml
*
* @param newsMessage
* 图文消息对象
* @return xml
*/
public String newsMessageToXml(ResponseNewsMessage newsMessage) {
xstream.alias("xml", newsMessage.getClass());
xstream.alias("item", new Article().getClass());
return xstream.toXML(newsMessage);
}
/**
* 扩展xstream,使其支持CDATA块
*
*/
private XStream xstream = new XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有xml节点的转换都增加CDATA标记
boolean cdata = true;
public void startNode(String name,
@SuppressWarnings("rawtypes") Class clazz) {
super.startNode(name, clazz);
}
protected void writeText(QuickWriter writer, String text) {
if (cdata) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
} else {
writer.write(text);
}
}
};
}
});
}