From 42b63bf0978b8056770d0b4d07b612b8c8399ab9 Mon Sep 17 00:00:00 2001 From: ZhouXY108 Date: Wed, 14 Dec 2022 14:35:09 +0800 Subject: [PATCH] first commit. --- .gitignore | 1 + .vscode/settings.json | 3 + pom.xml | 80 ++++ .../plusone/validator/BaseValidator.java | 86 ++++ .../validator/InvalidInputException.java | 53 +++ .../plusone/validator/ValidateUtil.java | 23 ++ .../zhouxy/plusone/validator/Validator.java | 42 ++ .../validator/validator2/BaseValidator2.java | 22 + .../validator/validator2/ValueValidator.java | 379 ++++++++++++++++++ 9 files changed, 689 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 pom.xml create mode 100644 src/main/java/xyz/zhouxy/plusone/validator/BaseValidator.java create mode 100644 src/main/java/xyz/zhouxy/plusone/validator/InvalidInputException.java create mode 100644 src/main/java/xyz/zhouxy/plusone/validator/ValidateUtil.java create mode 100644 src/main/java/xyz/zhouxy/plusone/validator/Validator.java create mode 100644 src/main/java/xyz/zhouxy/plusone/validator/validator2/BaseValidator2.java create mode 100644 src/main/java/xyz/zhouxy/plusone/validator/validator2/ValueValidator.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a6f89c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c5f3f6b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "interactive" +} \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..cdab09f --- /dev/null +++ b/pom.xml @@ -0,0 +1,80 @@ + + + + 4.0.0 + + xyz.zhouxy.plusone + plusone-validator + 0.0.1-SNAPSHOT + + plusone-validator + + http://www.example.com + + + UTF-8 + 1.8 + 1.8 + + + + + xyz.zhouxy.plusone + plusone-commons + 0.0.1-SNAPSHOT + + + junit + junit + 4.11 + test + + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + diff --git a/src/main/java/xyz/zhouxy/plusone/validator/BaseValidator.java b/src/main/java/xyz/zhouxy/plusone/validator/BaseValidator.java new file mode 100644 index 0000000..08f13d0 --- /dev/null +++ b/src/main/java/xyz/zhouxy/plusone/validator/BaseValidator.java @@ -0,0 +1,86 @@ +package xyz.zhouxy.plusone.validator; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +/** + * 校验器 + * + *

+ * 可以使用以下方式初始化一个校验器: + *

+ * + *
+ * BaseValidator<Integer> validator = new BaseValidator<>() {
+ *     {
+ *         withRule(value -> Objects.nonNull(value), "value 不能为空");
+ *         withRule(value -> (value >= 0 && value <= 500), "value 应在 [0, 500] 内");
+ *     }
+ * };
+ * 
+ * + *

+ * 也可以通过继承本类,定义一个校验器(可使用单例模式)。 + *

+ * + *

+ * 然后通过校验器的 {@link #validate} 方法,或 + * {@link ValidateUtil#validate(Object, Validator)} 对指定对象进行校验。 + *

+ * + *
+ * ValidateUtil.validate(255, validator);
+ * 
+ * + *
+ * validator.validate(666);
+ * 
+ *

+ * + * @author ZhouXY + * @see IValidateRequired + * @see ValidateUtil + * @see Validator + */ +public abstract class BaseValidator { + + private final List> rules = new ArrayList<>(); + + protected BaseValidator() { + } + + protected final void withRule(Predicate rule, String errorMessage) { + withRule(rule, () -> new InvalidInputException(errorMessage)); + } + + protected final void withRule(Predicate rule, Supplier exceptionCreator) { + withRule(rule, value -> exceptionCreator.get()); + } + + protected final void withRule(Predicate rule, Function exceptionCreator) { + this.rules.add(new RuleInfo<>(rule, exceptionCreator)); + } + + public void validate(T obj) { + this.rules.forEach(ruleInfo -> ruleInfo.validate(obj)); + } + + protected static class RuleInfo { + private final Predicate rule; + private final Function exceptionCreator; + + private RuleInfo(Predicate rule, Function exceptionCreator) { + this.rule = rule; + this.exceptionCreator = exceptionCreator; + } + + private void validate(T obj) { + if (!rule.test(obj)) { + throw exceptionCreator.apply(obj); + } + } + } +} diff --git a/src/main/java/xyz/zhouxy/plusone/validator/InvalidInputException.java b/src/main/java/xyz/zhouxy/plusone/validator/InvalidInputException.java new file mode 100644 index 0000000..5a23431 --- /dev/null +++ b/src/main/java/xyz/zhouxy/plusone/validator/InvalidInputException.java @@ -0,0 +1,53 @@ +package xyz.zhouxy.plusone.validator; + +import xyz.zhouxy.plusone.exception.PlusoneException; + +/** + * 4040200 - 无效的用户输入 + * + * @author ZhouXY + */ +public class InvalidInputException extends PlusoneException { + + private static final long serialVersionUID = 7956661913360059670L; + + public static final int ERROR_CODE = 4040200; + + private InvalidInputException(int code, String msg) { + super(code, msg); + } + + private InvalidInputException(int code, Throwable cause) { + super(code, cause); + } + + private InvalidInputException(int code, String msg, Throwable cause) { + super(code, msg, cause); + } + + public InvalidInputException(String msg) { + this(ERROR_CODE, msg); + } + + public InvalidInputException(Throwable cause) { + this(ERROR_CODE, cause); + } + + public InvalidInputException(String msg, Throwable cause) { + this(ERROR_CODE, msg, cause); + } + + /** + * 不支持的 Principal 类型出现时抛出的异常 + */ + public static InvalidInputException unsupportedPrincipalTypeException() { + return unsupportedPrincipalTypeException("不支持的 PrincipalType"); + } + + /** + * 不支持的 Principal 类型出现时抛出的异常 + */ + public static InvalidInputException unsupportedPrincipalTypeException(String message) { + return new InvalidInputException(4040201, message); + } +} diff --git a/src/main/java/xyz/zhouxy/plusone/validator/ValidateUtil.java b/src/main/java/xyz/zhouxy/plusone/validator/ValidateUtil.java new file mode 100644 index 0000000..438b197 --- /dev/null +++ b/src/main/java/xyz/zhouxy/plusone/validator/ValidateUtil.java @@ -0,0 +1,23 @@ +package xyz.zhouxy.plusone.validator; + +/** + * 校验工具类 + *

+ * 对 {@link IValidateRequired} 的实现类对象进行校验 + *

+ * + * @author ZhouXY + * + * @see BaseValidator + * @see Validator + * @see IValidateRequired + */ +public class ValidateUtil { + private ValidateUtil() { + throw new IllegalStateException("Utility class"); + } + + public static void validate(T obj, BaseValidator validator) { + validator.validate(obj); + } +} diff --git a/src/main/java/xyz/zhouxy/plusone/validator/Validator.java b/src/main/java/xyz/zhouxy/plusone/validator/Validator.java new file mode 100644 index 0000000..b56ff50 --- /dev/null +++ b/src/main/java/xyz/zhouxy/plusone/validator/Validator.java @@ -0,0 +1,42 @@ +package xyz.zhouxy.plusone.validator; + +import java.util.function.Predicate; + +/** + * 校验器 + * + *

+ * 可以使用以下方式初始化一个校验器: + *

+ * + *
+ * var validator = new Validator<Integer>()
+ *         .addRule(value -> Objects.nonNull(value), "value 不能为空")
+ *         .addRule(value -> (value >= 0 && value <= 500), "value 应在 [0, 500] 内");
+ * 
+ * + *

+ * 然后通过校验器的 {@link #validate} 方法,或 + * {@link ValidateUtil#validate(Object, Validator)} 对指定对象进行校验。 + *

+ * + *
+ * validator.validate(666);
+ * 
+ * + *
+ * ValidateUtil.validate(255, validator);
+ * 
+ *

+ * + * @author ZhouXY + * @see IValidateRequired + * @see ValidateUtil + * @see BaseValidator + */ +public final class Validator extends BaseValidator { + public final Validator addRule(final Predicate rule, final String errorMessage) { + withRule(rule, errorMessage); + return this; + } +} diff --git a/src/main/java/xyz/zhouxy/plusone/validator/validator2/BaseValidator2.java b/src/main/java/xyz/zhouxy/plusone/validator/validator2/BaseValidator2.java new file mode 100644 index 0000000..257af16 --- /dev/null +++ b/src/main/java/xyz/zhouxy/plusone/validator/validator2/BaseValidator2.java @@ -0,0 +1,22 @@ +package xyz.zhouxy.plusone.validator.validator2; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public abstract class BaseValidator2 { + + private List> valueValidators = new ArrayList<>(); + + protected final ValueValidator ruleFor(Function getter) { + ValueValidator validValueHolder = new ValueValidator<>(getter); + valueValidators.add(validValueHolder); + return validValueHolder; + } + + public void validate(T obj) { + for (ValueValidator valueValidator : this.valueValidators) { + valueValidator.validateProperty(obj); + } + } +} diff --git a/src/main/java/xyz/zhouxy/plusone/validator/validator2/ValueValidator.java b/src/main/java/xyz/zhouxy/plusone/validator/validator2/ValueValidator.java new file mode 100644 index 0000000..e80b136 --- /dev/null +++ b/src/main/java/xyz/zhouxy/plusone/validator/validator2/ValueValidator.java @@ -0,0 +1,379 @@ +package xyz.zhouxy.plusone.validator.validator2; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import cn.hutool.core.util.StrUtil; +import xyz.zhouxy.plusone.constant.RegexConsts; +import xyz.zhouxy.plusone.util.RegexUtil; +import xyz.zhouxy.plusone.validator.InvalidInputException; + +public class ValueValidator { + Function getter; + List> rules = new ArrayList<>(); + + public ValueValidator(Function getter) { + this.getter = getter; + } + + private void withRule(Predicate condition, + Function exceptionCreator) { + withRule(value -> { + if (!condition.test(value)) { + throw exceptionCreator.apply(value); + } + }); + } + + private void withRule(Consumer rule) { + this.rules.add(rule); + } + + // ==================== + // ====== Object ====== + // ==================== + + // ====== notNull ===== + + public ValueValidator notNull() { + return notNull("Value could not be null."); + } + + public ValueValidator notNull(String errMsg) { + return notNull(convertExceptionCreator(errMsg)); + } + + public ValueValidator notNull(Supplier exceptionCreator) { + return notNull(convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator notNull(Function exceptionCreator) { + withRule(Objects::nonNull, exceptionCreator); + return this; + } + + // ====== isNull ===== + + public ValueValidator isNull(String errMsg) { + return isNull(convertExceptionCreator(errMsg)); + } + + public ValueValidator isNull(Supplier exceptionCreator) { + return isNull(convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator isNull(Function exceptionCreator) { + withRule(Objects::isNull, exceptionCreator); + return this; + } + + // ===== equals ===== + + public ValueValidator equalsThat(Object that) { + return equalsThat(that, value -> new InvalidInputException(String.format("(%s) 必须与 (%s) 相等", value, that))); + } + + public ValueValidator equalsThat(Object that, String errMsg) { + return equalsThat(that, convertExceptionCreator(errMsg)); + } + + public ValueValidator equalsThat( + Object that, Supplier exceptionCreator) { + return equalsThat(that, convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator equalsThat( + Object that, Function exceptionCreator) { + withRule(value -> Objects.equals(value, that), exceptionCreator); + return this; + } + + // ===== state ===== + + public ValueValidator state(Predicate condition) { + return state(condition, "无效的用户输入"); + } + + public ValueValidator state(Predicate condition, String errMsg) { + return state(condition, convertExceptionCreator(errMsg)); + } + + public ValueValidator state( + Predicate condition, + Supplier exceptionCreator) { + return state(condition, convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator state( + Predicate condition, + Function exceptionCreator) { + withRule(condition, exceptionCreator); + return this; + } + + // ================= + // ====== int ====== + // ================= + + public ValueValidator between(int min, int max) { + return between(min, max, String.format("数值不在 %s 和 %s 之间", String.valueOf(min), String.valueOf(max))); + } + + public ValueValidator between(int min, int max, String errMsg) { + return between(min, max, convertExceptionCreator(errMsg)); + } + + public ValueValidator between(int min, int max, + Supplier exceptionCreator) { + return between(min, max, convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator between(int min, int max, + Function exceptionCreator) { + withRule(value -> ((int) value >= min && (int) value < max), exceptionCreator); + return this; + } + + // ==================== + // ====== double ====== + // ==================== + + public ValueValidator between(double min, double max) { + return between(min, max, String.format("数值不在 %s 和 %s 之间", String.valueOf(min), String.valueOf(max))); + } + + public ValueValidator between(double min, double max, String errMsg) { + return between(min, max, convertExceptionCreator(errMsg)); + } + + public ValueValidator between(double min, double max, + Supplier exceptionCreator) { + return between(min, max, convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator between(double min, double max, + Function exceptionCreator) { + withRule(value -> ((double) value >= min && (double) value < max), exceptionCreator); + return this; + } + + // ================================ + // ====== Collection, String ====== + // ================================ + + // ====== notEmpty ===== + + public ValueValidator notEmpty(String errMsg) { + return notEmpty(convertExceptionCreator(errMsg)); + } + + public ValueValidator notEmpty(Supplier exceptionCreator) { + return notEmpty(convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator notEmpty(Function exceptionCreator) { + withRule(value -> { + if (value == null) { + return false; + } + if (value instanceof Collection) { + return !((Collection) value).isEmpty(); + } + if (value instanceof String) { + return !((String) value).isEmpty(); + } + return false; + }, exceptionCreator); + return this; + } + + // ====== isEmpty ===== + + public ValueValidator isEmpty(String errMsg) { + return isEmpty(convertExceptionCreator(errMsg)); + } + + public ValueValidator isEmpty(Supplier exceptionCreator) { + return isEmpty(convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator isEmpty(Function exceptionCreator) { + withRule(value -> { + if (value == null) { + return false; + } + if (value instanceof Collection) { + return ((Collection) value).isEmpty(); + } + if (value instanceof String) { + return ((String) value).isEmpty(); + } + return false; + }, exceptionCreator); + return this; + } + + // ===================== + // ====== boolean ====== + // ===================== + + // ====== isTrue ====== + + public ValueValidator isTrue() { + return isTrue("The value must be true."); + } + + public ValueValidator isTrue(String errMsg) { + return isTrue(convertExceptionCreator(errMsg)); + } + + public ValueValidator isTrue(Supplier exceptionCreator) { + return isTrue(convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator isTrue(Function exceptionCreator) { + withRule(Boolean.TRUE::equals, exceptionCreator); + return this; + } + + // ====== isFalse ====== + + public ValueValidator isFalse() { + return isFalse("The value must be false."); + } + + public ValueValidator isFalse(String errMsg) { + return isFalse(convertExceptionCreator(errMsg)); + } + + public ValueValidator isFalse(Supplier exceptionCreator) { + return isFalse(convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator isFalse(Function exceptionCreator) { + withRule(Boolean.FALSE::equals, exceptionCreator); + return this; + } + + // ==================== + // ====== String ====== + // ==================== + + // ===== matches ===== + + public ValueValidator matches(String regex, String errMsg) { + return matches(regex, convertExceptionCreator(errMsg)); + } + + public ValueValidator matches( + String regex, + Supplier exceptionCreator) { + return matches(regex, convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator matches( + String regex, + Function exceptionCreator) { + withRule(input -> RegexUtil.matches((String) input, regex), exceptionCreator); + return this; + } + + // ===== matchesOr ===== + + public ValueValidator matchesOr(String[] regexs, String errMsg) { + return matchesOr(regexs, convertExceptionCreator(errMsg)); + } + + public ValueValidator matchesOr( + String[] regexs, + Supplier exceptionCreator) { + return matchesOr(regexs, convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator matchesOr( + String[] regexs, + Function exceptionCreator) { + withRule(input -> RegexUtil.matchesOr((String) input, regexs), exceptionCreator); + return this; + } + + // ===== matchesAnd ===== + + public ValueValidator matchesAnd(String[] regexs, String errMsg) { + return matchesAnd(regexs, convertExceptionCreator(errMsg)); + } + + public ValueValidator matchesAnd( + String[] regexs, + Supplier exceptionCreator) { + return matchesAnd(regexs, convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator matchesAnd( + String[] regexs, + Function exceptionCreator) { + withRule(input -> RegexUtil.matchesAnd((String) input, regexs), exceptionCreator); + return this; + } + + // ===== notBlank ===== + + public ValueValidator notBlank() { + return notBlank("This String argument must have text; it must not be null, empty, or blank"); + } + + public ValueValidator notBlank(String errMsg) { + return notBlank(convertExceptionCreator(errMsg)); + } + + public ValueValidator notBlank(Supplier exceptionCreator) { + return notBlank(convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator notBlank(Function exceptionCreator) { + withRule(input -> StrUtil.isNotBlank((String) input), exceptionCreator); + return this; + } + + // ===== email ===== + + public ValueValidator email() { + return email("The value is not an email address."); + } + + public ValueValidator email(String errMsg) { + return email(convertExceptionCreator(errMsg)); + } + + public ValueValidator email(Supplier exceptionCreator) { + return email(convertExceptionCreator(exceptionCreator)); + } + + public ValueValidator email(Function exceptionCreator) { + return matches(RegexConsts.EMAIL, exceptionCreator); + } + + // ======================================================================== + + void validateProperty(DTO obj) { + PROPERTY value = this.getter.apply(obj); + for (Consumer rule : this.rules) { + rule.accept(value); + } + } + + private static Function convertExceptionCreator(String errMsg) { + return convertExceptionCreator(errMsg); + } + + private static Function convertExceptionCreator( + Supplier exceptionSupplier) { + return value -> exceptionSupplier.get(); + } +}