package com.runachina.sc.designer.domain.validator;
import com.runachina.cloud.starter.base.exception.RestResultException;
import com.runachina.cloud.starter.base.rest.ResultStatus;
import com.runachina.sc.designer.domain.validator.annotations.UniqueField;
import com.runachina.sc.designer.domain.validator.utils.MessageUtil;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
public class UniqueFieldValidator implements ConstraintValidator<UniqueField, Collection> {
private String[] fieldNames;
@Override
public void initialize(UniqueField constraintAnnotation) {
this.fieldNames = constraintAnnotation.filedNames();
ConstraintValidator.super.initialize(constraintAnnotation);
}
/**
* getDeclaredField()和 getField() 方法都是获取字段的
* getField 只能获取 public 的,包括从父类继承来的字段。
* getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。 (注: 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true))
* 因此在获取父类的私有属性时,要通过getSuperclass的之后再通过getDeclaredFiled获取
*/
@Override
public boolean isValid(Collection valueList, ConstraintValidatorContext constraintValidatorContext) {
Map<String, String> valuesMap = new HashMap<>();
String fields = String.join("&", fieldNames);
List<String> methodNames = field2method(fieldNames);
for (Object value : valueList) {
String values = getValues(value, methodNames);
if (valuesMap.containsKey(values)) {
String message = "字段【" + fields + "】的值:" + values + " 重复";
MessageUtil.setMessage(constraintValidatorContext, message);
return false;
}
valuesMap.put(values, "");
}
return true;
}
/**
* 获取属性的值
*/
private String getValues(Object o, List<String> methodNames) {
Class<?> aClass = o.getClass();
List values = new ArrayList();
// 获取方法的返回值
for (String methodName : methodNames) {
try {
Method method = aClass.getMethod(methodName);
values.add(method.invoke(o));
} catch (NoSuchMethodException e) {
throw new RestResultException(ResultStatus.ILLEGAL_ARGUMENT,
"类【" + aClass.getName() + "】中找不到【" + methodName + "】方法");
} catch (IllegalAccessException e) {
throw new RestResultException(ResultStatus.ILLEGAL_ARGUMENT,
"类【" + aClass.getName() + "】方法【" + methodName + "】拒绝访问");
} catch (InvocationTargetException e) {
throw new RestResultException(ResultStatus.ILLEGAL_ARGUMENT,
"类【" + aClass.getName() + "】执行方法【" + methodName + "】异常");
}
}
return String.join("&", values);
}
/**
* 字段名转get方法名
* 因为父类私有属性的值获取不到,得采取调用public的get方法获取属性值
*/
private List<String> field2method(String[] fieldNames) {
List<String> methodNames = new ArrayList();
for (String fieldName : fieldNames) {
methodNames.add("get" + upperFirst(fieldName));
}
return methodNames;
}
/**
* 首字母大写
*/
private String upperFirst(String name) {
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
}