package com.github.binarywang.wxpay.converter; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyCoupon; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter; import com.thoughtworks.xstream.converters.reflection.ReflectionProvider; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.mapper.Mapper; import org.apache.commons.lang3.StringUtils; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; /** * The type Wxpay order notify result converter. * * @author aimilin */ public class WxPayOrderNotifyResultConverter extends AbstractReflectionConverter { /** * Instantiates a new Wx pay order notify result converter. * * @param mapper the mapper * @param reflectionProvider the reflection provider */ public WxPayOrderNotifyResultConverter(Mapper mapper, ReflectionProvider reflectionProvider) { super(mapper, reflectionProvider); } @Override @SuppressWarnings("rawtypes") public boolean canConvert(Class type) { return type.equals(WxPayOrderNotifyResult.class); } @Override public void marshal(Object original, HierarchicalStreamWriter writer, MarshallingContext context) { super.marshal(original, writer, context); WxPayOrderNotifyResult obj = (WxPayOrderNotifyResult) original; List list = obj.getCouponList(); if (list == null || list.isEmpty()) { return; } for (int i = 0; i < list.size(); i++) { WxPayOrderNotifyCoupon coupon = list.get(i); writer.startNode("coupon_id_" + i); writer.setValue(coupon.getCouponId()); writer.endNode(); writer.startNode("coupon_type_" + i); writer.setValue(coupon.getCouponType()); writer.endNode(); writer.startNode("coupon_fee_" + i); writer.setValue(String.valueOf(coupon.getCouponFee())); writer.endNode(); } } @Override protected void marshallField(MarshallingContext context, Object newObj, Field field) { if ("couponList".equals(field.getName())) { return; } super.marshallField(context, newObj, field); } @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { WxPayOrderNotifyResult obj = new WxPayOrderNotifyResult(); List fields = new ArrayList<>(Arrays.asList(obj.getClass().getDeclaredFields())); fields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields())); Map fieldMap = getFieldMap(fields); Map coupons = Maps.newTreeMap(); while (reader.hasMoreChildren()) { reader.moveDown(); if (fieldMap.containsKey(reader.getNodeName())) { Field field = fieldMap.get(reader.getNodeName()); this.setFieldValue(context, obj, field); } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_id_")) { String id = (String) context.convertAnother(obj, String.class); this.getElement(coupons, reader.getNodeName()).setCouponId(id); } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_type_")) { String type = (String) context.convertAnother(obj, String.class); this.getElement(coupons, reader.getNodeName()).setCouponType(type); } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_fee_")) { Integer fee = (Integer) context.convertAnother(obj, Integer.class); this.getElement(coupons, reader.getNodeName()).setCouponFee(fee); } reader.moveUp(); } obj.setCouponList(Lists.newArrayList(coupons.values())); return obj; } private void setFieldValue(UnmarshallingContext context, WxPayOrderNotifyResult obj, Field field) { Object val = context.convertAnother(obj, field.getType()); try { if (val != null) { /* 这里加一个看似多余的(String)强转可解决高jdk版本下的编译报错问题, 详情见讨论https://github.com/vaadin/framework/issues/10737 */ PropertyDescriptor pd = new PropertyDescriptor((String) field.getName(), obj.getClass()); pd.getWriteMethod().invoke(obj, val); } } catch (Exception ignored) { } } private Map getFieldMap(List fields) { return Maps.uniqueIndex(fields, field -> { if (field.isAnnotationPresent(XStreamAlias.class)) { return field.getAnnotation(XStreamAlias.class).value(); } return field.getName(); }); } private WxPayOrderNotifyCoupon getElement(Map coupons, String nodeName) { Integer index = Integer.valueOf(StringUtils.substringAfterLast(nodeName, "_")); coupons.computeIfAbsent(index, k -> new WxPayOrderNotifyCoupon()); return coupons.get(index); } }