26 Commits

Author SHA1 Message Date
2977c9a7fb refactor!: 优化二元组校验的 API 设计 2025-07-25 10:57:47 +08:00
09d596b599 feat: 重载 BaseValidator#ruleForPair
- 重载 BaseValidator#ruleForPair,允许传入两个 Function,用于分别从目标对象中获取两个属性
- 升级项目版本至 1.0.0-RC2
2025-07-14 09:43:13 +08:00
b3ef6deebe release: 1.0.0-RC1
- 将 plusone-validator-parent 版本从 1.0.0-SNAPSHOT 更新为 1.0.0-RC1
- 将 plusone-commons 依赖版本从 1.1.0-SNAPSHOT 更新为 1.1.0-RC1
- 将 plusone-dependencies 依赖版本从 1.1.0-SNAPSHOT 更新为 1.1.0-RC1
2025-06-08 14:19:53 +08:00
f86232c404 docs: 修改 javadoc 中的格式错误 2025-06-08 13:09:44 +08:00
d0785d35e8 docs: 更新项目描述 2025-06-08 11:34:31 +08:00
a315edf88f docs: 统一参数描述 2025-06-08 11:34:15 +08:00
b6d47f0d00 refactor: 重构 MapValidator 的测试代码 2025-06-08 04:49:30 +08:00
12a5740dd6 refactor: 重构 BasePropertyValidator 中 equal 和 notEqual 方法的参数命名 2025-06-08 04:38:52 +08:00
654ecd8c63 docs: 更新文档注释 2025-06-08 04:34:08 +08:00
8b63eb6fe4 chore: 删除 IDE 的配置 2025-06-05 10:41:05 +08:00
62f7a9b03b refactor!: 将 matchesOne 方法重命名为 matchesAny
修改了 StringPropertyValidator 类中的 matchesOne 方法,将其重命名为 matchesAny。
2025-06-04 17:15:22 +08:00
e79d8e9ec8 refactor: 重构属性校验器 2025-06-04 01:30:51 +08:00
7f4f5748f8 feat(validator): 添加 notEqual 校验方法并优化 equalTo
- 新增 `notEqual` 校验方法,用于判断属性值不等于给定值。
- 优化 `equalTo` 方法的空值判断逻辑,当属性值为空时不进行校验。
2025-06-01 20:35:41 +08:00
88b3226b17 feat: 添加数组长度和集合大小的校验功能
- 在 ArrayPropertyValidator 中添加了 length 方法,用于校验数组长度。
- 在 CollectionPropertyValidator 中添加了 size 方法,用于校验集合大小。
2025-06-01 20:18:36 +08:00
0a83116e81 refactor: 将方法调用与返回语句合并,简化了代码结构 2025-06-01 20:16:42 +08:00
907d883be8 feat: 添加数组属性校验器
- 新增 `ArrayPropertyValidator` 类,提供针对数组类型的属性校验功能。
- 在 `BaseValidator` 中添加 `ruleForArray` 方法,用于创建数组属性校验器。
2025-06-01 19:00:10 +08:00
7a9e15fd45 refactor: 优化集合属性校验器
- 更新类注释
- 优化 allMatch 方法的实现,使用 forEach 替代 stream().forEach()
2025-06-01 18:57:58 +08:00
b29e1e07aa feat: 为 CollectionPropertyValidator 添加 allMatch 方法
- 新增 allMatch 方法,用于校验集合中的所有元素是否满足指定条件。支持自定义异常信息和异常类型。
- 添加相关单元测试用例。
2025-06-01 18:10:36 +08:00
3f23d5383d refactor: 默认使用 SimpleImmutableEntry 作为二元组
- 在 `MapValidator` 类中,将 `SimpleEntry` 替换为 `SimpleImmutableEntry`,作为二元组的默认实现。
- 在 `PairPropertyValidatorTests` 类中,做同样的替换。
2025-06-01 08:56:00 +08:00
c27525a637 test: 修改测试用例以覆盖 BaseValidator#ruleFor 2025-06-01 08:48:23 +08:00
3ef2ebac2f feat: 添加二元组属性校验支持
- 新增 `PairPropertyValidator` 类,用于校验二元组属性
- 在 `BaseValidator` 和 `MapValidator` 中添加对二元组校验器的支持
- 添加相关单元测试
2025-06-01 08:46:13 +08:00
8be8be8f17 chore: 更新 README 中的示例 2025-06-01 06:48:30 +08:00
5603b72897 chore: 更新 README 中的许可证链接 2025-06-01 06:11:59 +08:00
2ac8e39387 chore: 添加 README 2025-06-01 06:01:06 +08:00
3b9a224e72 refactor: 修改 MapValidator#ruleFor 的泛型以支持使用具体类型的规则 2025-06-01 05:42:10 +08:00
44ea11e0e9 refactor!: 删除 BasePropertyValidator 多余的 withRule 方法 2025-06-01 05:40:30 +08:00
31 changed files with 3060 additions and 2079 deletions

View File

@@ -1,5 +0,0 @@
{
"java.configuration.updateBuildConfiguration": "automatic",
"java.dependency.packagePresentation": "hierarchical",
"java.compile.nullAnalysis.mode": "automatic"
}

106
README.md Normal file
View File

@@ -0,0 +1,106 @@
# Plusone Validator
## 简介
Plusone Validator 是一个校验库,使用 lambda 表达式(包括方法引用)和流式 API 构建校验规则,对对象进行校验。
## 安装
Plusone Validator 暂未提交 maven 中央仓库,可 clone 代码仓库,通过 maven 安装到本地库,然后在项目中引入。
## 示例
### 校验对象
定义校验器:
```java
class CustomerValidator extends BaseValidator<Customer> {
private static final CustomerValidator INSTANCE = new CustomerValidator();
private CustomerValidator() {
ruleFor(Customer::getName).notBlank("姓名不能为空");
ruleFor(Customer::getEmailAddress).notBlank().emailAddress();
ruleFor(Customer::getVipLevel).notNull().inRange(Range.closed(0, 10), "会员等级必须在0-10之间");
ruleFor(Customer::getCustomerId).notBlank("客户编号不能为空");
ruleFor(Customer::getBirthday)
.notNull("生日不能为空")
.must(LocalDate.now().minusYears(16)::isAfter, "用户必须大于16周岁");
ruleFor(Customer::getAddress).length(20, 250, "地址长度必须在20-250之间");
ruleFor((Customer customer) -> Pair.of(customer.getVipLevel(), customer.getBirthday()))
.must(CustomerValidator::validateAge, "5级以上会员必须满18周岁");
}
private static boolean validateAge(Pair<Integer, LocalDate> vipLevelAndBirthday) {
Integer vipLevel = vipLevelAndBirthday.getLeft();
LocalDate birthday = vipLevelAndBirthday.getRight();
return vipLevel <= 5 || LocalDate.now().minusYears(18).isAfter(birthday);
}
public static CustomerValidator getInstance() {
return INSTANCE;
}
}
```
使用:
```java
public void foo(Customer customer) {
CustomerValidator.getInstance().validate(customer);
// ...
}
```
### 校验 Map
定义校验器:
```java
class CustomerMapValidator extends MapValidator<String, Object> {
private static final CustomerMapValidator INSTANCE = new CustomerMapValidator();
private static final String[] FIELD_NAMES = {
"name", "emailAddress", "vipLevel", "customerId", "birthday", "address"
};
private CustomerMapValidator() {
// validateAndCopy() 时默认保留的 key
super(FIELD_NAMES);
ruleForString("name").notBlank("姓名不能为空");
ruleForString("emailAddress").notBlank().emailAddress();
ruleForInt("vipLevel").notNull().inRange(Range.closed(0, 10), "会员等级必须在0-10之间");
ruleForString("customerId").notBlank("客户编号不能为空");
this.<LocalDate>ruleFor("birthday")
.notNull("生日不能为空")
.must(LocalDate.now().minusYears(16)::isAfter, "用户必须大于16周岁");
ruleForString("address").length(20, 250, "地址长度必须在20-250之间");
this.<Pair<Integer, LocalDate>>ruleFor((Map<String, Object> customer) ->
Pair.of(MapUtils.getInteger(customer, "vipLevel"), (LocalDate) customer.get("birthday")))
.must(CustomerMapValidator::validateAge, "5级以上会员必须满18周岁");
}
private static boolean validateAge(Pair<Integer, LocalDate> vipLevelAndBirthday) {
Integer vipLevel = vipLevelAndBirthday.getLeft();
LocalDate birthday = vipLevelAndBirthday.getRight();
return vipLevel <= 5 || LocalDate.now().minusYears(18).isAfter(birthday);
}
public static CustomerMapValidator getInstance() {
return INSTANCE;
}
}
```
使用:
```java
public void foo(Map<String, Object> customer) {
Map<String, Object> validatedCustomer = CustomerMapValidator.getInstance().validateAndCopy(customer);
// ...
}
```
---
## 其他
Plusone Validator 是个人在学习 Microsoft 的 [eShop](https://github.com/dotnet/eShop) 时,被其中 [FluentValidation](https://github.com/FluentValidation/FluentValidation) 的 API 所吸引,出于学习和个人使用的目的进行开发和维护。使用 [Apache License 2.0](./LICENSE) 开源。
欢迎通过 issue 反馈使用过程中发现的问题和建议。

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-validator-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>1.0.0-RC2</version>
</parent>
<artifactId>plusone-validator</artifactId>
@@ -16,7 +16,7 @@
<url>http://zhouxy.xyz</url>
<description>
Plusone Validator 是一个校验库,用于构建校验规则对对象尤其是入参进行校验。API 参考自 .NET 的 FluentValidation
Plusone Validator 是一个校验库,使用 lambda 表达式(包括方法引用)和流式 API 构建校验规则对对象进行校验
</description>
<properties>
@@ -29,7 +29,7 @@
<dependency>
<groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-commons</artifactId>
<version>1.1.0-SNAPSHOT</version>
<version>1.1.0-RC1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>

View File

@@ -0,0 +1,347 @@
/*
* Copyright 2023-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.zhouxy.plusone.validator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import xyz.zhouxy.plusone.commons.util.ArrayTools;
import xyz.zhouxy.plusone.commons.util.AssertTools;
/**
* 数组类型属性的校验器
*
* <p>
* 用于构建校验数组类型属性的规则链。
*
* @param <T> 待校验对象的类型
* @param <E> 数组元素的类型
* @author ZhouXY
*/
public class ArrayPropertyValidator<T, E>
extends BasePropertyValidator<T, E[], ArrayPropertyValidator<T, E>> {
ArrayPropertyValidator(Function<T, E[]> getter) {
super(getter);
}
// ================================
// #region - notEmpty
// ================================
/**
* 添加一条校验属性的规则,校验属性是否非空
*
* @return 当前校验器实例,用于链式调用
*/
public final ArrayPropertyValidator<T, E> notEmpty() {
return withRule(Conditions.notEmpty(), "The input must not be empty.");
}
/**
* 添加一条校验属性的规则,校验属性是否非空
*
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public final ArrayPropertyValidator<T, E> notEmpty(
final String errorMessage) {
return withRule(Conditions.notEmpty(), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否非空
*
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> notEmpty(
final Supplier<X> exceptionSupplier) {
return withRule(Conditions.notEmpty(), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否非空
*
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> notEmpty(
final Function<E[], X> exceptionFunction) {
return withRule(Conditions.notEmpty(), exceptionFunction);
}
// ================================
// #endregion - notEmpty
// ================================
// ================================
// #region - isEmpty
// ================================
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @return 当前校验器实例,用于链式调用
*/
public final ArrayPropertyValidator<T, E> isEmpty() {
return withRule(Conditions.isEmpty(), "The input must be empty.");
}
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public final ArrayPropertyValidator<T, E> isEmpty(
final String errorMessage) {
return withRule(Conditions.isEmpty(), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> isEmpty(
final Supplier<X> exceptionSupplier) {
return withRule(Conditions.isEmpty(), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> isEmpty(
final Function<E[], X> exceptionFunction) {
return withRule(Conditions.isEmpty(), exceptionFunction);
}
// ================================
// #endregion - isEmpty
// ================================
// ================================
// #region - allMatch
// ================================
/**
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
*
* @param condition 校验条件
* @return 当前校验器实例,用于链式调用
*/
public final ArrayPropertyValidator<T, E> allMatch(final Predicate<E> condition) {
return withRule(c -> {
for (E element : c) {
if (!condition.test(element)) {
throw ValidationException.withMessage("All elements must match the condition.");
}
}
});
}
/**
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
*
* @param condition 校验条件
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public final ArrayPropertyValidator<T, E> allMatch(
final Predicate<E> condition, final String errorMessage) {
return withRule(c -> {
for (E element : c) {
if (!condition.test(element)) {
throw ValidationException.withMessage(errorMessage);
}
}
});
}
/**
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
*
* @param <X> 自定义异常类型
* @param condition 校验条件
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> allMatch(
final Predicate<E> condition, final Supplier<X> exceptionSupplier) {
return withRule(c -> {
for (E element : c) {
if (!condition.test(element)) {
throw exceptionSupplier.get();
}
}
});
}
/**
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
*
* @param <X> 自定义异常类型
* @param condition 校验条件
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> allMatch(
final Predicate<E> condition, final Function<E, X> exceptionFunction) {
return withRule(c -> {
for (E element : c) {
if (!condition.test(element)) {
throw exceptionFunction.apply(element);
}
}
});
}
// ================================
// #endregion - allMatch
// ================================
// ================================
// #region - length
// ================================
/**
* 添加一条校验属性的规则,校验属性长度是否等于指定长度
*
* @param length 预期长度
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public final ArrayPropertyValidator<T, E> length(
final int length, final String errorMessage) {
return withRule(Conditions.length(length), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性长度是否等于指定长度
*
* @param <X> 自定义异常类型
* @param length 预期长度
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> length(
final int length, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.length(length), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性长度是否等于指定长度
*
* @param <X> 自定义异常类型
* @param length 预期长度
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> length(
final int length, final Function<E[], X> exceptionFunction) {
return withRule(Conditions.length(length), exceptionFunction);
}
/**
* 添加一条校验属性的规则,校验属性的长度范围
*
* @param min 最小长度(包含)
* @param max 最大长度(包含)
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public final ArrayPropertyValidator<T, E> length(
final int min, final int max, final String errorMessage) {
return withRule(Conditions.length(min, max), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性的长度范围
*
* @param <X> 自定义异常类型
* @param min 最小长度(包含)
* @param max 最大长度(包含)
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> length(
final int min, final int max, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.length(min, max), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性的长度范围
*
* @param <X> 自定义异常类型
* @param min 最小长度(包含)
* @param max 最大长度(包含)
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> length(
final int min, final int max, final Function<E[], X> exceptionFunction) {
return withRule(Conditions.length(min, max), exceptionFunction);
}
// ================================
// #endregion - length
// ================================
private static class Conditions {
private static <T> Predicate<T[]> isEmpty() {
return ArrayTools::isEmpty;
}
private static <T> Predicate<T[]> notEmpty() {
return ArrayTools::isNotEmpty;
}
private static <T> Predicate<T[]> length(final int length) {
AssertTools.checkArgument(length >= 0,
"The expected length must be non-negative.");
return input -> input == null || input.length == length;
}
private static <T> Predicate<T[]> length(final int min, final int max) {
AssertTools.checkArgument(min >= 0, "min must be non-negative.");
AssertTools.checkArgument(min <= max, "min must be less than or equal to max.");
return input -> {
if (input == null) {
return true;
}
final int len = input.length;
return len >= min && len <= max;
};
}
}
@Override
protected ArrayPropertyValidator<T, E> thisObject() {
return this;
}
}

View File

@@ -17,23 +17,24 @@
package xyz.zhouxy.plusone.validator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import com.google.common.collect.Range;
/**
* 针对 {@code Comparable} 类型属性校验器基类
* {@code Comparable} 类型属性校验器基类
*
* <p>
* 内置了判断属性是否在给定区间内的校验规则。
*
* @param <T> 待校验对象类型
* @param <TProperty> 属性类型
* @param <TPropertyValidator> 当前属性校验器类型,用于链式调用
* @param <T> 待校验对象的类型
* @param <TProperty> 待校验属性的类型,必须实现 {@code Comparable} 接口
* @param <TPropertyValidator> 具体校验器类型,用于支持链式调用
* @see Range
* @author ZhouXY
*/
public abstract class BaseComparablePropertyValidator<T, TProperty extends Comparable<TProperty>, TPropertyValidator extends BaseComparablePropertyValidator<T, TProperty, TPropertyValidator>>
public abstract class BaseComparablePropertyValidator<
T,
TProperty extends Comparable<TProperty>,
TPropertyValidator extends BaseComparablePropertyValidator<T, TProperty, TPropertyValidator>>
extends BasePropertyValidator<T, TProperty, TPropertyValidator> {
BaseComparablePropertyValidator(Function<T, ? extends TProperty> getter) {
@@ -41,52 +42,62 @@ public abstract class BaseComparablePropertyValidator<T, TProperty extends Compa
}
/**
* 添加一条校验属性的规则,校验属性是否在给定的区间之内
* 添加一条校验属性的规则,校验属性的取值范围。
*
* @param range 区间
* @return 属性校验器
* @return 当前校验器实例,用于链式调用
*/
public TPropertyValidator inRange(Range<TProperty> range) {
withRule(value -> value != null && range.contains(value), value -> ValidationException.withMessage(
"The input must in the interval %s. You entered %s.", range, value));
return thisObject();
public final TPropertyValidator inRange(final Range<TProperty> range) {
return withRule(Conditions.inRange(range), value -> ValidationException.withMessage(
"The input must in the interval %s. You entered %s.", range, value));
}
/**
* 添加一条校验属性的规则,校验属性是否在给定的区间之内
* 添加一条校验属性的规则,校验属性的取值范围。
*
* @param range 区间
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 自定义错误消息模板
* @return 当前校验器实例,用于链式调用
*/
public TPropertyValidator inRange(Range<TProperty> range, String errMsg) {
withRule(value -> value != null && range.contains(value), convertToExceptionFunction(errMsg));
return thisObject();
public final TPropertyValidator inRange(
final Range<TProperty> range, final String errorMessage) {
return withRule(Conditions.inRange(range), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否在给定的区间之内
* 添加一条校验属性的规则,校验属性的取值范围。
*
* @param <X> 自定义异常类型
* @param range 区间
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> TPropertyValidator inRange(
Range<TProperty> range, Supplier<E> e) {
withRule(value -> value != null && range.contains(value), e);
return thisObject();
public final <X extends RuntimeException> TPropertyValidator inRange(
final Range<TProperty> range, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.inRange(range), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否在给定的区间之内
* 添加一条校验属性的规则,校验属性的取值范围。
*
* @param <X> 自定义异常类型
* @param range 区间
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> TPropertyValidator inRange(
Range<TProperty> range, Function<TProperty, E> e) {
withRule(value -> value != null && range.contains(value), e);
return thisObject();
public final <X extends RuntimeException> TPropertyValidator inRange(
final Range<TProperty> range, final Function<TProperty, X> exceptionFunction) {
return withRule(Conditions.inRange(range), exceptionFunction);
}
/**
* 校验条件的实现
*/
private static class Conditions {
private static <TProperty extends Comparable<TProperty>> Predicate<TProperty> inRange(
final Range<TProperty> range) {
return value -> value == null || range.contains(value);
}
}
}

View File

@@ -16,7 +16,6 @@
package xyz.zhouxy.plusone.validator;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
@@ -29,12 +28,17 @@ import java.util.function.Supplier;
* 属性校验器。包含针对属性的校验规则。
*
* <p>
* <i>内置基础的校验规则。</i>
* </p>
* 用于构建针对特定属性的校验规则链,支持通过链式调用添加多种校验规则。
*
* @param <T> 待校验对象的类型
* @param <TProperty> 待校验属性的类型
* @param <TPropertyValidator> 具体校验器类型,用于支持链式调用
* @author ZhouXY
*/
public abstract class BasePropertyValidator<T, TProperty, TPropertyValidator extends BasePropertyValidator<T, TProperty, TPropertyValidator>> {
public abstract class BasePropertyValidator<
T,
TProperty,
TPropertyValidator extends BasePropertyValidator<T, TProperty, TPropertyValidator>> {
private final Function<T, ? extends TProperty> getter;
@@ -45,63 +49,97 @@ public abstract class BasePropertyValidator<T, TProperty, TPropertyValidator ext
}
/**
* 添加一条校验属性的规则
* 添加一条校验属性的规则,当条件不满足时抛出异常。
*
* @param rule 校验规则
* @return 属性校验器
* @param condition 校验条件
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
* @throws ValidationException 校验失败时抛出的异常
*/
public final TPropertyValidator withRule(Predicate<? super TProperty> rule) {
return withRule(rule, v -> ValidationException.withDefaultMessage());
}
/**
* 添加一条校验属性的规则
*
* @param rule 校验规则
* @param errMsg 校验失败的错误信息
* @return 属性校验器
*/
public final TPropertyValidator withRule(
Predicate<? super TProperty> rule, String errMsg) {
return withRule(rule, convertToExceptionFunction(errMsg));
}
/**
* 添加一条校验属性的规则
*
* @param rule 校验规则
* @param e 自定义异常
* @return 属性校验器
*/
public final <E extends RuntimeException> TPropertyValidator withRule(
Predicate<? super TProperty> rule, Supplier<E> e) {
return withRule(rule, convertToExceptionFunction(e));
}
/**
* 添加一条校验属性的规则
*
* @param rule 校验规则
* @param e 自定义异常
* @return 属性校验器
*/
public final <E extends RuntimeException> TPropertyValidator withRule(
Predicate<? super TProperty> rule, Function<TProperty, E> e) {
this.consumers.add(v -> {
if (!rule.test(v)) {
throw e.apply(v);
protected final TPropertyValidator withRule(
final Predicate<? super TProperty> condition,
final String errorMessage) {
return withRule(input -> {
if (!condition.test(input)) {
throw ValidationException.withMessage(errorMessage);
}
});
}
/**
* 添加一条校验属性的规则
*
* @param condition 校验条件
* @param errorMessageTemplate 异常信息模板
* @param errorMessageArgs 异常信息参数
* @return 当前校验器实例,用于链式调用
* @throws ValidationException 校验失败时抛出的异常
*/
protected final TPropertyValidator withRule(
final Predicate<? super TProperty> condition,
final String errorMessageTemplate, Object... errorMessageArgs) {
return withRule(input -> {
if (!condition.test(input)) {
throw ValidationException.withMessage(errorMessageTemplate, errorMessageArgs);
}
});
}
/**
* 添加一条校验属性的规则
*
* @param <X> 自定义异常类型
* @param condition 校验条件
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
protected final <X extends RuntimeException> TPropertyValidator withRule(
final Predicate<? super TProperty> condition,
final Supplier<X> exceptionSupplier) {
return withRule(input -> {
if (!condition.test(input)) {
throw exceptionSupplier.get();
}
});
}
/**
* 添加一条校验属性的规则,当条件不满足时抛出自定义异常。可以根据当前属性的值创建异常。
*
* @param <X> 自定义异常类型
* @param condition 校验条件
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
protected final <X extends RuntimeException> TPropertyValidator withRule(
final Predicate<? super TProperty> condition,
final Function<? super TProperty, X> exceptionFunction) {
return withRule(input -> {
if (!condition.test(input)) {
throw exceptionFunction.apply(input);
}
});
}
/**
* 添加一条校验属性的规则
*
* @param rule 自定义校验规则
* @return 当前校验器实例,用于链式调用
*/
protected final TPropertyValidator withRule(Consumer<? super TProperty> rule) {
this.consumers.add(rule);
return thisObject();
}
/**
* 校验属性
* @param propertyValue 属性值
*
* @param obj 属性所在的对象
*/
public final void validate(T propertyValue) {
public final void validate(T obj) {
for (Consumer<? super TProperty> consumer : consumers) {
consumer.accept(getter.apply(propertyValue));
consumer.accept(getter.apply(obj));
}
}
@@ -118,43 +156,44 @@ public abstract class BasePropertyValidator<T, TProperty, TPropertyValidator ext
/**
* 添加一条校验属性的规则,校验属性是否不为空
*
* @return 属性校验器
* @return 当前校验器实例,用于链式调用
*/
public TPropertyValidator notNull() {
return notNull("The input must not be null.");
public final TPropertyValidator notNull() {
return withRule(Objects::nonNull, "The input must not be null.");
}
/**
* 添加一条校验属性的规则,校验属性是否不为空
*
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public TPropertyValidator notNull(String errMsg) {
return notNull(convertToExceptionFunction(errMsg));
public final TPropertyValidator notNull(final String errorMessage) {
return withRule(Objects::nonNull, errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否不为空
*
* @param <E> 自定义异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> TPropertyValidator notNull(Supplier<E> e) {
return notNull(convertToExceptionFunction(e));
public final <X extends RuntimeException> TPropertyValidator notNull(
final Supplier<X> exceptionSupplier) {
return withRule(Objects::nonNull, exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否不为空
*
* @param <E> 自定义异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> TPropertyValidator notNull(Function<TProperty, E> e) {
withRule(Objects::nonNull, e);
return thisObject();
public final <X extends RuntimeException> TPropertyValidator notNull(
final Function<TProperty, X> exceptionFunction) {
return withRule(Objects::nonNull, exceptionFunction);
}
// ================================
@@ -168,43 +207,44 @@ public abstract class BasePropertyValidator<T, TProperty, TPropertyValidator ext
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @return 属性校验器
* @return 当前校验器实例,用于链式调用
*/
public TPropertyValidator isNull() {
return isNull("The input must be null.");
public final TPropertyValidator isNull() {
return withRule(Objects::isNull, "The input must be null.");
}
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public TPropertyValidator isNull(String errMsg) {
return isNull(convertToExceptionFunction(errMsg));
public final TPropertyValidator isNull(final String errorMessage) {
return withRule(Objects::isNull, errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @param <E> 自定义异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> TPropertyValidator isNull(Supplier<E> e) {
return isNull(convertToExceptionFunction(e));
public final <X extends RuntimeException> TPropertyValidator isNull(
final Supplier<X> exceptionSupplier) {
return withRule(Objects::isNull, exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @param <E> 自定义异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> TPropertyValidator isNull(Function<TProperty, E> e) {
withRule(Objects::isNull, e);
return thisObject();
public final <X extends RuntimeException> TPropertyValidator isNull(
final Function<TProperty, X> exceptionFunction) {
return withRule(Objects::isNull, exceptionFunction);
}
// ================================
@@ -212,60 +252,116 @@ public abstract class BasePropertyValidator<T, TProperty, TPropertyValidator ext
// ================================
// ================================
// #region - equalTo
// #region - equal
// ================================
/**
* 添加一条校验属性的规则,校验属性是否等于给定值
*
* @param that 给定值
* @return 属性校验器
* @param obj 用于比较的对象
* @return 当前校验器实例,用于链式调用
*/
public TPropertyValidator equalTo(Object that) {
return equalTo(that, value -> ValidationException
.withMessage("The input must be equal to '%s'.", that));
public final TPropertyValidator equal(Object obj) {
return withRule(Conditions.equal(obj),
"The input must be equal to '%s'.", obj);
}
/**
* 添加一条校验属性的规则,校验属性是否等于给定值
*
* @param that 给定值
* @param errMsg 错误信息
* @return 属性校验器
* @param obj 用于比较的对象
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public TPropertyValidator equalTo(Object that, String errMsg) {
return equalTo(that, convertToExceptionFunction(errMsg));
public final TPropertyValidator equal(
final Object obj, final String errorMessage) {
return withRule(Conditions.equal(obj), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否等于给定值
*
* @param <E> 自定义异常类型
* @param that 给定值
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param obj 用于比较的对象
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> TPropertyValidator equalTo(
Object that, Supplier<E> e) {
return equalTo(that, convertToExceptionFunction(e));
public final <X extends RuntimeException> TPropertyValidator equal(
final Object obj, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.equal(obj), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否等于给定值
*
* @param <E> 自定义异常类型
* @param that 给定值
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param obj 用于比较的对象
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> TPropertyValidator equalTo(
Object that, Function<TProperty, E> e) {
withRule(value -> Objects.equals(value, that), e);
return thisObject();
public final <X extends RuntimeException> TPropertyValidator equal(
final Object obj, final Function<TProperty, X> exceptionFunction) {
return withRule(Conditions.equal(obj), exceptionFunction);
}
// ================================
// #endregion - equalTo
// #endregion - equal
// ================================
// ================================
// #region - notEqual
// ================================
/**
* 添加一条校验属性的规则,校验属性是否等于给定值
*
* @param obj 用于比较的对象
* @return 当前校验器实例,用于链式调用
*/
public final TPropertyValidator notEqual(final Object obj) {
return withRule(Conditions.notEqual(obj),
"The input must not equal '%s'.", obj);
}
/**
* 添加一条校验属性的规则,校验属性是否等于给定值
*
* @param obj 用于比较的对象
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public final TPropertyValidator notEqual(final Object obj, final String errorMessage) {
return withRule(Conditions.notEqual(obj), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否等于给定值
*
* @param <X> 自定义异常类型
* @param obj 用于比较的对象
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> TPropertyValidator notEqual(
final Object obj, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.notEqual(obj), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否等于给定值
*
* @param <X> 自定义异常类型
* @param obj 用于比较的对象
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> TPropertyValidator notEqual(
final Object obj, final Function<TProperty, X> exceptionFunction) {
return withRule(Conditions.notEqual(obj), exceptionFunction);
}
// ================================
// #endregion - notEqual
// ================================
// ================================
@@ -275,119 +371,79 @@ public abstract class BasePropertyValidator<T, TProperty, TPropertyValidator ext
/**
* 添加一条校验属性的规则,校验属性是否满足给定的条件
*
* @param condition 校验规则
* @return 属性校验器
* @param condition 校验条件
* @return 当前校验器实例,用于链式调用
*/
public TPropertyValidator must(Predicate<? super TProperty> condition) {
return must(condition, "The specified condition was not met for the input.");
public final TPropertyValidator must(final Predicate<? super TProperty> condition) {
return withRule(condition,
"The specified condition was not met for the input.");
}
/**
* 添加一条校验属性的规则,校验属性是否满足给定的条件
*
* @param condition 校验规则
* @param errMsg 错误信息
* @return 属性校验器
* @param condition 校验条件
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public TPropertyValidator must(Predicate<? super TProperty> condition, String errMsg) {
return must(condition, convertToExceptionFunction(errMsg));
public final TPropertyValidator must(
final Predicate<? super TProperty> condition,
final String errorMessage) {
return withRule(condition, errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否满足给定的条件
*
* @param <E> 自定义异常类型
* @param <X> 自定义异常类型
* @param condition 校验规则
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> TPropertyValidator must(
Predicate<? super TProperty> condition,
Supplier<E> e) {
return must(condition, convertToExceptionFunction(e));
public final <X extends RuntimeException> TPropertyValidator must(
final Predicate<? super TProperty> condition,
final Supplier<X> exceptionSupplier) {
return withRule(condition, exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否满足给定的条件
*
* @param <E> 自定义异常类型
* @param <X> 自定义异常类型
* @param condition 校验规则
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> TPropertyValidator must(
Predicate<? super TProperty> condition,
Function<TProperty, E> e) {
withRule(condition, e);
return thisObject();
}
/**
* 添加多条校验属性的规则,校验属性是否满足给定的所有条件
*
* @param conditions 校验规则
* @return 属性校验器
*/
public TPropertyValidator must(Collection<Predicate<? super TProperty>> conditions) {
return must(conditions, "The specified conditions were not met for the input.");
}
/**
* 添加多条校验属性的规则,校验属性是否满足给定的所有条件
*
* @param conditions 校验规则
* @param errMsg 错误信息
* @return 属性校验器
*/
public TPropertyValidator must(Collection<Predicate<? super TProperty>> conditions, String errMsg) {
return must(conditions, convertToExceptionFunction(errMsg));
}
/**
* 添加多条校验属性的规则,校验属性是否满足给定的所有条件
*
* @param <E> 自定义异常类型
* @param conditions 校验规则
* @param e 自定义异常
* @return 属性校验器
*/
public <E extends RuntimeException> TPropertyValidator must(
Collection<Predicate<? super TProperty>> conditions, Supplier<E> e) {
return must(conditions, convertToExceptionFunction(e));
}
/**
* 添加多条校验属性的规则,校验属性是否满足给定的所有条件
*
* @param <E> 自定义异常类型
* @param conditions 校验规则
* @param e 自定义异常
* @return 属性校验器
*/
public <E extends RuntimeException> TPropertyValidator must(
Collection<Predicate<? super TProperty>> conditions,
Function<TProperty, E> e) {
for (Predicate<? super TProperty> condition : conditions) {
withRule(condition, e);
}
return thisObject();
public final <X extends RuntimeException> TPropertyValidator must(
final Predicate<? super TProperty> condition,
final Function<TProperty, X> exceptionFunction) {
return withRule(condition, exceptionFunction);
}
// ================================
// #endregion - must
// ================================
static <V> Function<V, ValidationException> convertToExceptionFunction(String errMsg) {
return value -> ValidationException.withMessage(errMsg);
// ================================
// #region - conditions
// ================================
/**
* 常用校验条件的实现
*/
private static class Conditions {
private static <TProperty> Predicate<TProperty> equal(Object obj) {
return input -> input == null || input.equals(obj);
}
private static <TProperty> Predicate<TProperty> notEqual(Object obj) {
return input -> input == null || !input.equals(obj);
}
}
static <V> Function<V, ValidationException> convertToExceptionFunction(
String errorMessageTemplate, Object... errorMessageArgs) {
return value -> ValidationException.withMessage(errorMessageTemplate, errorMessageArgs);
}
static <V, E extends RuntimeException> Function<V, E> convertToExceptionFunction(
Supplier<E> exceptionSupplier) {
return value -> exceptionSupplier.get();
}
// ================================
// #endregion - conditions
// ================================
}

View File

@@ -19,6 +19,8 @@ package xyz.zhouxy.plusone.validator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Map.Entry;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -27,72 +29,71 @@ import java.util.function.Supplier;
import xyz.zhouxy.plusone.validator.function.*;
/**
* 校验器基类
*
* 校验器基类
* <p>
* 通过继承 {@code BaseValidator},可以自定义一个针对特定类型的校验器,包含对该类型的校验逻辑
* 子类可通过添加不同的校验规则,构建完整的校验逻辑,用于校验对象
*
* @param <T> 待校验对象的类型
* @author ZhouXY
*/
public abstract class BaseValidator<T> implements IValidator<T> {
/**
* 规则集合
*/
private final List<Consumer<? super T>> rules = new ArrayList<>();
/**
* 添加一个校验规则
* 添加一条用于校验整个对象的规则
*
* @param rule 校验规则
* @param errorMessage 错误信息
*/
protected final void withRule(final Predicate<? super T> rule, final String errorMessage) {
withRule(rule, () -> ValidationException.withMessage(errorMessage));
}
/**
* 添加一个校验规则
*
* @param <E> 自定义异常类型
* @param rule 校验规则
* @param e 自定义异常
*/
protected final <E extends RuntimeException> void withRule(
final Predicate<? super T> rule, final Supplier<E> e) {
withRule(rule, value -> e.get());
}
/**
* 添加一个校验规则
*
* @param <E> 自定义异常类型
* @param condition 校验条件
* @param e 自定义异常
* @param errorMessage 异常信息
*/
protected final <E extends RuntimeException> void withRule(
final Predicate<? super T> condition, final Function<T, E> e) {
protected final void withRule(final Predicate<? super T> condition, final String errorMessage) {
withRule(condition, () -> ValidationException.withMessage(errorMessage));
}
/**
* 添加一条用于校验整个对象的规则
*
* @param <X> 自定义异常类型
* @param condition 校验条件
* @param exceptionSupplier 自定义异常
*/
protected final <X extends RuntimeException> void withRule(
final Predicate<? super T> condition, final Supplier<X> exceptionSupplier) {
withRule(condition, value -> exceptionSupplier.get());
}
/**
* 添加一条用于校验整个对象的规则
*
* @param <X> 自定义异常类型
* @param condition 校验条件
* @param exceptionFunction 自定义异常
*/
protected final <X extends RuntimeException> void withRule(
final Predicate<? super T> condition, final Function<T, X> exceptionFunction) {
withRule(value -> {
if (!condition.test(value)) {
throw e.apply(value);
throw exceptionFunction.apply(value);
}
});
}
/**
* 添加一个校验规则
* 添加一条用于校验整个对象的规则
*
* @param rule 校验规则。内部包含断言条件,如果条件不满足,则抛出异常。
* @param rule 自定义校验规则
*/
protected final void withRule(Consumer<? super T> rule) {
this.rules.add(rule);
}
/**
* 添加一个属性校验器
* 添加一个通用的属性校验器
*
* @param getter 属性获取函数
* @return 属性校验器
* @param <R> 属性类型
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code ObjectPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final <R> ObjectPropertyValidator<T, R> ruleFor(Function<T, R> getter) {
ObjectPropertyValidator<T, R> validator = new ObjectPropertyValidator<>(getter);
@@ -101,11 +102,12 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code Comparable} 属性校验器
* 添加一个用于校验 {@code Comparable} 类型的属性校验器
*
* @param <R> 属性类型
* @param getter 属性获取函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code ComparablePropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final <R extends Comparable<R>> ComparablePropertyValidator<T, R> ruleForComparable(
Function<T, R> getter) {
@@ -115,10 +117,11 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code Integer} 属性校验器
* 添加一个用于校验 {@code Integer} 类型的属性校验器
*
* @param getter 属性获取函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code IntPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final IntPropertyValidator<T> ruleForInt(Function<T, Integer> getter) {
IntPropertyValidator<T> validator = new IntPropertyValidator<>(getter);
@@ -127,10 +130,11 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code Integer} 属性校验器
* 添加一个用于校验 {@code Integer} 类型的属性校验器
*
* @param getter 属性获取函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code IntPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final IntPropertyValidator<T> ruleFor(ToIntegerFunction<T> getter) {
IntPropertyValidator<T> validator = new IntPropertyValidator<>(getter);
@@ -139,10 +143,11 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code Long} 属性校验器
* 添加一个用于校验 {@code Long} 类型的属性校验器
*
* @param getter 属性获取函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code LongPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final LongPropertyValidator<T> ruleForLong(Function<T, Long> getter) {
LongPropertyValidator<T> validator = new LongPropertyValidator<>(getter);
@@ -151,10 +156,11 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code Long} 属性校验器
* 添加一个用于校验 {@code Long} 类型的属性校验器
*
* @param getter 属性获取函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code LongPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final LongPropertyValidator<T> ruleFor(ToLongObjectFunction<T> getter) {
LongPropertyValidator<T> validator = new LongPropertyValidator<>(getter);
@@ -163,10 +169,11 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code Double} 属性校验器
* 添加一个用于校验 {@code Double} 类型的属性校验器
*
* @param getter 属性获取函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code DoublePropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final DoublePropertyValidator<T> ruleForDouble(Function<T, Double> getter) {
DoublePropertyValidator<T> validator = new DoublePropertyValidator<>(getter);
@@ -175,10 +182,11 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code Double} 属性校验器
* 添加一个用于校验 {@code Double} 类型的属性校验器
*
* @param getter 属性获取函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code DoublePropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final DoublePropertyValidator<T> ruleFor(ToDoubleObjectFunction<T> getter) {
DoublePropertyValidator<T> validator = new DoublePropertyValidator<>(getter);
@@ -187,10 +195,11 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code Boolean} 属性校验器
* 添加一个用于校验 {@code Boolean} 类型的属性校验器
*
* @param getter 属性获取函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code BoolPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final BoolPropertyValidator<T> ruleForBool(Function<T, Boolean> getter) {
BoolPropertyValidator<T> validator = new BoolPropertyValidator<>(getter);
@@ -199,10 +208,11 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code Boolean} 属性校验器
* 添加一个用于校验 {@code Boolean} 类型的属性校验器
*
* @param getter 属性获取函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code BoolPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final BoolPropertyValidator<T> ruleFor(ToBoolObjectFunction<T> getter) {
BoolPropertyValidator<T> validator = new BoolPropertyValidator<>(getter);
@@ -211,10 +221,11 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code String} 属性校验器
* 添加一个用于校验 {@code String} 类型的属性校验器
*
* @param getter 获取属性值的函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code StringPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final StringPropertyValidator<T> ruleForString(Function<T, String> getter) {
StringPropertyValidator<T> validator = new StringPropertyValidator<>(getter);
@@ -223,10 +234,11 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code String} 属性校验器
* 添加一个用于校验 {@code String} 类型的属性校验器
*
* @param getter 获取属性值的函数
* @return 属性校验器
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code StringPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final StringPropertyValidator<T> ruleFor(ToStringFunction<T> getter) {
StringPropertyValidator<T> validator = new StringPropertyValidator<>(getter);
@@ -235,10 +247,12 @@ public abstract class BaseValidator<T> implements IValidator<T> {
}
/**
* 添加一个针对 {@code Collection} 属性校验器
* 添加一个用于校验集合类型的属性校验器
*
* @param getter 获取属性值的函数
* @return 集合属性校验器
* @param <E> 集合元素类型
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code CollectionPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final <E> CollectionPropertyValidator<T, E> ruleForCollection(Function<T, Collection<E>> getter) {
CollectionPropertyValidator<T, E> validator = new CollectionPropertyValidator<>(getter);
@@ -246,6 +260,55 @@ public abstract class BaseValidator<T> implements IValidator<T> {
return validator;
}
/**
* 添加一个用于校验数组类型的属性校验器
*
* @param <E> 数组元素类型
* @param getter 用于从目标对象获取属性值的函数式接口。
* 示例:{@code Person::getName}。
* @return {@code ArrayPropertyValidator}。用于添加针对该属性的校验规则。
*/
protected final <E> ArrayPropertyValidator<T, E> ruleForArray(Function<T, E[]> getter) {
ArrayPropertyValidator<T, E> validator = new ArrayPropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
/**
* 添加一个针对二元组的校验器
*
* @param <V1> 第一个元素的类型
* @param <V2> 第二个元素的类型
* @param getter 根据对象构造一个二元组,通常是两个属性的值。
* @return {@code PairPropertyValidator}。用于添加针对该二元组的校验规则。
*
* @deprecated 请使用 {@link #ruleFor(Function, Function)} 代替。
*/
@Deprecated
protected final <V1, V2> PairPropertyValidator<T, V1, V2> ruleForPair( // NOSONAR
Function<T, Entry<V1, V2>> getter) {
PairPropertyValidator<T, V1, V2> validator = new PairPropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
/**
* 添加一个针对二元组的校验器
*
* @param <V1> 第1个元素的类型
* @param <V2> 第2个元素的类型
* @param v1Getter 用于从目标对象获取第1个元素的函数式接口。示例{@code Person::getName1}。
* @param v2Getter 用于从目标对象获取第2个元素的函数式接口。示例{@code Person::getName2}。
* @return {@code PairPropertyValidator}。用于添加针对该二元组的校验规则。
*/
protected final <V1, V2> PairPropertyValidator<T, V1, V2> ruleFor(
Function<T, V1> v1Getter, Function<T, V2> v2Getter) {
PairPropertyValidator<T, V1, V2> validator = new PairPropertyValidator<>(
t -> new SimpleImmutableEntry<>(v1Getter.apply(t), v2Getter.apply(t)));
this.rules.add(validator::validate);
return validator;
}
/** {@inheritDoc} */
@Override
public void validate(T obj) {

View File

@@ -17,18 +17,20 @@
package xyz.zhouxy.plusone.validator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* 针对 {@code Boolean} 类型属性校验器
* {@code Boolean} 类型属性校验器
*
* <p>
* 内置了判断 Boolean 值是否为 true 或 false 的校验规则。
* </p>
* 用于构建校验 {@code Boolean} 类型属性的规则
*
* @param <T> 待校验对象的类型
* @author ZhouXY
*/
public class BoolPropertyValidator<T> extends BasePropertyValidator<T, Boolean, BoolPropertyValidator<T>> {
public class BoolPropertyValidator<T>
extends BasePropertyValidator<T, Boolean, BoolPropertyValidator<T>> {
BoolPropertyValidator(Function<T, Boolean> getter) {
super(getter);
@@ -37,89 +39,102 @@ public class BoolPropertyValidator<T> extends BasePropertyValidator<T, Boolean,
// ====== isTrueValue ======
/**
* 添加一条判断属性是否为 {@code true} 的校验规则
* 添加一条校验属性的规则,校验属性是否为 {@code true}
*
* @return 属性校验器
* @return 当前校验器实例,用于链式调用
*/
public BoolPropertyValidator<T> isTrueValue() {
return isTrueValue("The input must be true.");
public final BoolPropertyValidator<T> isTrueValue() {
return withRule(Conditions.isTrueValue(), "The input must be true.");
}
/**
* 添加一条判断属性是否为 {@code true} 的校验规则
* 添加一条校验属性的规则,校验属性是否为 {@code true}
*
* @param errMsg 校验失败的错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public BoolPropertyValidator<T> isTrueValue(String errMsg) {
return isTrueValue(convertToExceptionFunction(errMsg));
public final BoolPropertyValidator<T> isTrueValue(final String errorMessage) {
return withRule(Conditions.isTrueValue(), errorMessage);
}
/**
* 添加一条判断属性是否为 {@code true} 的校验规则
* 添加一条校验属性的规则,校验属性是否为 {@code true}
*
* @param <E> 自定义异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> BoolPropertyValidator<T> isTrueValue(Supplier<E> e) {
return isTrueValue(convertToExceptionFunction(e));
public final <X extends RuntimeException> BoolPropertyValidator<T> isTrueValue(
final Supplier<X> exceptionSupplier) {
return withRule(Conditions.isTrueValue(), exceptionSupplier);
}
/**
* 添加一条判断属性是否为 {@code true} 的校验规则
* 添加一条校验属性的规则,校验属性是否为 {@code true}
*
* @param <E> 自定义异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> BoolPropertyValidator<T> isTrueValue(Function<Boolean, E> e) {
withRule(Boolean.TRUE::equals, e);
return this;
public final <X extends RuntimeException> BoolPropertyValidator<T> isTrueValue(
final Function<Boolean, X> exceptionFunction) {
return withRule(Conditions.isTrueValue(), exceptionFunction);
}
// ====== isFalseValue ======
/**
* 添加一条判断属性是否为 {@code false} 的校验规则
* 添加一条校验属性的规则,校验属性是否为 {@code false}
*
* @return 属性校验器
* @return 当前校验器实例,用于链式调用
*/
public BoolPropertyValidator<T> isFalseValue() {
return isFalseValue("The input must be false.");
public final BoolPropertyValidator<T> isFalseValue() {
return withRule(Conditions.isFalseValue(), "The input must be false.");
}
/**
* 添加一条判断属性是否为 {@code false} 的校验规则
* 添加一条校验属性的规则,校验属性是否为 {@code false}
*
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public BoolPropertyValidator<T> isFalseValue(String errMsg) {
return isFalseValue(convertToExceptionFunction(errMsg));
public final BoolPropertyValidator<T> isFalseValue(final String errorMessage) {
return withRule(Conditions.isFalseValue(), errorMessage);
}
/**
* 添加一条判断属性是否为 {@code false} 的校验规则
* 添加一条校验属性的规则,校验属性是否为 {@code false}
*
* @param <E> 异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> BoolPropertyValidator<T> isFalseValue(Supplier<E> e) {
return isFalseValue(convertToExceptionFunction(e));
public final <X extends RuntimeException> BoolPropertyValidator<T> isFalseValue(
final Supplier<X> exceptionSupplier) {
return withRule(Conditions.isFalseValue(), exceptionSupplier);
}
/**
* 添加一条判断属性是否为 {@code false} 的校验规则
* 添加一条校验属性的规则,校验属性是否为 {@code false}
*
* @param <E> 异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> BoolPropertyValidator<T> isFalseValue(Function<Boolean, E> e) {
withRule(Boolean.FALSE::equals, e);
return this;
public final <X extends RuntimeException> BoolPropertyValidator<T> isFalseValue(
final Function<Boolean, X> exceptionFunction) {
return withRule(Conditions.isFalseValue(), exceptionFunction);
}
private static class Conditions {
private static <TProperty> Predicate<TProperty> isTrueValue() {
return Boolean.TRUE::equals;
}
private static <TProperty> Predicate<TProperty> isFalseValue() {
return Boolean.FALSE::equals;
}
}
@Override

View File

@@ -18,117 +18,322 @@ 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;
import xyz.zhouxy.plusone.commons.util.AssertTools;
/**
* 针对集合类型属性校验器
* 集合类型属性校验器
*
* <p>
* 内置判断集合是否为空的校验规则。
* 用于构建校验集合类型属性的规则
*
* @param <T> 待校验对象的类型
* @param <E> 集合元素的类型
* @author ZhouXY
*/
public class CollectionPropertyValidator<T, TElement>
extends BasePropertyValidator<T, Collection<TElement>, CollectionPropertyValidator<T, TElement>> {
public class CollectionPropertyValidator<T, E>
extends BasePropertyValidator<T, Collection<E>, CollectionPropertyValidator<T, E>> {
CollectionPropertyValidator(Function<T, Collection<TElement>> getter) {
CollectionPropertyValidator(Function<T, Collection<E>> getter) {
super(getter);
}
// ====== notEmpty =====
// ================================
// #region - notEmpty
// ================================
/**
* 添加一条校验属性的规则,校验属性是否非空
*
* @return 属性校验器
* @return 当前校验器实例,用于链式调用
*/
public CollectionPropertyValidator<T, TElement> notEmpty() {
return notEmpty("The input must not be empty.");
public final CollectionPropertyValidator<T, E> notEmpty() {
return withRule(Conditions.notEmpty(), "The input must not be empty.");
}
/**
* 添加一条校验属性的规则,校验属性是否非空
*
* @param errMsg 异常信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public CollectionPropertyValidator<T, TElement> notEmpty(String errMsg) {
return notEmpty(convertToExceptionFunction(errMsg));
public final CollectionPropertyValidator<T, E> notEmpty(final String errorMessage) {
return withRule(Conditions.notEmpty(), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否非空
*
* @param <E> 自定义异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> CollectionPropertyValidator<T, TElement> notEmpty(
Supplier<E> e) {
return notEmpty(convertToExceptionFunction(e));
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> notEmpty(
final Supplier<X> exceptionSupplier) {
return withRule(Conditions.notEmpty(), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否非空
*
* @param <E> 自定义异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> CollectionPropertyValidator<T, TElement> notEmpty(
Function<Collection<TElement>, E> e) {
withRule(CollectionTools::isNotEmpty, e);
return this;
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> notEmpty(
final Function<Collection<E>, X> exceptionFunction) {
return withRule(Conditions.notEmpty(), exceptionFunction);
}
// ====== isEmpty =====
// ================================
// #endregion - notEmpty
// ================================
// ================================
// #region - isEmpty
// ================================
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @return 属性校验器
* @return 当前校验器实例,用于链式调用
*/
public CollectionPropertyValidator<T, TElement> isEmpty() {
return isEmpty("The input must be empty.");
public final CollectionPropertyValidator<T, E> isEmpty() {
return withRule(Conditions.isEmpty(), "The input must be empty.");
}
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @param errMsg 异常信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public CollectionPropertyValidator<T, TElement> isEmpty(String errMsg) {
return isEmpty(convertToExceptionFunction(errMsg));
public final CollectionPropertyValidator<T, E> isEmpty(
final String errorMessage) {
return withRule(Conditions.isEmpty(), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> CollectionPropertyValidator<T, TElement> isEmpty(
Supplier<E> e) {
return isEmpty(convertToExceptionFunction(e));
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> isEmpty(
final Supplier<X> exceptionSupplier) {
return withRule(Conditions.isEmpty(), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否为空
*
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> CollectionPropertyValidator<T, TElement> isEmpty(
Function<Collection<TElement>, E> e) {
withRule(CollectionTools::isEmpty, e);
return this;
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> isEmpty(
final Function<Collection<E>, X> exceptionFunction) {
return withRule(Conditions.isEmpty(), exceptionFunction);
}
// ================================
// #endregion - isEmpty
// ================================
// ================================
// #region - allMatch
// ================================
/**
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
*
* @param condition 校验条件
* @return 当前校验器实例,用于链式调用
*/
public final CollectionPropertyValidator<T, E> allMatch(
final Predicate<E> condition) {
return withRule(c -> c.forEach(element -> {
if (!condition.test(element)) {
throw ValidationException.withMessage("All elements must match the condition.");
}
}));
}
/**
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
* @param condition 校验条件
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public final CollectionPropertyValidator<T, E> allMatch(
final Predicate<E> condition, final String errorMessage) {
return withRule(c -> c.forEach(element -> {
if (!condition.test(element)) {
throw ValidationException.withMessage(errorMessage);
}
}));
}
/**
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
*
* @param <X> 自定义异常类型
* @param condition 校验条件
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> allMatch(
final Predicate<E> condition, final Supplier<X> exceptionSupplier) {
return withRule(c -> c.forEach(element -> {
if (!condition.test(element)) {
throw exceptionSupplier.get();
}
}));
}
/**
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
*
* @param <X> 自定义异常类型
* @param condition 校验条件
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> allMatch(
final Predicate<E> condition, final Function<E, X> exceptionFunction) {
return withRule(c -> c.forEach(element -> {
if (!condition.test(element)) {
throw exceptionFunction.apply(element);
}
}));
}
// ================================
// #endregion - allMatch
// ================================
// ================================
// #region - size
// ================================
/**
* 添加一条校验属性的规则,校验集合大小
*
* @param size 预期集合大小
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public final CollectionPropertyValidator<T, E> size(
final int size, final String errorMessage) {
return withRule(Conditions.size(size), errorMessage);
}
/**
* 添加一条校验属性的规则,校验集合大小
*
* @param <X> 自定义异常类型
* @param size 预期集合大小
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> size(
final int size, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.size(size), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验集合大小
*
* @param <X> 自定义异常类型
* @param size 预期集合大小
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> size(
final int size, final Function<Collection<E>, X> exceptionFunction) {
return withRule(Conditions.size(size), exceptionFunction);
}
/**
* 添加一条校验属性的规则,校验集合大小是否在指定范围内
*
* @param min 最小大小(包含)
* @param max 最大大小(包含)
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public final CollectionPropertyValidator<T, E> size(
final int min, final int max, final String errorMessage) {
return withRule(Conditions.size(min, max), errorMessage);
}
/**
* 添加一条校验属性的规则,校验集合大小是否在指定范围内
*
* @param <X> 自定义异常类型
* @param min 最小大小(包含)
* @param max 最大大小(包含)
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> size(
final int min, final int max, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.size(min, max), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验集合大小是否在指定范围内
*
* @param <X> 自定义异常类型
* @param min 最小大小(包含)
* @param max 最大大小(包含)
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> size(
final int min, final int max, final Function<Collection<E>, X> exceptionFunction) {
return withRule(Conditions.size(min, max), exceptionFunction);
}
// ================================
// #endregion - size
// ================================
private static class Conditions {
private static Predicate<Collection<?>> isEmpty() {
return CollectionTools::isEmpty;
}
private static Predicate<Collection<?>> notEmpty() {
return CollectionTools::isNotEmpty;
}
private static Predicate<Collection<?>> size(int size) {
AssertTools.checkArgument(size >= 0,
"The expected size must be non-negative.");
return collection -> collection == null || collection.size() == size;
}
private static Predicate<Collection<?>> size(int min, int max) {
AssertTools.checkArgument(min >= 0, "min must be non-negative.");
AssertTools.checkArgument(min <= max, "min must be less than or equal to max.");
return collection -> {
if (collection == null) {
return true;
}
int size = collection.size();
return size >= min && size <= max;
};
}
}
@Override
protected CollectionPropertyValidator<T, TElement> thisObject() {
protected CollectionPropertyValidator<T, E> thisObject() {
return this;
}
}

View File

@@ -19,15 +19,11 @@ package xyz.zhouxy.plusone.validator;
import java.util.function.Function;
/**
* 针对 {@code Comparable} 类型的默认属性校验器
* {@code Comparable} 类型属性校验器
*
* <p>
* 继承自 {@link BaseComparablePropertyValidator},内置了判断属性是否在给定区间内的校验规则。
*
* @param <T> 待校验对象类型
* @param <TProperty> 属性类型
* @param <TPropertyValidator> 当前属性校验器类型,用于链式调用
* @see Range
* @param <T> 待校验对象的类型
* @param <TProperty> 待校验属性的类型,必须实现 {@code Comparable} 接口
* @see com.google.common.collect.Range
* @author ZhouXY
*/
public class ComparablePropertyValidator<T, TProperty extends Comparable<TProperty>>

View File

@@ -17,14 +17,16 @@
package xyz.zhouxy.plusone.validator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* 浮点数属性校验器
* {@code Double} 类型属性校验器
*
* <p>
* 内置对 {@code Double} 类型常用的校验规则。
* 用于构建校验 {@code Double} 类型属性的规则
*
* @param <T> 待校验对象的类型
* @author ZhouXY
*/
public class DoublePropertyValidator<T>
@@ -42,46 +44,49 @@ public class DoublePropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param min 最小值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public DoublePropertyValidator<T> gt(double min) {
return gt(min, convertToExceptionFunction("The input must be greater than '%s'.", min));
public final DoublePropertyValidator<T> gt(final double min) {
return withRule(Conditions.greaterThan(min),
"The input must be greater than '%s'.", min);
}
/**
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param min 最小值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public DoublePropertyValidator<T> gt(double min, String errMsg) {
return gt(min, convertToExceptionFunction(errMsg));
public final DoublePropertyValidator<T> gt(
final double min, final String errorMessage) {
return withRule(Conditions.greaterThan(min), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 错误信息
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> DoublePropertyValidator<T> gt(double min, Supplier<E> e) {
return gt(min, convertToExceptionFunction(e));
public final <X extends RuntimeException> DoublePropertyValidator<T> gt(
final double min, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.greaterThan(min), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> DoublePropertyValidator<T> gt(double min, Function<Double, E> e) {
withRule(value -> (value != null && value > min), e);
return this;
public final <X extends RuntimeException> DoublePropertyValidator<T> gt(
final double min, final Function<Double, X> exceptionFunction) {
return withRule(Conditions.greaterThan(min), exceptionFunction);
}
// ================================
@@ -96,46 +101,49 @@ public class DoublePropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param min 最小值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public DoublePropertyValidator<T> ge(double min) {
return ge(min, convertToExceptionFunction("The input must be greater than or equal to '%s'.", min));
public final DoublePropertyValidator<T> ge(final double min) {
return withRule(Conditions.greaterThanOrEqualTo(min),
"The input must be greater than or equal to '%s'.", min);
}
/**
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param min 最小值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public DoublePropertyValidator<T> ge(double min, String errMsg) {
return ge(min, convertToExceptionFunction(errMsg));
public final DoublePropertyValidator<T> ge(
final double min, final String errorMessage) {
return withRule(Conditions.greaterThanOrEqualTo(min), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> DoublePropertyValidator<T> ge(double min, Supplier<E> e) {
return ge(min, convertToExceptionFunction(e));
public final <X extends RuntimeException> DoublePropertyValidator<T> ge(
final double min, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> DoublePropertyValidator<T> ge(double min, Function<Double, E> e) {
withRule(value -> (value != null && value >= min), e);
return this;
public final <X extends RuntimeException> DoublePropertyValidator<T> ge(
final double min, final Function<Double, X> exceptionFunction) {
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionFunction);
}
// ================================
@@ -150,46 +158,49 @@ public class DoublePropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param max 最大值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public DoublePropertyValidator<T> lt(double max) {
return lt(max, convertToExceptionFunction("The input must be less than '%s'.", max));
public final DoublePropertyValidator<T> lt(final double max) {
return withRule(Conditions.lessThan(max),
"The input must be less than '%s'.", max);
}
/**
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param max 最大值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public DoublePropertyValidator<T> lt(double max, String errMsg) {
return lt(max, convertToExceptionFunction(errMsg));
public final DoublePropertyValidator<T> lt(
final double max, final String errorMessage) {
return withRule(Conditions.lessThan(max), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> DoublePropertyValidator<T> lt(double max, Supplier<E> e) {
return lt(max, convertToExceptionFunction(e));
public final <X extends RuntimeException> DoublePropertyValidator<T> lt(
final double max, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.lessThan(max), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> DoublePropertyValidator<T> lt(double max, Function<Double, E> e) {
withRule(value -> (value != null && value < max), e);
return this;
public final <X extends RuntimeException> DoublePropertyValidator<T> lt(
final double max, final Function<Double, X> exceptionFunction) {
return withRule(Conditions.lessThan(max), exceptionFunction);
}
// ================================
@@ -204,46 +215,49 @@ public class DoublePropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param max 最大值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public DoublePropertyValidator<T> le(double max) {
return le(max, convertToExceptionFunction("The input must be less than or equal to '%s'.", max));
public final DoublePropertyValidator<T> le(final double max) {
return withRule(Conditions.lessThanOrEqualTo(max),
"The input must be less than or equal to '%s'.", max);
}
/**
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param max 最大值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public DoublePropertyValidator<T> le(double max, String errMsg) {
return le(max, convertToExceptionFunction(errMsg));
public final DoublePropertyValidator<T> le(
final double max, final String errorMessage) {
return withRule(Conditions.lessThanOrEqualTo(max), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> DoublePropertyValidator<T> le(double max, Supplier<E> e) {
return le(max, convertToExceptionFunction(e));
public final <X extends RuntimeException> DoublePropertyValidator<T> le(
final double max, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.lessThanOrEqualTo(max), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> DoublePropertyValidator<T> le(double max, Function<Double, E> e) {
withRule(value -> (value != null && value <= max), e);
return this;
public final <X extends RuntimeException> DoublePropertyValidator<T> le(
final double max, final Function<Double, X> exceptionFunction) {
return withRule(Conditions.lessThanOrEqualTo(max), exceptionFunction);
}
// ================================
@@ -254,4 +268,23 @@ public class DoublePropertyValidator<T>
protected DoublePropertyValidator<T> thisObject() {
return this;
}
private static class Conditions {
private static Predicate<Double> greaterThan(double min) {
return input -> input == null || input > min;
}
private static Predicate<Double> greaterThanOrEqualTo(double min) {
return input -> input == null || input >= min;
}
private static Predicate<Double> lessThan(double max) {
return input -> input == null || input < max;
}
private static Predicate<Double> lessThanOrEqualTo(double max) {
return input -> input == null || input <= max;
}
}
}

View File

@@ -18,14 +18,19 @@ package xyz.zhouxy.plusone.validator;
/**
* 校验器
*
* <p>
* 用于定义对特定类型对象的校验规则
* </p>
*
* @param <T> 待校验对象的类型
* @author ZhouXY
*/
public interface IValidator<T> {
/**
* 校验对象
* 校验指定对象是否符合预定义规则
*
* @param obj
* @param obj 待校验的对象实例
*/
void validate(T obj);
}

View File

@@ -17,14 +17,16 @@
package xyz.zhouxy.plusone.validator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* 整数属性校验器
* {@code Integer} 类型属性校验器
*
* <p>
* 内置对 {@code Integer} 类型常用的校验规则。
* 用于构建校验 {@code Integer} 类型属性的规则
*
* @param <T> 待校验对象的类型
* @author ZhouXY
*/
public class IntPropertyValidator<T>
@@ -42,46 +44,49 @@ public class IntPropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param min 最小值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public IntPropertyValidator<T> gt(int min) {
return gt(min, convertToExceptionFunction("The input must be greater than '%d'.", min));
public final IntPropertyValidator<T> gt(final int min) {
return withRule(Conditions.greaterThan(min),
"The input must be greater than '%d'.", min);
}
/**
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param min 最小值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public IntPropertyValidator<T> gt(int min, String errMsg) {
return gt(min, convertToExceptionFunction(errMsg));
public final IntPropertyValidator<T> gt(
final int min, final String errorMessage) {
return withRule(Conditions.greaterThan(min), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 错误信息
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> IntPropertyValidator<T> gt(int min, Supplier<E> e) {
return gt(min, convertToExceptionFunction(e));
public final <X extends RuntimeException> IntPropertyValidator<T> gt(
final int min, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.greaterThan(min), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> IntPropertyValidator<T> gt(int min, Function<Integer, E> e) {
withRule(value -> (value != null && value > min), e);
return this;
public final <X extends RuntimeException> IntPropertyValidator<T> gt(
final int min, final Function<Integer, X> exceptionFunction) {
return withRule(Conditions.greaterThan(min), exceptionFunction);
}
// ================================
@@ -96,46 +101,48 @@ public class IntPropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param min 最小值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public IntPropertyValidator<T> ge(int min) {
return ge(min, convertToExceptionFunction("The input must be greater than or equal to '%d'.", min));
public final IntPropertyValidator<T> ge(final int min) {
return withRule(Conditions.greaterThanOrEqualTo(min),
"The input must be greater than or equal to '%d'.", min);
}
/**
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param min 最小值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public IntPropertyValidator<T> ge(int min, String errMsg) {
return ge(min, convertToExceptionFunction(errMsg));
public final IntPropertyValidator<T> ge(final int min, final String errorMessage) {
return withRule(Conditions.greaterThanOrEqualTo(min), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> IntPropertyValidator<T> ge(int min, Supplier<E> e) {
return ge(min, convertToExceptionFunction(e));
public final <X extends RuntimeException> IntPropertyValidator<T> ge(
final int min, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> IntPropertyValidator<T> ge(int min, Function<Integer, E> e) {
withRule(value -> (value != null && value >= min), e);
return this;
public final <X extends RuntimeException> IntPropertyValidator<T> ge(
final int min, final Function<Integer, X> exceptionFunction) {
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionFunction);
}
// ================================
@@ -150,46 +157,49 @@ public class IntPropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param max 最大值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public IntPropertyValidator<T> lt(int max) {
return lt(max, convertToExceptionFunction("The input must be less than '%d'.", max));
public final IntPropertyValidator<T> lt(final int max) {
return withRule(Conditions.lessThan(max),
"The input must be less than '%d'.", max);
}
/**
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param max 最大值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public IntPropertyValidator<T> lt(int max, String errMsg) {
return lt(max, convertToExceptionFunction(errMsg));
public final IntPropertyValidator<T> lt(
final int max, final String errorMessage) {
return withRule(Conditions.lessThan(max), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> IntPropertyValidator<T> lt(int max, Supplier<E> e) {
return lt(max, convertToExceptionFunction(e));
public final <X extends RuntimeException> IntPropertyValidator<T> lt(
final int max, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.lessThan(max), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> IntPropertyValidator<T> lt(int max, Function<Integer, E> e) {
withRule(value -> (value != null && value < max), e);
return this;
public final <X extends RuntimeException> IntPropertyValidator<T> lt(
final int max, final Function<Integer, X> exceptionFunction) {
return withRule(Conditions.lessThan(max), exceptionFunction);
}
// ================================
@@ -204,46 +214,49 @@ public class IntPropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param max 最大值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public IntPropertyValidator<T> le(int max) {
return le(max, convertToExceptionFunction("The input must be less than or equal to '%d'.", max));
public final IntPropertyValidator<T> le(final int max) {
return withRule(Conditions.lessThanOrEqualTo(max),
"The input must be less than or equal to '%d'.", max);
}
/**
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param max 最大值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public IntPropertyValidator<T> le(int max, String errMsg) {
return le(max, convertToExceptionFunction(errMsg));
public final IntPropertyValidator<T> le(
final int max, final String errorMessage) {
return withRule(Conditions.lessThanOrEqualTo(max), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> IntPropertyValidator<T> le(int max, Supplier<E> e) {
return le(max, convertToExceptionFunction(e));
public final <X extends RuntimeException> IntPropertyValidator<T> le(
final int max, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.lessThanOrEqualTo(max), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> IntPropertyValidator<T> le(int max, Function<Integer, E> e) {
withRule(value -> (value != null && value <= max), e);
return this;
public final <X extends RuntimeException> IntPropertyValidator<T> le(
final int max, final Function<Integer, X> exceptionFunction) {
return withRule(Conditions.lessThanOrEqualTo(max), exceptionFunction);
}
// ================================
@@ -254,4 +267,23 @@ public class IntPropertyValidator<T>
protected IntPropertyValidator<T> thisObject() {
return this;
}
private static class Conditions {
private static Predicate<Integer> greaterThan(int min) {
return input -> input == null || input > min;
}
private static Predicate<Integer> greaterThanOrEqualTo(int min) {
return input -> input == null || input >= min;
}
private static Predicate<Integer> lessThan(int max) {
return input -> input == null || input < max;
}
private static Predicate<Integer> lessThanOrEqualTo(int max) {
return input -> input == null || input <= max;
}
}
}

View File

@@ -17,14 +17,16 @@
package xyz.zhouxy.plusone.validator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* 长整数属性校验器
* {@code Long} 类型属性校验器
*
* <p>
* 内置对 {@code Long} 类型常用的校验规则。
* 用于构建校验 {@code Long} 类型属性的规则
*
* @param <T> 待校验对象的类型
* @author ZhouXY
*/
public class LongPropertyValidator<T>
@@ -42,46 +44,49 @@ public class LongPropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param min 最小值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public LongPropertyValidator<T> gt(long min) {
return gt(min, convertToExceptionFunction("The input must be greater than '%d'.", min));
public final LongPropertyValidator<T> gt(final long min) {
return withRule(Conditions.greaterThan(min),
"The input must be greater than '%d'.", min);
}
/**
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param min 最小值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public LongPropertyValidator<T> gt(long min, String errMsg) {
return gt(min, convertToExceptionFunction(errMsg));
public final LongPropertyValidator<T> gt(
final long min, final String errorMessage) {
return withRule(Conditions.greaterThan(min), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 错误信息
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> LongPropertyValidator<T> gt(long min, Supplier<E> e) {
return gt(min, convertToExceptionFunction(e));
public final <X extends RuntimeException> LongPropertyValidator<T> gt(
final long min, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.greaterThan(min), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否大于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> LongPropertyValidator<T> gt(long min, Function<Long, E> e) {
withRule(value -> (value != null && value > min), e);
return this;
public final <X extends RuntimeException> LongPropertyValidator<T> gt(
final long min, final Function<Long, X> exceptionFunction) {
return withRule(Conditions.greaterThan(min), exceptionFunction);
}
// ================================
@@ -96,46 +101,48 @@ public class LongPropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param min 最小值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public LongPropertyValidator<T> ge(long min) {
return ge(min, convertToExceptionFunction("The input must be greater than or equal to '%d'.", min));
public final LongPropertyValidator<T> ge(final long min) {
return withRule(Conditions.greaterThanOrEqualTo(min),
"The input must be greater than or equal to '%d'.", min);
}
/**
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param min 最小值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public LongPropertyValidator<T> ge(long min, String errMsg) {
return ge(min, convertToExceptionFunction(errMsg));
public final LongPropertyValidator<T> ge(final long min, final String errorMessage) {
return withRule(Conditions.greaterThanOrEqualTo(min), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> LongPropertyValidator<T> ge(long min, Supplier<E> e) {
return ge(min, convertToExceptionFunction(e));
public final <X extends RuntimeException> LongPropertyValidator<T> ge(
final long min, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否大于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param min 最小值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> LongPropertyValidator<T> ge(long min, Function<Long, E> e) {
withRule(value -> (value != null && value >= min), e);
return this;
public final <X extends RuntimeException> LongPropertyValidator<T> ge(
final long min, final Function<Long, X> exceptionFunction) {
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionFunction);
}
// ================================
@@ -150,46 +157,49 @@ public class LongPropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param max 最大值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public LongPropertyValidator<T> lt(long max) {
return lt(max, convertToExceptionFunction("The input must be less than '%d'.", max));
public final LongPropertyValidator<T> lt(final long max) {
return withRule(Conditions.lessThan(max),
"The input must be less than '%d'.", max);
}
/**
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param max 最大值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public LongPropertyValidator<T> lt(long max, String errMsg) {
return lt(max, convertToExceptionFunction(errMsg));
public final LongPropertyValidator<T> lt(
final long max, final String errorMessage) {
return withRule(Conditions.lessThan(max), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> LongPropertyValidator<T> lt(long max, Supplier<E> e) {
return lt(max, convertToExceptionFunction(e));
public final <X extends RuntimeException> LongPropertyValidator<T> lt(
final long max, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.lessThan(max), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否小于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> LongPropertyValidator<T> lt(long max, Function<Long, E> e) {
withRule(value -> (value != null && value < max), e);
return this;
public final <X extends RuntimeException> LongPropertyValidator<T> lt(
final long max, final Function<Long, X> exceptionFunction) {
return withRule(Conditions.lessThan(max), exceptionFunction);
}
// ================================
@@ -204,46 +214,49 @@ public class LongPropertyValidator<T>
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param max 最大值
* @return 属性校验器
* @return 当前验证器实例,用于链式调用
*/
public LongPropertyValidator<T> le(long max) {
return le(max, convertToExceptionFunction("The input must be less than or equal to '%d'.", max));
public final LongPropertyValidator<T> le(final long max) {
return withRule(Conditions.lessThanOrEqualTo(max),
"The input must be less than or equal to '%d'.", max);
}
/**
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param max 最大值
* @param errMsg 错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前验证器实例,用于链式调用
*/
public LongPropertyValidator<T> le(long max, String errMsg) {
return le(max, convertToExceptionFunction(errMsg));
public final LongPropertyValidator<T> le(
final long max, final String errorMessage) {
return withRule(Conditions.lessThanOrEqualTo(max), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> LongPropertyValidator<T> le(long max, Supplier<E> e) {
return le(max, convertToExceptionFunction(e));
public final <X extends RuntimeException> LongPropertyValidator<T> le(
final long max, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.lessThanOrEqualTo(max), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否小于等于给定值
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param max 最大值
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前验证器实例,用于链式调用
*/
public <E extends RuntimeException> LongPropertyValidator<T> le(long max, Function<Long, E> e) {
withRule(value -> (value != null && value <= max), e);
return this;
public final <X extends RuntimeException> LongPropertyValidator<T> le(
final long max, final Function<Long, X> exceptionFunction) {
return withRule(Conditions.lessThanOrEqualTo(max), exceptionFunction);
}
// ================================
@@ -254,4 +267,23 @@ public class LongPropertyValidator<T>
protected LongPropertyValidator<T> thisObject() {
return this;
}
private static class Conditions {
private static Predicate<Long> greaterThan(long min) {
return input -> input == null || input > min;
}
private static Predicate<Long> greaterThanOrEqualTo(long min) {
return input -> input == null || input >= min;
}
private static Predicate<Long> lessThan(long max) {
return input -> input == null || input < max;
}
private static Predicate<Long> lessThanOrEqualTo(long max) {
return input -> input == null || input <= max;
}
}
}

View File

@@ -107,12 +107,14 @@ public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
/**
* 添加一个属性校验器,对指定 key 对应的 value 进行校验
*
* @param <T> 属性类型
* @param key key
* @return 属性校验器
*/
protected final ObjectPropertyValidator<Map<K, V>, V> ruleFor(K key) {
final Function<Map<K, V>, V> func = m -> m.get(key);
return ruleFor(func);
protected final <T extends V> ObjectPropertyValidator<Map<K, V>, T> ruleFor(K key) {
@SuppressWarnings("unchecked")
final Function<Map<K, V>, T> func = m -> (T) m.get(key);
return super.<T>ruleFor(func);
}
/**
@@ -190,6 +192,23 @@ public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
return ruleForCollection(getter);
}
/**
* 添加一个属性校验器,对指定的两个 key 对应的 value 进行校验
* @param <V1> 第1个属性的类型
* @param <V2> 第2个属性的类型
* @param k1 第1个 key
* @param k2 第2个 key
* @return 属性校验器
*/
protected final <V1 extends V, V2 extends V>
PairPropertyValidator<Map<K, V>, V1, V2> ruleForPair(K k1, K k2) {
@SuppressWarnings("unchecked")
final Function<Map<K, V>, V1> v1Getter = m -> (V1) m.get(k1);
@SuppressWarnings("unchecked")
final Function<Map<K, V>, V2> v2Getter = m -> (V2) m.get(k2);
return ruleFor(v1Getter, v2Getter);
}
// ================================
// #endregion - ruleFor
// ================================

View File

@@ -21,6 +21,8 @@ import java.util.function.Function;
/**
* 通用类型属性校验器。继承自 {@link BasePropertyValidator},包含针对属性的校验规则。
*
* @param <T> 待校验对象的类型
* @param <TProperty> 待校验属性的类型
* @author ZhouXY
*/
public class ObjectPropertyValidator<T, TProperty>

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.zhouxy.plusone.validator;
import java.util.Map.Entry;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* 针对二元组的属性校验器
*
* @param <T> 被验证对象类型
* @param <V1> 第一个元素的类型
* @param <V2> 第二个元素的类型
* @author ZhouXY
*/
public class PairPropertyValidator<T, V1, V2>
extends BasePropertyValidator<T, Entry<V1, V2>, PairPropertyValidator<T, V1, V2>> {
protected PairPropertyValidator(Function<T, ? extends Entry<V1, V2>> getter) {
super(getter);
}
/**
* 添加一条校验属性的规则,校验二元组是否满足给定的条件
*
* @param condition 校验条件
* @return 属性校验器
*/
public final PairPropertyValidator<T, V1, V2> must(BiPredicate<V1, V2> condition) {
return must(pair -> condition.test(pair.getKey(), pair.getValue()));
}
/**
* 添加一条校验属性的规则,校验二元组是否满足给定的条件
*
* @param condition 校验条件
* @param errorMessage 异常信息
* @return 属性校验器
*/
public final PairPropertyValidator<T, V1, V2> must(BiPredicate<V1, V2> condition, String errorMessage) {
return must(pair -> condition.test(pair.getKey(), pair.getValue()), errorMessage);
}
/**
* 添加一条校验属性的规则,校验二元组是否满足给定的条件
*
* @param <X> 自定义异常类型
* @param condition 校验条件
* @param exceptionSupplier 自定义异常
* @return 属性校验器
*/
public final <X extends RuntimeException> PairPropertyValidator<T, V1, V2> must(
BiPredicate<V1, V2> condition, Supplier<X> exceptionSupplier) {
return must(pair -> condition.test(pair.getKey(), pair.getValue()), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验二元组是否满足给定的条件
*
* @param <X> 自定义异常类型
* @param condition 校验条件
* @param exceptionFunction 自定义异常
* @return 属性校验器
*/
public final <X extends RuntimeException> PairPropertyValidator<T, V1, V2> must(
BiPredicate<V1, V2> condition, BiFunction<V1, V2, X> exceptionFunction) {
return must(pair -> condition.test(pair.getKey(), pair.getValue()),
pair -> exceptionFunction.apply(pair.getKey(), pair.getValue()));
}
@Override
protected PairPropertyValidator<T, V1, V2> thisObject() {
return this;
}
}

View File

@@ -17,26 +17,28 @@
package xyz.zhouxy.plusone.validator;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
import xyz.zhouxy.plusone.commons.util.ArrayTools;
import xyz.zhouxy.plusone.commons.util.AssertTools;
import xyz.zhouxy.plusone.commons.util.RegexTools;
import xyz.zhouxy.plusone.commons.util.StringTools;
/**
* StringPropertyValidator
* {@code String} 类型属性的校验器
*
* <p>
* 针对文本字段的校验器
* </p>
* 用于构建校验 {@code String} 类型属性的规则链
*
* @param <T> 待校验对象的类型
* @author ZhouXY
*/
public class StringPropertyValidator<T> extends BaseComparablePropertyValidator<T, String, StringPropertyValidator<T>> {
public class StringPropertyValidator<T>
extends BaseComparablePropertyValidator<T, String, StringPropertyValidator<T>> {
StringPropertyValidator(Function<T, String> getter) {
super(getter);
@@ -49,39 +51,39 @@ public class StringPropertyValidator<T> extends BaseComparablePropertyValidator<
/**
* 添加一条校验属性的规则,校验属性是否匹配正则表达式
*
* @param regex 正则表达式
* @param errMsg 异常信息
* @return 属性校验器
* @param pattern 正则表达式
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> matches(Pattern regex, String errMsg) {
return matches(regex, convertToExceptionFunction(errMsg));
public final StringPropertyValidator<T> matches(
final Pattern pattern, final String errorMessage) {
return withRule(Conditions.matches(pattern), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配正则表达式
*
* @param <E> 异常类型
* @param regex 正则表达式
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param pattern 正则表达式
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> matches(
Pattern regex, Supplier<E> e) {
return matches(regex, convertToExceptionFunction(e));
public <X extends RuntimeException> StringPropertyValidator<T> matches(
final Pattern pattern, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.matches(pattern), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配正则表达式
*
* @param <E> 异常类型
* @param regex 正则表达式
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param pattern 正则表达式
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> matches(
Pattern regex, Function<String, E> e) {
withRule(input -> (input == null || RegexTools.matches(input, regex)), e);
return this;
public final <X extends RuntimeException> StringPropertyValidator<T> matches(
final Pattern pattern, final Function<String, X> exceptionFunction) {
return withRule(Conditions.matches(pattern), exceptionFunction);
}
// ================================
@@ -89,87 +91,87 @@ public class StringPropertyValidator<T> extends BaseComparablePropertyValidator<
// ================================
// ================================
// #region - matchesOne
// #region - matchesAny
// ================================
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的多个正则表达式的其中一个
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
*
* @param regexs 正则表达式
* @param errMsg 异常信息
* @return 属性校验器
* @param patterns 正则表达式
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> matchesOne(Pattern[] regexs, String errMsg) {
return matchesOne(regexs, convertToExceptionFunction(errMsg));
public final StringPropertyValidator<T> matchesAny(
final Pattern[] patterns, final String errorMessage) {
return withRule(Conditions.matchesAny(patterns), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的多个正则表达式的其中一个
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
*
* @param <E> 异常类型
* @param regexs 正则表达式
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param patterns 正则表达式
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> matchesOne(
Pattern[] regexs, Supplier<E> e) {
return matchesOne(regexs, convertToExceptionFunction(e));
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAny(
final Pattern[] patterns, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.matchesAny(patterns), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的多个正则表达式的其中一个
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
*
* @param <E> 异常类型
* @param regexs 正则表达式
* @param e 自定义异常
* @return
* @param <X> 自定义异常类型
* @param patterns 正则表达式
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> matchesOne(
Pattern[] regexs, Function<String, E> e) {
withRule(input -> input == null || RegexTools.matchesOne(input, regexs), e);
return this;
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAny(
final Pattern[] patterns, final Function<String, X> exceptionFunction) {
return withRule(Conditions.matchesAny(patterns), exceptionFunction);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的多个正则表达式的其中一个
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
*
* @param regexs 正则表达式
* @param errMsg 异常信息
* @return 属性校验器
* @param patterns 正则表达式
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> matchesOne(List<Pattern> regexs, String errMsg) {
return matchesOne(regexs, convertToExceptionFunction(errMsg));
public final StringPropertyValidator<T> matchesAny(
final Collection<Pattern> patterns, final String errorMessage) {
return withRule(Conditions.matchesAny(patterns), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的多个正则表达式的其中一个
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
*
* @param <E> 异常类型
* @param regexs 正则表达式
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param patterns 正则表达式
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> matchesOne(
List<Pattern> regexs, Supplier<E> e) {
return matchesOne(regexs, convertToExceptionFunction(e));
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAny(
final Collection<Pattern> patterns, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.matchesAny(patterns), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的多个正则表达式的其中一个
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
*
* @param <E> 异常类型
* @param regexs 正则表达式
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param patterns 正则表达式
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> matchesOne(
List<Pattern> regexs, Function<String, E> e) {
withRule(input -> input == null || RegexTools.matchesOne(input, regexs.toArray(new Pattern[regexs.size()])), e);
return this;
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAny(
final Collection<Pattern> patterns, final Function<String, X> exceptionFunction) {
return withRule(Conditions.matchesAny(patterns), exceptionFunction);
}
// ================================
// #endregion - matchesOne
// #endregion - matchesAny
// ================================
// ================================
@@ -179,77 +181,77 @@ public class StringPropertyValidator<T> extends BaseComparablePropertyValidator<
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
*
* @param regexs 正则表达式
* @param errMsg 异常信息
* @return 属性校验器
* @param patterns 正则表达式
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> matchesAll(Pattern[] regexs, String errMsg) {
return matchesAll(regexs, convertToExceptionFunction(errMsg));
public final StringPropertyValidator<T> matchesAll(
final Pattern[] patterns, final String errorMessage) {
return withRule(Conditions.matchesAll(patterns), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
*
* @param <E> 异常类型
* @param regexs 正则表达式
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param patterns 正则表达式
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> matchesAll(
Pattern[] regexs, Supplier<E> e) {
return matchesAll(regexs, convertToExceptionFunction(e));
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAll(
final Pattern[] patterns, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.matchesAll(patterns), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
*
* @param <E> 异常类型
* @param regexs 正则表达式
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param patterns 正则表达式
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> matchesAll(
Pattern[] regexs, Function<String, E> e) {
withRule(input -> input == null || RegexTools.matchesAll(input, regexs), e);
return this;
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAll(
final Pattern[] patterns, final Function<String, X> exceptionFunction) {
return withRule(Conditions.matchesAll(patterns), exceptionFunction);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
*
* @param regexs 正则表达式
* @param errMsg 异常信息
* @return 属性校验器
* @param patterns 正则表达式
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> matchesAll(Collection<Pattern> regexs, String errMsg) {
return matchesAll(regexs, convertToExceptionFunction(errMsg));
public final StringPropertyValidator<T> matchesAll(
final Collection<Pattern> patterns, final String errorMessage) {
return withRule(Conditions.matchesAll(patterns), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
*
* @param <E> 异常类型
* @param regexs 正则表达式
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param patterns 正则表达式
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> matchesAll(
Collection<Pattern> regexs, Supplier<E> e) {
return matchesAll(regexs, convertToExceptionFunction(e));
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAll(
final Collection<Pattern> patterns, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.matchesAll(patterns), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
*
* @param <E> 异常类型
* @param regexs 正则表达式
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param patterns 正则表达式
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> matchesAll(
Collection<Pattern> regexs, Function<String, E> e) {
withRule(input -> input == null || RegexTools.matchesAll(input, regexs.toArray(new Pattern[regexs.size()])), e);
return this;
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAll(
final Collection<Pattern> patterns, final Function<String, X> exceptionFunction) {
return withRule(Conditions.matchesAll(patterns), exceptionFunction);
}
// ================================
@@ -263,43 +265,45 @@ public class StringPropertyValidator<T> extends BaseComparablePropertyValidator<
/**
* 添加一条校验属性的规则,校验属性是否不为空白字符串
*
* @return 属性校验器
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> notBlank() {
return notBlank("The input must not be blank.");
public final StringPropertyValidator<T> notBlank() {
return withRule(Conditions.notBlank(),
"The input must not be blank.");
}
/**
* 添加一条校验属性的规则,校验属性是否不为空白字符串
*
* @param errMsg 异常信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> notBlank(String errMsg) {
return notBlank(convertToExceptionFunction(errMsg));
public final StringPropertyValidator<T> notBlank(final String errorMessage) {
return withRule(Conditions.notBlank(), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否不为空白字符串
*
* @param <E> 异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> notBlank(Supplier<E> e) {
return notBlank(convertToExceptionFunction(e));
public final <X extends RuntimeException> StringPropertyValidator<T> notBlank(
final Supplier<X> exceptionSupplier) {
return withRule(Conditions.notBlank(), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否不为空白字符串
*
* @param <E> 异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> notBlank(Function<String, E> e) {
withRule(StringTools::isNotBlank, e);
return this;
public final <X extends RuntimeException> StringPropertyValidator<T> notBlank(
final Function<String, X> exceptionFunction) {
return withRule(Conditions.notBlank(), exceptionFunction);
}
// ================================
@@ -311,45 +315,47 @@ public class StringPropertyValidator<T> extends BaseComparablePropertyValidator<
// ================================
/**
* 添加一条校验属性的规则,校验属性是否是邮箱地址
* 添加一条校验属性的规则,校验属性是否满足邮箱格式
*
* @return 属性校验器
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> emailAddress() {
return emailAddress("The input is not a valid email address.");
public final StringPropertyValidator<T> emailAddress() {
return withRule(Conditions.emailAddress(),
"The input is not a valid email address.");
}
/**
* 添加一条校验属性的规则,校验属性是否是邮箱地址
* 添加一条校验属性的规则,校验属性是否满足邮箱格式
*
* @param errMsg 校验失败的错误信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> emailAddress(String errMsg) {
return emailAddress(convertToExceptionFunction(errMsg));
public final StringPropertyValidator<T> emailAddress(final String errorMessage) {
return withRule(Conditions.emailAddress(), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性是否是邮箱地址
* 添加一条校验属性的规则,校验属性是否满足邮箱格式
*
* @param <E> 异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> emailAddress(Supplier<E> e) {
return emailAddress(convertToExceptionFunction(e));
public final <X extends RuntimeException> StringPropertyValidator<T> emailAddress(
final Supplier<X> exceptionSupplier) {
return withRule(Conditions.emailAddress(), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性是否是邮箱地址
* 添加一条校验属性的规则,校验属性是否满足邮箱格式
*
* @param <E> 异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> emailAddress(
Function<String, E> e) {
return matches(PatternConsts.EMAIL, e);
public final <X extends RuntimeException> StringPropertyValidator<T> emailAddress(
final Function<String, X> exceptionFunction) {
return withRule(Conditions.emailAddress(), exceptionFunction);
}
// ================================
@@ -363,44 +369,45 @@ public class StringPropertyValidator<T> extends BaseComparablePropertyValidator<
/**
* 添加一条校验属性的规则,校验字符串属性是否不为空
*
* @return 属性校验器
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> notEmpty() {
return notEmpty("The input must not be empty.");
public final StringPropertyValidator<T> notEmpty() {
return withRule(Conditions.notEmpty(),
"The input must not be empty.");
}
/**
* 添加一条校验属性的规则,校验字符串属性是否不为空
*
* @param errMsg 异常信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> notEmpty(String errMsg) {
return notEmpty(convertToExceptionFunction(errMsg));
public final StringPropertyValidator<T> notEmpty(final String errorMessage) {
return withRule(Conditions.notEmpty(), errorMessage);
}
/**
* 添加一条校验属性的规则,校验字符串属性是否不为空
*
* @param <E> 异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> notEmpty(Supplier<E> e) {
return notEmpty(convertToExceptionFunction(e));
public final <X extends RuntimeException> StringPropertyValidator<T> notEmpty(
final Supplier<X> exceptionSupplier) {
return withRule(Conditions.notEmpty(), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验字符串属性是否不为空
*
* @param <E> 异常类型
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> notEmpty(
Function<String, E> e) {
withRule(s -> s != null && !s.isEmpty(), e);
return this;
public final <X extends RuntimeException> StringPropertyValidator<T> notEmpty(
final Function<String, X> exceptionFunction) {
return withRule(Conditions.notEmpty(), exceptionFunction);
}
// ================================
@@ -415,87 +422,79 @@ public class StringPropertyValidator<T> extends BaseComparablePropertyValidator<
* 添加一条校验属性的规则,校验属性长度是否等于指定长度
*
* @param length 指定长度
* @param errMsg 异常信息
* @return 属性校验器
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> length(int length, String errMsg) {
return length(length, convertToExceptionFunction(errMsg));
public final StringPropertyValidator<T> length(
final int length, final String errorMessage) {
return withRule(Conditions.length(length), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性长度是否等于指定长度
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param length 指定长度
* @param e 自定义异常
* @return 属性校验器
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> length(int length, Supplier<E> e) {
return length(length, convertToExceptionFunction(e));
public final <X extends RuntimeException> StringPropertyValidator<T> length(
final int length, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.length(length), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性长度是否等于指定长度
*
* @param <E> 异常类型
* @param <X> 自定义异常类型
* @param length 指定长度
* @param e 自定义异常
* @return 属性校验器
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> length(int length, Function<String, E> e) {
AssertTools.checkArgument(length >= 0,
"The expected length must be greater than or equal to 0.");
withRule(s -> s == null || s.length() == length, e);
return this;
}
static boolean length(String str, int min, int max) {
if (str == null) {
return true;
}
final int len = str.length();
return len >= min && len <= max;
public final <X extends RuntimeException> StringPropertyValidator<T> length(
final int length, final Function<String, X> exceptionFunction) {
return withRule(Conditions.length(length), exceptionFunction);
}
/**
* 添加一条校验属性的规则,校验属性的长度范围
*
* @param min 最小长度
* @param max 最大长度
* @param errMsg 错误信息
* @return 属性校验器
* @param min 最小长度(包含)
* @param max 最大长度(包含)
* @param errorMessage 异常信息
* @return 当前校验器实例,用于链式调用
*/
public StringPropertyValidator<T> length(int min, int max, String errMsg) {
return length(min, max, convertToExceptionFunction(errMsg));
public final StringPropertyValidator<T> length(
final int min, final int max, final String errorMessage) {
return withRule(Conditions.length(min, max), errorMessage);
}
/**
* 添加一条校验属性的规则,校验属性的长度范围
*
* @param min 最小长度
* @param max长度
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param min长度(包含)
* @param max 最大长度(包含)
* @param exceptionSupplier 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> length(int min, int max,
Supplier<E> e) {
return length(min, max, convertToExceptionFunction(e));
public final <X extends RuntimeException> StringPropertyValidator<T> length(
final int min, final int max, final Supplier<X> exceptionSupplier) {
return withRule(Conditions.length(min, max), exceptionSupplier);
}
/**
* 添加一条校验属性的规则,校验属性的长度范围
*
* @param min 最小长度
* @param max长度
* @param e 自定义异常
* @return 属性校验器
* @param <X> 自定义异常类型
* @param min长度(包含)
* @param max 最大长度(包含)
* @param exceptionFunction 自定义异常
* @return 当前校验器实例,用于链式调用
*/
public <E extends RuntimeException> StringPropertyValidator<T> length(int min, int max,
Function<String, E> e) {
AssertTools.checkArgument(min >= 0, "min must be non-negative.");
AssertTools.checkArgument(min <= max, "min must be less than or equal to max.");
withRule(s -> length(s, min, max), e);
return this;
public final <X extends RuntimeException> StringPropertyValidator<T> length(
final int min, final int max, final Function<String, X> exceptionFunction) {
return withRule(Conditions.length(min, max), exceptionFunction);
}
// ================================
@@ -506,4 +505,63 @@ public class StringPropertyValidator<T> extends BaseComparablePropertyValidator<
protected StringPropertyValidator<T> thisObject() {
return this;
}
private static class Conditions {
private static Predicate<String> notEmpty() {
return StringTools::isNotEmpty;
}
private static Predicate<String> notBlank() {
return StringTools::isNotBlank;
}
private static Predicate<String> matches(Pattern pattern) {
AssertTools.checkArgumentNotNull(pattern);
return input -> input == null || RegexTools.matches(input, pattern);
}
private static Predicate<String> matchesAny(Pattern[] patterns) {
AssertTools.checkArgument(ArrayTools.isAllElementsNotNull(patterns));
return input -> input == null || RegexTools.matchesAny(input, patterns);
}
private static Predicate<String> matchesAny(Collection<Pattern> patterns) {
AssertTools.checkArgumentNotNull(patterns, "patterns must not be null.");
return input -> input == null || RegexTools.matchesAny(input, patterns.toArray(new Pattern[0]));
}
private static Predicate<String> matchesAll(Pattern[] patterns) {
AssertTools.checkArgument(ArrayTools.isAllElementsNotNull(patterns));
return input -> input == null || RegexTools.matchesAll(input, patterns);
}
private static Predicate<String> matchesAll(Collection<Pattern> patterns) {
AssertTools.checkArgumentNotNull(patterns, "patterns must not be null.");
return input -> input == null || RegexTools.matchesAll(input, patterns.toArray(new Pattern[0]));
}
private static Predicate<String> emailAddress() {
return input -> input == null || RegexTools.matches(input, PatternConsts.EMAIL);
}
private static Predicate<String> length(int length) {
AssertTools.checkArgument(length >= 0,
"The expected length must be non-negative.");
return input -> input == null || input.length() == length;
}
private static Predicate<String> length(int min, int max) {
AssertTools.checkArgument(min >= 0, "min must be non-negative.");
AssertTools.checkArgument(min <= max, "min must be less than or equal to max.");
return input -> {
if (input == null) {
return true;
}
final int len = input.length();
return len >= min && len <= max;
};
}
}
}

View File

@@ -16,7 +16,7 @@
package xyz.zhouxy.plusone.validator;
/**
* 验失败异常
* 验失败异常
*
* @author ZhouXY
*/
@@ -39,51 +39,51 @@ public class ValidationException extends RuntimeException {
}
/**
* 创建一个验证失败异常
* 创建 {@code ValidationException} 实例
*
* @return 异常
* @return {@code ValidationException} 实例
*/
public static ValidationException withDefaultMessage() {
return new ValidationException(DEFAULT_MESSAGE);
}
/**
* 创建一个验证失败异常
* 创建 {@code ValidationException} 实例
*
* @param message 错误信息
* @return 异常
* @param message 异常信息
* @return {@code ValidationException} 实例
*/
public static ValidationException withMessage(String message) {
return new ValidationException(message);
}
/**
* 创建一个验证失败异常
* 创建 {@code ValidationException} 实例
*
* @param errorMessageTemplate 错误信息模
* @param errorMessageArgs 错误信息参数
* @return 异常
* @param errorMessageTemplate 异常信息模
* @param errorMessageArgs 异常信息参数列表
* @return {@code ValidationException} 实例
*/
public static ValidationException withMessage(String errorMessageTemplate, Object... errorMessageArgs) {
return new ValidationException(String.format(errorMessageTemplate, errorMessageArgs));
}
/**
* 创建一个验证失败异常
* 创建 {@code ValidationException} 实例
*
* @param cause 错误 cause
* @return 异常
* @param cause 导致校验失败的根本异常
* @return {@code ValidationException} 实例
*/
public static ValidationException withCause(Throwable cause) {
return new ValidationException(cause);
}
/**
* 创建一个验证失败异常
* 创建 {@code ValidationException} 实例
*
* @param message 错误信息
* @param cause 错误 cause
* @return 异常
* @param message 异常信息
* @param cause 导致校验失败的根本异常
* @return {@code ValidationException} 实例
*/
public static ValidationException withMessageAndCause(String message, Throwable cause) {
return new ValidationException(message, cause);

View File

@@ -16,6 +16,7 @@
package xyz.zhouxy.plusone.example;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
/**
@@ -30,13 +31,14 @@ public class ExampleCommand {
private LocalDateTime dateTimeProperty;
private Foo objectProperty;
private List<String> stringListProperty;
private String[] stringArrayProperty;
public ExampleCommand() {
}
public ExampleCommand(Boolean boolProperty, Integer intProperty, Long longProperty, Double doubleProperty,
String stringProperty, LocalDateTime dateTimeProperty, Foo objectProperty,
List<String> stringListProperty) {
List<String> stringListProperty, String[] stringArrayProperty) {
this.boolProperty = boolProperty;
this.intProperty = intProperty;
this.longProperty = longProperty;
@@ -45,6 +47,7 @@ public class ExampleCommand {
this.dateTimeProperty = dateTimeProperty;
this.objectProperty = objectProperty;
this.stringListProperty = stringListProperty;
this.stringArrayProperty = stringArrayProperty;
}
public Boolean getBoolProperty() {
@@ -111,11 +114,20 @@ public class ExampleCommand {
this.stringListProperty = stringListProperty;
}
public String[] getStringArrayProperty() {
return stringArrayProperty;
}
public void setStringArrayProperty(String[] stringArrayProperty) {
this.stringArrayProperty = stringArrayProperty;
}
@Override
public String toString() {
return "ExampleCommand [boolProperty=" + boolProperty + ", intProperty=" + intProperty + ", longProperty="
+ longProperty + ", doubleProperty=" + doubleProperty + ", stringProperty=" + stringProperty
+ ", dateTimeProperty=" + dateTimeProperty + ", objectProperty=" + objectProperty
+ ", stringListProperty=" + stringListProperty + "]";
+ ", stringListProperty=" + stringListProperty + ", stringArrayProperty="
+ Arrays.toString(stringArrayProperty) + "]";
}
}

View File

@@ -0,0 +1,516 @@
/*
* Copyright 2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.zhouxy.plusone.example.validator;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import xyz.zhouxy.plusone.ExampleException;
import xyz.zhouxy.plusone.example.ExampleCommand;
import xyz.zhouxy.plusone.validator.BaseValidator;
import xyz.zhouxy.plusone.validator.IValidator;
import xyz.zhouxy.plusone.validator.ValidationException;
public class ArrayPropertyValidatorTests {
static final String MESSAGE_NOT_EMPTY = "The stringArrayProperty should not be empty.";
static final String MESSAGE_EMPTY = "The stringArrayProperty should be empty.";
// ================================
// #region - notEmpty
// ================================
@Test
void notEmpty_stringListIsNotEmpty() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty).notEmpty();
ruleForArray(ExampleCommand::getStringArrayProperty).notEmpty(MESSAGE_NOT_EMPTY);
ruleForArray(ExampleCommand::getStringArrayProperty)
.notEmpty(() -> ExampleException.withMessage(MESSAGE_NOT_EMPTY));
ruleForArray(ExampleCommand::getStringArrayProperty)
.notEmpty(strList -> ExampleException.withMessage(
"The stringArrayProperty should not be empty, but it is %s.", Arrays.toString(strList)));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] {"A", "B", "C"});
assertDoesNotThrow(() -> validator.validate(command));
}
@Test
void notEmpty_default_stringListIsEmpty() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty).notEmpty();
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] {});
ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command));
assertEquals("The input must not be empty.", e.getMessage());
}
@Test
void notEmpty_message_stringListIsEmpty() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty).notEmpty(MESSAGE_NOT_EMPTY);
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] {});
ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_NOT_EMPTY, e.getMessage());
}
@Test
void notEmpty_exceptionSupplier_stringListIsEmpty() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.notEmpty(() -> ExampleException.withMessage(MESSAGE_NOT_EMPTY));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] {});
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_NOT_EMPTY, e.getMessage());
}
@Test
void notEmpty_exceptionFunction_stringListIsEmpty() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.notEmpty(strList -> ExampleException.withMessage(
"The stringArrayProperty should not be empty, but it is %s.", Arrays.toString(strList)));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] {});
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
assertEquals("The stringArrayProperty should not be empty, but it is [].", e.getMessage());
}
@Test
void notEmpty_message_stringListIsNull() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty).notEmpty(MESSAGE_NOT_EMPTY);
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(null);
ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_NOT_EMPTY, e.getMessage());
}
@Test
void notEmpty_exceptionSupplier_stringListIsNull() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.notEmpty(() -> ExampleException.withMessage(MESSAGE_NOT_EMPTY));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(null);
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_NOT_EMPTY, e.getMessage());
}
@Test
void notEmpty_exceptionFunction_stringListIsNull() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.notEmpty(strList -> ExampleException.withMessage(
"The stringArrayProperty should not be empty, but it is %s.", Arrays.toString(strList)));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(null);
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
assertEquals("The stringArrayProperty should not be empty, but it is null.", e.getMessage());
}
// ================================
// #endregion - notEmpty
// ================================
// ================================
// #region - isEmpty
// ================================
@Test
void isEmpty_stringListIsEmpty() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty).isEmpty();
ruleForArray(ExampleCommand::getStringArrayProperty).isEmpty(MESSAGE_EMPTY);
ruleForArray(ExampleCommand::getStringArrayProperty)
.isEmpty(() -> ExampleException.withMessage(MESSAGE_EMPTY));
ruleForArray(ExampleCommand::getStringArrayProperty)
.isEmpty(strList -> ExampleException.withMessage(
"The stringArrayProperty should be empty, but it is %s.", Arrays.toString(strList)));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] {});
assertDoesNotThrow(() -> validator.validate(command));
}
@Test
void isEmpty_stringListIsNull() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty).isEmpty();
ruleForArray(ExampleCommand::getStringArrayProperty).isEmpty(MESSAGE_EMPTY);
ruleForArray(ExampleCommand::getStringArrayProperty)
.isEmpty(() -> ExampleException.withMessage(MESSAGE_EMPTY));
ruleForArray(ExampleCommand::getStringArrayProperty)
.isEmpty(strList -> ExampleException.withMessage(
"The stringArrayProperty should be empty, but it is %s.", Arrays.toString(strList)));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(null);
assertDoesNotThrow(() -> validator.validate(command));
}
@Test
void isEmpty_default_stringListIsNotEmpty() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty).isEmpty();
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] { "A", "B", "C" });
ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command));
assertEquals("The input must be empty.", e.getMessage());
}
@Test
void isEmpty_message_stringListIsNotEmpty() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty).isEmpty(MESSAGE_EMPTY);
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] { "A", "B", "C" });
ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_EMPTY, e.getMessage());
}
@Test
void isEmpty_exceptionSupplier_stringListIsNotEmpty() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.isEmpty(() -> ExampleException.withMessage(MESSAGE_EMPTY));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] { "A", "B", "C" });
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_EMPTY, e.getMessage());
}
@Test
void isEmpty_exceptionFunction_stringListIsNotEmpty() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.isEmpty(strList -> ExampleException.withMessage(
"The stringArrayProperty should be empty, but it is %s.", Arrays.toString(strList)));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] { "A", "B", "C" });
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
assertEquals("The stringArrayProperty should be empty, but it is [A, B, C].", e.getMessage());
}
// ================================
// #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<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.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 = exampleCommandWithStringArrayProperty(new String[] { "1234", "12345", "123456" });
assertDoesNotThrow(() -> validator.validate(command));
}
@Test
void allMatch_default_invalidInput() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.allMatch(str -> checkStringLength(str, 4, 6));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] { 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<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.allMatch(str -> checkStringLength(str, 4, 6),
"String length must in the interval [4,6].");
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] { "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<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.allMatch(str -> checkStringLength(str, 4, 6),
() -> ExampleException.withMessage("String length must in the interval [4,6]."));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] { "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<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.allMatch(str -> checkStringLength(str, 4, 6),
str -> ExampleException.withMessage("Validation failed: '%s'.", str));
}
};
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] { "1234", "12345", "123456", "1234567" });
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
assertEquals("Validation failed: '1234567'.", e.getMessage());
}
// ================================
// #endregion - allMatch
// ================================
// ================================
// #region - length
// ================================
private static final int MIN_LENGTH = 6;
private static final int MAX_LENGTH = 8;
@Test
void length_specifiedLength_validLength() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.length(MIN_LENGTH, "The length of the array must be 6")
.length(MIN_LENGTH, () -> ExampleException.withMessage("The length of the array must be 6"))
.length(MIN_LENGTH, arr -> ExampleException.withMessage("The length of the array must be 6, but it was %d", arr.length));
}
};
ExampleCommand validCommand = exampleCommandWithStringArrayProperty(6);
assertDoesNotThrow(() -> validator.validate(validCommand));
ExampleCommand commandWithNullStringProperty = exampleCommandWithStringArrayProperty(null);
assertDoesNotThrow(() -> validator.validate(commandWithNullStringProperty));
}
@ParameterizedTest
@ValueSource(ints = { 0, 1, 2, 3, 4, 5, 7, 8, 9, 10 })
void length_specifiedLength_invalidLength(int length) {
ExampleCommand command = exampleCommandWithStringArrayProperty(length);
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.length(MIN_LENGTH, "The length of the array must be 6");
}
};
ValidationException eWithSpecifiedMessage = assertThrows(
ValidationException.class,
() -> ruleWithMessage.validate(command));
assertEquals("The length of the array must be 6", eWithSpecifiedMessage.getMessage());
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.length(MIN_LENGTH, () -> ExampleException.withMessage("The length of the array must be 6"));
}
};
ExampleException specifiedException = assertThrows(
ExampleException.class,
() -> ruleWithExceptionSupplier.validate(command));
assertEquals("The length of the array must be 6", specifiedException.getMessage());
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.length(MIN_LENGTH, arr -> ExampleException.withMessage("The length of the array must be 6, but it was %d", arr.length));
}
};
ExampleException specifiedException2 = assertThrows(
ExampleException.class,
() -> ruleWithExceptionFunction.validate(command));
assertEquals(
String.format("The length of the array must be 6, but it was %d", length),
specifiedException2.getMessage());
}
@ParameterizedTest
@ValueSource(ints = { 6, 7, 8 })
void length_specifiedMinLengthAndMaxLength_validLength(int length) {
ExampleCommand command = exampleCommandWithStringArrayProperty(length);
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.length(MIN_LENGTH, MAX_LENGTH, String.format("Min length is %d, max length is %d", MIN_LENGTH, MAX_LENGTH))
.length(MIN_LENGTH, MAX_LENGTH, () -> ExampleException.withMessage("Min length is %d, max length is %d", MIN_LENGTH, MAX_LENGTH))
.length(MIN_LENGTH, MAX_LENGTH, arr -> ExampleException.withMessage("Length of stringArrayProperty is %d, min length is %d, max length is %d", arr.length, MIN_LENGTH, MAX_LENGTH));
}
};
assertDoesNotThrow(() -> validator.validate(command));
}
@Test
void length_specifiedMinLengthAndMaxLength_null() {
ExampleCommand command = exampleCommandWithStringArrayProperty(null);
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.length(MIN_LENGTH, MAX_LENGTH, String.format("Min length is %d, max length is %d", MIN_LENGTH, MAX_LENGTH))
.length(MIN_LENGTH, MAX_LENGTH, () -> ExampleException.withMessage("Min length is %d, max length is %d", MIN_LENGTH, MAX_LENGTH))
.length(MIN_LENGTH, MAX_LENGTH, arr -> ExampleException.withMessage("Length of stringArrayProperty is %d, min length is %d, max length is %d", arr.length, MIN_LENGTH, MAX_LENGTH));
}
};
assertDoesNotThrow(() -> validator.validate(command));
}
@ParameterizedTest
@ValueSource(ints = { 0, 1, 2, 3, 4, 5, 9, 10, 11, 12 })
void length_specifiedMinLengthAndMaxLength_invalidLength(int length) {
ExampleCommand command = exampleCommandWithStringArrayProperty(length);
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.length(MIN_LENGTH, MAX_LENGTH, String.format("Min length is %d, max length is %d", MIN_LENGTH, MAX_LENGTH));
}
};
ValidationException eWithSpecifiedMessage = assertThrows(
ValidationException.class,
() -> ruleWithMessage.validate(command));
assertEquals("Min length is 6, max length is 8", eWithSpecifiedMessage.getMessage());
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.length(MIN_LENGTH, MAX_LENGTH, () -> ExampleException.withMessage("Min length is %d, max length is %d", MIN_LENGTH, MAX_LENGTH));
}
};
ExampleException specifiedException = assertThrows(
ExampleException.class,
() -> ruleWithExceptionSupplier.validate(command));
assertEquals("Min length is 6, max length is 8", specifiedException.getMessage());
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleForArray(ExampleCommand::getStringArrayProperty)
.length(MIN_LENGTH, MAX_LENGTH, arr -> ExampleException.withMessage("Length of stringArrayProperty is %d, min length is %d, max length is %d", arr.length, MIN_LENGTH, MAX_LENGTH));
}
};
ExampleException specifiedException2 = assertThrows(
ExampleException.class,
() -> ruleWithExceptionFunction.validate(command));
assertEquals(
String.format("Length of stringArrayProperty is %d, min length is %d, max length is %d", length, MIN_LENGTH, MAX_LENGTH),
specifiedException2.getMessage());
}
// ================================
// #endregion - length
// ================================
static ExampleCommand exampleCommandWithStringArrayProperty(String[] property) {
ExampleCommand exampleCommand = new ExampleCommand();
exampleCommand.setStringArrayProperty(property);
return exampleCommand;
}
static ExampleCommand exampleCommandWithStringArrayProperty(int specifiedLength) {
ExampleCommand exampleCommand = new ExampleCommand();
String[] arr = new String[specifiedLength];
Arrays.fill(arr, "a");
exampleCommand.setStringArrayProperty(arr);
return exampleCommand;
}
}

View File

@@ -20,10 +20,13 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import com.google.common.collect.Lists;
@@ -271,9 +274,247 @@ 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<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
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<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
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<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
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<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
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<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
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
// ================================
// ================================
// #region - size
// ================================
private static final int MIN_SIZE = 6;
private static final int MAX_SIZE = 8;
@Test
void size_specifiedSize_validSize() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForCollection(ExampleCommand::getStringListProperty)
.size(MIN_SIZE, "The size of the collection must be 6")
.size(MIN_SIZE, () -> ExampleException.withMessage("The size of the collection must be 6"))
.size(MIN_SIZE, c -> ExampleException.withMessage("The size of the collection must be 6, but it was %d", c.size()));
}
};
ExampleCommand validCommand = exampleCommandWithStringListProperty(6);
assertDoesNotThrow(() -> validator.validate(validCommand));
ExampleCommand commandWithNullStringProperty = exampleCommandWithStringListProperty(null);
assertDoesNotThrow(() -> validator.validate(commandWithNullStringProperty));
}
@ParameterizedTest
@ValueSource(ints = { 0, 1, 2, 3, 4, 5, 7, 8, 9, 10 })
void size_specifiedSize_invalidSize(int size) {
ExampleCommand command = exampleCommandWithStringListProperty(size);
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleForCollection(ExampleCommand::getStringListProperty)
.size(MIN_SIZE, "The size of the collection must be 6");
}
};
ValidationException eWithSpecifiedMessage = assertThrows(
ValidationException.class,
() -> ruleWithMessage.validate(command));
assertEquals("The size of the collection must be 6", eWithSpecifiedMessage.getMessage());
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleForCollection(ExampleCommand::getStringListProperty)
.size(MIN_SIZE, () -> ExampleException.withMessage("The size of the collection must be 6"));
}
};
ExampleException specifiedException = assertThrows(
ExampleException.class,
() -> ruleWithExceptionSupplier.validate(command));
assertEquals("The size of the collection must be 6", specifiedException.getMessage());
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleForCollection(ExampleCommand::getStringListProperty)
.size(MIN_SIZE, c -> ExampleException.withMessage("The size of the collection must be 6, but it was %d", c.size()));
}
};
ExampleException specifiedException2 = assertThrows(
ExampleException.class,
() -> ruleWithExceptionFunction.validate(command));
assertEquals(
String.format("The size of the collection must be 6, but it was %d", size),
specifiedException2.getMessage());
}
@ParameterizedTest
@ValueSource(ints = { 6, 7, 8 })
void size_specifiedMinSizeAndMaxSize_validSize(int size) {
ExampleCommand command = exampleCommandWithStringListProperty(size);
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForCollection(ExampleCommand::getStringListProperty)
.size(MIN_SIZE, MAX_SIZE, String.format("Min size is %d, max size is %d", MIN_SIZE, MAX_SIZE))
.size(MIN_SIZE, MAX_SIZE, () -> ExampleException.withMessage("Min size is %d, max size is %d", MIN_SIZE, MAX_SIZE))
.size(MIN_SIZE, MAX_SIZE, c -> ExampleException.withMessage("Size of stringCollectionProperty is %d, min size is %d, max size is %d", c.size(), MIN_SIZE, MAX_SIZE));
}
};
assertDoesNotThrow(() -> validator.validate(command));
}
@Test
void size_specifiedMinSizeAndMaxSize_null() {
ExampleCommand command = exampleCommandWithStringListProperty(null);
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForCollection(ExampleCommand::getStringListProperty)
.size(MIN_SIZE, MAX_SIZE, String.format("Min size is %d, max size is %d", MIN_SIZE, MAX_SIZE))
.size(MIN_SIZE, MAX_SIZE, () -> ExampleException.withMessage("Min size is %d, max size is %d", MIN_SIZE, MAX_SIZE))
.size(MIN_SIZE, MAX_SIZE, c -> ExampleException.withMessage("Size of stringCollectionProperty is %d, min size is %d, max size is %d", c.size(), MIN_SIZE, MAX_SIZE));
}
};
assertDoesNotThrow(() -> validator.validate(command));
}
@ParameterizedTest
@ValueSource(ints = { 0, 1, 2, 3, 4, 5, 9, 10, 11, 12 })
void size_specifiedMinSizeAndMaxSize_invalidSize(int size) {
ExampleCommand command = exampleCommandWithStringListProperty(size);
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleForCollection(ExampleCommand::getStringListProperty)
.size(MIN_SIZE, MAX_SIZE, String.format("Min size is %d, max size is %d", MIN_SIZE, MAX_SIZE));
}
};
ValidationException eWithSpecifiedMessage = assertThrows(
ValidationException.class,
() -> ruleWithMessage.validate(command));
assertEquals("Min size is 6, max size is 8", eWithSpecifiedMessage.getMessage());
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleForCollection(ExampleCommand::getStringListProperty)
.size(MIN_SIZE, MAX_SIZE, () -> ExampleException.withMessage("Min size is %d, max size is %d", MIN_SIZE, MAX_SIZE));
}
};
ExampleException specifiedException = assertThrows(
ExampleException.class,
() -> ruleWithExceptionSupplier.validate(command));
assertEquals("Min size is 6, max size is 8", specifiedException.getMessage());
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleForCollection(ExampleCommand::getStringListProperty)
.size(MIN_SIZE, MAX_SIZE, c -> ExampleException.withMessage("Size of stringCollectionProperty is %d, min size is %d, max size is %d", c.size(), MIN_SIZE, MAX_SIZE));
}
};
ExampleException specifiedException2 = assertThrows(
ExampleException.class,
() -> ruleWithExceptionFunction.validate(command));
assertEquals(
String.format("Size of stringCollectionProperty is %d, min size is %d, max size is %d", size, MIN_SIZE, MAX_SIZE),
specifiedException2.getMessage());
}
// ================================
// #endregion - size
// ================================
static ExampleCommand exampleCommandWithStringListProperty(List<String> property) {
ExampleCommand exampleCommand = new ExampleCommand();
exampleCommand.setStringListProperty(property);
return exampleCommand;
}
static ExampleCommand exampleCommandWithStringListProperty(int specifiedSize) {
ExampleCommand exampleCommand = new ExampleCommand();
String[] arr = new String[specifiedSize];
Arrays.fill(arr, "a");
exampleCommand.setStringListProperty(Arrays.asList(arr));
return exampleCommand;
}
}

View File

@@ -65,8 +65,9 @@ public class ComparablePropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithComparableProperty(18, 10000000000L, MIN);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -156,89 +157,6 @@ public class ComparablePropertyValidatorTests {
// #endregion - not in the interval
// ================================
// ================================
// #region - null
// ================================
@Test
void inRange_default_valueIsNull() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForComparable(ExampleCommand::getDateTimeProperty)
.inRange(DATE_TIME_RANGE);
}
};
ExampleCommand command = exampleCommandWithComparableProperty(null, null, null);
ValidationException e = assertThrows(
ValidationException.class,
() -> validator.validate(command));
final String expected = String.format("The input must in the interval %s. You entered null.", DATE_TIME_RANGE);
assertEquals(expected, e.getMessage());
}
@Test
void inRange_message_valueIsNull() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForComparable(ExampleCommand::getDateTimeProperty)
.inRange(DATE_TIME_RANGE, MESSAGE);
}
};
ExampleCommand command = exampleCommandWithComparableProperty(null, null, null);
ValidationException e = assertThrows(
ValidationException.class,
() -> validator.validate(command));
assertEquals(MESSAGE, e.getMessage());
}
@Test
void inRange_exceptionSupplier_valueIsNull() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForComparable(ExampleCommand::getDateTimeProperty)
.inRange(DATE_TIME_RANGE, () -> ExampleException.withMessage(MESSAGE));
}
};
ExampleCommand command = exampleCommandWithComparableProperty(null, null, null);
ExampleException e = assertThrows(
ExampleException.class,
() -> validator.validate(command));
assertEquals(MESSAGE, e.getMessage());
}
@Test
void inRange_exceptionFunction_valueIsNull() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForComparable(ExampleCommand::getDateTimeProperty)
.inRange(DATE_TIME_RANGE, property -> ExampleException.withMessage(
"The dateTimeProperty should in the interval [%s,%s), but it is %s", MIN, MAX, property));
}
};
ExampleCommand command = exampleCommandWithComparableProperty(null, null, null);
ExampleException e = assertThrows(
ExampleException.class,
() -> validator.validate(command));
final String expected = String.format("The dateTimeProperty should in the interval [%s,%s), but it is null", MIN, MAX);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - null
// ================================
static ExampleCommand exampleCommandWithComparableProperty(
Integer intProperty,
Long longProperty,

View File

@@ -18,7 +18,6 @@ package xyz.zhouxy.plusone.example.validator;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -61,8 +60,9 @@ public class DoublePropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithDoubleProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -147,80 +147,6 @@ public class DoublePropertyValidatorTests {
// #endregion - gt_invalidValue
// ================================
// ================================
// #region - gt_null
// ================================
@Test
void gt_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.gt(MIN);
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be greater than '%s'.", MIN), e.getMessage());
}
@Test
void gt_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.gt(MIN, MESSAGE_GT);
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GT, e.getMessage());
}
@Test
void gt_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.gt(MIN, () -> ExampleException.withMessage(MESSAGE_GT));
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GT, e.getMessage());
}
@Test
void gt_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.gt(MIN, property -> ExampleException.withMessage(
"The doubleProperty should be greater than %s, but it is %s", MIN, property));
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The doubleProperty should be greater than %s, but it is null", MIN);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - gt_null
// ================================
// ================================
// #region - ge_validValue
// ================================
@@ -243,8 +169,9 @@ public class DoublePropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithDoubleProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -329,80 +256,6 @@ public class DoublePropertyValidatorTests {
// #endregion - ge_invalidValue
// ================================
// ================================
// #region - ge_null
// ================================
@Test
void ge_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.ge(MIN);
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be greater than or equal to '%s'.", MIN), e.getMessage());
}
@Test
void ge_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.ge(MIN, MESSAGE_GE);
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GE, e.getMessage());
}
@Test
void ge_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.ge(MIN, () -> ExampleException.withMessage(MESSAGE_GE));
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GE, e.getMessage());
}
@Test
void ge_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.ge(MIN, property -> ExampleException.withMessage(
"The doubleProperty should be greater than or equal to %s, but it is %s", MIN, property));
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The doubleProperty should be greater than or equal to %s, but it is null", MIN);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - ge_null
// ================================
// ================================
// #region - lt_validValue
// ================================
@@ -425,8 +278,9 @@ public class DoublePropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithDoubleProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -511,80 +365,6 @@ public class DoublePropertyValidatorTests {
// #endregion - lt_invalidValue
// ================================
// ================================
// #region - lt_null
// ================================
@Test
void lt_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.lt(MAX);
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be less than '%s'.", MAX), e.getMessage());
}
@Test
void lt_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.lt(MAX, MESSAGE_LT);
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LT, e.getMessage());
}
@Test
void lt_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.lt(MAX, () -> ExampleException.withMessage(MESSAGE_LT));
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LT, e.getMessage());
}
@Test
void lt_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.lt(MAX, property -> ExampleException.withMessage(
"The doubleProperty should be less than %s, but it is %s", MAX, property));
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The doubleProperty should be less than %s, but it is null", MAX);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - lt_null
// ================================
// ================================
// #region - le_validValue
// ================================
@@ -607,8 +387,9 @@ public class DoublePropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithDoubleProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -693,80 +474,6 @@ public class DoublePropertyValidatorTests {
// #endregion - le_invalidValue
// ================================
// ================================
// #region - le_null
// ================================
@Test
void le_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.le(MAX);
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be less than or equal to '%s'.", MAX), e.getMessage());
}
@Test
void le_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.le(MAX, MESSAGE_LE);
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LE, e.getMessage());
}
@Test
void le_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.le(MAX, () -> ExampleException.withMessage(MESSAGE_LE));
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LE, e.getMessage());
}
@Test
void le_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForDouble(ExampleCommand::getDoubleProperty)
.le(MAX, property -> ExampleException.withMessage(
"The doubleProperty should be less than or equal to %s, but it is %s", MAX, property));
}
};
ExampleCommand command = exampleCommandWithDoubleProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The doubleProperty should be less than or equal to %s, but it is null", MAX);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - le_null
// ================================
static ExampleCommand exampleCommandWithDoubleProperty(Double doubleProperty) {
ExampleCommand exampleCommand = new ExampleCommand();
exampleCommand.setDoubleProperty(doubleProperty);

View File

@@ -17,7 +17,6 @@ package xyz.zhouxy.plusone.example.validator;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -60,8 +59,9 @@ public class IntPropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithIntProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -146,80 +146,6 @@ public class IntPropertyValidatorTests {
// #endregion - gt_invalidValue
// ================================
// ================================
// #region - gt_null
// ================================
@Test
void gt_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.gt(MIN);
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be greater than '%d'.", MIN), e.getMessage());
}
@Test
void gt_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.gt(MIN, MESSAGE_GT);
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GT, e.getMessage());
}
@Test
void gt_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.gt(MIN, () -> ExampleException.withMessage(MESSAGE_GT));
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GT, e.getMessage());
}
@Test
void gt_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.gt(MIN, property -> ExampleException.withMessage(
"The intProperty should be greater than %d, but it is %d", MIN, property));
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The intProperty should be greater than %d, but it is null", MIN);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - gt_null
// ================================
// ================================
// #region - ge_validValue
// ================================
@@ -242,8 +168,9 @@ public class IntPropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithIntProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -328,80 +255,6 @@ public class IntPropertyValidatorTests {
// #endregion - ge_invalidValue
// ================================
// ================================
// #region - ge_null
// ================================
@Test
void ge_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.ge(MIN);
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be greater than or equal to '%d'.", MIN), e.getMessage());
}
@Test
void ge_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.ge(MIN, MESSAGE_GE);
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GE, e.getMessage());
}
@Test
void ge_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.ge(MIN, () -> ExampleException.withMessage(MESSAGE_GE));
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GE, e.getMessage());
}
@Test
void ge_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.ge(MIN, property -> ExampleException.withMessage(
"The intProperty should be greater than or equal to %d, but it is %d", MIN, property));
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The intProperty should be greater than or equal to %d, but it is null", MIN);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - ge_null
// ================================
// ================================
// #region - lt_validValue
// ================================
@@ -424,8 +277,9 @@ public class IntPropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithIntProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -510,80 +364,6 @@ public class IntPropertyValidatorTests {
// #endregion - lt_invalidValue
// ================================
// ================================
// #region - lt_null
// ================================
@Test
void lt_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.lt(MAX);
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be less than '%d'.", MAX), e.getMessage());
}
@Test
void lt_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.lt(MAX, MESSAGE_LT);
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LT, e.getMessage());
}
@Test
void lt_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.lt(MAX, () -> ExampleException.withMessage(MESSAGE_LT));
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LT, e.getMessage());
}
@Test
void lt_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.lt(MAX, property -> ExampleException.withMessage(
"The intProperty should be less than %d, but it is %d", MAX, property));
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The intProperty should be less than %d, but it is null", MAX);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - lt_null
// ================================
// ================================
// #region - le_validValue
// ================================
@@ -606,8 +386,9 @@ public class IntPropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithIntProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -692,80 +473,6 @@ public class IntPropertyValidatorTests {
// #endregion - le_invalidValue
// ================================
// ================================
// #region - le_null
// ================================
@Test
void le_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.le(MAX);
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be less than or equal to '%d'.", MAX), e.getMessage());
}
@Test
void le_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.le(MAX, MESSAGE_LE);
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LE, e.getMessage());
}
@Test
void le_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.le(MAX, () -> ExampleException.withMessage(MESSAGE_LE));
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LE, e.getMessage());
}
@Test
void le_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForInt(ExampleCommand::getIntProperty)
.le(MAX, property -> ExampleException.withMessage(
"The intProperty should be less than or equal to %d, but it is %d", MAX, property));
}
};
ExampleCommand command = exampleCommandWithIntProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The intProperty should be less than or equal to %d, but it is null", MAX);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - le_null
// ================================
static ExampleCommand exampleCommandWithIntProperty(Integer intProperty) {
ExampleCommand exampleCommand = new ExampleCommand();
exampleCommand.setIntProperty(intProperty);

View File

@@ -17,7 +17,6 @@ package xyz.zhouxy.plusone.example.validator;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -61,8 +60,9 @@ public class LongPropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithLongProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -147,80 +147,6 @@ public class LongPropertyValidatorTests {
// #endregion - gt_invalidValue
// ================================
// ================================
// #region - gt_null
// ================================
@Test
void gt_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.gt(MIN);
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be greater than '%d'.", MIN), e.getMessage());
}
@Test
void gt_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.gt(MIN, MESSAGE_GT);
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GT, e.getMessage());
}
@Test
void gt_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.gt(MIN, () -> ExampleException.withMessage(MESSAGE_GT));
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GT, e.getMessage());
}
@Test
void gt_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.gt(MIN, property -> ExampleException.withMessage(
"The longProperty should be greater than %d, but it is %d", MIN, property));
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The longProperty should be greater than %d, but it is null", MIN);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - gt_null
// ================================
// ================================
// #region - ge_validValue
// ================================
@@ -243,8 +169,9 @@ public class LongPropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithLongProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -329,80 +256,6 @@ public class LongPropertyValidatorTests {
// #endregion - ge_invalidValue
// ================================
// ================================
// #region - ge_null
// ================================
@Test
void ge_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.ge(MIN);
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be greater than or equal to '%d'.", MIN), e.getMessage());
}
@Test
void ge_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.ge(MIN, MESSAGE_GE);
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GE, e.getMessage());
}
@Test
void ge_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.ge(MIN, () -> ExampleException.withMessage(MESSAGE_GE));
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_GE, e.getMessage());
}
@Test
void ge_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.ge(MIN, property -> ExampleException.withMessage(
"The longProperty should be greater than or equal to %d, but it is %d", MIN, property));
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The longProperty should be greater than or equal to %d, but it is null", MIN);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - ge_null
// ================================
// ================================
// #region - lt_validValue
// ================================
@@ -425,8 +278,9 @@ public class LongPropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithLongProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -511,80 +365,6 @@ public class LongPropertyValidatorTests {
// #endregion - lt_invalidValue
// ================================
// ================================
// #region - lt_null
// ================================
@Test
void lt_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.lt(MAX);
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be less than '%d'.", MAX), e.getMessage());
}
@Test
void lt_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.lt(MAX, MESSAGE_LT);
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LT, e.getMessage());
}
@Test
void lt_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.lt(MAX, () -> ExampleException.withMessage(MESSAGE_LT));
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LT, e.getMessage());
}
@Test
void lt_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.lt(MAX, property -> ExampleException.withMessage(
"The longProperty should be less than %d, but it is %d", MAX, property));
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The longProperty should be less than %d, but it is null", MAX);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - lt_null
// ================================
// ================================
// #region - le_validValue
// ================================
@@ -607,8 +387,9 @@ public class LongPropertyValidatorTests {
};
ExampleCommand command = exampleCommandWithLongProperty(value);
assertDoesNotThrow(() -> validator.validate(command));
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
}
// ================================
@@ -693,80 +474,6 @@ public class LongPropertyValidatorTests {
// #endregion - le_invalidValue
// ================================
// ================================
// #region - le_null
// ================================
@Test
void le_default_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.le(MAX);
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(String.format("The input must be less than or equal to '%d'.", MAX), e.getMessage());
}
@Test
void le_message_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.le(MAX, MESSAGE_LE);
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ValidationException e = assertThrows(
ValidationException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LE, e.getMessage());
}
@Test
void le_exceptionSupplier_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.le(MAX, () -> ExampleException.withMessage(MESSAGE_LE));
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
assertEquals(MESSAGE_LE, e.getMessage());
}
@Test
void le_exceptionFunction_null() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForLong(ExampleCommand::getLongProperty)
.le(MAX, property -> ExampleException.withMessage(
"The longProperty should be less than or equal to %d, but it is %d", MAX, property));
}
};
ExampleCommand command = exampleCommandWithLongProperty(null);
ExampleException e = assertThrows(
ExampleException.class, () -> validator.validate(command));
final String expected = String.format("The longProperty should be less than or equal to %d, but it is null", MAX);
assertEquals(expected, e.getMessage());
}
// ================================
// #endregion - le_null
// ================================
static ExampleCommand exampleCommandWithLongProperty(Long longProperty) {
ExampleCommand exampleCommand = new ExampleCommand();
exampleCommand.setLongProperty(longProperty);

View File

@@ -20,18 +20,16 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.time.DateTimeException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Objects;
import org.junit.jupiter.api.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import xyz.zhouxy.plusone.ExampleException;
import xyz.zhouxy.plusone.commons.collection.CollectionTools;
import xyz.zhouxy.plusone.commons.util.DateTimeTools;
import xyz.zhouxy.plusone.commons.function.PredicateTools;
import xyz.zhouxy.plusone.commons.util.StringTools;
import xyz.zhouxy.plusone.example.ExampleCommand;
import xyz.zhouxy.plusone.example.Foo;
@@ -41,114 +39,6 @@ import xyz.zhouxy.plusone.validator.ValidationException;
public class ObjectPropertyValidatorTests {
// ================================
// #region - withRule
// ================================
@Test
void withRule_validInput() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getBoolProperty)
.notNull("The boolProperty cannot be null.")
.withRule(Boolean.TRUE::equals);
ruleFor(ExampleCommand::getIntProperty)
.withRule(intProperty -> intProperty > 0, "The intProperty should be greater than 0.");
ruleFor(ExampleCommand::getLongProperty)
.withRule(longProperty -> longProperty > 0L,
() -> ExampleException.withMessage("The longProperty should be greater than 0."));
ruleFor(ExampleCommand::getDoubleProperty)
.withRule(doubleProperty -> doubleProperty > 0.00,
doubleProperty -> ExampleException.withMessage("The doubleProperty should be greater than 0, but it was: %s", doubleProperty));
ruleFor(ExampleCommand::getStringProperty)
.notNull()
.withRule(stringProperty -> stringProperty.length() > 2,
() -> ExampleException.withMessage("The length of stringProperty should be greater than 2."));
ruleFor(ExampleCommand::getDateTimeProperty)
.withRule(DateTimeTools::isFuture,
() -> new DateTimeException("The dateTimeProperty should be a future time."));
ruleFor(ExampleCommand::getObjectProperty)
.notNull("The objectProperty cannot be null.");
ruleFor(ExampleCommand::getStringListProperty)
.withRule(CollectionTools::isNotEmpty, "The stringListProperty cannot be empty.");
withRule(command -> {
Foo objectProperty = command.getObjectProperty();
if (!Objects.equals(command.getIntProperty(), objectProperty.getIntProperty())) {
throw ExampleException.withMessage("intProperty invalid.");
}
});
}
};
ExampleCommand command = new ExampleCommand(
true,
Integer.MAX_VALUE,
Long.MAX_VALUE,
Double.MAX_VALUE,
"StringValue",
LocalDateTime.now().plusDays(1),
new Foo(Integer.MAX_VALUE, "StringValue"),
Lists.newArrayList("ABC", "DEF"));
assertDoesNotThrow(() -> validator.validate(command));
}
@Test
void withRule_invalidInputs() {
ExampleCommand command = new ExampleCommand();
IValidator<ExampleCommand> ruleWithDefaultMessage = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getObjectProperty)
.withRule(x -> false);
}
};
ValidationException eWithDefaultMessage = assertThrows(
ValidationException.class, () -> ruleWithDefaultMessage.validate(command));
assertEquals(ValidationException.DEFAULT_MESSAGE, eWithDefaultMessage.getMessage());
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getObjectProperty)
.withRule(x -> false, "invalid input.");
}
};
ValidationException eWithMessage = assertThrows(
ValidationException.class, () -> ruleWithMessage.validate(command));
assertEquals("invalid input.", eWithMessage.getMessage());
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getObjectProperty)
.withRule(x -> false, () -> ExampleException.withMessage("invalid input."));
}
};
ExampleException specifiedException = assertThrows(
ExampleException.class, () -> ruleWithExceptionSupplier.validate(command));
assertEquals("invalid input.", specifiedException.getMessage());
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getObjectProperty)
.withRule(x -> false, x -> ExampleException.withMessage("invalid input: [%s].", x));
}
};
ExampleException specifiedException2 = assertThrows(
ExampleException.class, () -> ruleWithExceptionFunction.validate(command));
assertEquals("invalid input: [null].", specifiedException2.getMessage());
}
// ================================
// #endregion - withRule
// ================================
// ================================
// #region - notNull
// ================================
@@ -157,22 +47,24 @@ public class ObjectPropertyValidatorTests {
void notNull_validInput() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForBool(ExampleCommand::getBoolProperty)
ruleFor(ExampleCommand::getBoolProperty)
.notNull();
ruleForInt(ExampleCommand::getIntProperty)
ruleFor(ExampleCommand::getIntProperty)
.notNull("The intProperty cannot be null");
ruleForLong(ExampleCommand::getLongProperty)
ruleFor(ExampleCommand::getLongProperty)
.notNull(() -> ExampleException.withMessage("The longProperty cannot be null"));
ruleForDouble(ExampleCommand::getDoubleProperty)
ruleFor(ExampleCommand::getDoubleProperty)
.notNull(d -> ExampleException.withMessage("The doubleProperty cannot be null, but it was %s", d));
ruleForString(ExampleCommand::getStringProperty)
ruleFor(ExampleCommand::getStringProperty)
.notNull();
ruleForComparable(ExampleCommand::getDateTimeProperty)
ruleFor(ExampleCommand::getDateTimeProperty)
.notNull("The dateTimeProperty cannot be null");
ruleFor(ExampleCommand::getObjectProperty)
.notNull(() -> ExampleException.withMessage("The objectProperty cannot be null"));
ruleForCollection(ExampleCommand::getStringListProperty)
ruleFor(ExampleCommand::getStringListProperty)
.notNull(d -> ExampleException.withMessage("The stringListProperty cannot be null, but it was %s", d));
ruleFor(ExampleCommand::getStringArrayProperty)
.notNull(d -> ExampleException.withMessage("The stringListProperty cannot be null, but it was %s", Arrays.toString(d)));
}
};
ExampleCommand command = new ExampleCommand(
@@ -183,7 +75,8 @@ public class ObjectPropertyValidatorTests {
"StringValue",
LocalDateTime.now().plusDays(1),
new Foo(Integer.MAX_VALUE, "StringValue"),
Lists.newArrayList("ABC", "DEF"));
Lists.newArrayList("ABC", "DEF"),
new String[] { "ABC", "DEF" });
assertDoesNotThrow(() -> validator.validate(command));
}
@@ -245,22 +138,24 @@ public class ObjectPropertyValidatorTests {
void isNull_validInput() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForBool(ExampleCommand::getBoolProperty)
ruleFor(ExampleCommand::getBoolProperty)
.isNull();
ruleForInt(ExampleCommand::getIntProperty)
ruleFor(ExampleCommand::getIntProperty)
.isNull("The intProperty should be null");
ruleForLong(ExampleCommand::getLongProperty)
ruleFor(ExampleCommand::getLongProperty)
.isNull(() -> ExampleException.withMessage("The longProperty should be null"));
ruleForDouble(ExampleCommand::getDoubleProperty)
ruleFor(ExampleCommand::getDoubleProperty)
.isNull(d -> ExampleException.withMessage("The doubleProperty should be null, but it was %s", d));
ruleForString(ExampleCommand::getStringProperty)
ruleFor(ExampleCommand::getStringProperty)
.isNull();
ruleForComparable(ExampleCommand::getDateTimeProperty)
ruleFor(ExampleCommand::getDateTimeProperty)
.isNull("The dateTimeProperty should be null");
ruleFor(ExampleCommand::getObjectProperty)
.isNull(() -> ExampleException.withMessage("The objectProperty should be null"));
ruleForCollection(ExampleCommand::getStringListProperty)
ruleFor(ExampleCommand::getStringListProperty)
.isNull(d -> ExampleException.withMessage("The stringListProperty should be null, but it was %s", d));
ruleFor(ExampleCommand::getStringArrayProperty)
.isNull(d -> ExampleException.withMessage("The stringListProperty should be null, but it was %s", Arrays.toString(d)));
}
};
ExampleCommand command = new ExampleCommand();
@@ -319,36 +214,39 @@ public class ObjectPropertyValidatorTests {
// ================================
// ================================
// #region - equalTo
// #region - equal
// ================================
@Test
void equalTo_validInput() {
void equal_validInput() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.equalTo("Foo")
.equalTo("Foo", "The stringProperty should be equal to 'Foo'.")
.equalTo("Foo", () ->
.equal("Foo")
.equal("Foo", "The stringProperty should be equal to 'Foo'.")
.equal("Foo", () ->
ExampleException.withMessage("The stringProperty should be equal to 'Foo'."))
.equalTo("Foo", str ->
.equal("Foo", str ->
ExampleException.withMessage("The stringProperty should be equal to 'Foo', but is was '%s'.", str));
}
};
ExampleCommand command = new ExampleCommand();
command.setStringProperty("Foo");
command.setStringProperty(null);
assertDoesNotThrow(() -> validator.validate(command));
command.setStringProperty("Foo");
assertDoesNotThrow(() -> validator.validate(command));
}
@Test
void equalTo_invalidInput() {
void equal_invalidInput() {
ExampleCommand command = new ExampleCommand();
command.setStringProperty("Bar");
IValidator<ExampleCommand> defaultRule = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo");
ruleForString(ExampleCommand::getStringProperty).equal("Foo");
}
};
ValidationException eWithDefaultMessage = assertThrows(
@@ -357,7 +255,7 @@ public class ObjectPropertyValidatorTests {
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
ruleForString(ExampleCommand::getStringProperty).equal("Foo",
"The stringProperty should be equal to 'Foo'.");
}
};
@@ -367,7 +265,7 @@ public class ObjectPropertyValidatorTests {
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
ruleForString(ExampleCommand::getStringProperty).equal("Foo",
() -> ExampleException.withMessage("The stringProperty should be equal to 'Foo'."));
}
};
@@ -377,7 +275,7 @@ public class ObjectPropertyValidatorTests {
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
ruleForString(ExampleCommand::getStringProperty).equal("Foo",
str -> ExampleException.withMessage("The stringProperty should be equal to 'Foo', but is was '%s'.", str));
}
};
@@ -386,52 +284,83 @@ public class ObjectPropertyValidatorTests {
assertEquals("The stringProperty should be equal to 'Foo', but is was 'Bar'.", specifiedException2.getMessage());
}
// ================================
// #endregion - equal
// ================================
// ================================
// #region - notEqual
// ================================
@Test
void equalTo_nullInput() {
void notEqual_validInput() {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.notEqual("Foo")
.notEqual("Foo", "The stringProperty should not equal 'Foo'.")
.notEqual("Foo", () ->
ExampleException.withMessage("The stringProperty should not equal 'Foo'."))
.notEqual("Foo", str ->
ExampleException.withMessage("The stringProperty should not equal 'Foo', but is was '%s'.", str));
}
};
ExampleCommand command = new ExampleCommand();
command.setStringProperty(null);
assertDoesNotThrow(() -> validator.validate(command));
command.setStringProperty("Bar");
assertDoesNotThrow(() -> validator.validate(command));
}
@Test
void notEqual_invalidInput() {
ExampleCommand command = new ExampleCommand();
command.setStringProperty("Foo");
IValidator<ExampleCommand> defaultRule = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo");
ruleForString(ExampleCommand::getStringProperty).notEqual("Foo");
}
};
ValidationException eWithDefaultMessage = assertThrows(
ValidationException.class, () -> defaultRule.validate(command));
assertEquals("The input must be equal to 'Foo'.", eWithDefaultMessage.getMessage());
assertEquals("The input must not equal 'Foo'.", eWithDefaultMessage.getMessage());
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
"The stringProperty should be equal to 'Foo'.");
ruleForString(ExampleCommand::getStringProperty).notEqual("Foo",
"The stringProperty should not equal 'Foo'.");
}
};
ValidationException eWithSpecifiedMessage = assertThrows(
ValidationException.class, () -> ruleWithMessage.validate(command));
assertEquals("The stringProperty should be equal to 'Foo'.", eWithSpecifiedMessage.getMessage());
assertEquals("The stringProperty should not equal 'Foo'.", eWithSpecifiedMessage.getMessage());
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
() -> ExampleException.withMessage("The stringProperty should be equal to 'Foo'."));
ruleForString(ExampleCommand::getStringProperty).notEqual("Foo",
() -> ExampleException.withMessage("The stringProperty should not equal 'Foo'."));
}
};
ExampleException specifiedException = assertThrows(
ExampleException.class, () -> ruleWithExceptionSupplier.validate(command));
assertEquals("The stringProperty should be equal to 'Foo'.", specifiedException.getMessage());
assertEquals("The stringProperty should not equal 'Foo'.", specifiedException.getMessage());
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
str -> ExampleException.withMessage("The stringProperty should be equal to 'Foo', but is was '%s'.", str));
ruleForString(ExampleCommand::getStringProperty).notEqual("Foo",
str -> ExampleException.withMessage("The stringProperty should not equal 'Foo', but is was '%s'.", str));
}
};
ExampleException specifiedException2 = assertThrows(
ExampleException.class, () -> ruleWithExceptionFunction.validate(command));
assertEquals("The stringProperty should be equal to 'Foo', but is was 'null'.", specifiedException2.getMessage());
assertEquals("The stringProperty should not equal 'Foo', but is was 'Foo'.", specifiedException2.getMessage());
}
// ================================
// #endregion - equalTo
// #endregion - notEqual
// ================================
// ================================
@@ -511,10 +440,10 @@ public class ObjectPropertyValidatorTests {
IValidator<ExampleCommand> ruleWithDefaultMessage = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.must(ImmutableList.of(StringTools::isNotEmpty, str -> Objects.equals(str, "Foo")))
.must(ImmutableList.of(StringTools::isNotEmpty, str -> Objects.equals(str, "Foo")), "The stringProperty must be equal to 'Foo'.")
.must(ImmutableList.of(StringTools::isNotEmpty, str -> Objects.equals(str, "Foo")), () -> ExampleException.withMessage("The stringProperty must be equal to 'Foo'."))
.must(ImmutableList.of(StringTools::isNotEmpty, str -> Objects.equals(str, "Foo")), str -> ExampleException.withMessage("The stringProperty must be equal to 'Foo', but is was '%s'.", str));
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals))
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals), "The stringProperty must be equal to 'Foo'.")
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals), () -> ExampleException.withMessage("The stringProperty must be equal to 'Foo'."))
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals), str -> ExampleException.withMessage("The stringProperty must be equal to 'Foo', but is was '%s'.", str));
}
};
assertDoesNotThrow(() -> ruleWithDefaultMessage.validate(command));
@@ -528,17 +457,17 @@ public class ObjectPropertyValidatorTests {
IValidator<ExampleCommand> ruleWithDefaultMessage = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.must(ImmutableList.of(StringTools::isNotEmpty, str -> Objects.equals(str, "Foo")));
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals));
}
};
ValidationException eWithDefaultMessage = assertThrows(
ValidationException.class, () -> ruleWithDefaultMessage.validate(command));
assertEquals("The specified conditions were not met for the input.", eWithDefaultMessage.getMessage());
assertEquals("The specified condition was not met for the input.", eWithDefaultMessage.getMessage());
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.must(ImmutableList.of(StringTools::isNotEmpty, str -> Objects.equals(str, "Foo")),
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals),
"The stringProperty must be equal to 'Foo'.");
}
};
@@ -549,7 +478,7 @@ public class ObjectPropertyValidatorTests {
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.must(ImmutableList.of(StringTools::isNotEmpty, str -> Objects.equals(str, "Foo")),
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals),
() -> ExampleException.withMessage("The stringProperty must be equal to 'Foo'."));
}
};
@@ -560,7 +489,7 @@ public class ObjectPropertyValidatorTests {
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.must(ImmutableList.of(StringTools::isNotEmpty, str -> Objects.equals(str, "Foo")),
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals),
str -> ExampleException.withMessage("The stringProperty must be equal to 'Foo', but is was '%s'.", str));
}
};

View File

@@ -0,0 +1,176 @@
/*
* Copyright 2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.zhouxy.plusone.example.validator;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.Objects;
import java.util.AbstractMap.SimpleImmutableEntry;
import org.junit.jupiter.api.Test;
import xyz.zhouxy.plusone.ExampleException;
import xyz.zhouxy.plusone.example.ExampleCommand;
import xyz.zhouxy.plusone.validator.BaseValidator;
import xyz.zhouxy.plusone.validator.IValidator;
import xyz.zhouxy.plusone.validator.ValidationException;
@SuppressWarnings("deprecation")
public class PairPropertyValidatorTests {
static final String MESSAGE = "Validation failed.";
// ================================
// #region - must
// ================================
@Test
void must_validInput() {
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "100");
IValidator<ExampleCommand> validator1 = new BaseValidator<ExampleCommand>() {
{
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
.must((str, intValue) -> Objects.equals(str, intValue.toString()))
.must((str, intValue) -> Objects.equals(str, intValue.toString()), MESSAGE)
.must((str, intValue) -> Objects.equals(str, intValue.toString()), () -> ExampleException.withMessage(MESSAGE))
.must((str, intValue) -> Objects.equals(str, intValue.toString()),
(str, intValue) -> ExampleException.withMessage("Validation failed: ('%s', %d).", str, intValue));
}
};
assertDoesNotThrow(() -> validator1.validate(command));
IValidator<ExampleCommand> validator2 = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getStringProperty, ExampleCommand::getIntProperty)
.must((str, intValue) -> Objects.equals(str, intValue.toString()))
.must((str, intValue) -> Objects.equals(str, intValue.toString()), MESSAGE)
.must((str, intValue) -> Objects.equals(str, intValue.toString()), () -> ExampleException.withMessage(MESSAGE))
.must((str, intValue) -> Objects.equals(str, intValue.toString()),
(str, intValue) -> ExampleException.withMessage("Validation failed: ('%s', %d).", str, intValue));
}
};
assertDoesNotThrow(() -> validator2.validate(command));
}
@Test
void must_default_invalidInput() {
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
IValidator<ExampleCommand> validator1 = new BaseValidator<ExampleCommand>() {
{
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
.must((str, intValue) -> Objects.equals(str, intValue.toString()));
}
};
ValidationException e1 = assertThrows(ValidationException.class, () -> validator1.validate(command));
assertEquals("The specified condition was not met for the input.", e1.getMessage());
IValidator<ExampleCommand> validator2 = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getStringProperty, ExampleCommand::getIntProperty)
.must((str, intValue) -> Objects.equals(str, intValue.toString()));
}
};
ValidationException e2 = assertThrows(ValidationException.class, () -> validator2.validate(command));
assertEquals("The specified condition was not met for the input.", e2.getMessage());
}
@Test
void must_message_invalidInput() {
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
IValidator<ExampleCommand> validator1 = new BaseValidator<ExampleCommand>() {
{
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
.must((str, intValue) -> Objects.equals(str, intValue.toString()), MESSAGE);
}
};
ValidationException e1 = assertThrows(ValidationException.class, () -> validator1.validate(command));
assertEquals(MESSAGE, e1.getMessage());
IValidator<ExampleCommand> validator2 = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getStringProperty, ExampleCommand::getIntProperty)
.must((str, intValue) -> Objects.equals(str, intValue.toString()), MESSAGE);
}
};
ValidationException e2 = assertThrows(ValidationException.class, () -> validator2.validate(command));
assertEquals(MESSAGE, e2.getMessage());
}
@Test
void must_exceptionSupplier_invalidInput() {
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
IValidator<ExampleCommand> validator1 = new BaseValidator<ExampleCommand>() {
{
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
.must((str, intValue) -> Objects.equals(str, intValue.toString()), () -> ExampleException.withMessage(MESSAGE));
}
};
ExampleException e1 = assertThrows(ExampleException.class, () -> validator1.validate(command));
assertEquals(MESSAGE, e1.getMessage());
IValidator<ExampleCommand> validator2 = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getStringProperty, ExampleCommand::getIntProperty)
.must((str, intValue) -> Objects.equals(str, intValue.toString()), () -> ExampleException.withMessage(MESSAGE));
}
};
ExampleException e2 = assertThrows(ExampleException.class, () -> validator2.validate(command));
assertEquals(MESSAGE, e2.getMessage());
}
@Test
void must_exceptionFunction_invalidInput() {
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
IValidator<ExampleCommand> validator1 = new BaseValidator<ExampleCommand>() {
{
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
.must((str, intValue) -> Objects.equals(str, intValue.toString()),
(str, intValue) -> ExampleException.withMessage("Validation failed: ('%s', %d).", str, intValue));
}
};
ExampleException e1 = assertThrows(ExampleException.class, () -> validator1.validate(command));
assertEquals("Validation failed: ('', 100).", e1.getMessage());
IValidator<ExampleCommand> validator2 = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getStringProperty, ExampleCommand::getIntProperty)
.must((str, intValue) -> Objects.equals(str, intValue.toString()),
(str, intValue) -> ExampleException.withMessage("Validation failed: ('%s', %d).", str, intValue));
}
};
ExampleException e2 = assertThrows(ExampleException.class, () -> validator2.validate(command));
assertEquals("Validation failed: ('', 100).", e2.getMessage());
}
// ================================
// #endregion - must
// ================================
static ExampleCommand exampleCommandWithIntAndStringListProperty(Integer intValue, String str) {
ExampleCommand exampleCommand = new ExampleCommand();
exampleCommand.setIntProperty(intValue);
exampleCommand.setStringProperty(str);
return exampleCommand;
}
}

View File

@@ -158,11 +158,11 @@ public class StringPropertyValidatorTests {
// ================================
// ================================
// #region - matchesOne
// #region - matchesAny
// ================================
@Test
void matchesOne_patternArray_InputMatchesPattern() {
void matchesAny_patternArray_InputMatchesPattern() {
final Pattern[] patterns = {
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}")
@@ -170,9 +170,9 @@ public class StringPropertyValidatorTests {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, MESSAGE_SHOULD_MATCH)
.matchesOne(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH))
.matchesOne(patterns, str -> ExampleException.withMessage(
.matchesAny(patterns, MESSAGE_SHOULD_MATCH)
.matchesAny(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH))
.matchesAny(patterns, str -> ExampleException.withMessage(
"Input should match pattern, but it is %s", StringTools.toQuotedString(str)));
}
};
@@ -182,7 +182,7 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternArray_message_InputDoesNotMatchPattern() {
void matchesAny_patternArray_message_InputDoesNotMatchPattern() {
final Pattern[] patterns = {
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}")
@@ -190,7 +190,7 @@ public class StringPropertyValidatorTests {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, MESSAGE_SHOULD_MATCH);
.matchesAny(patterns, MESSAGE_SHOULD_MATCH);
}
};
@@ -202,7 +202,7 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternArray_exceptionSupplier_InputDoesNotMatchPattern() {
void matchesAny_patternArray_exceptionSupplier_InputDoesNotMatchPattern() {
final Pattern[] patterns = {
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}")
@@ -210,7 +210,7 @@ public class StringPropertyValidatorTests {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH));
.matchesAny(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH));
}
};
@@ -222,7 +222,7 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternArray_exceptionFunction_InputDoesNotMatchPattern() {
void matchesAny_patternArray_exceptionFunction_InputDoesNotMatchPattern() {
final Pattern[] patterns = {
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}")
@@ -230,7 +230,7 @@ public class StringPropertyValidatorTests {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, str -> ExampleException.withMessage(
.matchesAny(patterns, str -> ExampleException.withMessage(
"Input should match pattern, but it is %s", StringTools.toQuotedString(str)));
}
};
@@ -243,7 +243,7 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternArray_message_InputIsNull() {
void matchesAny_patternArray_message_InputIsNull() {
final Pattern[] patterns = {
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}")
@@ -251,7 +251,7 @@ public class StringPropertyValidatorTests {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, MESSAGE_SHOULD_MATCH);
.matchesAny(patterns, MESSAGE_SHOULD_MATCH);
}
};
@@ -260,7 +260,7 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternArray_exceptionSupplier_InputIsNull() {
void matchesAny_patternArray_exceptionSupplier_InputIsNull() {
final Pattern[] patterns = {
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}")
@@ -268,7 +268,7 @@ public class StringPropertyValidatorTests {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH));
.matchesAny(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH));
}
};
@@ -277,7 +277,7 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternArray_exceptionFunction_InputIsNull() {
void matchesAny_patternArray_exceptionFunction_InputIsNull() {
final Pattern[] patterns = {
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}")
@@ -285,7 +285,7 @@ public class StringPropertyValidatorTests {
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, str -> ExampleException.withMessage(
.matchesAny(patterns, str -> ExampleException.withMessage(
"Input should match pattern, but it is %s", StringTools.toQuotedString(str)));
}
};
@@ -295,16 +295,16 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternList_InputMatchesPattern() {
void matchesAny_patternList_InputMatchesPattern() {
final List<Pattern> patterns = Lists.newArrayList(
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}"));
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, MESSAGE_SHOULD_MATCH)
.matchesOne(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH))
.matchesOne(patterns, str -> ExampleException.withMessage(
.matchesAny(patterns, MESSAGE_SHOULD_MATCH)
.matchesAny(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH))
.matchesAny(patterns, str -> ExampleException.withMessage(
"Input should match pattern, but it is %s", StringTools.toQuotedString(str)));
}
};
@@ -314,14 +314,14 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternList_message_InputDoesNotMatchPattern() {
void matchesAny_patternList_message_InputDoesNotMatchPattern() {
final List<Pattern> patterns = Lists.newArrayList(
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}"));
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, MESSAGE_SHOULD_MATCH);
.matchesAny(patterns, MESSAGE_SHOULD_MATCH);
}
};
@@ -333,14 +333,14 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternList_exceptionSupplier_InputDoesNotMatchPattern() {
void matchesAny_patternList_exceptionSupplier_InputDoesNotMatchPattern() {
final List<Pattern> patterns = Lists.newArrayList(
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}"));
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH));
.matchesAny(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH));
}
};
@@ -352,14 +352,14 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternList_exceptionFunction_InputDoesNotMatchPattern() {
void matchesAny_patternList_exceptionFunction_InputDoesNotMatchPattern() {
final List<Pattern> patterns = Lists.newArrayList(
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}"));
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, str -> ExampleException.withMessage(
.matchesAny(patterns, str -> ExampleException.withMessage(
"Input should match pattern, but it is %s", StringTools.toQuotedString(str)));
}
};
@@ -372,14 +372,14 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternList_message_InputIsNull() {
void matchesAny_patternList_message_InputIsNull() {
final List<Pattern> patterns = Lists.newArrayList(
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}"));
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, MESSAGE_SHOULD_MATCH);
.matchesAny(patterns, MESSAGE_SHOULD_MATCH);
}
};
@@ -388,14 +388,14 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternList_exceptionSupplier_InputIsNull() {
void matchesAny_patternList_exceptionSupplier_InputIsNull() {
final List<Pattern> patterns = Lists.newArrayList(
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}"));
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH));
.matchesAny(patterns, () -> ExampleException.withMessage(MESSAGE_SHOULD_MATCH));
}
};
@@ -404,14 +404,14 @@ public class StringPropertyValidatorTests {
}
@Test
void matchesOne_patternList_exceptionFunction_InputIsNull() {
void matchesAny_patternList_exceptionFunction_InputIsNull() {
final List<Pattern> patterns = Lists.newArrayList(
Pattern.compile("\\w{1,3}"),
Pattern.compile("\\w{4,6}"));
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.matchesOne(patterns, str -> ExampleException.withMessage(
.matchesAny(patterns, str -> ExampleException.withMessage(
"Input should match pattern, but it is %s", StringTools.toQuotedString(str)));
}
};
@@ -421,7 +421,7 @@ public class StringPropertyValidatorTests {
}
// ================================
// #endregion - matchesOne
// #endregion - matchesAny
// ================================
// ================================

View File

@@ -19,10 +19,10 @@ package xyz.zhouxy.plusone.map.validator;
import static org.junit.jupiter.api.Assertions.*;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.junit.jupiter.api.Test;
@@ -59,7 +59,7 @@ class MapValidatorTests {
params.put(ParamsValidator.STRING_PROPERTY2, "Foo");
assertAll(() -> {
Map<String, Object> validatedParams = validator.validateAndCopy(params);
assertEquals(ParamsValidator.keySet(), validatedParams.keySet());
assertEquals(ImmutableSet.copyOf(ParamsValidator.reservedProperties()), validatedParams.keySet());
assertEquals(true, validatedParams.get(ParamsValidator.BOOL_PROPERTY));
assertEquals(Integer.MAX_VALUE, validatedParams.get(ParamsValidator.INT_PROPERTY));
@@ -104,11 +104,14 @@ class ParamsValidator extends MapValidator<String, Object> {
public static final String OBJECT_PROPERTY = "objectProperty";
public static final String STRING_LIST_PROPERTY = "stringListProperty";
private static final String[] RESERVED_PROPERTIES = {
BOOL_PROPERTY, INT_PROPERTY, LONG_PROPERTY, DOUBLE_PROPERTY, STRING_PROPERTY,
DATE_TIME_PROPERTY, OBJECT_PROPERTY, STRING_LIST_PROPERTY };
public static final ParamsValidator INSTANCE = new ParamsValidator();
private ParamsValidator() {
super(new String[] { BOOL_PROPERTY, INT_PROPERTY, LONG_PROPERTY, DOUBLE_PROPERTY, STRING_PROPERTY,
DATE_TIME_PROPERTY, OBJECT_PROPERTY, STRING_LIST_PROPERTY });
super(RESERVED_PROPERTIES);
ruleForBool(BOOL_PROPERTY)
.notNull();
ruleForInt(INT_PROPERTY)
@@ -126,13 +129,12 @@ class ParamsValidator extends MapValidator<String, Object> {
ruleForCollection(STRING_LIST_PROPERTY)
.notNull(d -> ExampleException.withMessage("The stringListProperty cannot be null, but it was %s", d));
// 校验到多个属性,只能针对 map 本身进行校验
withRule(m -> Objects.equals(m.get(STRING_PROPERTY), m.get(STRING_PROPERTY2)),
"'stringProperty' must be equal to 'stringProperty2'.");
ruleForPair(STRING_PROPERTY, STRING_PROPERTY2)
.must((str1, str2) -> str1 != null && str1.equals(str2),
"'stringProperty' must be equal to 'stringProperty2'.");
}
public static Set<String> keySet() {
return ImmutableSet.of(BOOL_PROPERTY, INT_PROPERTY, LONG_PROPERTY, DOUBLE_PROPERTY, STRING_PROPERTY,
DATE_TIME_PROPERTY, OBJECT_PROPERTY, STRING_LIST_PROPERTY);
public static String[] reservedProperties() {
return Arrays.copyOf(RESERVED_PROPERTIES, RESERVED_PROPERTIES.length);
}
}

View File

@@ -6,7 +6,7 @@
<groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-validator-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>1.0.0-RC2</version>
<name>plusone-validator-parent</name>
<url>http://zhouxy.xyz</url>
@@ -18,7 +18,7 @@
</modules>
<description>
Plusone Validator 是一个校验库,用于构建校验规则对对象尤其是入参进行校验。API 参考自 .NET 的 FluentValidation
Plusone Validator 是一个校验库,使用 lambda 表达式(包括方法引用)和流式 API 构建校验规则对对象进行校验
</description>
<properties>
@@ -30,7 +30,7 @@
<dependency>
<groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-dependencies</artifactId>
<version>1.1.0-SNAPSHOT</version>
<version>1.1.0-RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>