Compare commits
51 Commits
45dc111eb6
...
1.0.0-RC1
| Author | SHA1 | Date | |
|---|---|---|---|
| b3ef6deebe | |||
| f86232c404 | |||
| d0785d35e8 | |||
| a315edf88f | |||
| b6d47f0d00 | |||
| 12a5740dd6 | |||
| 654ecd8c63 | |||
| 8b63eb6fe4 | |||
| 62f7a9b03b | |||
| e79d8e9ec8 | |||
| 7f4f5748f8 | |||
| 88b3226b17 | |||
| 0a83116e81 | |||
| 907d883be8 | |||
| 7a9e15fd45 | |||
| b29e1e07aa | |||
| 3f23d5383d | |||
| c27525a637 | |||
| 3ef2ebac2f | |||
| 8be8be8f17 | |||
| 5603b72897 | |||
| 2ac8e39387 | |||
| 3b9a224e72 | |||
| 44ea11e0e9 | |||
| 2d769fde26 | |||
| a4d91dde35 | |||
| 9f0c7cd2fb | |||
| 0a5dbd9f53 | |||
| 2d6ead8417 | |||
| 0e9dbf9bd9 | |||
| f21e9727fa | |||
| 33fb20590b | |||
| 08ebfc7d4b | |||
| 41ccb652d4 | |||
| 37f4af67cd | |||
| 6cd47e369e | |||
| dd8ae71192 | |||
| f15178f500 | |||
| 83d9b05d63 | |||
| d81e6acc23 | |||
| 124ce63323 | |||
| ff374a049e | |||
| ae970cb393 | |||
| a28a6135a8 | |||
| 9f2ade6252 | |||
| e38be765a7 | |||
| bce648dc51 | |||
| ad74a0bcd0 | |||
| dcf620b63e | |||
| 358cdaf1ad | |||
| 07483627a8 |
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"java.configuration.updateBuildConfiguration": "automatic",
|
||||
"java.dependency.packagePresentation": "hierarchical",
|
||||
"java.compile.nullAnalysis.mode": "automatic"
|
||||
}
|
||||
106
README.md
Normal file
106
README.md
Normal 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 反馈使用过程中发现的问题和建议。
|
||||
@@ -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-RC1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>plusone-validator</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<url>http://zhouxy.xyz</url>
|
||||
|
||||
<description>
|
||||
Plusone Validator 是一个参数校验框架,可针对 DTO 创建对应的校验器,并复用该校验器实例,对 DTO 进行校验。
|
||||
Plusone Validator 是一个校验库,使用 lambda 表达式(包括方法引用)和流式 API 构建校验规则,对对象进行校验。
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
@@ -29,16 +29,11 @@
|
||||
<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>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -17,50 +17,87 @@
|
||||
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;
|
||||
|
||||
public abstract
|
||||
class BaseComparablePropertyValidator<TObj,
|
||||
TProperty extends Comparable<TProperty>,
|
||||
TPropertyValidator extends BaseComparablePropertyValidator<TObj, TProperty, TPropertyValidator>>
|
||||
extends BasePropertyValidator<TObj, TProperty, TPropertyValidator> {
|
||||
/**
|
||||
* {@code Comparable} 类型属性的校验器的基类
|
||||
*
|
||||
* @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>>
|
||||
extends BasePropertyValidator<T, TProperty, TPropertyValidator> {
|
||||
|
||||
BaseComparablePropertyValidator(Function<TObj, ? extends TProperty> getter) {
|
||||
BaseComparablePropertyValidator(Function<T, ? extends TProperty> getter) {
|
||||
super(getter);
|
||||
}
|
||||
|
||||
public TPropertyValidator inRange(Range<TProperty> range) {
|
||||
withRule(value -> value != null && range.contains(value),
|
||||
convertExceptionCreator("The value is not in " + range.toString()));
|
||||
return thisObject();
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性的取值范围。
|
||||
*
|
||||
* @param range 区间
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
public TPropertyValidator inRange(Range<TProperty> range, String errMsg) {
|
||||
withRule(value -> value != null && range.contains(value), convertExceptionCreator(errMsg));
|
||||
return thisObject();
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性的取值范围。
|
||||
*
|
||||
* @param range 区间
|
||||
* @param errorMessage 自定义错误消息模板
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator inRange(
|
||||
final Range<TProperty> range, final String errorMessage) {
|
||||
return withRule(Conditions.inRange(range), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator inRange(
|
||||
Range<TProperty> range,
|
||||
Supplier<E> exceptionCreator) {
|
||||
withRule(value -> value != null && range.contains(value), exceptionCreator);
|
||||
return thisObject();
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性的取值范围。
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param range 区间
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator inRange(
|
||||
final Range<TProperty> range, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.inRange(range), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator inRange(
|
||||
Range<TProperty> range,
|
||||
Function<TProperty, E> exceptionCreator) {
|
||||
withRule(value -> value != null && range.contains(value), exceptionCreator);
|
||||
return thisObject();
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性的取值范围。
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param range 区间
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator inRange(
|
||||
final Range<TProperty> range, final Function<TProperty, X> exceptionFunction) {
|
||||
return withRule(Conditions.inRange(range), exceptionFunction);
|
||||
}
|
||||
|
||||
static <V> Function<V, IllegalArgumentException> convertExceptionCreator(String errMsg) {
|
||||
return value -> new IllegalArgumentException(errMsg);
|
||||
}
|
||||
/**
|
||||
* 校验条件的实现
|
||||
*/
|
||||
private static class Conditions {
|
||||
|
||||
static <V, E extends RuntimeException> Function<V, E> convertExceptionCreator(Supplier<E> exceptionSupplier) {
|
||||
return value -> exceptionSupplier.get();
|
||||
private static <TProperty extends Comparable<TProperty>> Predicate<TProperty> inRange(
|
||||
final Range<TProperty> range) {
|
||||
return value -> value == null || range.contains(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -25,44 +24,120 @@ import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class BasePropertyValidator< //
|
||||
TObj, //
|
||||
TProperty, //
|
||||
TPropertyValidator extends BasePropertyValidator<TObj, TProperty, TPropertyValidator>> {
|
||||
/**
|
||||
* 属性校验器。包含针对属性的校验规则。
|
||||
*
|
||||
* <p>
|
||||
* 用于构建针对特定属性的校验规则链,支持通过链式调用添加多种校验规则。
|
||||
*
|
||||
* @param <T> 待校验对象的类型
|
||||
* @param <TProperty> 待校验属性的类型
|
||||
* @param <TPropertyValidator> 具体校验器类型,用于支持链式调用
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public abstract class BasePropertyValidator<
|
||||
T,
|
||||
TProperty,
|
||||
TPropertyValidator extends BasePropertyValidator<T, TProperty, TPropertyValidator>> {
|
||||
|
||||
private final Function<TObj, ? extends TProperty> getter;
|
||||
private final Function<T, ? extends TProperty> getter;
|
||||
|
||||
private final List<Consumer<? super TProperty>> consumers = new LinkedList<>();
|
||||
|
||||
protected BasePropertyValidator(Function<TObj, ? extends TProperty> getter) {
|
||||
protected BasePropertyValidator(Function<T, ? extends TProperty> getter) {
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
public final TPropertyValidator withRule(Predicate<? super TProperty> rule) {
|
||||
return withRule(rule, v -> new IllegalArgumentException());
|
||||
}
|
||||
|
||||
public final TPropertyValidator withRule(
|
||||
Predicate<? super TProperty> rule, String errMsg) {
|
||||
return withRule(rule, convertExceptionCreator(errMsg));
|
||||
}
|
||||
|
||||
public final <E extends RuntimeException> TPropertyValidator withRule(
|
||||
Predicate<? super TProperty> rule, Supplier<E> e) {
|
||||
return withRule(rule, convertExceptionCreator(e));
|
||||
}
|
||||
|
||||
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);
|
||||
/**
|
||||
* 添加一条校验属性的规则,当条件不满足时抛出异常。
|
||||
*
|
||||
* @param condition 校验条件
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
* @throws ValidationException 校验失败时抛出的异常
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
public final <T extends TObj> void validate(T obj) {
|
||||
/**
|
||||
* 校验属性
|
||||
*
|
||||
* @param obj 属性所在的对象
|
||||
*/
|
||||
public final void validate(T obj) {
|
||||
for (Consumer<? super TProperty> consumer : consumers) {
|
||||
consumer.accept(getter.apply(obj));
|
||||
}
|
||||
@@ -74,114 +149,301 @@ public abstract class BasePropertyValidator< //
|
||||
// ====== Object ======
|
||||
// ====================
|
||||
|
||||
// ====== notNull =====
|
||||
// ================================
|
||||
// #region - notNull
|
||||
// ================================
|
||||
|
||||
public TPropertyValidator notNull() {
|
||||
return notNull("Value could not be null.");
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否不为空
|
||||
*
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator notNull() {
|
||||
return withRule(Objects::nonNull, "The input must not be null.");
|
||||
}
|
||||
|
||||
public TPropertyValidator notNull(String errMsg) {
|
||||
return notNull(convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否不为空
|
||||
*
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator notNull(final String errorMessage) {
|
||||
return withRule(Objects::nonNull, errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator notNull(Supplier<E> exceptionCreator) {
|
||||
return notNull(convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否不为空
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator notNull(
|
||||
final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Objects::nonNull, exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator notNull(Function<TProperty, E> exceptionCreator) {
|
||||
withRule(Objects::nonNull, exceptionCreator);
|
||||
return thisObject();
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否不为空
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator notNull(
|
||||
final Function<TProperty, X> exceptionFunction) {
|
||||
return withRule(Objects::nonNull, exceptionFunction);
|
||||
}
|
||||
|
||||
// ====== isNull =====
|
||||
// ================================
|
||||
// #endregion - notNull
|
||||
// ================================
|
||||
|
||||
public TPropertyValidator isNull(String errMsg) {
|
||||
return isNull(convertExceptionCreator(errMsg));
|
||||
// ================================
|
||||
// #region - isNull
|
||||
// ================================
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为空
|
||||
*
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator isNull() {
|
||||
return withRule(Objects::isNull, "The input must be null.");
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator isNull(Supplier<E> exceptionCreator) {
|
||||
return isNull(convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为空
|
||||
*
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator isNull(final String errorMessage) {
|
||||
return withRule(Objects::isNull, errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator isNull(Function<TProperty, E> exceptionCreator) {
|
||||
withRule(Objects::isNull, exceptionCreator);
|
||||
return thisObject();
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为空
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator isNull(
|
||||
final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Objects::isNull, exceptionSupplier);
|
||||
}
|
||||
|
||||
// ===== equals =====
|
||||
|
||||
public TPropertyValidator equalsThat(Object that) {
|
||||
return equalsThat(that, value -> new IllegalArgumentException(String.format("(%s) 必须与 (%s) 相等", value, that)));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为空
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator isNull(
|
||||
final Function<TProperty, X> exceptionFunction) {
|
||||
return withRule(Objects::isNull, exceptionFunction);
|
||||
}
|
||||
|
||||
public TPropertyValidator equalsThat(Object that, String errMsg) {
|
||||
return equalsThat(that, convertExceptionCreator(errMsg));
|
||||
// ================================
|
||||
// #endregion - isNull
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - equal
|
||||
// ================================
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* @param obj 用于比较的对象
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator equal(Object obj) {
|
||||
return withRule(Conditions.equal(obj),
|
||||
"The input must be equal to '%s'.", obj);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator equalsThat(
|
||||
Object that, Supplier<E> exceptionCreator) {
|
||||
return equalsThat(that, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* @param obj 用于比较的对象
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator equal(
|
||||
final Object obj, final String errorMessage) {
|
||||
return withRule(Conditions.equal(obj), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator equalsThat(
|
||||
Object that, Function<TProperty, E> exceptionCreator) {
|
||||
withRule(value -> Objects.equals(value, that), exceptionCreator);
|
||||
return thisObject();
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param obj 用于比较的对象
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator equal(
|
||||
final Object obj, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.equal(obj), exceptionSupplier);
|
||||
}
|
||||
|
||||
// ===== must =====
|
||||
|
||||
public TPropertyValidator must(Predicate<? super TProperty> condition) {
|
||||
return must(condition, "无效的用户输入");
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param obj 用于比较的对象
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator equal(
|
||||
final Object obj, final Function<TProperty, X> exceptionFunction) {
|
||||
return withRule(Conditions.equal(obj), exceptionFunction);
|
||||
}
|
||||
|
||||
public TPropertyValidator must(Predicate<? super TProperty> condition, String errMsg) {
|
||||
return must(condition, convertExceptionCreator(errMsg));
|
||||
// ================================
|
||||
// #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);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator must(
|
||||
Predicate<? super TProperty> condition,
|
||||
Supplier<E> exceptionCreator) {
|
||||
return must(condition, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* @param obj 用于比较的对象
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator notEqual(final Object obj, final String errorMessage) {
|
||||
return withRule(Conditions.notEqual(obj), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator must(
|
||||
Predicate<? super TProperty> condition,
|
||||
Function<TProperty, E> exceptionCreator) {
|
||||
withRule(condition, exceptionCreator);
|
||||
return thisObject();
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
// ===== must =====
|
||||
|
||||
public TPropertyValidator must(Collection<Predicate<? super TProperty>> conditions) {
|
||||
return must(conditions, "无效的用户输入");
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
public TPropertyValidator must(Collection<Predicate<? super TProperty>> conditions, String errMsg) {
|
||||
return must(conditions, convertExceptionCreator(errMsg));
|
||||
// ================================
|
||||
// #endregion - notEqual
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - must
|
||||
// ================================
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否满足给定的条件
|
||||
*
|
||||
* @param condition 校验条件
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator must(final Predicate<? super TProperty> condition) {
|
||||
return withRule(condition,
|
||||
"The specified condition was not met for the input.");
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator must(
|
||||
Collection<Predicate<? super TProperty>> conditions,
|
||||
Supplier<E> exceptionCreator) {
|
||||
return must(conditions, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否满足给定的条件
|
||||
*
|
||||
* @param condition 校验条件
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator must(
|
||||
final Predicate<? super TProperty> condition,
|
||||
final String errorMessage) {
|
||||
return withRule(condition, errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> TPropertyValidator must(
|
||||
Collection<Predicate<? super TProperty>> conditions,
|
||||
Function<TProperty, E> exceptionCreator) {
|
||||
for (Predicate<? super TProperty> condition : conditions) {
|
||||
withRule(condition, exceptionCreator);
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否满足给定的条件
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param condition 校验规则
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator must(
|
||||
final Predicate<? super TProperty> condition,
|
||||
final Supplier<X> exceptionSupplier) {
|
||||
return withRule(condition, exceptionSupplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否满足给定的条件
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param condition 校验规则
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator must(
|
||||
final Predicate<? super TProperty> condition,
|
||||
final Function<TProperty, X> exceptionFunction) {
|
||||
return withRule(condition, exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - must
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - conditions
|
||||
// ================================
|
||||
|
||||
/**
|
||||
* 常用校验条件的实现
|
||||
*/
|
||||
private static class Conditions {
|
||||
|
||||
private static <TProperty> Predicate<TProperty> equal(Object obj) {
|
||||
return input -> input == null || input.equals(obj);
|
||||
}
|
||||
return thisObject();
|
||||
|
||||
private static <TProperty> Predicate<TProperty> notEqual(Object obj) {
|
||||
return input -> input == null || !input.equals(obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static <V> Function<V, IllegalArgumentException> convertExceptionCreator(String errMsg) {
|
||||
return value -> new IllegalArgumentException(errMsg);
|
||||
}
|
||||
|
||||
static <V, E extends RuntimeException> Function<V, E> convertExceptionCreator(Supplier<E> exceptionSupplier) {
|
||||
return value -> exceptionSupplier.get();
|
||||
}
|
||||
// ================================
|
||||
// #endregion - conditions
|
||||
// ================================
|
||||
}
|
||||
|
||||
@@ -19,96 +19,276 @@ package xyz.zhouxy.plusone.validator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import xyz.zhouxy.plusone.validator.function.*;
|
||||
|
||||
/**
|
||||
* BaseValidator
|
||||
*
|
||||
* 校验器基类
|
||||
* <p>
|
||||
* 校验器的基类
|
||||
* </p>
|
||||
* 子类可通过添加不同的校验规则,构建完整的校验逻辑,用于校验对象。
|
||||
*
|
||||
* <p>
|
||||
* <b>NOTE: content.</b>
|
||||
* </p>
|
||||
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
|
||||
* @since 0.0.1
|
||||
* @param <T> 待校验对象的类型
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public abstract class BaseValidator<T> {
|
||||
public abstract class BaseValidator<T> implements IValidator<T> {
|
||||
|
||||
private final List<Consumer<? super T>> rules = new ArrayList<>();
|
||||
|
||||
protected void withRule(final Predicate<? super T> rule, final String errorMessage) {
|
||||
withRule(rule, () -> new IllegalArgumentException(errorMessage));
|
||||
/**
|
||||
* 添加一条用于校验整个对象的规则
|
||||
*
|
||||
* @param condition 校验条件
|
||||
* @param errorMessage 异常信息
|
||||
*/
|
||||
protected final void withRule(final Predicate<? super T> condition, final String errorMessage) {
|
||||
withRule(condition, () -> ValidationException.withMessage(errorMessage));
|
||||
}
|
||||
|
||||
protected <E extends RuntimeException> void withRule(Predicate<? super T> rule, Supplier<E> exceptionBuilder) {
|
||||
withRule(rule, value -> exceptionBuilder.get());
|
||||
/**
|
||||
* 添加一条用于校验整个对象的规则
|
||||
*
|
||||
* @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());
|
||||
}
|
||||
|
||||
protected <E extends RuntimeException> void withRule(
|
||||
Predicate<? super T> condition, Function<T, E> exceptionBuilder) {
|
||||
/**
|
||||
* 添加一条用于校验整个对象的规则
|
||||
*
|
||||
* @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 exceptionBuilder.apply(value);
|
||||
throw exceptionFunction.apply(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void withRule(Consumer<? super T> rule) {
|
||||
/**
|
||||
* 添加一条用于校验整个对象的规则
|
||||
*
|
||||
* @param rule 自定义校验规则
|
||||
*/
|
||||
protected final void withRule(Consumer<? super T> rule) {
|
||||
this.rules.add(rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个通用的属性校验器
|
||||
*
|
||||
* @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);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
protected final <R extends Comparable<R>> ComparablePropertyValidator<T, R> ruleForComparable(Function<T, R> getter) {
|
||||
/**
|
||||
* 添加一个用于校验 {@code Comparable} 类型的属性校验器
|
||||
*
|
||||
* @param <R> 属性类型
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code ComparablePropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final <R extends Comparable<R>> ComparablePropertyValidator<T, R> ruleForComparable(
|
||||
Function<T, R> getter) {
|
||||
ComparablePropertyValidator<T, R> validator = new ComparablePropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验 {@code Integer} 类型的属性校验器
|
||||
*
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code IntPropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final IntPropertyValidator<T> ruleForInt(Function<T, Integer> getter) {
|
||||
IntPropertyValidator<T> validator = new IntPropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验 {@code Integer} 类型的属性校验器
|
||||
*
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code IntPropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final IntPropertyValidator<T> ruleFor(ToIntegerFunction<T> getter) {
|
||||
IntPropertyValidator<T> validator = new IntPropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验 {@code Long} 类型的属性校验器
|
||||
*
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code LongPropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final LongPropertyValidator<T> ruleForLong(Function<T, Long> getter) {
|
||||
LongPropertyValidator<T> validator = new LongPropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验 {@code Long} 类型的属性校验器
|
||||
*
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code LongPropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final LongPropertyValidator<T> ruleFor(ToLongObjectFunction<T> getter) {
|
||||
LongPropertyValidator<T> validator = new LongPropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验 {@code Double} 类型的属性校验器
|
||||
*
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code DoublePropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final DoublePropertyValidator<T> ruleForDouble(Function<T, Double> getter) {
|
||||
DoublePropertyValidator<T> validator = new DoublePropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验 {@code Double} 类型的属性校验器
|
||||
*
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code DoublePropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final DoublePropertyValidator<T> ruleFor(ToDoubleObjectFunction<T> getter) {
|
||||
DoublePropertyValidator<T> validator = new DoublePropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验 {@code Boolean} 类型的属性校验器
|
||||
*
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code BoolPropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final BoolPropertyValidator<T> ruleForBool(Function<T, Boolean> getter) {
|
||||
BoolPropertyValidator<T> validator = new BoolPropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验 {@code Boolean} 类型的属性校验器
|
||||
*
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code BoolPropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final BoolPropertyValidator<T> ruleFor(ToBoolObjectFunction<T> getter) {
|
||||
BoolPropertyValidator<T> validator = new BoolPropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验 {@code String} 类型的属性校验器
|
||||
*
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code StringPropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final StringPropertyValidator<T> ruleForString(Function<T, String> getter) {
|
||||
StringPropertyValidator<T> validator = new StringPropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验 {@code String} 类型的属性校验器
|
||||
*
|
||||
* @param getter 用于从目标对象获取属性值的函数式接口。
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code StringPropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final StringPropertyValidator<T> ruleFor(ToStringFunction<T> getter) {
|
||||
StringPropertyValidator<T> validator = new StringPropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个用于校验集合类型的属性校验器
|
||||
*
|
||||
* @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);
|
||||
this.rules.add(validator::validate);
|
||||
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}。用于添加针对该二元组的校验规则。
|
||||
*/
|
||||
protected final <V1, V2> PairPropertyValidator<T, V1, V2> ruleForPair(Function<T, Entry<V1, V2>> getter) {
|
||||
PairPropertyValidator<T, V1, V2> validator = new PairPropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void validate(T obj) {
|
||||
this.rules.forEach(rule -> rule.accept(obj));
|
||||
}
|
||||
|
||||
@@ -17,58 +17,128 @@
|
||||
package xyz.zhouxy.plusone.validator;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class BoolPropertyValidator<DTO> extends BasePropertyValidator<DTO, Boolean, BoolPropertyValidator<DTO>> {
|
||||
/**
|
||||
* {@code Boolean} 类型属性的校验器
|
||||
*
|
||||
* <p>
|
||||
* 用于构建校验 {@code Boolean} 类型属性的规则链。
|
||||
*
|
||||
* @param <T> 待校验对象的类型
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public class BoolPropertyValidator<T>
|
||||
extends BasePropertyValidator<T, Boolean, BoolPropertyValidator<T>> {
|
||||
|
||||
BoolPropertyValidator(Function<DTO, Boolean> getter) {
|
||||
BoolPropertyValidator(Function<T, Boolean> getter) {
|
||||
super(getter);
|
||||
}
|
||||
|
||||
// ====== isTrueValue ======
|
||||
|
||||
public BoolPropertyValidator<DTO> isTrueValue() {
|
||||
return isTrueValue("The value must be true.");
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为 {@code true}
|
||||
*
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final BoolPropertyValidator<T> isTrueValue() {
|
||||
return withRule(Conditions.isTrueValue(), "The input must be true.");
|
||||
}
|
||||
|
||||
public BoolPropertyValidator<DTO> isTrueValue(String errMsg) {
|
||||
return isTrueValue(convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为 {@code true}
|
||||
*
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final BoolPropertyValidator<T> isTrueValue(final String errorMessage) {
|
||||
return withRule(Conditions.isTrueValue(), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> BoolPropertyValidator<DTO> isTrueValue(
|
||||
Supplier<E> exceptionCreator) {
|
||||
return isTrueValue(convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为 {@code true}
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> BoolPropertyValidator<T> isTrueValue(
|
||||
final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.isTrueValue(), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> BoolPropertyValidator<DTO> isTrueValue(
|
||||
Function<Boolean, E> exceptionCreator) {
|
||||
withRule(Boolean.TRUE::equals, exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为 {@code true}
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> BoolPropertyValidator<T> isTrueValue(
|
||||
final Function<Boolean, X> exceptionFunction) {
|
||||
return withRule(Conditions.isTrueValue(), exceptionFunction);
|
||||
}
|
||||
|
||||
// ====== isFalseValue ======
|
||||
|
||||
public BoolPropertyValidator<DTO> isFalseValue() {
|
||||
return isFalseValue("The value must be false.");
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为 {@code false}
|
||||
*
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final BoolPropertyValidator<T> isFalseValue() {
|
||||
return withRule(Conditions.isFalseValue(), "The input must be false.");
|
||||
}
|
||||
|
||||
public BoolPropertyValidator<DTO> isFalseValue(String errMsg) {
|
||||
return isFalseValue(convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为 {@code false}
|
||||
*
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final BoolPropertyValidator<T> isFalseValue(final String errorMessage) {
|
||||
return withRule(Conditions.isFalseValue(), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> BoolPropertyValidator<DTO> isFalseValue(
|
||||
Supplier<E> exceptionCreator) {
|
||||
return isFalseValue(convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为 {@code false}
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> BoolPropertyValidator<T> isFalseValue(
|
||||
final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.isFalseValue(), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> BoolPropertyValidator<DTO> isFalseValue(
|
||||
Function<Boolean, E> exceptionCreator) {
|
||||
withRule(Boolean.FALSE::equals, exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为 {@code false}
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
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
|
||||
protected BoolPropertyValidator<DTO> thisObject() {
|
||||
protected BoolPropertyValidator<T> thisObject() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,51 +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;
|
||||
|
||||
public class CollectionPropertyValidator<DTO, T>
|
||||
extends BasePropertyValidator<DTO, Collection<T>, CollectionPropertyValidator<DTO, T>> {
|
||||
/**
|
||||
* 集合类型属性的校验器
|
||||
*
|
||||
* <p>
|
||||
* 用于构建校验集合类型属性的规则链。
|
||||
*
|
||||
* @param <T> 待校验对象的类型
|
||||
* @param <E> 集合元素的类型
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public class CollectionPropertyValidator<T, E>
|
||||
extends BasePropertyValidator<T, Collection<E>, CollectionPropertyValidator<T, E>> {
|
||||
|
||||
CollectionPropertyValidator(Function<DTO, Collection<T>> getter) {
|
||||
CollectionPropertyValidator(Function<T, Collection<E>> getter) {
|
||||
super(getter);
|
||||
}
|
||||
|
||||
// ====== notEmpty =====
|
||||
// ================================
|
||||
// #region - notEmpty
|
||||
// ================================
|
||||
|
||||
public CollectionPropertyValidator<DTO, T> notEmpty(String errMsg) {
|
||||
return notEmpty(convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否非空
|
||||
*
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final CollectionPropertyValidator<T, E> notEmpty() {
|
||||
return withRule(Conditions.notEmpty(), "The input must not be empty.");
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> CollectionPropertyValidator<DTO, T> notEmpty(Supplier<E> exceptionCreator) {
|
||||
return notEmpty(convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否非空
|
||||
*
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final CollectionPropertyValidator<T, E> notEmpty(final String errorMessage) {
|
||||
return withRule(Conditions.notEmpty(), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> CollectionPropertyValidator<DTO, T> notEmpty(
|
||||
Function<Collection<T>, E> exceptionCreator) {
|
||||
withRule(CollectionTools::isNotEmpty, exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否非空
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> notEmpty(
|
||||
final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.notEmpty(), exceptionSupplier);
|
||||
}
|
||||
|
||||
// ====== isEmpty =====
|
||||
|
||||
public CollectionPropertyValidator<DTO, T> isEmpty(String errMsg) {
|
||||
return isEmpty(convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否非空
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> notEmpty(
|
||||
final Function<Collection<E>, X> exceptionFunction) {
|
||||
return withRule(Conditions.notEmpty(), exceptionFunction);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> CollectionPropertyValidator<DTO, T> isEmpty(Supplier<E> exceptionCreator) {
|
||||
return isEmpty(convertExceptionCreator(exceptionCreator));
|
||||
// ================================
|
||||
// #endregion - notEmpty
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - isEmpty
|
||||
// ================================
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为空
|
||||
*
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final CollectionPropertyValidator<T, E> isEmpty() {
|
||||
return withRule(Conditions.isEmpty(), "The input must be empty.");
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> CollectionPropertyValidator<DTO, T> isEmpty(
|
||||
Function<Collection<T>, E> exceptionCreator) {
|
||||
withRule(CollectionTools::isEmpty, exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为空
|
||||
*
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final CollectionPropertyValidator<T, E> isEmpty(
|
||||
final String errorMessage) {
|
||||
return withRule(Conditions.isEmpty(), errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为空
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> isEmpty(
|
||||
final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.isEmpty(), exceptionSupplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否为空
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
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<DTO, T> thisObject() {
|
||||
protected CollectionPropertyValidator<T, E> thisObject() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,15 +18,23 @@ package xyz.zhouxy.plusone.validator;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ComparablePropertyValidator<TObj, TProperty extends Comparable<TProperty>>
|
||||
extends BaseComparablePropertyValidator<TObj, TProperty, ComparablePropertyValidator<TObj, TProperty>> {
|
||||
/**
|
||||
* {@code Comparable} 类型属性的校验器
|
||||
*
|
||||
* @param <T> 待校验对象的类型
|
||||
* @param <TProperty> 待校验属性的类型,必须实现 {@code Comparable} 接口
|
||||
* @see com.google.common.collect.Range
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public class ComparablePropertyValidator<T, TProperty extends Comparable<TProperty>>
|
||||
extends BaseComparablePropertyValidator<T, TProperty, ComparablePropertyValidator<T, TProperty>> {
|
||||
|
||||
ComparablePropertyValidator(Function<TObj, ? extends TProperty> getter) {
|
||||
ComparablePropertyValidator(Function<T, ? extends TProperty> getter) {
|
||||
super(getter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ComparablePropertyValidator<TObj, TProperty> thisObject() {
|
||||
protected ComparablePropertyValidator<T, TProperty> thisObject() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,22 @@
|
||||
package xyz.zhouxy.plusone.validator;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class DoublePropertyValidator<DTO>
|
||||
extends BaseComparablePropertyValidator<DTO, Double, DoublePropertyValidator<DTO>> {
|
||||
/**
|
||||
* {@code Double} 类型属性的校验器
|
||||
*
|
||||
* <p>
|
||||
* 用于构建校验 {@code Double} 类型属性的规则链。
|
||||
*
|
||||
* @param <T> 待校验对象的类型
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public class DoublePropertyValidator<T>
|
||||
extends BaseComparablePropertyValidator<T, Double, DoublePropertyValidator<T>> {
|
||||
|
||||
DoublePropertyValidator(Function<DTO, Double> getter) {
|
||||
DoublePropertyValidator(Function<T, Double> getter) {
|
||||
super(getter);
|
||||
}
|
||||
|
||||
@@ -30,23 +40,53 @@ public class DoublePropertyValidator<DTO>
|
||||
// #region - greater than
|
||||
// ================================
|
||||
|
||||
public DoublePropertyValidator<DTO> gt(double min) {
|
||||
return gt(min, String.format("The value should be greater than %s", min));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final DoublePropertyValidator<T> gt(final double min) {
|
||||
return withRule(Conditions.greaterThan(min),
|
||||
"The input must be greater than '%s'.", min);
|
||||
}
|
||||
|
||||
public DoublePropertyValidator<DTO> gt(double min, String errMsg) {
|
||||
return gt(min, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final DoublePropertyValidator<T> gt(
|
||||
final double min, final String errorMessage) {
|
||||
return withRule(Conditions.greaterThan(min), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> DoublePropertyValidator<DTO> gt(
|
||||
double min, Supplier<E> exceptionCreator) {
|
||||
return gt(min, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> DoublePropertyValidator<T> gt(
|
||||
final double min, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.greaterThan(min), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> DoublePropertyValidator<DTO> gt(
|
||||
double min, Function<Double, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value > min), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> DoublePropertyValidator<T> gt(
|
||||
final double min, final Function<Double, X> exceptionFunction) {
|
||||
return withRule(Conditions.greaterThan(min), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -57,23 +97,53 @@ public class DoublePropertyValidator<DTO>
|
||||
// #region - greater than or equal to
|
||||
// ================================
|
||||
|
||||
public DoublePropertyValidator<DTO> ge(double min) {
|
||||
return ge(min, String.format("The value should be greater than or equal to %s", min));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final DoublePropertyValidator<T> ge(final double min) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min),
|
||||
"The input must be greater than or equal to '%s'.", min);
|
||||
}
|
||||
|
||||
public DoublePropertyValidator<DTO> ge(double min, String errMsg) {
|
||||
return ge(min, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final DoublePropertyValidator<T> ge(
|
||||
final double min, final String errorMessage) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> DoublePropertyValidator<DTO> ge(
|
||||
double min, Supplier<E> exceptionCreator) {
|
||||
return ge(min, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> DoublePropertyValidator<T> ge(
|
||||
final double min, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> DoublePropertyValidator<DTO> ge(
|
||||
double min, Function<Double, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value >= min), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> DoublePropertyValidator<T> ge(
|
||||
final double min, final Function<Double, X> exceptionFunction) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -84,23 +154,53 @@ public class DoublePropertyValidator<DTO>
|
||||
// #region - less than
|
||||
// ================================
|
||||
|
||||
public DoublePropertyValidator<DTO> lt(double max) {
|
||||
return lt(max, String.format("The value should be less than %s", max));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final DoublePropertyValidator<T> lt(final double max) {
|
||||
return withRule(Conditions.lessThan(max),
|
||||
"The input must be less than '%s'.", max);
|
||||
}
|
||||
|
||||
public DoublePropertyValidator<DTO> lt(double max, String errMsg) {
|
||||
return lt(max, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final DoublePropertyValidator<T> lt(
|
||||
final double max, final String errorMessage) {
|
||||
return withRule(Conditions.lessThan(max), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> DoublePropertyValidator<DTO> lt(
|
||||
double max, Supplier<E> exceptionCreator) {
|
||||
return lt(max, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> DoublePropertyValidator<T> lt(
|
||||
final double max, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.lessThan(max), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> DoublePropertyValidator<DTO> lt(
|
||||
double max, Function<Double, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value < max), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> DoublePropertyValidator<T> lt(
|
||||
final double max, final Function<Double, X> exceptionFunction) {
|
||||
return withRule(Conditions.lessThan(max), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -111,23 +211,53 @@ public class DoublePropertyValidator<DTO>
|
||||
// #region - less than or equal to
|
||||
// ================================
|
||||
|
||||
public DoublePropertyValidator<DTO> le(double max) {
|
||||
return le(max, String.format("The value should be less than or equal to %s", max));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final DoublePropertyValidator<T> le(final double max) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max),
|
||||
"The input must be less than or equal to '%s'.", max);
|
||||
}
|
||||
|
||||
public DoublePropertyValidator<DTO> le(double max, String errMsg) {
|
||||
return le(max, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final DoublePropertyValidator<T> le(
|
||||
final double max, final String errorMessage) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> DoublePropertyValidator<DTO> le(
|
||||
double max, Supplier<E> exceptionCreator) {
|
||||
return le(max, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> DoublePropertyValidator<T> le(
|
||||
final double max, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> DoublePropertyValidator<DTO> le(
|
||||
double max, Function<Double, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value <= max), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> DoublePropertyValidator<T> le(
|
||||
final double max, final Function<Double, X> exceptionFunction) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -135,7 +265,26 @@ public class DoublePropertyValidator<DTO>
|
||||
// ================================
|
||||
|
||||
@Override
|
||||
protected DoublePropertyValidator<DTO> thisObject() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,8 @@ package xyz.zhouxy.plusone.validator;
|
||||
/**
|
||||
* 自带校验方法,校验不通过时直接抛异常。
|
||||
*
|
||||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
* @author ZhouXY
|
||||
*
|
||||
* @see ValidTools
|
||||
* @see BaseValidator
|
||||
*/
|
||||
public interface IValidateRequired {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 校验器
|
||||
*
|
||||
* <p>
|
||||
* 用于定义对特定类型对象的校验规则
|
||||
* </p>
|
||||
*
|
||||
* @param <T> 待校验对象的类型
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public interface IValidator<T> {
|
||||
|
||||
/**
|
||||
* 校验指定对象是否符合预定义规则
|
||||
*
|
||||
* @param obj 待校验的对象实例
|
||||
*/
|
||||
void validate(T obj);
|
||||
}
|
||||
@@ -17,12 +17,22 @@
|
||||
package xyz.zhouxy.plusone.validator;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class IntPropertyValidator<DTO>
|
||||
extends BaseComparablePropertyValidator<DTO, Integer, IntPropertyValidator<DTO>> {
|
||||
/**
|
||||
* {@code Integer} 类型属性的校验器
|
||||
*
|
||||
* <p>
|
||||
* 用于构建校验 {@code Integer} 类型属性的规则链。
|
||||
*
|
||||
* @param <T> 待校验对象的类型
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public class IntPropertyValidator<T>
|
||||
extends BaseComparablePropertyValidator<T, Integer, IntPropertyValidator<T>> {
|
||||
|
||||
IntPropertyValidator(Function<DTO, Integer> getter) {
|
||||
IntPropertyValidator(Function<T, Integer> getter) {
|
||||
super(getter);
|
||||
}
|
||||
|
||||
@@ -30,23 +40,53 @@ public class IntPropertyValidator<DTO>
|
||||
// #region - greater than
|
||||
// ================================
|
||||
|
||||
public IntPropertyValidator<DTO> gt(int min) {
|
||||
return gt(min, String.format("The value should be greater than %d", min));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final IntPropertyValidator<T> gt(final int min) {
|
||||
return withRule(Conditions.greaterThan(min),
|
||||
"The input must be greater than '%d'.", min);
|
||||
}
|
||||
|
||||
public IntPropertyValidator<DTO> gt(int min, String errMsg) {
|
||||
return gt(min, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final IntPropertyValidator<T> gt(
|
||||
final int min, final String errorMessage) {
|
||||
return withRule(Conditions.greaterThan(min), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> IntPropertyValidator<DTO> gt(
|
||||
int min, Supplier<E> exceptionCreator) {
|
||||
return gt(min, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> IntPropertyValidator<T> gt(
|
||||
final int min, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.greaterThan(min), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> IntPropertyValidator<DTO> gt(
|
||||
int min, Function<Integer, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value > min), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> IntPropertyValidator<T> gt(
|
||||
final int min, final Function<Integer, X> exceptionFunction) {
|
||||
return withRule(Conditions.greaterThan(min), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -57,23 +97,52 @@ public class IntPropertyValidator<DTO>
|
||||
// #region - greater than or equal to
|
||||
// ================================
|
||||
|
||||
public IntPropertyValidator<DTO> ge(int min) {
|
||||
return ge(min, String.format("The value should be greater than or equal to %d", min));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final IntPropertyValidator<T> ge(final int min) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min),
|
||||
"The input must be greater than or equal to '%d'.", min);
|
||||
}
|
||||
|
||||
public IntPropertyValidator<DTO> ge(int min, String errMsg) {
|
||||
return ge(min, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final IntPropertyValidator<T> ge(final int min, final String errorMessage) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> IntPropertyValidator<DTO> ge(
|
||||
int min, Supplier<E> exceptionCreator) {
|
||||
return ge(min, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> IntPropertyValidator<T> ge(
|
||||
final int min, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> IntPropertyValidator<DTO> ge(
|
||||
int min, Function<Integer, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value >= min), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> IntPropertyValidator<T> ge(
|
||||
final int min, final Function<Integer, X> exceptionFunction) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -84,23 +153,53 @@ public class IntPropertyValidator<DTO>
|
||||
// #region - less than
|
||||
// ================================
|
||||
|
||||
public IntPropertyValidator<DTO> lt(int max) {
|
||||
return lt(max, String.format("The value should be less than %d", max));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final IntPropertyValidator<T> lt(final int max) {
|
||||
return withRule(Conditions.lessThan(max),
|
||||
"The input must be less than '%d'.", max);
|
||||
}
|
||||
|
||||
public IntPropertyValidator<DTO> lt(int max, String errMsg) {
|
||||
return lt(max, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final IntPropertyValidator<T> lt(
|
||||
final int max, final String errorMessage) {
|
||||
return withRule(Conditions.lessThan(max), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> IntPropertyValidator<DTO> lt(
|
||||
int max, Supplier<E> exceptionCreator) {
|
||||
return lt(max, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> IntPropertyValidator<T> lt(
|
||||
final int max, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.lessThan(max), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> IntPropertyValidator<DTO> lt(
|
||||
int max, Function<Integer, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value < max), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> IntPropertyValidator<T> lt(
|
||||
final int max, final Function<Integer, X> exceptionFunction) {
|
||||
return withRule(Conditions.lessThan(max), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -111,23 +210,53 @@ public class IntPropertyValidator<DTO>
|
||||
// #region - less than or equal to
|
||||
// ================================
|
||||
|
||||
public IntPropertyValidator<DTO> le(int max) {
|
||||
return le(max, String.format("The value should be less than or equal to %d", max));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final IntPropertyValidator<T> le(final int max) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max),
|
||||
"The input must be less than or equal to '%d'.", max);
|
||||
}
|
||||
|
||||
public IntPropertyValidator<DTO> le(int max, String errMsg) {
|
||||
return le(max, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final IntPropertyValidator<T> le(
|
||||
final int max, final String errorMessage) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> IntPropertyValidator<DTO> le(
|
||||
int max, Supplier<E> exceptionCreator) {
|
||||
return le(max, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> IntPropertyValidator<T> le(
|
||||
final int max, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> IntPropertyValidator<DTO> le(
|
||||
int max, Function<Integer, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value <= max), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> IntPropertyValidator<T> le(
|
||||
final int max, final Function<Integer, X> exceptionFunction) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -135,7 +264,26 @@ public class IntPropertyValidator<DTO>
|
||||
// ================================
|
||||
|
||||
@Override
|
||||
protected IntPropertyValidator<DTO> thisObject() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,22 @@
|
||||
package xyz.zhouxy.plusone.validator;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class LongPropertyValidator<DTO>
|
||||
extends BaseComparablePropertyValidator<DTO, Long, LongPropertyValidator<DTO>> {
|
||||
/**
|
||||
* {@code Long} 类型属性的校验器
|
||||
*
|
||||
* <p>
|
||||
* 用于构建校验 {@code Long} 类型属性的规则链。
|
||||
*
|
||||
* @param <T> 待校验对象的类型
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public class LongPropertyValidator<T>
|
||||
extends BaseComparablePropertyValidator<T, Long, LongPropertyValidator<T>> {
|
||||
|
||||
LongPropertyValidator(Function<DTO, Long> getter) {
|
||||
LongPropertyValidator(Function<T, Long> getter) {
|
||||
super(getter);
|
||||
}
|
||||
|
||||
@@ -30,23 +40,53 @@ public class LongPropertyValidator<DTO>
|
||||
// #region - greater than
|
||||
// ================================
|
||||
|
||||
public LongPropertyValidator<DTO> gt(long min) {
|
||||
return gt(min, String.format("The value should be greater than %d", min));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final LongPropertyValidator<T> gt(final long min) {
|
||||
return withRule(Conditions.greaterThan(min),
|
||||
"The input must be greater than '%d'.", min);
|
||||
}
|
||||
|
||||
public LongPropertyValidator<DTO> gt(long min, String errMsg) {
|
||||
return gt(min, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final LongPropertyValidator<T> gt(
|
||||
final long min, final String errorMessage) {
|
||||
return withRule(Conditions.greaterThan(min), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> LongPropertyValidator<DTO> gt(
|
||||
long min, Supplier<E> exceptionCreator) {
|
||||
return gt(min, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> LongPropertyValidator<T> gt(
|
||||
final long min, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.greaterThan(min), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> LongPropertyValidator<DTO> gt(
|
||||
long min, Function<Long, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value > min), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> LongPropertyValidator<T> gt(
|
||||
final long min, final Function<Long, X> exceptionFunction) {
|
||||
return withRule(Conditions.greaterThan(min), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -57,23 +97,52 @@ public class LongPropertyValidator<DTO>
|
||||
// #region - greater than or equal to
|
||||
// ================================
|
||||
|
||||
public LongPropertyValidator<DTO> ge(long min) {
|
||||
return ge(min, String.format("The value should be greater than or equal to %d", min));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final LongPropertyValidator<T> ge(final long min) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min),
|
||||
"The input must be greater than or equal to '%d'.", min);
|
||||
}
|
||||
|
||||
public LongPropertyValidator<DTO> ge(long min, String errMsg) {
|
||||
return ge(min, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param min 最小值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final LongPropertyValidator<T> ge(final long min, final String errorMessage) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> LongPropertyValidator<DTO> ge(
|
||||
long min, Supplier<E> exceptionCreator) {
|
||||
return ge(min, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> LongPropertyValidator<T> ge(
|
||||
final long min, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> LongPropertyValidator<DTO> ge(
|
||||
long min, Function<Long, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value >= min), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否大于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> LongPropertyValidator<T> ge(
|
||||
final long min, final Function<Long, X> exceptionFunction) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -84,23 +153,53 @@ public class LongPropertyValidator<DTO>
|
||||
// #region - less than
|
||||
// ================================
|
||||
|
||||
public LongPropertyValidator<DTO> lt(long max) {
|
||||
return lt(max, String.format("The value should be less than %d", max));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final LongPropertyValidator<T> lt(final long max) {
|
||||
return withRule(Conditions.lessThan(max),
|
||||
"The input must be less than '%d'.", max);
|
||||
}
|
||||
|
||||
public LongPropertyValidator<DTO> lt(long max, String errMsg) {
|
||||
return lt(max, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final LongPropertyValidator<T> lt(
|
||||
final long max, final String errorMessage) {
|
||||
return withRule(Conditions.lessThan(max), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> LongPropertyValidator<DTO> lt(
|
||||
long max, Supplier<E> exceptionCreator) {
|
||||
return lt(max, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> LongPropertyValidator<T> lt(
|
||||
final long max, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.lessThan(max), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> LongPropertyValidator<DTO> lt(
|
||||
long max, Function<Long, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value < max), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> LongPropertyValidator<T> lt(
|
||||
final long max, final Function<Long, X> exceptionFunction) {
|
||||
return withRule(Conditions.lessThan(max), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -111,23 +210,53 @@ public class LongPropertyValidator<DTO>
|
||||
// #region - less than or equal to
|
||||
// ================================
|
||||
|
||||
public LongPropertyValidator<DTO> le(long max) {
|
||||
return le(max, String.format("The value should be less than or equal to %d", max));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final LongPropertyValidator<T> le(final long max) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max),
|
||||
"The input must be less than or equal to '%d'.", max);
|
||||
}
|
||||
|
||||
public LongPropertyValidator<DTO> le(long max, String errMsg) {
|
||||
return le(max, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param max 最大值
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final LongPropertyValidator<T> le(
|
||||
final long max, final String errorMessage) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> LongPropertyValidator<DTO> le(
|
||||
long max, Supplier<E> exceptionCreator) {
|
||||
return le(max, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> LongPropertyValidator<T> le(
|
||||
final long max, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> LongPropertyValidator<DTO> le(
|
||||
long max, Function<Long, E> exceptionCreator) {
|
||||
withRule(value -> (value != null && value <= max), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否小于等于给定值
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param max 最大值
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前验证器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> LongPropertyValidator<T> le(
|
||||
final long max, final Function<Long, X> exceptionFunction) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -135,7 +264,26 @@ public class LongPropertyValidator<DTO>
|
||||
// ================================
|
||||
|
||||
@Override
|
||||
protected LongPropertyValidator<DTO> thisObject() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,35 +16,76 @@
|
||||
|
||||
package xyz.zhouxy.plusone.validator;
|
||||
|
||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 对 Map 进行校验的校验器
|
||||
*
|
||||
* <p>
|
||||
* 校验后拷贝出一个新的 Map 对象,仅保留指定的 key。
|
||||
*
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
|
||||
|
||||
private final Set<K> keys;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param keys 要保留的 key 的集合
|
||||
*/
|
||||
protected MapValidator(K[] keys) {
|
||||
this(Arrays.asList(keys));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param keys 要保留的 key 的集合
|
||||
*/
|
||||
protected MapValidator(Collection<K> keys) {
|
||||
this.keys = keys.stream().collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
// ========== validate & validateAndCopy ==========
|
||||
// ================================
|
||||
// #region - validateAndCopy
|
||||
// ================================
|
||||
|
||||
/**
|
||||
* 校验并拷贝,仅保留指定 key 的属性。
|
||||
*
|
||||
* @param obj 待校验的 map
|
||||
* @return 拷贝后的 map
|
||||
*/
|
||||
public final Map<K, V> validateAndCopy(Map<K, V> obj) {
|
||||
return validateAndCopyInternal(obj, this.keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并拷贝,仅保留指定 key 的属性。
|
||||
*
|
||||
* @param obj 待校验的 map
|
||||
* @param keys 指定 key
|
||||
* @return 拷贝后的 map
|
||||
*/
|
||||
public final Map<K, V> validateAndCopy(Map<K, V> obj, Collection<K> keys) {
|
||||
return validateAndCopyInternal(obj, keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并拷贝,仅保留指定 key 的属性。
|
||||
*
|
||||
* @param obj 待校验的 map
|
||||
* @param keys 待校验的 key
|
||||
* @return 拷贝后的 map
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final Map<K, V> validateAndCopy(Map<K, V> obj, K... keys) {
|
||||
return validateAndCopyInternal(obj, Arrays.asList(keys));
|
||||
@@ -57,35 +98,119 @@ public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
// ========== ruleFor ==========
|
||||
// ================================
|
||||
// #endregion - validateAndCopy
|
||||
// ================================
|
||||
|
||||
protected final ObjectPropertyValidator<Map<K, V>, V> ruleFor(K key) {
|
||||
return ruleFor(m -> m.get(key));
|
||||
// ================================
|
||||
// #region - ruleFor
|
||||
// ================================
|
||||
|
||||
/**
|
||||
* 添加一个属性校验器,对指定 key 对应的 value 进行校验
|
||||
*
|
||||
* @param <T> 属性类型
|
||||
* @param key key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个属性校验器,对指定 key 对应的 {@code Integer} 类型的 value 进行校验
|
||||
*
|
||||
* @param key key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
protected final IntPropertyValidator<Map<K, V>> ruleForInt(K key) {
|
||||
return ruleForInt(m -> (Integer) m.get(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个属性校验器,对指定 key 对应的 {@code Long} 类型的 value 进行校验
|
||||
*
|
||||
* @param key key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
protected final LongPropertyValidator<Map<K, V>> ruleForLong(K key) {
|
||||
return ruleForLong(m -> (Long) m.get(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个属性校验器,对指定 key 对应的 {@code Double} 类型的 value 进行校验
|
||||
*
|
||||
* @param key key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
protected final DoublePropertyValidator<Map<K, V>> ruleForDouble(K key) {
|
||||
return ruleForDouble(m -> (Double) m.get(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个属性校验器,对指定 key 对应的 {@code Boolean} 类型的 value 进行校验
|
||||
*
|
||||
* @param key key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
protected final BoolPropertyValidator<Map<K, V>> ruleForBool(K key) {
|
||||
return ruleForBool(m -> (Boolean) m.get(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个属性校验器,对指定 key 对应的 {@code String} 类型的 value 进行校验
|
||||
*
|
||||
* @param key key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
protected final StringPropertyValidator<Map<K, V>> ruleForString(K key) {
|
||||
return ruleForString(m -> (String) m.get(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个属性校验器,对指定 key 对应的 {@code Comparable} 的 value 进行校验
|
||||
*
|
||||
* @param key key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
protected final <E extends Comparable<E>> ComparablePropertyValidator<Map<K, V>, E> ruleForComparable(K key) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Map<K, V>, E> getter = m -> (E) m.get(key);
|
||||
return ruleForComparable(getter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个属性校验器,对指定 key 对应的集合类型的 value 进行校验
|
||||
*
|
||||
* @param <E> 集合元素的类型
|
||||
* @param key key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
protected final <E> CollectionPropertyValidator<Map<K, V>, E> ruleForCollection(K key) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Map<K, V>, Collection<E>> getter = m -> (Collection<E>) m.get(key);
|
||||
return ruleForCollection(getter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个属性校验器,对指定的两个 key 对应的 value 进行校验
|
||||
* @param <V1> 第一个属性的类型
|
||||
* @param <V2> 第二个属性的类型
|
||||
* @param k1 第一个 key
|
||||
* @param k2 第二个 key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
protected final <V1 extends V, V2 extends V>
|
||||
PairPropertyValidator<Map<K, V>, V1, V2> ruleForPair(K k1, K k2) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Map<K, V>, Entry<V1, V2>> getter = m ->
|
||||
new SimpleImmutableEntry<>((V1) m.get(k1), (V2) m.get(k2));
|
||||
return ruleForPair(getter);
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - ruleFor
|
||||
// ================================
|
||||
}
|
||||
|
||||
@@ -18,14 +18,22 @@ package xyz.zhouxy.plusone.validator;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ObjectPropertyValidator<DTO, T> extends BasePropertyValidator<DTO, T, ObjectPropertyValidator<DTO, T>> {
|
||||
/**
|
||||
* 通用类型属性校验器。继承自 {@link BasePropertyValidator},包含针对属性的校验规则。
|
||||
*
|
||||
* @param <T> 待校验对象的类型
|
||||
* @param <TProperty> 待校验属性的类型
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public class ObjectPropertyValidator<T, TProperty>
|
||||
extends BasePropertyValidator<T, TProperty, ObjectPropertyValidator<T, TProperty>> {
|
||||
|
||||
ObjectPropertyValidator(Function<DTO, T> getter) {
|
||||
ObjectPropertyValidator(Function<T, TProperty> getter) {
|
||||
super(getter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectPropertyValidator<DTO, T> thisObject() {
|
||||
protected ObjectPropertyValidator<T, TProperty> thisObject() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -17,30 +17,30 @@
|
||||
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 com.google.common.base.Strings;
|
||||
|
||||
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} 类型属性的规则链。
|
||||
*
|
||||
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
|
||||
* @param <T> 待校验对象的类型
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public class StringPropertyValidator<DTO> extends BaseComparablePropertyValidator<DTO, String, StringPropertyValidator<DTO>> {
|
||||
public class StringPropertyValidator<T>
|
||||
extends BaseComparablePropertyValidator<T, String, StringPropertyValidator<T>> {
|
||||
|
||||
StringPropertyValidator(Function<DTO, String> getter) {
|
||||
StringPropertyValidator(Function<T, String> getter) {
|
||||
super(getter);
|
||||
}
|
||||
|
||||
@@ -48,21 +48,42 @@ public class StringPropertyValidator<DTO> extends BaseComparablePropertyValidato
|
||||
// #region - matches
|
||||
// ================================
|
||||
|
||||
public StringPropertyValidator<DTO> matches(Pattern regex, String errMsg) {
|
||||
return matches(regex, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配正则表达式
|
||||
*
|
||||
* @param pattern 正则表达式
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> matches(
|
||||
final Pattern pattern, final String errorMessage) {
|
||||
return withRule(Conditions.matches(pattern), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> matches(
|
||||
Pattern regex,
|
||||
Supplier<E> exceptionCreator) {
|
||||
return matches(regex, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配正则表达式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param pattern 正则表达式
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public <X extends RuntimeException> StringPropertyValidator<T> matches(
|
||||
final Pattern pattern, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.matches(pattern), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> matches(
|
||||
Pattern regex,
|
||||
Function<String, E> exceptionCreator) {
|
||||
withRule(input -> RegexTools.matches(input, regex), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配正则表达式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param pattern 正则表达式
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> matches(
|
||||
final Pattern pattern, final Function<String, X> exceptionFunction) {
|
||||
return withRule(Conditions.matches(pattern), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -70,83 +91,167 @@ public class StringPropertyValidator<DTO> extends BaseComparablePropertyValidato
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - matchesOne
|
||||
// #region - matchesAny
|
||||
// ================================
|
||||
|
||||
public StringPropertyValidator<DTO> matchesOne(Pattern[] regexs, String errMsg) {
|
||||
return matchesOne(regexs, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
|
||||
*
|
||||
* @param patterns 正则表达式
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> matchesAny(
|
||||
final Pattern[] patterns, final String errorMessage) {
|
||||
return withRule(Conditions.matchesAny(patterns), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> matchesOne(
|
||||
Pattern[] regexs,
|
||||
Supplier<E> exceptionCreator) {
|
||||
return matchesOne(regexs, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param patterns 正则表达式
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAny(
|
||||
final Pattern[] patterns, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.matchesAny(patterns), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> matchesOne(
|
||||
Pattern[] regexs,
|
||||
Function<String, E> exceptionCreator) {
|
||||
withRule(input -> RegexTools.matchesOne(input, regexs), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param patterns 正则表达式
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAny(
|
||||
final Pattern[] patterns, final Function<String, X> exceptionFunction) {
|
||||
return withRule(Conditions.matchesAny(patterns), exceptionFunction);
|
||||
}
|
||||
|
||||
public StringPropertyValidator<DTO> matchesOne(List<Pattern> regexs, String errMsg) {
|
||||
return matchesOne(regexs, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
|
||||
*
|
||||
* @param patterns 正则表达式
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> matchesAny(
|
||||
final Collection<Pattern> patterns, final String errorMessage) {
|
||||
return withRule(Conditions.matchesAny(patterns), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> matchesOne(
|
||||
List<Pattern> regexs,
|
||||
Supplier<E> exceptionCreator) {
|
||||
return matchesOne(regexs, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param patterns 正则表达式
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAny(
|
||||
final Collection<Pattern> patterns, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.matchesAny(patterns), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> matchesOne(
|
||||
List<Pattern> regexs,
|
||||
Function<String, E> exceptionCreator) {
|
||||
withRule(input -> RegexTools.matchesOne(input, regexs.toArray(new Pattern[regexs.size()])), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的任一正则表达式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param patterns 正则表达式
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
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
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - matchesAll
|
||||
// ================================
|
||||
|
||||
public StringPropertyValidator<DTO> matchesAll(Pattern[] regexs, String errMsg) {
|
||||
return matchesAll(regexs, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
|
||||
*
|
||||
* @param patterns 正则表达式
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> matchesAll(
|
||||
final Pattern[] patterns, final String errorMessage) {
|
||||
return withRule(Conditions.matchesAll(patterns), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> matchesAll(
|
||||
Pattern[] regexs,
|
||||
Supplier<E> exceptionCreator) {
|
||||
return matchesAll(regexs, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param patterns 正则表达式
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAll(
|
||||
final Pattern[] patterns, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.matchesAll(patterns), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> matchesAll(
|
||||
Pattern[] regexs,
|
||||
Function<String, E> exceptionCreator) {
|
||||
withRule(input -> RegexTools.matchesAll(input, regexs), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param patterns 正则表达式
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAll(
|
||||
final Pattern[] patterns, final Function<String, X> exceptionFunction) {
|
||||
return withRule(Conditions.matchesAll(patterns), exceptionFunction);
|
||||
}
|
||||
|
||||
public StringPropertyValidator<DTO> matchesAll(Collection<Pattern> regexs, String errMsg) {
|
||||
return matchesAll(regexs, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
|
||||
*
|
||||
* @param patterns 正则表达式
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> matchesAll(
|
||||
final Collection<Pattern> patterns, final String errorMessage) {
|
||||
return withRule(Conditions.matchesAll(patterns), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> matchesAll(
|
||||
Collection<Pattern> regexs,
|
||||
Supplier<E> exceptionCreator) {
|
||||
return matchesAll(regexs, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param patterns 正则表达式
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAll(
|
||||
final Collection<Pattern> patterns, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.matchesAll(patterns), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> matchesAll(
|
||||
Collection<Pattern> regexs,
|
||||
Function<String, E> exceptionCreator) {
|
||||
withRule(input -> RegexTools.matchesAll(input, regexs.toArray(new Pattern[regexs.size()])), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否匹配指定的所有正则表达式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param patterns 正则表达式
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> matchesAll(
|
||||
final Collection<Pattern> patterns, final Function<String, X> exceptionFunction) {
|
||||
return withRule(Conditions.matchesAll(patterns), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -157,22 +262,48 @@ public class StringPropertyValidator<DTO> extends BaseComparablePropertyValidato
|
||||
// #region - notBlank
|
||||
// ================================
|
||||
|
||||
public StringPropertyValidator<DTO> notBlank() {
|
||||
return notBlank("This String argument must have text; it must not be null, empty, or blank");
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否不为空白字符串
|
||||
*
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> notBlank() {
|
||||
return withRule(Conditions.notBlank(),
|
||||
"The input must not be blank.");
|
||||
}
|
||||
|
||||
public StringPropertyValidator<DTO> notBlank(String errMsg) {
|
||||
return notBlank(convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否不为空白字符串
|
||||
*
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> notBlank(final String errorMessage) {
|
||||
return withRule(Conditions.notBlank(), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> notBlank(Supplier<E> exceptionCreator) {
|
||||
return notBlank(convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否不为空白字符串
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> notBlank(
|
||||
final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.notBlank(), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> notBlank(
|
||||
Function<String, E> exceptionCreator) {
|
||||
withRule(StringTools::isNotBlank, exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否不为空白字符串
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> notBlank(
|
||||
final Function<String, X> exceptionFunction) {
|
||||
return withRule(Conditions.notBlank(), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -183,22 +314,48 @@ public class StringPropertyValidator<DTO> extends BaseComparablePropertyValidato
|
||||
// #region - emailAddress
|
||||
// ================================
|
||||
|
||||
public StringPropertyValidator<DTO> emailAddress() {
|
||||
return emailAddress("The value is not an email address.");
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否满足邮箱格式
|
||||
*
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> emailAddress() {
|
||||
return withRule(Conditions.emailAddress(),
|
||||
"The input is not a valid email address.");
|
||||
}
|
||||
|
||||
public StringPropertyValidator<DTO> emailAddress(String errMsg) {
|
||||
return emailAddress(convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否满足邮箱格式
|
||||
*
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> emailAddress(final String errorMessage) {
|
||||
return withRule(Conditions.emailAddress(), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> emailAddress(
|
||||
Supplier<E> exceptionCreator) {
|
||||
return emailAddress(convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否满足邮箱格式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> emailAddress(
|
||||
final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.emailAddress(), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> emailAddress(
|
||||
Function<String, E> exceptionCreator) {
|
||||
return matches(PatternConsts.EMAIL, exceptionCreator);
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否满足邮箱格式
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> emailAddress(
|
||||
final Function<String, X> exceptionFunction) {
|
||||
return withRule(Conditions.emailAddress(), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -209,90 +366,135 @@ public class StringPropertyValidator<DTO> extends BaseComparablePropertyValidato
|
||||
// #region - notEmpty
|
||||
// ================================
|
||||
|
||||
public StringPropertyValidator<DTO> notEmpty(String errMsg) {
|
||||
return notEmpty(convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验字符串属性是否不为空
|
||||
*
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> notEmpty() {
|
||||
return withRule(Conditions.notEmpty(),
|
||||
"The input must not be empty.");
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> notEmpty(Supplier<E> exceptionCreator) {
|
||||
return notEmpty(convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验字符串属性是否不为空
|
||||
*
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> notEmpty(final String errorMessage) {
|
||||
return withRule(Conditions.notEmpty(), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> notEmpty(
|
||||
Function<String, E> exceptionCreator) {
|
||||
withRule(s -> s != null && !s.isEmpty(), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验字符串属性是否不为空
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> notEmpty(
|
||||
final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.notEmpty(), exceptionSupplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验字符串属性是否不为空
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> notEmpty(
|
||||
final Function<String, X> exceptionFunction) {
|
||||
return withRule(Conditions.notEmpty(), exceptionFunction);
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - notEmpty
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - isNullOrEmpty
|
||||
// ================================
|
||||
|
||||
public StringPropertyValidator<DTO> isNullOrEmpty(String errMsg) {
|
||||
return isNullOrEmpty(convertExceptionCreator(errMsg));
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> isNullOrEmpty(Supplier<E> exceptionCreator) {
|
||||
return isNullOrEmpty(convertExceptionCreator(exceptionCreator));
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> isNullOrEmpty(
|
||||
Function<String, E> exceptionCreator) {
|
||||
withRule(Strings::isNullOrEmpty, exceptionCreator);
|
||||
return this;
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - isNullOrEmpty
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - length
|
||||
// ================================
|
||||
|
||||
public StringPropertyValidator<DTO> length(int length, String errMsg) {
|
||||
return length(length, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性长度是否等于指定长度
|
||||
*
|
||||
* @param length 指定长度
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> length(
|
||||
final int length, final String errorMessage) {
|
||||
return withRule(Conditions.length(length), errorMessage);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> length(int length,
|
||||
Supplier<E> exceptionCreator) {
|
||||
return length(length, convertExceptionCreator(exceptionCreator));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性长度是否等于指定长度
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param length 指定长度
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> length(
|
||||
final int length, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.length(length), exceptionSupplier);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> length(int length,
|
||||
Function<String, E> exceptionCreator) {
|
||||
AssertTools.checkArgument(length >= 0,
|
||||
"The required length must be greater than or equal to 0.");
|
||||
withRule(s -> s != null && s.length() == length, exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性长度是否等于指定长度
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param length 指定长度
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> StringPropertyValidator<T> length(
|
||||
final int length, final Function<String, X> exceptionFunction) {
|
||||
return withRule(Conditions.length(length), exceptionFunction);
|
||||
}
|
||||
|
||||
static boolean length(String str, int min, int max) {
|
||||
if (str == null) {
|
||||
return false;
|
||||
}
|
||||
final int len = str.length();
|
||||
return len >= min && len < max;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性的长度范围
|
||||
*
|
||||
* @param min 最小长度(包含)
|
||||
* @param max 最大长度(包含)
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final StringPropertyValidator<T> length(
|
||||
final int min, final int max, final String errorMessage) {
|
||||
return withRule(Conditions.length(min, max), errorMessage);
|
||||
}
|
||||
|
||||
public StringPropertyValidator<DTO> length(int min, int max, String errMsg) {
|
||||
return length(min, max, convertExceptionCreator(errMsg));
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性的长度范围
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小长度(包含)
|
||||
* @param max 最大长度(包含)
|
||||
* @param exceptionSupplier 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> length(int min, int max,
|
||||
Supplier<E> exceptionCreator) {
|
||||
return length(min, max, convertExceptionCreator(exceptionCreator));
|
||||
}
|
||||
|
||||
public <E extends RuntimeException> StringPropertyValidator<DTO> length(int min, int max,
|
||||
Function<String, E> exceptionCreator) {
|
||||
AssertTools.checkArgument(min >= 0, "The minimum value must be greater than equal to 0.");
|
||||
AssertTools.checkArgument(min < max, "The minimum value must be less than the maximum value.");
|
||||
withRule(s -> length(s, min, max), exceptionCreator);
|
||||
return this;
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性的长度范围
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param min 最小长度(包含)
|
||||
* @param max 最大长度(包含)
|
||||
* @param exceptionFunction 自定义异常
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -300,7 +502,66 @@ public class StringPropertyValidator<DTO> extends BaseComparablePropertyValidato
|
||||
// ================================
|
||||
|
||||
@Override
|
||||
protected StringPropertyValidator<DTO> thisObject() {
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022-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;
|
||||
|
||||
/**
|
||||
* 校验工具类
|
||||
* <p>
|
||||
* 对 {@link IValidateRequired} 的实现类对象进行校验
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
*
|
||||
* @see BaseValidator
|
||||
* @see Validator
|
||||
* @see IValidateRequired
|
||||
*/
|
||||
public class ValidTools {
|
||||
private ValidTools() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static void validate(Object obj) {
|
||||
if (obj instanceof IValidateRequired) {
|
||||
((IValidateRequired) obj).validate();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void validate(T obj, BaseValidator<T> validator) {
|
||||
validator.validate(obj);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* 校验失败异常
|
||||
*
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public class ValidationException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -49385010625414401L;
|
||||
|
||||
public static final String DEFAULT_MESSAGE = "Validation failed.";
|
||||
|
||||
private ValidationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
private ValidationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
private ValidationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 {@code ValidationException} 实例
|
||||
*
|
||||
* @return {@code ValidationException} 实例
|
||||
*/
|
||||
public static ValidationException withDefaultMessage() {
|
||||
return new ValidationException(DEFAULT_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 {@code ValidationException} 实例
|
||||
*
|
||||
* @param message 异常信息
|
||||
* @return {@code ValidationException} 实例
|
||||
*/
|
||||
public static ValidationException withMessage(String message) {
|
||||
return new ValidationException(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 {@code ValidationException} 实例
|
||||
*
|
||||
* @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 导致校验失败的根本异常
|
||||
* @return {@code ValidationException} 实例
|
||||
*/
|
||||
public static ValidationException withCause(Throwable cause) {
|
||||
return new ValidationException(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 {@code ValidationException} 实例
|
||||
*
|
||||
* @param message 异常信息
|
||||
* @param cause 导致校验失败的根本异常
|
||||
* @return {@code ValidationException} 实例
|
||||
*/
|
||||
public static ValidationException withMessageAndCause(String message, Throwable cause) {
|
||||
return new ValidationException(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022-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.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 校验器
|
||||
*
|
||||
* <p>
|
||||
* 可以使用以下方式初始化一个校验器:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* var validator = new Validator<Integer>()
|
||||
* .addRule(value -> Objects.nonNull(value), "value 不能为空")
|
||||
* .addRule(value -> (value >= 0 && value <= 500), "value 应在 [0, 500] 内");
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* 然后通过校验器的 {@link #validate} 方法,或
|
||||
* {@link ValidTools#validate(Object, Validator)} 对指定对象进行校验。
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* validator.validate(666);
|
||||
* </pre>
|
||||
*
|
||||
* <pre>
|
||||
* ValidTools.validate(255, validator);
|
||||
* </pre>
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
* @see IValidateRequired
|
||||
* @see ValidTools
|
||||
* @see BaseValidator
|
||||
*/
|
||||
public final class Validator<T> extends BaseValidator<T> {
|
||||
public final Validator<T> addRule(final Predicate<? super T> rule, final String errorMessage) {
|
||||
withRule(rule, errorMessage);
|
||||
return this;
|
||||
}
|
||||
|
||||
public final <E extends RuntimeException> Validator<T> addRule(Predicate<? super T> rule, Supplier<E> exceptionCreator) {
|
||||
withRule(rule, exceptionCreator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public final <E extends RuntimeException> Validator<T> addRule(Predicate<? super T> rule, Function<T, E> exceptionCreator) {
|
||||
withRule(rule, exceptionCreator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public final Validator<T> addRule(Consumer<? super T> rule) {
|
||||
withRule(rule);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Function<T, Boolean>
|
||||
*
|
||||
* @author ZhouXY
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ToBoolObjectFunction<T> extends Function<T, Boolean>, Serializable {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Function<T, Double>
|
||||
*
|
||||
* @author ZhouXY
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ToDoubleObjectFunction<T> extends Function<T, Double>, Serializable {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Function<T, Integer>
|
||||
*
|
||||
* @author ZhouXY
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ToIntegerFunction<T> extends Function<T, Integer>, Serializable {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Function<T, Long>
|
||||
*
|
||||
* @author ZhouXY
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ToLongObjectFunction<T> extends Function<T, Long>, Serializable {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.function;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Function<T, String>
|
||||
*
|
||||
* @author ZhouXY
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ToStringFunction<T> extends Function<T, String>, Serializable {
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
|
||||
|
||||
public class ExampleException extends RuntimeException {
|
||||
|
||||
private ExampleException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@StaticFactoryMethod
|
||||
public static ExampleException withMessage(String message) {
|
||||
return new ExampleException(message);
|
||||
}
|
||||
|
||||
@StaticFactoryMethod
|
||||
public static ExampleException withMessage(String format, Object... args) {
|
||||
return new ExampleException(String.format(format, args));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 接口入参的 DTO 示例
|
||||
*/
|
||||
public class ExampleCommand {
|
||||
private Boolean boolProperty;
|
||||
private Integer intProperty;
|
||||
private Long longProperty;
|
||||
private Double doubleProperty;
|
||||
private String stringProperty;
|
||||
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, String[] stringArrayProperty) {
|
||||
this.boolProperty = boolProperty;
|
||||
this.intProperty = intProperty;
|
||||
this.longProperty = longProperty;
|
||||
this.doubleProperty = doubleProperty;
|
||||
this.stringProperty = stringProperty;
|
||||
this.dateTimeProperty = dateTimeProperty;
|
||||
this.objectProperty = objectProperty;
|
||||
this.stringListProperty = stringListProperty;
|
||||
this.stringArrayProperty = stringArrayProperty;
|
||||
}
|
||||
|
||||
public Boolean getBoolProperty() {
|
||||
return boolProperty;
|
||||
}
|
||||
|
||||
public void setBoolProperty(Boolean boolProperty) {
|
||||
this.boolProperty = boolProperty;
|
||||
}
|
||||
|
||||
public Integer getIntProperty() {
|
||||
return intProperty;
|
||||
}
|
||||
|
||||
public void setIntProperty(Integer intProperty) {
|
||||
this.intProperty = intProperty;
|
||||
}
|
||||
|
||||
public Long getLongProperty() {
|
||||
return longProperty;
|
||||
}
|
||||
|
||||
public void setLongProperty(Long longProperty) {
|
||||
this.longProperty = longProperty;
|
||||
}
|
||||
|
||||
public Double getDoubleProperty() {
|
||||
return doubleProperty;
|
||||
}
|
||||
|
||||
public void setDoubleProperty(Double doubleProperty) {
|
||||
this.doubleProperty = doubleProperty;
|
||||
}
|
||||
|
||||
public String getStringProperty() {
|
||||
return stringProperty;
|
||||
}
|
||||
|
||||
public void setStringProperty(String stringProperty) {
|
||||
this.stringProperty = stringProperty;
|
||||
}
|
||||
|
||||
public LocalDateTime getDateTimeProperty() {
|
||||
return dateTimeProperty;
|
||||
}
|
||||
|
||||
public void setDateTimeProperty(LocalDateTime dateTimeProperty) {
|
||||
this.dateTimeProperty = dateTimeProperty;
|
||||
}
|
||||
|
||||
public Foo getObjectProperty() {
|
||||
return objectProperty;
|
||||
}
|
||||
|
||||
public void setObjectProperty(Foo objectProperty) {
|
||||
this.objectProperty = objectProperty;
|
||||
}
|
||||
|
||||
public List<String> getStringListProperty() {
|
||||
return stringListProperty;
|
||||
}
|
||||
|
||||
public void setStringListProperty(List<String> stringListProperty) {
|
||||
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 + ", stringArrayProperty="
|
||||
+ Arrays.toString(stringArrayProperty) + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Foo {
|
||||
private Integer intProperty;
|
||||
private String stringProperty;
|
||||
|
||||
public Foo() {
|
||||
}
|
||||
|
||||
public Foo(Integer intProperty, String stringProperty) {
|
||||
this.intProperty = intProperty;
|
||||
this.stringProperty = stringProperty;
|
||||
}
|
||||
|
||||
public Integer getIntProperty() {
|
||||
return intProperty;
|
||||
}
|
||||
|
||||
public void setIntProperty(Integer intProperty) {
|
||||
this.intProperty = intProperty;
|
||||
}
|
||||
|
||||
public String getStringProperty() {
|
||||
return stringProperty;
|
||||
}
|
||||
|
||||
public void setStringProperty(String stringProperty) {
|
||||
this.stringProperty = stringProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Foo [intProperty=" + intProperty + ", stringProperty=" + stringProperty + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(intProperty, stringProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (!(obj instanceof Foo))
|
||||
return false;
|
||||
Foo other = (Foo) obj;
|
||||
return Objects.equals(intProperty, other.intProperty) && Objects.equals(stringProperty, other.stringProperty);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.example.validator;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
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;
|
||||
|
||||
class BaseValidatorTest {
|
||||
|
||||
@Test
|
||||
void withRule_validInput() {
|
||||
ExampleCommand exampleCommand = new ExampleCommand();
|
||||
exampleCommand.setStringProperty("Foo");
|
||||
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
withRule(command -> Objects.equals(command.getStringProperty(), "Foo"),
|
||||
"The stringProperty must be equal to 'Foo'");
|
||||
withRule(command -> Objects.equals(command.getStringProperty(), "Foo"),
|
||||
() -> ExampleException.withMessage("The stringProperty must be equal to 'Foo'"));
|
||||
withRule(command -> Objects.equals(command.getStringProperty(), "Foo"),
|
||||
str -> ExampleException.withMessage("The stringProperty must be equal to 'Foo', but is was '%s'.", str));
|
||||
withRule(command -> {
|
||||
final String stringProperty = command.getStringProperty();
|
||||
if (!Objects.equals(stringProperty, "Foo")) {
|
||||
throw ExampleException.withMessage("");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
assertDoesNotThrow(() -> validator.validate(exampleCommand));
|
||||
}
|
||||
|
||||
@Test
|
||||
void withRule_invalidInput() {
|
||||
ExampleCommand command = new ExampleCommand();
|
||||
|
||||
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
withRule(command -> Objects.equals(command.getStringProperty(), "Foo"),
|
||||
"The stringProperty must be equal to 'Foo'");
|
||||
}
|
||||
};
|
||||
ValidationException eWithSpecifiedMessage = assertThrows(
|
||||
ValidationException.class, () -> ruleWithMessage.validate(command));
|
||||
assertEquals("The stringProperty must be equal to 'Foo'", eWithSpecifiedMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
withRule(command -> Objects.equals(command.getStringProperty(), "Foo"),
|
||||
() -> ExampleException.withMessage("The stringProperty must be equal to 'Foo'"));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> ruleWithExceptionSupplier.validate(command));
|
||||
assertEquals("The stringProperty must be equal to 'Foo'", specifiedException.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
withRule(command -> Objects.equals(command.getStringProperty(), "Foo"), command -> ExampleException
|
||||
.withMessage("The stringProperty must be equal to 'Foo', but is was '%s'.", command.getStringProperty()));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException2 = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> ruleWithExceptionFunction.validate(command));
|
||||
assertEquals("The stringProperty must be equal to 'Foo', but is was 'null'.", specifiedException2.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> rule = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
withRule(command -> {
|
||||
final String stringProperty = command.getStringProperty();
|
||||
if (!Objects.equals(stringProperty, "Foo")) {
|
||||
throw ExampleException.withMessage("");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
ExampleException e = assertThrows(ExampleException.class, () -> rule.validate(command));
|
||||
assertEquals("", e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* 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.*;
|
||||
|
||||
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;
|
||||
|
||||
public class BoolPropertyValidatorTests {
|
||||
|
||||
// ================================
|
||||
// #region - isTrueValue
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void isTrueValue_trueProperty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty).isTrueValue();
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isTrueValue("The boolProperty should be true.");
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isTrueValue(() -> ExampleException.withMessage("The boolProperty should be true."));
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isTrueValue(property -> ExampleException.withMessage(
|
||||
"The boolProperty should be true, but it is `%s`", property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(true);
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isTrueValue_default_falseProperty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty).isTrueValue();
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(false);
|
||||
|
||||
ValidationException exception = assertThrows(
|
||||
ValidationException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals("The input must be true.", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isTrueValue_message_falseProperty() {
|
||||
final String message = "The boolProperty should be true.";
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isTrueValue(message);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(false);
|
||||
|
||||
ValidationException exception = assertThrows(
|
||||
ValidationException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals(message, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isTrueValue_exceptionSupplier_falseProperty() {
|
||||
final String message = "The boolProperty should be true.";
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isTrueValue(() -> ExampleException.withMessage(message));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(false);
|
||||
|
||||
ExampleException exception = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals(message, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isTrueValue_exceptionFunction_falseProperty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isTrueValue(property -> ExampleException.withMessage(
|
||||
"The boolProperty should be true, but it is `%s`", property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(false);
|
||||
|
||||
ExampleException exception = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals("The boolProperty should be true, but it is `false`", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isTrueValue_default_nullProperty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty).isTrueValue();
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(null);
|
||||
|
||||
ValidationException exception = assertThrows(
|
||||
ValidationException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals("The input must be true.", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isTrueValue_message_nullProperty() {
|
||||
final String message = "The boolProperty should be true.";
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isTrueValue(message);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(null);
|
||||
|
||||
ValidationException exception = assertThrows(
|
||||
ValidationException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals(message, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isTrueValue_exceptionSupplier_nullProperty() {
|
||||
final String message = "The boolProperty should be true.";
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isTrueValue(() -> ExampleException.withMessage(message));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(null);
|
||||
|
||||
ExampleException exception = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals(message, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isTrueValue_exceptionFunction_nullProperty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isTrueValue(property -> ExampleException.withMessage(
|
||||
"The boolProperty should be true, but it is `%s`", property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(null);
|
||||
|
||||
ExampleException exception = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals("The boolProperty should be true, but it is `null`", exception.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - isTrueValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - isFalseValue
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void isFalseValue_falseProperty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty).isFalseValue();
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isFalseValue("The boolProperty should be false.");
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isFalseValue(() -> ExampleException.withMessage("The boolProperty should be false."));
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isFalseValue(property -> ExampleException.withMessage(
|
||||
"The boolProperty should be false, but it is `%s`", property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(false);
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isFalseValue_default_trueProperty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty).isFalseValue();
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(true);
|
||||
|
||||
ValidationException exception = assertThrows(
|
||||
ValidationException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals("The input must be false.", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isFalseValue_message_trueProperty() {
|
||||
final String message = "The boolProperty should be false.";
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isFalseValue(message);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(true);
|
||||
|
||||
ValidationException exception = assertThrows(
|
||||
ValidationException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals(message, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isFalseValue_exceptionSupplier_trueProperty() {
|
||||
final String message = "The boolProperty should be false.";
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isFalseValue(() -> ExampleException.withMessage(message));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(true);
|
||||
|
||||
ExampleException exception = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals(message, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isFalseValue_exceptionFunction_trueProperty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isFalseValue(property -> ExampleException.withMessage(
|
||||
"The boolProperty should be false, but it is `%s`", property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(true);
|
||||
|
||||
ExampleException exception = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals("The boolProperty should be false, but it is `true`", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isFalseValue_default_nullProperty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty).isFalseValue();
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(null);
|
||||
|
||||
ValidationException exception = assertThrows(
|
||||
ValidationException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals("The input must be false.", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isFalseValue_message_nullProperty() {
|
||||
final String message = "The boolProperty should be false.";
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isFalseValue(message);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(null);
|
||||
|
||||
ValidationException exception = assertThrows(
|
||||
ValidationException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals(message, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isFalseValue_exceptionSupplier_nullProperty() {
|
||||
final String message = "The boolProperty should be false.";
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isFalseValue(() -> ExampleException.withMessage(message));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(null);
|
||||
|
||||
ExampleException exception = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals(message, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void isFalseValue_exceptionFunction_nullProperty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForBool(ExampleCommand::getBoolProperty)
|
||||
.isFalseValue(property -> ExampleException.withMessage(
|
||||
"The boolProperty should be false, but it is `%s`", property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithBoolProperty(null);
|
||||
|
||||
ExampleException exception = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals("The boolProperty should be false, but it is `null`", exception.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - isFalseValue
|
||||
// ================================
|
||||
|
||||
static ExampleCommand exampleCommandWithBoolProperty(Boolean boolProperty) {
|
||||
ExampleCommand exampleCommand = new ExampleCommand();
|
||||
exampleCommand.setBoolProperty(boolProperty);
|
||||
return exampleCommand;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,520 @@
|
||||
/*
|
||||
* 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 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;
|
||||
|
||||
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 CollectionPropertyValidatorTests {
|
||||
|
||||
static final String MESSAGE_NOT_EMPTY = "The stringListProperty should not be empty.";
|
||||
static final String MESSAGE_EMPTY = "The stringListProperty should be empty.";
|
||||
|
||||
// ================================
|
||||
// #region - notEmpty
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void notEmpty_stringListIsNotEmpty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).notEmpty();
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).notEmpty(MESSAGE_NOT_EMPTY);
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.notEmpty(() -> ExampleException.withMessage(MESSAGE_NOT_EMPTY));
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.notEmpty(strList -> ExampleException.withMessage(
|
||||
"The stringListProperty should not be empty, but it is %s.", strList));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("A", "B", "C"));
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void notEmpty_default_stringListIsEmpty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).notEmpty();
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Collections.emptyList());
|
||||
|
||||
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>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).notEmpty(MESSAGE_NOT_EMPTY);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Collections.emptyList());
|
||||
|
||||
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>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.notEmpty(() -> ExampleException.withMessage(MESSAGE_NOT_EMPTY));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Collections.emptyList());
|
||||
|
||||
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>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.notEmpty(strList -> ExampleException.withMessage(
|
||||
"The stringListProperty should not be empty, but it is %s.", strList));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Collections.emptyList());
|
||||
|
||||
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals("The stringListProperty should not be empty, but it is [].", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void notEmpty_message_stringListIsNull() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).notEmpty(MESSAGE_NOT_EMPTY);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(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>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.notEmpty(() -> ExampleException.withMessage(MESSAGE_NOT_EMPTY));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(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>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.notEmpty(strList -> ExampleException.withMessage(
|
||||
"The stringListProperty should not be empty, but it is %s.", strList));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(null);
|
||||
|
||||
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals("The stringListProperty should not be empty, but it is null.", e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - notEmpty
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - isEmpty
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void isEmpty_stringListIsEmpty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).isEmpty();
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).isEmpty(MESSAGE_EMPTY);
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.isEmpty(() -> ExampleException.withMessage(MESSAGE_EMPTY));
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.isEmpty(strList -> ExampleException.withMessage(
|
||||
"The stringListProperty should be empty, but it is %s.", strList));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Collections.emptyList());
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isEmpty_stringListIsNull() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).isEmpty();
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).isEmpty(MESSAGE_EMPTY);
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.isEmpty(() -> ExampleException.withMessage(MESSAGE_EMPTY));
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.isEmpty(strList -> ExampleException.withMessage(
|
||||
"The stringListProperty should be empty, but it is %s.", strList));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(null);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isEmpty_default_stringListIsNotEmpty() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).isEmpty();
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("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>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty).isEmpty(MESSAGE_EMPTY);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("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>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.isEmpty(() -> ExampleException.withMessage(MESSAGE_EMPTY));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("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>() {
|
||||
{
|
||||
ruleForCollection(ExampleCommand::getStringListProperty)
|
||||
.isEmpty(strList -> ExampleException.withMessage(
|
||||
"The stringListProperty should be empty, but it is %s.", strList));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("A", "B", "C"));
|
||||
|
||||
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals("The stringListProperty 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>() {
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.chrono.ChronoLocalDateTime;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
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 ComparablePropertyValidatorTests {
|
||||
|
||||
static final LocalDateTime MIN = LocalDate.of(2025, 5, 1).atStartOfDay();
|
||||
static final LocalDateTime MAX = LocalDate.of(2025, 5, 31).atStartOfDay();
|
||||
static final Range<ChronoLocalDateTime<?>> DATE_TIME_RANGE = Range.closedOpen(MIN, MAX);
|
||||
|
||||
static final String MESSAGE = String.format("The value should in the interval [%s,%s)", MIN, MAX);
|
||||
|
||||
// ================================
|
||||
// #region - in the interval
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void inRange_valueIsInTheInterval() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForComparable(ExampleCommand::getDateTimeProperty)
|
||||
.inRange(DATE_TIME_RANGE);
|
||||
ruleForComparable(ExampleCommand::getDateTimeProperty)
|
||||
.inRange(DATE_TIME_RANGE, MESSAGE);
|
||||
ruleForComparable(ExampleCommand::getDateTimeProperty)
|
||||
.inRange(DATE_TIME_RANGE, () -> ExampleException.withMessage(MESSAGE));
|
||||
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));
|
||||
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.inRange(Range.closed(18, 60));
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.inRange(Range.closed(10000000000L, 20000000000L));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithComparableProperty(18, 10000000000L, MIN);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - in the interval
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - not in the interval
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void inRange_default_valueIsNotInTheInterval() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForComparable(ExampleCommand::getDateTimeProperty)
|
||||
.inRange(DATE_TIME_RANGE);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithComparableProperty(18, 10000000000L, MAX);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
final String expected = String.format("The input must in the interval %s. You entered %s.", DATE_TIME_RANGE, MAX);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void inRange_message_valueIsNotInTheInterval() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForComparable(ExampleCommand::getDateTimeProperty)
|
||||
.inRange(DATE_TIME_RANGE, MESSAGE);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithComparableProperty(18, 10000000000L, MAX);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals(MESSAGE, e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void inRange_exceptionSupplier_valueIsNotInTheInterval() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForComparable(ExampleCommand::getDateTimeProperty)
|
||||
.inRange(DATE_TIME_RANGE, () -> ExampleException.withMessage(MESSAGE));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithComparableProperty(18, 10000000000L, MAX);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
assertEquals(MESSAGE, e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void inRange_exceptionFunction_valueIsNotInTheInterval() {
|
||||
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(18, 10000000000L, MAX);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class,
|
||||
() -> validator.validate(command));
|
||||
|
||||
final String expected = String.format("The dateTimeProperty should in the interval [%s,%s), but it is %s", MIN, MAX, MAX);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - not in the interval
|
||||
// ================================
|
||||
|
||||
static ExampleCommand exampleCommandWithComparableProperty(
|
||||
Integer intProperty,
|
||||
Long longProperty,
|
||||
LocalDateTime dateTimeProperty) {
|
||||
ExampleCommand exampleCommand = new ExampleCommand();
|
||||
exampleCommand.setIntProperty(intProperty);
|
||||
exampleCommand.setLongProperty(longProperty);
|
||||
exampleCommand.setDateTimeProperty(dateTimeProperty);
|
||||
return exampleCommand;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
* 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.*;
|
||||
|
||||
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 DoublePropertyValidatorTests {
|
||||
|
||||
static final double MIN = 1.0;
|
||||
static final double MAX = 5.0;
|
||||
|
||||
static final String MESSAGE_GT = "The input must be greater than " + MIN;
|
||||
static final String MESSAGE_GE = "The input must be greater than or equal to " + MIN;
|
||||
|
||||
static final String MESSAGE_LT = "The input must be less than " + MAX;
|
||||
static final String MESSAGE_LE = "The input must be less than or equal to " + MAX;
|
||||
|
||||
// ================================
|
||||
// #region - gt_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MIN + 0.000000000000001, Double.MAX_VALUE })
|
||||
void gt_all_validValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.gt(MIN);
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.gt(MIN, MESSAGE_GT);
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.gt(MIN, () -> ExampleException.withMessage(MESSAGE_GT));
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.gt(MIN, property -> ExampleException.withMessage(
|
||||
"The doubleProperty should be greater than %s, but it is %s", MIN, property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - gt_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - gt_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MIN, MIN - 0.000000000000001, Double.MIN_VALUE })
|
||||
void gt_default_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.gt(MIN);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be greater than '%s'.", MIN), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MIN, MIN - 0.000000000000001, Double.MIN_VALUE })
|
||||
void gt_message_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.gt(MIN, MESSAGE_GT);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MIN, MIN - 0.000000000000001, Double.MIN_VALUE })
|
||||
void gt_exceptionSupplier_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.gt(MIN, () -> ExampleException.withMessage(MESSAGE_GT));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MIN, MIN - 0.000000000000001, Double.MIN_VALUE })
|
||||
void gt_exceptionFunction_invalidValue(double value) {
|
||||
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(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
final String expected = String.format("The doubleProperty should be greater than %s, but it is %s", MIN, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - gt_invalidValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - ge_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MIN, MIN + 0.000000000000001, Double.MAX_VALUE })
|
||||
void ge_all_validValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.ge(MIN);
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.ge(MIN, MESSAGE_GE);
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.ge(MIN, () -> ExampleException.withMessage(MESSAGE_GE));
|
||||
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(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - ge_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - ge_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MIN - 0.000000000000001, Double.MIN_VALUE })
|
||||
void ge_default_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.ge(MIN);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be greater than or equal to '%s'.", MIN), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MIN - 0.000000000000001, Double.MIN_VALUE })
|
||||
void ge_message_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.ge(MIN, MESSAGE_GE);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MIN - 0.000000000000001, Double.MIN_VALUE })
|
||||
void ge_exceptionSupplier_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.ge(MIN, () -> ExampleException.withMessage(MESSAGE_GE));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MIN - 0.000000000000001, Double.MIN_VALUE })
|
||||
void ge_exceptionFunction_invalidValue(double value) {
|
||||
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(value);
|
||||
|
||||
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 %s", MIN, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - ge_invalidValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - lt_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MAX - 0.000000000000001, Double.MIN_VALUE })
|
||||
void lt_all_validValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.lt(MAX);
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.lt(MAX, MESSAGE_LT);
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.lt(MAX, () -> ExampleException.withMessage(MESSAGE_LT));
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.lt(MAX, property -> ExampleException.withMessage(
|
||||
"The doubleProperty should be less than %s, but it is %s", MAX, property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - lt_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - lt_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MAX, MAX + 0.000000000000001, Double.MAX_VALUE })
|
||||
void lt_default_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.lt(MAX);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be less than '%s'.", MAX), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MAX, MAX + 0.000000000000001, Double.MAX_VALUE })
|
||||
void lt_message_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.lt(MAX, MESSAGE_LT);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MAX, MAX + 0.000000000000001, Double.MAX_VALUE })
|
||||
void lt_exceptionSupplier_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.lt(MAX, () -> ExampleException.withMessage(MESSAGE_LT));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MAX, MAX + 0.000000000000001, Double.MAX_VALUE })
|
||||
void lt_exceptionFunction_invalidValue(double value) {
|
||||
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(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
final String expected = String.format("The doubleProperty should be less than %s, but it is %s", MAX, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - lt_invalidValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - le_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MAX, MAX - 0.000000000000001, Double.MIN_VALUE })
|
||||
void le_all_validValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.le(MAX);
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.le(MAX, MESSAGE_LE);
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.le(MAX, () -> ExampleException.withMessage(MESSAGE_LE));
|
||||
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(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - le_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - le_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MAX + 0.000000000000001, Double.MAX_VALUE })
|
||||
void le_default_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.le(MAX);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be less than or equal to '%s'.", MAX), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MAX + 0.000000000000001, Double.MAX_VALUE })
|
||||
void le_message_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.le(MAX, MESSAGE_LE);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MAX + 0.000000000000001, Double.MAX_VALUE })
|
||||
void le_exceptionSupplier_invalidValue(double value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForDouble(ExampleCommand::getDoubleProperty)
|
||||
.le(MAX, () -> ExampleException.withMessage(MESSAGE_LE));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithDoubleProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { MAX + 0.000000000000001, Double.MAX_VALUE })
|
||||
void le_exceptionFunction_invalidValue(double value) {
|
||||
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(value);
|
||||
|
||||
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 %s", MAX, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - le_invalidValue
|
||||
// ================================
|
||||
|
||||
static ExampleCommand exampleCommandWithDoubleProperty(Double doubleProperty) {
|
||||
ExampleCommand exampleCommand = new ExampleCommand();
|
||||
exampleCommand.setDoubleProperty(doubleProperty);
|
||||
return exampleCommand;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* 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.*;
|
||||
|
||||
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 IntPropertyValidatorTests {
|
||||
|
||||
static final int MIN = 0;
|
||||
static final int MAX = 5;
|
||||
|
||||
static final String MESSAGE_GT = "The value should be greater than " + MIN;
|
||||
static final String MESSAGE_GE = "The value should be greater than or equal to " + MIN;
|
||||
|
||||
static final String MESSAGE_LT = "The value should be less than " + MAX;
|
||||
static final String MESSAGE_LE = "The value should be less than or equal to " + MAX;
|
||||
|
||||
// ================================
|
||||
// #region - gt_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MIN + 1, Integer.MAX_VALUE })
|
||||
void gt_all_validValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.gt(MIN);
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.gt(MIN, MESSAGE_GT);
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.gt(MIN, () -> ExampleException.withMessage(MESSAGE_GT));
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.gt(MIN, property -> ExampleException.withMessage(
|
||||
"The intProperty should be greater than %d, but it is %d", MIN, property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - gt_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - gt_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MIN, MIN - 1, Integer.MIN_VALUE })
|
||||
void gt_default_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.gt(MIN);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be greater than '%d'.", MIN), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MIN, MIN - 1, Integer.MIN_VALUE })
|
||||
void gt_message_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.gt(MIN, MESSAGE_GT);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MIN, MIN - 1, Integer.MIN_VALUE })
|
||||
void gt_exceptionSupplier_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.gt(MIN, () -> ExampleException.withMessage(MESSAGE_GT));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MIN, MIN - 1, Integer.MIN_VALUE })
|
||||
void gt_exceptionFunction_invalidValue(int value) {
|
||||
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(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
final String expected = String.format("The intProperty should be greater than %d, but it is %d", MIN, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - gt_invalidValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - ge_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MIN, MIN + 1, Integer.MAX_VALUE })
|
||||
void ge_all_validValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.ge(MIN);
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.ge(MIN, MESSAGE_GE);
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.ge(MIN, () -> ExampleException.withMessage(MESSAGE_GE));
|
||||
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(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - ge_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - ge_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MIN - 1, Integer.MIN_VALUE })
|
||||
void ge_default_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.ge(MIN);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be greater than or equal to '%d'.", MIN), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MIN - 1, Integer.MIN_VALUE })
|
||||
void ge_message_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.ge(MIN, MESSAGE_GE);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MIN - 1, Integer.MIN_VALUE })
|
||||
void ge_exceptionSupplier_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.ge(MIN, () -> ExampleException.withMessage(MESSAGE_GE));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MIN - 1, Integer.MIN_VALUE })
|
||||
void ge_exceptionFunction_invalidValue(int value) {
|
||||
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(value);
|
||||
|
||||
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 %d", MIN, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - ge_invalidValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - lt_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MAX - 1, Integer.MIN_VALUE })
|
||||
void lt_all_validValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.lt(MAX);
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.lt(MAX, MESSAGE_LT);
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.lt(MAX, () -> ExampleException.withMessage(MESSAGE_LT));
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.lt(MAX, property -> ExampleException.withMessage(
|
||||
"The intProperty should be less than %d, but it is %d", MAX, property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - lt_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - lt_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MAX, MAX + 1, Integer.MAX_VALUE })
|
||||
void lt_default_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.lt(MAX);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be less than '%d'.", MAX), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MAX, MAX + 1, Integer.MAX_VALUE })
|
||||
void lt_message_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.lt(MAX, MESSAGE_LT);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MAX, MAX + 1, Integer.MAX_VALUE })
|
||||
void lt_exceptionSupplier_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.lt(MAX, () -> ExampleException.withMessage(MESSAGE_LT));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MAX, MAX + 1, Integer.MAX_VALUE })
|
||||
void lt_exceptionFunction_invalidValue(int value) {
|
||||
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(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
final String expected = String.format("The intProperty should be less than %d, but it is %d", MAX, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - lt_invalidValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - le_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MAX, MAX - 1, Integer.MIN_VALUE })
|
||||
void le_all_validValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.le(MAX);
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.le(MAX, MESSAGE_LE);
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.le(MAX, () -> ExampleException.withMessage(MESSAGE_LE));
|
||||
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(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - le_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - le_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MAX + 1, Integer.MAX_VALUE })
|
||||
void le_default_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.le(MAX);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be less than or equal to '%d'.", MAX), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MAX + 1, Integer.MAX_VALUE })
|
||||
void le_message_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.le(MAX, MESSAGE_LE);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MAX + 1, Integer.MAX_VALUE })
|
||||
void le_exceptionSupplier_invalidValue(int value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForInt(ExampleCommand::getIntProperty)
|
||||
.le(MAX, () -> ExampleException.withMessage(MESSAGE_LE));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = { MAX + 1, Integer.MAX_VALUE })
|
||||
void le_exceptionFunction_invalidValue(int value) {
|
||||
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(value);
|
||||
|
||||
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 %d", MAX, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - le_invalidValue
|
||||
// ================================
|
||||
|
||||
static ExampleCommand exampleCommandWithIntProperty(Integer intProperty) {
|
||||
ExampleCommand exampleCommand = new ExampleCommand();
|
||||
exampleCommand.setIntProperty(intProperty);
|
||||
return exampleCommand;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
* 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.*;
|
||||
|
||||
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 LongPropertyValidatorTests {
|
||||
|
||||
static final long MIN = 10000000000L;
|
||||
static final long MAX = 10000000008L;
|
||||
|
||||
|
||||
static final String MESSAGE_GT = "The value should be greater than " + MIN;
|
||||
static final String MESSAGE_GE = "The value should be greater than or equal to " + MIN;
|
||||
|
||||
static final String MESSAGE_LT = "The value should be less than " + MAX;
|
||||
static final String MESSAGE_LE = "The value should be less than or equal to " + MAX;
|
||||
|
||||
// ================================
|
||||
// #region - gt_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MIN + 1, Long.MAX_VALUE })
|
||||
void gt_all_validValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.gt(MIN);
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.gt(MIN, MESSAGE_GT);
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.gt(MIN, () -> ExampleException.withMessage(MESSAGE_GT));
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.gt(MIN, property -> ExampleException.withMessage(
|
||||
"The longProperty should be greater than %d, but it is %d", MIN, property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - gt_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - gt_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MIN, MIN - 1, Long.MIN_VALUE })
|
||||
void gt_default_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.gt(MIN);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be greater than '%d'.", MIN), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MIN, MIN - 1, Long.MIN_VALUE })
|
||||
void gt_message_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.gt(MIN, MESSAGE_GT);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MIN, MIN - 1, Long.MIN_VALUE })
|
||||
void gt_exceptionSupplier_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.gt(MIN, () -> ExampleException.withMessage(MESSAGE_GT));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MIN, MIN - 1, Long.MIN_VALUE })
|
||||
void gt_exceptionFunction_invalidValue(long value) {
|
||||
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(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
final String expected = String.format("The longProperty should be greater than %d, but it is %d", MIN, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - gt_invalidValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - ge_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MIN, MIN + 1, Long.MAX_VALUE })
|
||||
void ge_all_validValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.ge(MIN);
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.ge(MIN, MESSAGE_GE);
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.ge(MIN, () -> ExampleException.withMessage(MESSAGE_GE));
|
||||
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(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - ge_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - ge_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MIN - 1, Long.MIN_VALUE })
|
||||
void ge_default_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.ge(MIN);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be greater than or equal to '%d'.", MIN), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MIN - 1, Long.MIN_VALUE })
|
||||
void ge_message_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.ge(MIN, MESSAGE_GE);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MIN - 1, Long.MIN_VALUE })
|
||||
void ge_exceptionSupplier_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.ge(MIN, () -> ExampleException.withMessage(MESSAGE_GE));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_GE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MIN - 1, Long.MIN_VALUE })
|
||||
void ge_exceptionFunction_invalidValue(long value) {
|
||||
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(value);
|
||||
|
||||
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 %d", MIN, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - ge_invalidValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - lt_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MAX - 1, Long.MIN_VALUE })
|
||||
void lt_all_validValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.lt(MAX);
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.lt(MAX, MESSAGE_LT);
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.lt(MAX, () -> ExampleException.withMessage(MESSAGE_LT));
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.lt(MAX, property -> ExampleException.withMessage(
|
||||
"The longProperty should be less than %d, but it is %d", MAX, property));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - lt_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - lt_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MAX, MAX + 1, Long.MAX_VALUE })
|
||||
void lt_default_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.lt(MAX);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be less than '%d'.", MAX), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MAX, MAX + 1, Long.MAX_VALUE })
|
||||
void lt_message_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.lt(MAX, MESSAGE_LT);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MAX, MAX + 1, Long.MAX_VALUE })
|
||||
void lt_exceptionSupplier_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.lt(MAX, () -> ExampleException.withMessage(MESSAGE_LT));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LT, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MAX, MAX + 1, Long.MAX_VALUE })
|
||||
void lt_exceptionFunction_invalidValue(long value) {
|
||||
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(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
final String expected = String.format("The longProperty should be less than %d, but it is %d", MAX, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - lt_invalidValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - le_validValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MAX, MAX - 1, Long.MIN_VALUE })
|
||||
void le_all_validValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.le(MAX);
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.le(MAX, MESSAGE_LE);
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.le(MAX, () -> ExampleException.withMessage(MESSAGE_LE));
|
||||
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(value);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(new ExampleCommand()));
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - le_validValue
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - le_invalidValue
|
||||
// ================================
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MAX + 1, Long.MAX_VALUE })
|
||||
void le_default_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.le(MAX);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be less than or equal to '%d'.", MAX), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MAX + 1, Long.MAX_VALUE })
|
||||
void le_message_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.le(MAX, MESSAGE_LE);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MAX + 1, Long.MAX_VALUE })
|
||||
void le_exceptionSupplier_invalidValue(long value) {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForLong(ExampleCommand::getLongProperty)
|
||||
.le(MAX, () -> ExampleException.withMessage(MESSAGE_LE));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithLongProperty(value);
|
||||
|
||||
ExampleException e = assertThrows(
|
||||
ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE_LE, e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = { MAX + 1, Long.MAX_VALUE })
|
||||
void le_exceptionFunction_invalidValue(long value) {
|
||||
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(value);
|
||||
|
||||
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 %d", MAX, value);
|
||||
assertEquals(expected, e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - le_invalidValue
|
||||
// ================================
|
||||
|
||||
static ExampleCommand exampleCommandWithLongProperty(Long longProperty) {
|
||||
ExampleCommand exampleCommand = new ExampleCommand();
|
||||
exampleCommand.setLongProperty(longProperty);
|
||||
return exampleCommand;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,504 @@
|
||||
/*
|
||||
* 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.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import xyz.zhouxy.plusone.ExampleException;
|
||||
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;
|
||||
import xyz.zhouxy.plusone.validator.BaseValidator;
|
||||
import xyz.zhouxy.plusone.validator.IValidator;
|
||||
import xyz.zhouxy.plusone.validator.ValidationException;
|
||||
|
||||
public class ObjectPropertyValidatorTests {
|
||||
|
||||
// ================================
|
||||
// #region - notNull
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void notNull_validInput() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getBoolProperty)
|
||||
.notNull();
|
||||
ruleFor(ExampleCommand::getIntProperty)
|
||||
.notNull("The intProperty cannot be null");
|
||||
ruleFor(ExampleCommand::getLongProperty)
|
||||
.notNull(() -> ExampleException.withMessage("The longProperty cannot be null"));
|
||||
ruleFor(ExampleCommand::getDoubleProperty)
|
||||
.notNull(d -> ExampleException.withMessage("The doubleProperty cannot be null, but it was %s", d));
|
||||
ruleFor(ExampleCommand::getStringProperty)
|
||||
.notNull();
|
||||
ruleFor(ExampleCommand::getDateTimeProperty)
|
||||
.notNull("The dateTimeProperty cannot be null");
|
||||
ruleFor(ExampleCommand::getObjectProperty)
|
||||
.notNull(() -> ExampleException.withMessage("The objectProperty cannot be null"));
|
||||
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(
|
||||
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"),
|
||||
new String[] { "ABC", "DEF" });
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void notNull_invalidInput() {
|
||||
ExampleCommand command = new ExampleCommand();
|
||||
|
||||
IValidator<ExampleCommand> defaultRule = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getObjectProperty)
|
||||
.notNull();
|
||||
}
|
||||
};
|
||||
ValidationException eWithDefaultMessage = assertThrows(
|
||||
ValidationException.class, () -> defaultRule.validate(command));
|
||||
assertEquals("The input must not be null.", eWithDefaultMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getObjectProperty)
|
||||
.notNull("The objectProperty could not be null.");
|
||||
}
|
||||
};
|
||||
ValidationException eWithSpecifiedMessage = assertThrows(
|
||||
ValidationException.class, () -> ruleWithMessage.validate(command));
|
||||
assertEquals("The objectProperty could not be null.", eWithSpecifiedMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getObjectProperty)
|
||||
.notNull(() -> ExampleException.withMessage("The objectProperty could not be null."));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException = assertThrows(
|
||||
ExampleException.class, () -> ruleWithExceptionSupplier.validate(command));
|
||||
assertEquals("The objectProperty could not be null.", specifiedException.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getObjectProperty)
|
||||
.notNull(str -> ExampleException.withMessage("The objectProperty could not be null, but is was " + str));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException2 = assertThrows(
|
||||
ExampleException.class, () -> ruleWithExceptionFunction.validate(command));
|
||||
assertEquals("The objectProperty could not be null, but is was null", specifiedException2.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - notNull
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - isNull
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void isNull_validInput() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getBoolProperty)
|
||||
.isNull();
|
||||
ruleFor(ExampleCommand::getIntProperty)
|
||||
.isNull("The intProperty should be null");
|
||||
ruleFor(ExampleCommand::getLongProperty)
|
||||
.isNull(() -> ExampleException.withMessage("The longProperty should be null"));
|
||||
ruleFor(ExampleCommand::getDoubleProperty)
|
||||
.isNull(d -> ExampleException.withMessage("The doubleProperty should be null, but it was %s", d));
|
||||
ruleFor(ExampleCommand::getStringProperty)
|
||||
.isNull();
|
||||
ruleFor(ExampleCommand::getDateTimeProperty)
|
||||
.isNull("The dateTimeProperty should be null");
|
||||
ruleFor(ExampleCommand::getObjectProperty)
|
||||
.isNull(() -> ExampleException.withMessage("The objectProperty should be null"));
|
||||
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();
|
||||
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isNull_invalidInput() {
|
||||
ExampleCommand command = new ExampleCommand();
|
||||
command.setObjectProperty(new Foo(Integer.MAX_VALUE, "StringValue"));
|
||||
|
||||
IValidator<ExampleCommand> ruleWithDefaultMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getObjectProperty)
|
||||
.isNull();
|
||||
}
|
||||
};
|
||||
ValidationException eWithDefaultMessage = assertThrows(
|
||||
ValidationException.class, () -> ruleWithDefaultMessage.validate(command));
|
||||
assertEquals("The input must be null.", eWithDefaultMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getObjectProperty)
|
||||
.isNull("The objectProperty should be null.");
|
||||
}
|
||||
};
|
||||
ValidationException eWithSpecifiedMessage = assertThrows(
|
||||
ValidationException.class, () -> ruleWithMessage.validate(command));
|
||||
assertEquals("The objectProperty should be null.", eWithSpecifiedMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getObjectProperty)
|
||||
.isNull(() -> ExampleException.withMessage("The objectProperty should be null."));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException = assertThrows(
|
||||
ExampleException.class, () -> ruleWithExceptionSupplier.validate(command));
|
||||
assertEquals("The objectProperty should be null.", specifiedException.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getObjectProperty)
|
||||
.isNull(str -> ExampleException.withMessage("The objectProperty should be null, but is was " + str));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException2 = assertThrows(
|
||||
ExampleException.class, () -> ruleWithExceptionFunction.validate(command));
|
||||
assertEquals("The objectProperty should be null, but is was " + command.getObjectProperty(), specifiedException2.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - isNull
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - equal
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void equal_validInput() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.equal("Foo")
|
||||
.equal("Foo", "The stringProperty should be equal to 'Foo'.")
|
||||
.equal("Foo", () ->
|
||||
ExampleException.withMessage("The stringProperty should be equal to 'Foo'."))
|
||||
.equal("Foo", str ->
|
||||
ExampleException.withMessage("The stringProperty should be equal to 'Foo', but is was '%s'.", str));
|
||||
}
|
||||
};
|
||||
ExampleCommand command = new ExampleCommand();
|
||||
|
||||
command.setStringProperty(null);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
|
||||
command.setStringProperty("Foo");
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void equal_invalidInput() {
|
||||
ExampleCommand command = new ExampleCommand();
|
||||
command.setStringProperty("Bar");
|
||||
|
||||
IValidator<ExampleCommand> defaultRule = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty).equal("Foo");
|
||||
}
|
||||
};
|
||||
ValidationException eWithDefaultMessage = assertThrows(
|
||||
ValidationException.class, () -> defaultRule.validate(command));
|
||||
assertEquals("The input must be equal to 'Foo'.", eWithDefaultMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty).equal("Foo",
|
||||
"The stringProperty should be equal to 'Foo'.");
|
||||
}
|
||||
};
|
||||
ValidationException eWithSpecifiedMessage = assertThrows(
|
||||
ValidationException.class, () -> ruleWithMessage.validate(command));
|
||||
assertEquals("The stringProperty should be equal to 'Foo'.", eWithSpecifiedMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty).equal("Foo",
|
||||
() -> ExampleException.withMessage("The stringProperty should be equal to 'Foo'."));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException = assertThrows(
|
||||
ExampleException.class, () -> ruleWithExceptionSupplier.validate(command));
|
||||
assertEquals("The stringProperty should be equal to 'Foo'.", specifiedException.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty).equal("Foo",
|
||||
str -> ExampleException.withMessage("The stringProperty should be equal to '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 'Bar'.", specifiedException2.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - equal
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - notEqual
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
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).notEqual("Foo");
|
||||
}
|
||||
};
|
||||
ValidationException eWithDefaultMessage = assertThrows(
|
||||
ValidationException.class, () -> defaultRule.validate(command));
|
||||
assertEquals("The input must not equal 'Foo'.", eWithDefaultMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty).notEqual("Foo",
|
||||
"The stringProperty should not equal 'Foo'.");
|
||||
}
|
||||
};
|
||||
ValidationException eWithSpecifiedMessage = assertThrows(
|
||||
ValidationException.class, () -> ruleWithMessage.validate(command));
|
||||
assertEquals("The stringProperty should not equal 'Foo'.", eWithSpecifiedMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
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 not equal 'Foo'.", specifiedException.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
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 not equal 'Foo', but is was 'Foo'.", specifiedException2.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - notEqual
|
||||
// ================================
|
||||
|
||||
// ================================
|
||||
// #region - must
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void must_oneCondition_valid() {
|
||||
ExampleCommand command = new ExampleCommand();
|
||||
command.setStringProperty("Foo");
|
||||
|
||||
IValidator<ExampleCommand> ruleWithDefaultMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.must(str -> Objects.equals(str, "Foo"))
|
||||
.must(str -> Objects.equals(str, "Foo"), "The stringProperty must be equal to 'Foo'.")
|
||||
.must(str -> Objects.equals(str, "Foo"), () -> ExampleException.withMessage("The stringProperty must be equal to 'Foo'."))
|
||||
.must(str -> Objects.equals(str, "Foo"), str -> ExampleException.withMessage("The stringProperty must be equal to 'Foo', but is was '%s'.", str));
|
||||
}
|
||||
};
|
||||
assertDoesNotThrow(() -> ruleWithDefaultMessage.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_oneCondition_invalid() {
|
||||
ExampleCommand command = new ExampleCommand();
|
||||
|
||||
IValidator<ExampleCommand> ruleWithDefaultMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.must(str -> Objects.equals(str, "Foo"));
|
||||
}
|
||||
};
|
||||
ValidationException eWithDefaultMessage = assertThrows(
|
||||
ValidationException.class, () -> ruleWithDefaultMessage.validate(command));
|
||||
assertEquals("The specified condition was not met for the input.", eWithDefaultMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.must(str -> Objects.equals(str, "Foo"),
|
||||
"The stringProperty must be equal to 'Foo'.");
|
||||
}
|
||||
};
|
||||
ValidationException eWithSpecifiedMessage = assertThrows(
|
||||
ValidationException.class, () -> ruleWithMessage.validate(command));
|
||||
assertEquals("The stringProperty must be equal to 'Foo'.", eWithSpecifiedMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.must(str -> Objects.equals(str, "Foo"),
|
||||
() -> ExampleException.withMessage("The stringProperty must be equal to 'Foo'."));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException = assertThrows(
|
||||
ExampleException.class, () -> ruleWithExceptionSupplier.validate(command));
|
||||
assertEquals("The stringProperty must be equal to 'Foo'.", specifiedException.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.must(str -> Objects.equals(str, "Foo"),
|
||||
str -> ExampleException.withMessage("The stringProperty must be equal to 'Foo', but is was '%s'.", str));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException2 = assertThrows(
|
||||
ExampleException.class, () -> ruleWithExceptionFunction.validate(command));
|
||||
assertEquals("The stringProperty must be equal to 'Foo', but is was 'null'.", specifiedException2.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_multipleConditions_valid() {
|
||||
ExampleCommand command = new ExampleCommand();
|
||||
command.setStringProperty("Foo");
|
||||
|
||||
IValidator<ExampleCommand> ruleWithDefaultMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.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));
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_multipleConditions_invalid() {
|
||||
ExampleCommand command = new ExampleCommand();
|
||||
command.setStringProperty("Bar");
|
||||
|
||||
IValidator<ExampleCommand> ruleWithDefaultMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals));
|
||||
}
|
||||
};
|
||||
ValidationException eWithDefaultMessage = assertThrows(
|
||||
ValidationException.class, () -> ruleWithDefaultMessage.validate(command));
|
||||
assertEquals("The specified condition was not met for the input.", eWithDefaultMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals),
|
||||
"The stringProperty must be equal to 'Foo'.");
|
||||
}
|
||||
};
|
||||
ValidationException eWithSpecifiedMessage = assertThrows(
|
||||
ValidationException.class, () -> ruleWithMessage.validate(command));
|
||||
assertEquals("The stringProperty must be equal to 'Foo'.", eWithSpecifiedMessage.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals),
|
||||
() -> ExampleException.withMessage("The stringProperty must be equal to 'Foo'."));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException = assertThrows(
|
||||
ExampleException.class, () -> ruleWithExceptionSupplier.validate(command));
|
||||
assertEquals("The stringProperty must be equal to 'Foo'.", specifiedException.getMessage());
|
||||
|
||||
IValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForString(ExampleCommand::getStringProperty)
|
||||
.must(PredicateTools.from(StringTools::isNotEmpty).and("Foo"::equals),
|
||||
str -> ExampleException.withMessage("The stringProperty must be equal to 'Foo', but is was '%s'.", str));
|
||||
}
|
||||
};
|
||||
ExampleException specifiedException2 = assertThrows(
|
||||
ExampleException.class, () -> ruleWithExceptionFunction.validate(command));
|
||||
assertEquals("The stringProperty must be equal to 'Foo', but is was 'Bar'.", specifiedException2.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - must
|
||||
// ================================
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public class PairPropertyValidatorTests {
|
||||
|
||||
static final String MESSAGE = "Validation failed.";
|
||||
|
||||
// ================================
|
||||
// #region - must
|
||||
// ================================
|
||||
|
||||
@Test
|
||||
void must_validInput() {
|
||||
IValidator<ExampleCommand> validator = 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));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "100");
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_default_invalidInput() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
|
||||
ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals("The specified condition was not met for the input.", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_message_invalidInput() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()), MESSAGE);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE, e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_exceptionSupplier_invalidInput() {
|
||||
IValidator<ExampleCommand> validator = 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));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
|
||||
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE, e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_exceptionFunction_invalidInput() {
|
||||
IValidator<ExampleCommand> validator = 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));
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
|
||||
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals("Validation failed: ('', 100).", e.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
// #endregion - must
|
||||
// ================================
|
||||
|
||||
static ExampleCommand exampleCommandWithIntAndStringListProperty(Integer intValue, String str) {
|
||||
ExampleCommand exampleCommand = new ExampleCommand();
|
||||
exampleCommand.setIntProperty(intValue);
|
||||
exampleCommand.setStringProperty(str);
|
||||
return exampleCommand;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2024-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.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.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import xyz.zhouxy.plusone.ExampleException;
|
||||
import xyz.zhouxy.plusone.example.Foo;
|
||||
import xyz.zhouxy.plusone.validator.MapValidator;
|
||||
import xyz.zhouxy.plusone.validator.ValidationException;
|
||||
|
||||
class MapValidatorTests {
|
||||
|
||||
private static final MapValidator<String, Object> validator = ParamsValidator.INSTANCE;
|
||||
|
||||
@Test
|
||||
void testValidateAndCopy() {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put(ParamsValidator.BOOL_PROPERTY, true);
|
||||
params.put(ParamsValidator.INT_PROPERTY, Integer.MAX_VALUE);
|
||||
params.put(ParamsValidator.LONG_PROPERTY, Long.MAX_VALUE);
|
||||
params.put(ParamsValidator.DOUBLE_PROPERTY, Double.MAX_VALUE);
|
||||
params.put(ParamsValidator.STRING_PROPERTY, "Foo");
|
||||
params.put(ParamsValidator.STRING_PROPERTY2, "Bar");
|
||||
params.put(ParamsValidator.DATE_TIME_PROPERTY, LocalDateTime.of(2008, 8, 8, 20, 8));
|
||||
params.put(ParamsValidator.OBJECT_PROPERTY, new Foo(1, "Foo"));
|
||||
params.put(ParamsValidator.STRING_LIST_PROPERTY, Collections.emptyList());
|
||||
|
||||
ValidationException e = assertThrows(ValidationException.class, () -> {
|
||||
validator.validateAndCopy(params);
|
||||
});
|
||||
assertEquals("'stringProperty' must be equal to 'stringProperty2'.", e.getMessage());
|
||||
|
||||
params.put(ParamsValidator.STRING_PROPERTY2, "Foo");
|
||||
assertAll(() -> {
|
||||
Map<String, Object> validatedParams = validator.validateAndCopy(params);
|
||||
assertEquals(ImmutableSet.copyOf(ParamsValidator.reservedProperties()), validatedParams.keySet());
|
||||
|
||||
assertEquals(true, validatedParams.get(ParamsValidator.BOOL_PROPERTY));
|
||||
assertEquals(Integer.MAX_VALUE, validatedParams.get(ParamsValidator.INT_PROPERTY));
|
||||
assertEquals(Long.MAX_VALUE, validatedParams.get(ParamsValidator.LONG_PROPERTY));
|
||||
assertEquals(Double.MAX_VALUE, validatedParams.get(ParamsValidator.DOUBLE_PROPERTY));
|
||||
assertEquals("Foo", validatedParams.get(ParamsValidator.STRING_PROPERTY));
|
||||
assertEquals(LocalDateTime.of(2008, 8, 8, 20, 8), validatedParams.get(ParamsValidator.DATE_TIME_PROPERTY));
|
||||
assertEquals(new Foo(1, "Foo"), validatedParams.get(ParamsValidator.OBJECT_PROPERTY));
|
||||
assertEquals(Collections.emptyList(), validatedParams.get(ParamsValidator.STRING_LIST_PROPERTY));
|
||||
});
|
||||
|
||||
assertAll(() -> {
|
||||
Map<String, Object> validatedParams = validator.validateAndCopy(params,
|
||||
ParamsValidator.LONG_PROPERTY, ParamsValidator.STRING_PROPERTY2);
|
||||
assertEquals(ImmutableSet.of(ParamsValidator.LONG_PROPERTY, ParamsValidator.STRING_PROPERTY2),
|
||||
validatedParams.keySet());
|
||||
|
||||
assertEquals(Long.MAX_VALUE, validatedParams.get(ParamsValidator.LONG_PROPERTY));
|
||||
assertEquals("Foo", validatedParams.get(ParamsValidator.STRING_PROPERTY2));
|
||||
|
||||
});
|
||||
|
||||
assertAll(() -> {
|
||||
Set<String> keySet = ImmutableSet.of(ParamsValidator.LONG_PROPERTY, ParamsValidator.STRING_PROPERTY2);
|
||||
Map<String, Object> validatedParams = validator.validateAndCopy(params, keySet);
|
||||
assertEquals(keySet, validatedParams.keySet());
|
||||
|
||||
assertEquals(Long.MAX_VALUE, validatedParams.get(ParamsValidator.LONG_PROPERTY));
|
||||
assertEquals("Foo", validatedParams.get(ParamsValidator.STRING_PROPERTY2));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class ParamsValidator extends MapValidator<String, Object> {
|
||||
public static final String BOOL_PROPERTY = "boolProperty";
|
||||
public static final String INT_PROPERTY = "intProperty";
|
||||
public static final String LONG_PROPERTY = "longProperty";
|
||||
public static final String DOUBLE_PROPERTY = "doubleProperty";
|
||||
public static final String STRING_PROPERTY = "stringProperty";
|
||||
public static final String STRING_PROPERTY2 = "stringProperty2";
|
||||
public static final String DATE_TIME_PROPERTY = "dateTimeProperty";
|
||||
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(RESERVED_PROPERTIES);
|
||||
ruleForBool(BOOL_PROPERTY)
|
||||
.notNull();
|
||||
ruleForInt(INT_PROPERTY)
|
||||
.notNull("The intProperty cannot be null");
|
||||
ruleForLong(LONG_PROPERTY)
|
||||
.notNull(() -> ExampleException.withMessage("The longProperty cannot be null"));
|
||||
ruleForDouble(DOUBLE_PROPERTY)
|
||||
.notNull(d -> ExampleException.withMessage("The doubleProperty cannot be null, but it was %s", d));
|
||||
ruleForString(STRING_PROPERTY)
|
||||
.notNull();
|
||||
ruleForComparable(DATE_TIME_PROPERTY)
|
||||
.notNull("The dateTimeProperty cannot be null");
|
||||
ruleFor(OBJECT_PROPERTY)
|
||||
.notNull(() -> ExampleException.withMessage("The objectProperty cannot be null"));
|
||||
ruleForCollection(STRING_LIST_PROPERTY)
|
||||
.notNull(d -> ExampleException.withMessage("The stringListProperty cannot be null, but it was %s", d));
|
||||
|
||||
ruleForPair(STRING_PROPERTY, STRING_PROPERTY2)
|
||||
.must((str1, str2) -> str1 != null && str1.equals(str2),
|
||||
"'stringProperty' must be equal to 'stringProperty2'.");
|
||||
}
|
||||
|
||||
public static String[] reservedProperties() {
|
||||
return Arrays.copyOf(RESERVED_PROPERTIES, RESERVED_PROPERTIES.length);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package xyz.zhouxy.plusone.validator;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ValidationExceptionTests {
|
||||
|
||||
@Test
|
||||
void withoutMessage() {
|
||||
ValidationException ex = ValidationException.withDefaultMessage();
|
||||
assertNotNull(ex);
|
||||
assertEquals(ValidationException.DEFAULT_MESSAGE, ex.getMessage());
|
||||
assertNull(ex.getCause());
|
||||
}
|
||||
|
||||
@Test
|
||||
void withMessage_String() {
|
||||
String message = "Validation failed";
|
||||
ValidationException ex = ValidationException.withMessage(message);
|
||||
assertNotNull(ex);
|
||||
assertEquals(message, ex.getMessage());
|
||||
assertNull(ex.getCause());
|
||||
}
|
||||
|
||||
@Test
|
||||
void withMessage_TemplateAndArgs() {
|
||||
String template = "Field %s is invalid: %s";
|
||||
Object[] args = {"username", "too short"};
|
||||
ValidationException ex = ValidationException.withMessage(template, args);
|
||||
assertNotNull(ex);
|
||||
assertEquals("Field username is invalid: too short", ex.getMessage());
|
||||
assertNull(ex.getCause());
|
||||
}
|
||||
|
||||
@Test
|
||||
void withCause() {
|
||||
Throwable cause = new IOException("IO error");
|
||||
ValidationException ex = ValidationException.withCause(cause);
|
||||
assertNotNull(ex);
|
||||
assertEquals(cause, ex.getCause());
|
||||
assertEquals(cause.getClass().getName() + ": " + cause.getMessage(), ex.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void withMessageAndCause() {
|
||||
String message = "Validation failed";
|
||||
Throwable cause = new IllegalArgumentException("Invalid argument");
|
||||
ValidationException ex = ValidationException.withMessageAndCause(message, cause);
|
||||
assertNotNull(ex);
|
||||
assertEquals(message, ex.getMessage());
|
||||
assertEquals(cause, ex.getCause());
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package xyz.zhouxy.plusone.validator.map.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
|
||||
import xyz.zhouxy.plusone.commons.util.StringTools;
|
||||
import xyz.zhouxy.plusone.validator.MapValidator;
|
||||
|
||||
class MapValidatorTests {
|
||||
|
||||
private static final MapValidator<String, Object> validator = ParamsValidator.INSTANCE;
|
||||
|
||||
@Test
|
||||
void testValidateAndCopy() {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put(ParamsValidator.USERNAME, "ZhouXY");
|
||||
params.put(ParamsValidator.ACCOUNT, "zhouxy@code108.cn");
|
||||
params.put(ParamsValidator.PASSWORD, "99Code108");
|
||||
params.put(ParamsValidator.PASSWORD2, "99Code108");
|
||||
params.put(ParamsValidator.AGE, 18);
|
||||
params.put(ParamsValidator.BOOLEAN, true);
|
||||
|
||||
params.put(ParamsValidator.ROLE_LIST, Arrays.asList("admin", ""));
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
validator.validateAndCopy(params);
|
||||
});
|
||||
|
||||
params.put(ParamsValidator.ROLE_LIST, Arrays.asList("admin", "developer"));
|
||||
Map<String, Object> validatedParams = validator.validateAndCopy(params);
|
||||
System.out.println(validatedParams);
|
||||
}
|
||||
}
|
||||
|
||||
class ParamsValidator extends MapValidator<String, Object> {
|
||||
public static final String USERNAME = "username";
|
||||
public static final String ACCOUNT = "account";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String PASSWORD2 = "password2";
|
||||
public static final String AGE = "age";
|
||||
public static final String BOOLEAN = "boolean";
|
||||
public static final String ROLE_LIST = "roleList";
|
||||
|
||||
public static final ParamsValidator INSTANCE = new ParamsValidator();
|
||||
|
||||
private ParamsValidator() {
|
||||
super(new String[] { USERNAME, ACCOUNT, PASSWORD, AGE, BOOLEAN, ROLE_LIST });
|
||||
ruleForString(USERNAME)
|
||||
.notBlank("用户名不能为空")
|
||||
.matches(PatternConsts.USERNAME,
|
||||
username -> new IllegalArgumentException(String.format("用户名【%s】不符合规范", username)));
|
||||
|
||||
ruleForString(ACCOUNT)
|
||||
.notBlank("账号不能为空")
|
||||
.matchesOne(new Pattern[] { PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE }, "请输入正确的邮箱地址或手机号");
|
||||
|
||||
ruleForString(PASSWORD)
|
||||
.notEmpty("密码不能为空")
|
||||
.matches(PatternConsts.PASSWORD, "密码不符合规范");
|
||||
|
||||
// 校验到多个属性,只能针对 map 本身进行校验
|
||||
withRule(m -> Objects.equals(m.get(PASSWORD), m.get(PASSWORD2)),
|
||||
"两次输入的密码不一样!");
|
||||
|
||||
ruleForInt(AGE)
|
||||
.withRule(Objects::nonNull)
|
||||
.ge(18)
|
||||
.le(60);
|
||||
|
||||
ruleForBool(BOOLEAN)
|
||||
.notNull("Boolean property could not be null.")
|
||||
.isTrueValue("Boolean property must be true.");
|
||||
|
||||
this.<String>ruleForCollection(ROLE_LIST)
|
||||
.notEmpty("角色列表不能为空!")
|
||||
.withRule(l -> l.stream().allMatch(StringTools::isNotBlank),
|
||||
() -> new IllegalArgumentException("角色标识不能为空!"));
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
package xyz.zhouxy.plusone.validator.test;
|
||||
|
||||
import java.time.Year;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
|
||||
import xyz.zhouxy.plusone.commons.function.PredicateTools;
|
||||
import xyz.zhouxy.plusone.commons.util.RegexTools;
|
||||
import xyz.zhouxy.plusone.commons.util.StringTools;
|
||||
import xyz.zhouxy.plusone.validator.BaseValidator;
|
||||
import xyz.zhouxy.plusone.validator.ValidTools;
|
||||
|
||||
class BaseValidatorTest {
|
||||
@Test
|
||||
void testValidate() {
|
||||
RegisterCommand registerCommand = new RegisterCommand("zhouxy108", "luquanlion@outlook.com", "22336",
|
||||
"A1b2C3d4",
|
||||
"A1b2C3d4",
|
||||
Arrays.asList(new String[] { "admin", "editor" }),
|
||||
2000);
|
||||
RegisterCommandValidator.INSTANCE.validate(registerCommand);
|
||||
ValidTools.validate(registerCommand, RegisterCommandValidator.INSTANCE);
|
||||
System.out.println(registerCommand);
|
||||
}
|
||||
|
||||
static class RegisterCommandValidator extends BaseValidator<RegisterCommand> {
|
||||
|
||||
static final RegisterCommandValidator INSTANCE = new RegisterCommandValidator();
|
||||
|
||||
private RegisterCommandValidator() {
|
||||
int thisYear = Year.now().getValue();
|
||||
|
||||
ruleForString(RegisterCommand::getUsername)
|
||||
.must(PredicateTools.<String>from(Objects::nonNull)
|
||||
.and(StringTools::isNotEmpty)
|
||||
.and(StringTools::isNotBlank)
|
||||
.and(username -> RegexTools.matches(username, PatternConsts.USERNAME)),
|
||||
username -> new IllegalArgumentException(String.format("用户名【%s】不符合规范", username)));
|
||||
ruleForString(RegisterCommand::getAccount)
|
||||
.notNull("请输入邮箱地址或手机号")
|
||||
.matchesOne(Arrays.asList(PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE), "请输入邮箱地址或手机号");
|
||||
ruleForString(RegisterCommand::getCode)
|
||||
.notNull("验证码不能为空")
|
||||
.matches(PatternConsts.CAPTCHA, "验证码不符合规范");
|
||||
ruleForString(RegisterCommand::getPassword)
|
||||
.notEmpty("密码不能为空")
|
||||
.matches(PatternConsts.PASSWORD, "密码不符合规范");
|
||||
ruleForCollection(RegisterCommand::getRoles)
|
||||
.notEmpty(() -> new RuntimeException("角色列表不能为空"));
|
||||
|
||||
ruleForComparable(RegisterCommand::getYearOfBirth)
|
||||
.notNull()
|
||||
.inRange(Range.closed(thisYear - 60, thisYear - 18));
|
||||
|
||||
ruleForInt(RegisterCommand::getYearOfBirth)
|
||||
.notNull()
|
||||
.inRange(Range.closed(thisYear - 60, thisYear - 18));
|
||||
|
||||
withRule(registerCommand -> Objects.equals(registerCommand.getPassword(), registerCommand.getPassword2()),
|
||||
"两次输入的密码不一致");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RegisterCommand
|
||||
*/
|
||||
static class RegisterCommand {
|
||||
|
||||
private String username;
|
||||
private String account;
|
||||
private String code;
|
||||
private String password;
|
||||
private String password2;
|
||||
private List<String> roles;
|
||||
|
||||
private Integer yearOfBirth;
|
||||
|
||||
public RegisterCommand() {
|
||||
}
|
||||
|
||||
public RegisterCommand(String username, String account, String code, String password, String password2,
|
||||
List<String> roles, Integer yearOfBirth) {
|
||||
this.username = username;
|
||||
this.account = account;
|
||||
this.code = code;
|
||||
this.password = password;
|
||||
this.password2 = password2;
|
||||
this.roles = roles;
|
||||
this.yearOfBirth = yearOfBirth;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getPassword2() {
|
||||
return password2;
|
||||
}
|
||||
|
||||
public void setPassword2(String password2) {
|
||||
this.password2 = password2;
|
||||
}
|
||||
|
||||
public List<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<String> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public Integer getYearOfBirth() {
|
||||
return yearOfBirth;
|
||||
}
|
||||
|
||||
public void setYearOfBirth(Integer yearOfBirth) {
|
||||
this.yearOfBirth = yearOfBirth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder()
|
||||
.append("RegisterCommand [")
|
||||
.append("username=").append(username)
|
||||
.append(", account=").append(account)
|
||||
.append(", code=").append(code)
|
||||
.append(", password=").append(password)
|
||||
.append(", password2=").append(password2)
|
||||
.append(", roles=").append(roles)
|
||||
.append(", yearOfBirth=").append(yearOfBirth)
|
||||
.append("]")
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
package xyz.zhouxy.plusone.validator.test;
|
||||
|
||||
import static xyz.zhouxy.plusone.commons.constant.PatternConsts.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import xyz.zhouxy.plusone.commons.collection.CollectionTools;
|
||||
import xyz.zhouxy.plusone.commons.function.PredicateTools;
|
||||
import xyz.zhouxy.plusone.commons.util.AssertTools;
|
||||
import xyz.zhouxy.plusone.commons.util.RegexTools;
|
||||
import xyz.zhouxy.plusone.commons.util.StringTools;
|
||||
import xyz.zhouxy.plusone.validator.Validator;
|
||||
|
||||
class ValidatorTests {
|
||||
@Test
|
||||
void testValidate() {
|
||||
RegisterCommand registerCommand = new RegisterCommand(
|
||||
"null", "luquanlion@outlook.com", "22336",
|
||||
"A1b2C3d4", "A1b2C3d4",
|
||||
Arrays.asList(new String[] { "admin", "editor" }));
|
||||
|
||||
Validator<RegisterCommand> registerCommandValidator = new Validator<RegisterCommand>()
|
||||
// 传入 predicate 和 Function<T, E extends RuntimeException>
|
||||
.addRule(command -> {
|
||||
String username = command.getUsername();
|
||||
return Objects.nonNull(username)
|
||||
&& StringTools.isNotEmpty(username)
|
||||
&& StringTools.isNotBlank(username)
|
||||
&& RegexTools.matches(username, USERNAME);
|
||||
}, command -> new IllegalArgumentException(String.format("用户名【%s】不符合规范", command.getUsername())))
|
||||
// 传入 predicate 和 error message
|
||||
.addRule(command -> PredicateTools
|
||||
.<String>from(Objects::nonNull)
|
||||
.and(account -> RegexTools.matchesOne(account, new Pattern[] { EMAIL, MOBILE_PHONE }))
|
||||
.test(command.getAccount()),
|
||||
"请输入邮箱地址或手机号")
|
||||
// 传入 rule
|
||||
.addRule(command -> {
|
||||
String code = command.getCode();
|
||||
AssertTools.checkArgument(Objects.nonNull(code), "验证码不能为空");
|
||||
AssertTools.checkArgument(RegexTools.matches(code, CAPTCHA), "验证码不符合规范");
|
||||
})
|
||||
// 传入 rule
|
||||
.addRule(command -> {
|
||||
String password = command.getPassword();
|
||||
AssertTools.checkArgument(StringTools.isNotEmpty(password), "密码不能为空");
|
||||
AssertTools.checkArgument(RegexTools.matches(password, PASSWORD), "密码不符合规范");
|
||||
})
|
||||
// 传入 predicate 和 Supplier<E extends RuntimeException>
|
||||
.addRule(command -> CollectionTools.isNotEmpty(command.getRoles()),
|
||||
() -> new RuntimeException("角色列表不能为空"))
|
||||
// 传入 predicate 和 error message
|
||||
.addRule(command -> Objects.equals(command.getPassword(), command.getPassword2()),
|
||||
"两次输入的密码不一致");
|
||||
registerCommandValidator.validate(registerCommand);
|
||||
System.out.println(registerCommand);
|
||||
}
|
||||
|
||||
/**
|
||||
* RegisterCommand
|
||||
*/
|
||||
static class RegisterCommand {
|
||||
|
||||
private String username;
|
||||
private String account;
|
||||
private String code;
|
||||
private String password;
|
||||
private String password2;
|
||||
private List<String> roles;
|
||||
|
||||
public RegisterCommand() {
|
||||
}
|
||||
|
||||
public RegisterCommand(String username, String account, String code, String password, String password2,
|
||||
List<String> roles) {
|
||||
this.username = username;
|
||||
this.account = account;
|
||||
this.code = code;
|
||||
this.password = password;
|
||||
this.password2 = password2;
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getPassword2() {
|
||||
return password2;
|
||||
}
|
||||
|
||||
public void setPassword2(String password2) {
|
||||
this.password2 = password2;
|
||||
}
|
||||
|
||||
public List<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<String> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("RegisterCommand [username=").append(username).append(", account=").append(account)
|
||||
.append(", code=").append(code).append(", password=").append(password).append(", password2=")
|
||||
.append(password2).append(", roles=").append(roles).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
6
pom.xml
6
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>xyz.zhouxy.plusone</groupId>
|
||||
<artifactId>plusone-validator-parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<version>1.0.0-RC1</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>
|
||||
|
||||
Reference in New Issue
Block a user