Copy package com.caster.test.bean;
import com.caster.test.bean.anno.FieldInfo;
import com.caster.test.bean.field.FieldChange;
import com.caster.test.bean.field.ConvertExternalNameWrapper;
import com.caster.test.bean.field.FieldWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.util.ClassUtils;
import java.lang.reflect.Field;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
@Slf4j
public class BeanUtils {
private static final Map<Class, List<Field>> fieldsMap = new HashMap<Class, List<Field>>();
/**
* 檢索類別字段及排除特定注解,並暫存暫存class提高效能。
*
* @param clazz
* @return
*/
public static List<Field> getAllFields(Class<?> clazz) {
if (!ClassUtils.isCglibProxyClass(clazz)) {
List<Field> result = fieldsMap.get(clazz);
if (result == null) {
result = _getAllFields(clazz);
fieldsMap.put(clazz, result);
}
return result;
} else {
return _getAllFields(clazz);
}
}
private static List<Field> _getAllFields(Class<?> clazz) {
List<Field> fieldList = new ArrayList<Field>();
Collections.addAll(fieldList, clazz.getDeclaredFields());
excludeField(fieldList);
Class<?> c = clazz.getSuperclass();
if (c != null) {
fieldList.addAll(getAllFields(c));
}
return fieldList;
}
private static List<Field> excludeField(List<Field> fieldList) {
return fieldList.stream()
.filter(o -> o.isAnnotationPresent(FieldInfo.class))
.filter(o -> o.getAnnotation(FieldInfo.class).include())
.collect(Collectors.toList());
}
/**
* Get field in class and its super class
*
* @param clazz
* @param fieldName
* @return
*/
public static Field getField(Class<?> clazz, String fieldName) {
for (Field field : clazz.getDeclaredFields()) {
if (field.getName().equals(fieldName)) {
return field;
}
}
Class<?> c = clazz.getSuperclass();
if (c != null) {
return getField(c, fieldName);
}
return null;
}
public static Map<String, FieldWrapper> extract(Object obj) {
Map<String, FieldWrapper> result = new HashMap<String, FieldWrapper>();
for (Field field : BeanUtils.getAllFields(obj.getClass())) {
try {
FieldInfo fieldAnno = field.getAnnotation(FieldInfo.class);
Object value = PropertyUtils.getProperty(obj, field.getName()); // here has large log out put
if ((Objects.nonNull(fieldAnno) && fieldAnno.allowNullValue()) || Objects.nonNull(value))
result.put(field.getName(), FieldWrapper.create(field, value));
} catch (Exception e) {
//log.error("", e);'
e.printStackTrace();
}
}
return result;
}
public static Map<String, FieldChange> compare(Object from, Object to, String... ignoreFields) {
Map<String, FieldChange> result = new HashMap<String, FieldChange>();
Map<String, FieldWrapper> valueList1 = extract(from);
Map<String, FieldWrapper> valueList2 = extract(to);
Set<String> ignoreFieldSet = new HashSet<String>();
if (ignoreFields != null)
Collections.addAll(ignoreFieldSet, ignoreFields);
for (String name : valueList1.keySet()) {
if (ignoreFieldSet.contains(name))
continue;
FieldWrapper fv1 = valueList1.get(name);
FieldWrapper fv2 = valueList2.get(name);
if (fv1 != null && fv2 != null && !fv1.equals(fv2)) {
result.put(name, new FieldChange(name, fv1, fv2));
}
}
return result;
}
public static ConvertExternalNameWrapper transExternalName(ConvertExternalNameWrapper convertWrapper) {
Map<String, Object> fromMap = new HashMap<>();
Map<String, Object> toMap = new HashMap<>();
for (FieldChange f : convertWrapper.getCompareResultMap().values()) {
fromMap.putAll(f.getFrom().toExternalString((o) -> {
FieldWrapper wrapper = (FieldWrapper) o;
String value = wrapper.stringValue();
if (convertWrapper.getConvertFunctionMap().containsKey(wrapper.getVariableName()))
return convertWrapper.getConvertFunctionMap().get(wrapper.getVariableName()).apply(wrapper.getValue());
return value;
}));
toMap.putAll(f.getTo().toExternalString((o) -> {
FieldWrapper wrapper = (FieldWrapper) o;
String value = wrapper.stringValue();
if (convertWrapper.getConvertFunctionMap().containsKey(wrapper.getVariableName()))
return convertWrapper.getConvertFunctionMap().get(wrapper.getVariableName()).apply(wrapper.getValue());
return value;
}));
}
convertWrapper.setFromMap(fromMap);
convertWrapper.setToMap(toMap);
return convertWrapper;
}
}