1 package com.foxinmy.weixin4j.xml;
2
3 import java.io.StringReader;
4 import java.io.StringWriter;
5 import java.lang.reflect.Field;
6 import java.lang.reflect.ParameterizedType;
7 import java.lang.reflect.Type;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Map.Entry;
13 import java.util.Set;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
16
17 import javax.xml.bind.JAXBContext;
18 import javax.xml.bind.JAXBException;
19 import javax.xml.bind.Unmarshaller;
20 import javax.xml.bind.annotation.XmlRootElement;
21 import javax.xml.stream.XMLInputFactory;
22 import javax.xml.stream.XMLOutputFactory;
23 import javax.xml.stream.XMLStreamConstants;
24 import javax.xml.stream.XMLStreamException;
25 import javax.xml.stream.XMLStreamReader;
26 import javax.xml.stream.XMLStreamWriter;
27 import javax.xml.transform.stream.StreamSource;
28
29 import com.foxinmy.weixin4j.util.Consts;
30 import com.foxinmy.weixin4j.util.ReflectionUtil;
31 import com.foxinmy.weixin4j.util.StringUtil;
32
33
34
35
36
37
38
39
40
41
42 public class ListsuffixResultDeserializer {
43
44 private static Pattern DEFAULT_PATTERN;
45 static {
46 String regex = null;
47 try {
48 Object value = ListsuffixResult.class.getMethod("value")
49 .getDefaultValue();
50 if (value instanceof String) {
51 regex = (String) value;
52 } else if (value instanceof String[]) {
53 regex = ((String[]) value)[0];
54 }
55 } catch (NoSuchMethodException e) {
56 ;
57 }
58 if (StringUtil.isBlank(regex)) {
59 regex = "(_\\d)$";
60 }
61 DEFAULT_PATTERN = Pattern.compile(regex);
62 }
63
64
65
66
67
68
69
70
71
72 public static <T> T deserialize(String content, Class<T> clazz) {
73 T t = XmlStream.fromXML(content, clazz);
74 Map<Field, String[]> listsuffixFields = getListsuffixFields(clazz);
75 if (!listsuffixFields.isEmpty()) {
76 for (Entry<Field, String[]> entry : listsuffixFields.entrySet()) {
77 Field field = entry.getKey();
78 Type type = field.getGenericType();
79 Class<?> wrapperClazz = null;
80 if (type instanceof ParameterizedType) {
81 wrapperClazz = (Class<?>) ((ParameterizedType) type)
82 .getActualTypeArguments()[0];
83 } else {
84 continue;
85 }
86 ListWrapper<?> listWrapper = deserializeToListWrapper(content,
87 wrapperClazz, entry.getValue());
88 if (listWrapper != null) {
89 try {
90 field.setAccessible(true);
91 field.set(t, listWrapper.getItems());
92 } catch (Exception e) {
93 ;
94 }
95 }
96 }
97 }
98 return t;
99 }
100
101 @SuppressWarnings("unchecked")
102 public static <T> ListWrapper<T> deserializeToListWrapper(String content,
103 Class<T> clazz, String... matchPattern) {
104 XMLStreamReader xr = null;
105 XMLStreamWriter xw = null;
106 try {
107 xr = XMLInputFactory.newInstance().createXMLStreamReader(
108 new StringReader(content));
109 List<Pattern> patterns = new ArrayList<Pattern>();
110 for (String pattern : matchPattern) {
111 patterns.add(Pattern.compile(pattern));
112 }
113 Matcher matcher = null;
114 Map<String, Map<String, String>> outMap = new HashMap<String, Map<String, String>>();
115 while (true) {
116 int event = xr.next();
117 if (event == XMLStreamConstants.END_DOCUMENT) {
118 break;
119 } else if (event == XMLStreamConstants.START_ELEMENT) {
120 String name = xr.getLocalName();
121 for (Pattern pattern : patterns) {
122 if ((matcher = pattern.matcher(name)).find()) {
123 while (true) {
124 event = xr.next();
125 if (event == XMLStreamConstants.START_ELEMENT) {
126 name = xr.getLocalName();
127 } else if (event == XMLStreamConstants.END_ELEMENT) {
128 break;
129 } else if (event == XMLStreamConstants.CHARACTERS || event == XMLStreamConstants.CDATA) {
130 String key = matcher.group();
131 if (!pattern.pattern().equals(
132 DEFAULT_PATTERN.pattern())) {
133 matcher = DEFAULT_PATTERN.matcher(name);
134 matcher.find();
135 key = matcher.group();
136 }
137 Map<String, String> innerMap = null;
138 if ((innerMap = outMap.get(key)) == null) {
139 innerMap = new HashMap<String, String>();
140 outMap.put(key, innerMap);
141 }
142 innerMap.put(name.replace(key, ""),
143 xr.getText());
144 }
145 }
146 break;
147 }
148 }
149 }
150 }
151 if (!outMap.isEmpty()) {
152 StringWriter sw = new StringWriter();
153 xw = XMLOutputFactory.newInstance().createXMLStreamWriter(sw);
154 xw.writeStartDocument(Consts.UTF_8.name(), "1.0");
155 xw.writeStartElement(clazz.getCanonicalName());
156 String itemName = StringUtil
157 .uncapitalize(clazz.getSimpleName());
158 XmlRootElement rootElement = clazz
159 .getAnnotation(XmlRootElement.class);
160 if (rootElement != null
161 && StringUtil.isNotBlank(rootElement.name())) {
162 try {
163 if (!rootElement.name().equals(
164 XmlRootElement.class.getMethod("name")
165 .getDefaultValue().toString())) {
166 itemName = rootElement.name();
167 }
168 } catch (NoSuchMethodException e) {
169 ;
170 }
171 }
172 for (Entry<String, Map<String, String>> outE : outMap
173 .entrySet()) {
174 xw.writeStartElement(itemName);
175 for (Entry<String, String> innerE : outE
176 .getValue().entrySet()) {
177 xw.writeStartElement(innerE.getKey());
178 xw.writeCharacters(innerE.getValue());
179 xw.writeEndElement();
180 }
181 xw.writeEndElement();
182 }
183 xw.writeEndElement();
184 xw.writeEndDocument();
185 JAXBContext ctx = JAXBContext.newInstance(ListWrapper.class,
186 clazz);
187 Unmarshaller u = ctx.createUnmarshaller();
188 return u.unmarshal(
189 new StreamSource(new StringReader(sw.getBuffer()
190 .toString())), ListWrapper.class).getValue();
191 }
192 return null;
193 } catch (XMLStreamException e) {
194 throw new IllegalArgumentException(e);
195 } catch (JAXBException e) {
196 throw new RuntimeException(e);
197 } finally {
198 try {
199 if (xw != null) {
200 xw.close();
201 }
202 if (xr != null) {
203 xr.close();
204 }
205 } catch (XMLStreamException e) {
206 ;
207 }
208 }
209 }
210
211 public static Map<Field, String[]> getListsuffixFields(Class<?> clazz) {
212 Map<Field, String[]> listsuffixFields = new HashMap<Field, String[]>();
213 Set<Field> allFields = ReflectionUtil.getAllField(clazz);
214 ListsuffixResult listsuffixResult = null;
215 for (Field field : allFields) {
216 listsuffixResult = field.getAnnotation(ListsuffixResult.class);
217 if (listsuffixResult != null) {
218 listsuffixFields.put(field, listsuffixResult.value());
219 }
220 }
221 return listsuffixFields;
222 }
223 }