From b29e1e07aac35d778659dcd85fc6b060119ac1c6 Mon Sep 17 00:00:00 2001 From: ZhouXY108 Date: Sun, 1 Jun 2025 18:10:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BA=20`CollectionPropertyValidato?= =?UTF-8?q?r`=20=E6=B7=BB=E5=8A=A0=20`allMatch`=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 allMatch 方法,用于校验集合中的所有元素是否满足指定条件。支持自定义异常信息和异常类型。 - 添加相关单元测试用例。 --- .../validator/BasePropertyValidator.java | 13 ++- .../CollectionPropertyValidator.java | 75 ++++++++++++++- .../CollectionPropertyValidatorTests.java | 91 +++++++++++++++++++ 3 files changed, 176 insertions(+), 3 deletions(-) diff --git a/plusone-validator/src/main/java/xyz/zhouxy/plusone/validator/BasePropertyValidator.java b/plusone-validator/src/main/java/xyz/zhouxy/plusone/validator/BasePropertyValidator.java index 4e80f9c..89b88b1 100644 --- a/plusone-validator/src/main/java/xyz/zhouxy/plusone/validator/BasePropertyValidator.java +++ b/plusone-validator/src/main/java/xyz/zhouxy/plusone/validator/BasePropertyValidator.java @@ -53,11 +53,22 @@ public abstract class BasePropertyValidator TPropertyValidator withRule( Predicate rule, Function e) { - this.consumers.add(v -> { + return withRule(v -> { if (!rule.test(v)) { throw e.apply(v); } }); + } + + /** + * 添加一条校验属性的规则 + * + * @param rule 校验规则 + * @param e 自定义异常 + * @return 属性校验器 + */ + protected final TPropertyValidator withRule(Consumer rule) { + this.consumers.add(rule); return thisObject(); } diff --git a/plusone-validator/src/main/java/xyz/zhouxy/plusone/validator/CollectionPropertyValidator.java b/plusone-validator/src/main/java/xyz/zhouxy/plusone/validator/CollectionPropertyValidator.java index e5d42fc..d3a485b 100644 --- a/plusone-validator/src/main/java/xyz/zhouxy/plusone/validator/CollectionPropertyValidator.java +++ b/plusone-validator/src/main/java/xyz/zhouxy/plusone/validator/CollectionPropertyValidator.java @@ -18,6 +18,7 @@ package xyz.zhouxy.plusone.validator; import java.util.Collection; import java.util.function.Function; +import java.util.function.Predicate; import java.util.function.Supplier; import xyz.zhouxy.plusone.commons.collection.CollectionTools; @@ -37,7 +38,9 @@ public class CollectionPropertyValidator super(getter); } - // ====== notEmpty ===== + // ================================ + // #region - notEmpty + // ================================ /** * 添加一条校验属性的规则,校验属性是否非空 @@ -83,7 +86,13 @@ public class CollectionPropertyValidator return this; } - // ====== isEmpty ===== + // ================================ + // #endregion - notEmpty + // ================================ + + // ================================ + // #region - isEmpty + // ================================ /** * 添加一条校验属性的规则,校验属性是否为空 @@ -127,6 +136,68 @@ public class CollectionPropertyValidator return this; } + // ================================ + // #endregion - isEmpty + // ================================ + + // ================================ + // #region - allMatch + // ================================ + + /** + * 添加一条校验属性的规则,校验是否所有元素都满足条件 + * + * @param condition 校验规则 + * @return 属性校验器 + */ + public CollectionPropertyValidator allMatch(Predicate condition) { + return allMatch(condition, convertToExceptionFunction("All elements must match the condition.")); + } + + /** + * 添加一条校验属性的规则,校验是否所有元素都满足条件 + * + * @param condition 校验规则 + * @param errMsg 异常信息 + * @return 属性校验器 + */ + public CollectionPropertyValidator allMatch(Predicate condition, String errMsg) { + return allMatch(condition, convertToExceptionFunction(errMsg)); + } + + /** + * 添加一条校验属性的规则,校验是否所有元素都满足条件 + * + * @param condition 校验规则 + * @param e 自定义异常 + * @return 属性校验器 + */ + public CollectionPropertyValidator allMatch( + Predicate condition, Supplier e) { + return allMatch(condition, convertToExceptionFunction(e)); + } + + /** + * 添加一条校验属性的规则,校验是否所有元素都满足条件 + * + * @param condition 校验规则 + * @param e 自定义异常 + * @return 属性校验器 + */ + public CollectionPropertyValidator allMatch( + Predicate condition, Function e) { + withRule(c -> c.stream().forEach(element -> { + if (!condition.test(element)) { + throw e.apply(element); + } + })); + return this; + } + + // ================================ + // #endregion - allMatch + // ================================ + @Override protected CollectionPropertyValidator thisObject() { return this; diff --git a/plusone-validator/src/test/java/xyz/zhouxy/plusone/example/validator/CollectionPropertyValidatorTests.java b/plusone-validator/src/test/java/xyz/zhouxy/plusone/example/validator/CollectionPropertyValidatorTests.java index 09f130b..54584be 100644 --- a/plusone-validator/src/test/java/xyz/zhouxy/plusone/example/validator/CollectionPropertyValidatorTests.java +++ b/plusone-validator/src/test/java/xyz/zhouxy/plusone/example/validator/CollectionPropertyValidatorTests.java @@ -271,6 +271,97 @@ public class CollectionPropertyValidatorTests { // #endregion - isEmpty // ================================ + // ================================ + // #region - allMatch + // ================================ + + static boolean checkStringLength(String str, int min, int max) { + return str != null && (str.length() >= min && str.length() <= max); + } + + @Test + void allMatch_validInput() { + + IValidator validator = new BaseValidator() { + { + ruleForCollection(ExampleCommand::getStringListProperty) + .allMatch(str -> checkStringLength(str, 4, 6)) + .allMatch(str -> checkStringLength(str, 4, 6), + "String length must in the interval [4,6].") + .allMatch(str -> checkStringLength(str, 4, 6), + () -> ExampleException.withMessage("String length must in the interval [4,6].")) + .allMatch(str -> checkStringLength(str, 4, 6), + str -> ExampleException.withMessage("Validation failed: '%s'.", str)); + } + }; + + ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("1234", "12345", "123456")); + assertDoesNotThrow(() -> validator.validate(command)); + } + + @Test + void allMatch_default_invalidInput() { + IValidator validator = new BaseValidator() { + { + ruleForCollection(ExampleCommand::getStringListProperty) + .allMatch(str -> checkStringLength(str, 4, 6)); + } + }; + + ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList(null, "1234", "12345", "123456")); + ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command)); + assertEquals("All elements must match the condition.", e.getMessage()); + } + + @Test + void allMatch_specifiedMessage_invalidInput() { + IValidator validator = new BaseValidator() { + { + ruleForCollection(ExampleCommand::getStringListProperty) + .allMatch(str -> checkStringLength(str, 4, 6), + "String length must in the interval [4,6]."); + } + }; + + ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("1234", "", "12345", "123456")); + ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command)); + assertEquals("String length must in the interval [4,6].", e.getMessage()); + } + + @Test + void allMatch_specifiedExceptionSupplier_invalidInput() { + IValidator validator = new BaseValidator() { + { + ruleForCollection(ExampleCommand::getStringListProperty) + .allMatch(str -> checkStringLength(str, 4, 6), + () -> ExampleException.withMessage("String length must in the interval [4,6].")); + } + }; + + ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("1234", "12345", "123", "123456")); + ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command)); + assertEquals("String length must in the interval [4,6].", e.getMessage()); + } + + @Test + void allMatch_specifiedExceptionFunction_invalidInput() { + IValidator validator = new BaseValidator() { + { + ruleForCollection(ExampleCommand::getStringListProperty) + .allMatch(str -> checkStringLength(str, 4, 6), + str -> ExampleException.withMessage("Validation failed: '%s'.", str)); + } + }; + + ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("1234", "12345", "123456", "1234567")); + ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command)); + assertEquals("Validation failed: '1234567'.", e.getMessage()); + } + + // ================================ + // #endregion - allMatch + // ================================ + static ExampleCommand exampleCommandWithStringListProperty(List property) { ExampleCommand exampleCommand = new ExampleCommand(); exampleCommand.setStringListProperty(property);