|
@@ -42,21 +42,27 @@ public class Validator {
|
|
|
/**
|
|
|
* the name of the verify method.
|
|
|
*/
|
|
|
- private static final String validateMethodName = "validate";
|
|
|
+ private static final String validateMethodName = "validate";
|
|
|
/**
|
|
|
* the list of validation annotation & method can be work in {@code javax.validation.constraints.*}
|
|
|
*/
|
|
|
- private static final Map<Class<?>, Method> ClassMethodCache = new ConcurrentHashMap<>();
|
|
|
- private static final Map<Class<?>, MethodHandle> ClassMethodHandleCache = new ConcurrentHashMap<>();
|
|
|
- private static final Map<Field, Annotation[]> FieldAnnotationCache = new ConcurrentHashMap<>();
|
|
|
+ private static final Map<Class<?>, Method> annotationValidMethodCache = new ConcurrentHashMap<>();
|
|
|
+ /**
|
|
|
+ * the cache for annotations of field.
|
|
|
+ */
|
|
|
+ private static final Map<Field, Annotation[]> annotationOnFieldCache = new ConcurrentHashMap<>();
|
|
|
+ /**
|
|
|
+ * MethodHandle
|
|
|
+ */
|
|
|
+ private static final Map<Class<?>, MethodHandle> annotationValidMethodHandleCache = new ConcurrentHashMap<>();
|
|
|
/**
|
|
|
* the max length for a valid email address local part.
|
|
|
*/
|
|
|
- private static final int MAX_LOCAL_PART_LENGTH = 64;
|
|
|
+ private static final int MAX_LOCAL_PART_LENGTH = 64;
|
|
|
/**
|
|
|
* the regular expression for local part of a valid email address.
|
|
|
*/
|
|
|
- private static final String LOCAL_PART_ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~\u0080-\uFFFF-]";
|
|
|
+ private static final String LOCAL_PART_ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~\u0080-\uFFFF-]";
|
|
|
/**
|
|
|
* the regular expression for the local part of an email address.
|
|
|
*/
|
|
@@ -120,12 +126,12 @@ public class Validator {
|
|
|
*/
|
|
|
private static final byte BYTE_ZERO = (byte) 0;
|
|
|
/**
|
|
|
- * to private the constrctor.
|
|
|
+ * to private the constructor.
|
|
|
*/
|
|
|
private Validator() {
|
|
|
}
|
|
|
/**
|
|
|
- * collect all vaild validation annotation from the methods.
|
|
|
+ * collect all valid validation annotation from the methods.
|
|
|
*/
|
|
|
static {
|
|
|
collectValidAnnotationMethod();
|
|
@@ -133,19 +139,19 @@ public class Validator {
|
|
|
|
|
|
private static void collectValidAnnotationMethod() {
|
|
|
Method[] declaredMethods = ValidateAction.class.getDeclaredMethods();
|
|
|
- List<Method> verifyMethods = Arrays.stream(declaredMethods).filter(method -> validateMethodName.equals(method.getName())).collect(Collectors.toList());
|
|
|
- isTrue(verifyMethods.isEmpty(), "No any method named " + validateMethodName + " in ValidateAction.");
|
|
|
- for (Method method : verifyMethods) {
|
|
|
- Optional<Class<?>> classOptional = Arrays.stream(method.getParameterTypes()).filter(Annotation.class::isAssignableFrom).findFirst();
|
|
|
- classOptional.ifPresent(verifyClass -> {
|
|
|
- if (!method.isAccessible()) {
|
|
|
- method.setAccessible(true);
|
|
|
+ List<Method> validateMethods = Arrays.stream(declaredMethods).filter(method -> validateMethodName.equals(method.getName())).collect(Collectors.toList());
|
|
|
+ isTrue(validateMethods.isEmpty(), "No any method named %s in ValidateAction.", validateMethodName);
|
|
|
+ for (Method validateMethod : validateMethods) {
|
|
|
+ Optional<Class<?>> classOptional = Arrays.stream(validateMethod.getParameterTypes()).filter(Annotation.class::isAssignableFrom).findFirst();
|
|
|
+ classOptional.ifPresent(validateAnnotation -> {
|
|
|
+ if (!validateMethod.isAccessible()) {
|
|
|
+ validateMethod.setAccessible(true);
|
|
|
}
|
|
|
- ClassMethodCache.put(verifyClass, method);
|
|
|
- log.info("@interface: {}", verifyClass.getCanonicalName());
|
|
|
+ annotationValidMethodCache.put(validateAnnotation, validateMethod);
|
|
|
+ log.info("@interface: {}", validateAnnotation.getCanonicalName());
|
|
|
});
|
|
|
}
|
|
|
- isTrue(ClassMethodCache.isEmpty(), "No valid validation annotation was resolved in ValidateAction.");
|
|
|
+ isTrue(annotationValidMethodCache.isEmpty(), "No valid validation annotation was resolved in ValidateAction.");
|
|
|
}
|
|
|
/**
|
|
|
* to do verify by using the singleton instance.
|
|
@@ -329,10 +335,10 @@ public class Validator {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * compare two bigdecimal value
|
|
|
+ * compare two BigDecimal value
|
|
|
*
|
|
|
* @param value any object value
|
|
|
- * @param val the bigdecimal value transform from the object value
|
|
|
+ * @param val the BigDecimal value transform from the object value
|
|
|
* @param bounds the boundary of the maximum or minimum
|
|
|
* @param treatNanAs return for the value isn't number when check for infinity
|
|
|
* @return return {@code -1} for the val is less than boundary, {@code 0} for equal,{@code 1} for greater than boundary.
|
|
@@ -342,8 +348,7 @@ public class Validator {
|
|
|
return val.compareTo(bounds);
|
|
|
}
|
|
|
if (isDouble(value)) {
|
|
|
- Double v = (Double) value;
|
|
|
- OptionalInt infinity = infinityCheck(v, treatNanAs);
|
|
|
+ OptionalInt infinity = infinityCheck((Double) value, treatNanAs);
|
|
|
if (infinity.isPresent()) {
|
|
|
return infinity.getAsInt();
|
|
|
} else {
|
|
@@ -351,8 +356,7 @@ public class Validator {
|
|
|
}
|
|
|
}
|
|
|
if (isFloat(value)) {
|
|
|
- Float v = (Float) value;
|
|
|
- OptionalInt infinity = infinityCheck(v, treatNanAs);
|
|
|
+ OptionalInt infinity = infinityCheck((Float) value, treatNanAs);
|
|
|
if (infinity.isPresent()) {
|
|
|
return infinity.getAsInt();
|
|
|
} else {
|
|
@@ -386,11 +390,11 @@ public class Validator {
|
|
|
}
|
|
|
int count;
|
|
|
if (value instanceof Iterator) {
|
|
|
- Iterator<?> iter = (Iterator<?>) value;
|
|
|
+ Iterator<?> iterator = (Iterator<?>) value;
|
|
|
count = 0;
|
|
|
- while (iter.hasNext()) {
|
|
|
+ while (iterator.hasNext()) {
|
|
|
count++;
|
|
|
- iter.next();
|
|
|
+ iterator.next();
|
|
|
}
|
|
|
return count;
|
|
|
}
|
|
@@ -1453,18 +1457,18 @@ public class Validator {
|
|
|
if (!field.isAccessible()) {
|
|
|
field.setAccessible(true);
|
|
|
}
|
|
|
- if (FieldAnnotationCache.keySet().contains(field)) {
|
|
|
- return FieldAnnotationCache.get(field);
|
|
|
+ if (annotationOnFieldCache.keySet().contains(field)) {
|
|
|
+ return annotationOnFieldCache.get(field);
|
|
|
}
|
|
|
//get all annotation of the field
|
|
|
Annotation[] annotations = field.getDeclaredAnnotations();
|
|
|
//filter the validation annotation
|
|
|
if (notEmpty(annotations)) {
|
|
|
- List<Annotation> validateAnnotations = Arrays.stream(annotations).filter(annotation -> ClassMethodCache.keySet().contains(annotation.annotationType())).collect(Collectors.toList());
|
|
|
+ List<Annotation> validateAnnotations = Arrays.stream(annotations).filter(annotation -> annotationValidMethodCache.keySet().contains(annotation.annotationType())).collect(Collectors.toList());
|
|
|
annotations = validateAnnotations.toArray(new Annotation[validateAnnotations.size()]);
|
|
|
}
|
|
|
- FieldAnnotationCache.put(field, annotations);
|
|
|
- log.info("Get Declared annotation on field '{}', cache size: {}", field.getName(), FieldAnnotationCache.size());
|
|
|
+ annotationOnFieldCache.put(field, annotations);
|
|
|
+ log.info("Get Declared annotation on field '{}', cache size: {}", field.getName(), annotationOnFieldCache.size());
|
|
|
return annotations;
|
|
|
}
|
|
|
|
|
@@ -1486,8 +1490,8 @@ public class Validator {
|
|
|
}
|
|
|
|
|
|
private static Method lookupMethod(final Class<?> target, final String methodName, final Class<?> annotationType) {
|
|
|
- if (ClassMethodCache.keySet().contains(annotationType)) {
|
|
|
- return ClassMethodCache.get(annotationType);
|
|
|
+ if (annotationValidMethodCache.keySet().contains(annotationType)) {
|
|
|
+ return annotationValidMethodCache.get(annotationType);
|
|
|
}
|
|
|
final Method method;
|
|
|
try {
|
|
@@ -1498,7 +1502,7 @@ public class Validator {
|
|
|
if (!method.isAccessible()) {
|
|
|
method.setAccessible(true);
|
|
|
}
|
|
|
- ClassMethodCache.put(annotationType, method);
|
|
|
+ annotationValidMethodCache.put(annotationType, method);
|
|
|
return method;
|
|
|
}
|
|
|
|
|
@@ -1511,8 +1515,8 @@ public class Validator {
|
|
|
* @return MethodHandle
|
|
|
*/
|
|
|
private static MethodHandle lookupMethod(final MethodHandles.Lookup lookup, final String methodName, final Class<?> annotationType) {
|
|
|
- if (ClassMethodHandleCache.keySet().contains(annotationType)) {
|
|
|
- return ClassMethodHandleCache.get(annotationType);
|
|
|
+ if (annotationValidMethodHandleCache.keySet().contains(annotationType)) {
|
|
|
+ return annotationValidMethodHandleCache.get(annotationType);
|
|
|
}
|
|
|
final Class<?> lookupClass = lookup.lookupClass();
|
|
|
final MethodHandle methodHandle;
|
|
@@ -1522,7 +1526,7 @@ public class Validator {
|
|
|
} catch (NoSuchMethodException | IllegalAccessException e) {
|
|
|
throw newIllegalArgException("No such method [%s(%s)] in %s.", methodName, methodType, lookupClass.getName());
|
|
|
}
|
|
|
- ClassMethodHandleCache.put(annotationType, methodHandle);
|
|
|
+ annotationValidMethodHandleCache.put(annotationType, methodHandle);
|
|
|
return methodHandle;
|
|
|
}
|
|
|
|
|
@@ -1603,7 +1607,7 @@ public class Validator {
|
|
|
* @return the message has format if necessary
|
|
|
*/
|
|
|
private static String format(String message, Object... values) {
|
|
|
- if(message.contains("%s") && null != values && values.length > 0) {
|
|
|
+ if(message.contains("%s") && notEmpty(values)) {
|
|
|
return String.format(message, values);
|
|
|
}
|
|
|
return message;
|
|
@@ -1614,13 +1618,13 @@ public class Validator {
|
|
|
* @param object any object.
|
|
|
* @param message if {@code true} that throw a {@link IllegalArgumentException} with message.
|
|
|
*/
|
|
|
- private static void isNull(Object object, String message) {
|
|
|
- isTrue(Objects.isNull(object), message);
|
|
|
+ private static void isNull(Object object, String message, Object... values) {
|
|
|
+ isTrue(Objects.isNull(object), message, values);
|
|
|
}
|
|
|
|
|
|
- private static void isTrue(boolean expression, String message) {
|
|
|
+ private static void isTrue(boolean expression, String message, Object... values) {
|
|
|
if (expression) {
|
|
|
- throw newIllegalArgException(message);
|
|
|
+ throw newIllegalArgException(format(message, values));
|
|
|
}
|
|
|
}
|
|
|
|