@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ChangePrimaryKey {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ChangeRecord {
String value() default "";
}
public class CompareUtils {
@SneakyThrows
public static List<Map<String, String>> compareList(List<Object> sourceList, List<Object> targetList) {
List<Map<String, String>> result = new ArrayList<>();
Map<Object, Object> targetMap = targetList.stream().collect(Collectors.toMap(target -> {
Object targetValue = null;
Field[] fields = target.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.isAnnotationPresent(ChangePrimaryKey.class)) {
try {
targetValue=field.get(target);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
return targetValue;
}, Function.identity(),(v1, v2) -> v2));
sourceList.forEach(source -> {
Field[] fields = source.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.isAnnotationPresent(ChangePrimaryKey.class)) {
try {
Object sourceValue =field.get(source);
if(sourceValue!=null&&targetMap!=null){
targetMap.forEach((key, value) -> {
if(doCompareObject(sourceValue,key)){
result.add(compareObject(source,value));
}
});
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
});
return result;
}
@SneakyThrows
public static Map<String, String> compareObject(Object source, Object target) {
Map<String, String> result = new HashMap<>();
JSONObject oldRecord = new JSONObject();
JSONObject newRecord = new JSONObject();
Field[] fields1 = source.getClass().getDeclaredFields();
Field[] fields2 = target.getClass().getDeclaredFields();
Set<String> allFields = new HashSet<>();
for (Field field1 : fields1) {
field1.setAccessible(true);
if(field1.isAnnotationPresent(ChangeRecord.class)||field1.isAnnotationPresent(FixFieldKey.class)||field1.isAnnotationPresent(ChangePrimaryKey.class)){
allFields.add(field1.getName());
}
}
for (Field field2 : fields2) {
field2.setAccessible(true);
if(field2.isAnnotationPresent(ChangeRecord.class)||field2.isAnnotationPresent(FixFieldKey.class)||field2.isAnnotationPresent(ChangePrimaryKey.class)){
allFields.add(field2.getName());
}
}
if(CollectionUtils.isNotEmpty(allFields)){
Iterator it = allFields.iterator();
while (it.hasNext()) {
String tar = (String) it.next();
Field f1 =Arrays.stream(fields1).filter(field1 -> tar.equals(field1.getName())).findAny().orElse(null);
Field f2 =Arrays.stream(fields2).filter(field1 -> tar.equals(field1.getName())).findAny().orElse(null);
if(f1==null&&f2!=null){
newRecord.put(f2.getName(), f2.get(target).toString());
}else if(f1!=null&&f2==null){
oldRecord.put(f1.getName(), f1.get(source).toString());
}else if(f1!=null&&f2!=null){
if (f1.isAnnotationPresent(ChangePrimaryKey.class)) {
if(f1.get(source)!=null){
result.put("id", f1.get(source).toString());
}
}
if (f1.isAnnotationPresent(FixFieldKey.class)) {
if(f1.get(source)!=null){
FixFieldKey annotation = f1.getAnnotation(FixFieldKey.class);
String recordName = ("").equals(annotation.value()) ? null : annotation.value();
result.put("old"+recordName, f1.get(source).toString());
}
}
if (f2.isAnnotationPresent(FixFieldKey.class)) {
if(f2.get(target)!=null){
FixFieldKey annotation = f2.getAnnotation(FixFieldKey.class);
String recordName = ("").equals(annotation.value()) ? null : annotation.value();
result.put("new"+recordName, f2.get(target).toString());
}
}
if (!doCompareObject(f1.get(source), f2.get(target))) {
ChangeRecord annotation = f1.getAnnotation(ChangeRecord.class);
if (annotation != null) {
String recordName = ("").equals(annotation.value()) ? null : annotation.value();
if(f1.get(source)!=null){
oldRecord.put(recordName, f1.get(source).toString());
}
if(f2.get(target)!=null){
newRecord.put(recordName, f2.get(target).toString());
}
}
}
}
}
}
result.put("oldRecord", oldRecord.toJSONString());
result.put("newRecord", newRecord.toJSONString());
return result;
}
private static boolean doCompareObject(Object source, Object target) {
if (source == null && target == null) {
return true;
}
if (source == null && target != null) {
return false;
}
if (source.equals(target)) {
return true;
}
if (source instanceof BigDecimal && target instanceof BigDecimal) {
if (source == null && target == null) {
return true;
}
if (source == null ^ target == null) {
return false;
}
return ((BigDecimal) source).compareTo((BigDecimal) target) == 0;
}
if (source instanceof String && target instanceof String) {
if (StrUtil.isBlank(source.toString()) && StrUtil.isBlank(target.toString())) {
return true;
}
if (StrUtil.isBlank(source.toString()) ^ StrUtil.isBlank(target.toString())) {
return false;
}
return false;
}
return false;
}
}