Compare commits

...

7 Commits

Author SHA1 Message Date
0e9dbf9bd9 refactor!: BasePropertyValidatorequalsThat 重命名为 equalTo 2025-05-28 14:30:06 +08:00
f21e9727fa refactor!: 修改异常信息 2025-05-28 14:28:09 +08:00
33fb20590b chore: 补充 copyright 声明 2025-05-28 14:27:28 +08:00
08ebfc7d4b docs: 删除关于 ValidTools 的描述 2025-05-28 14:26:12 +08:00
41ccb652d4 feat: 重载 ruleFor
通过自定义函数式接口,使 lambda 表达式作为入参时,可以进入不同的重载版本,从而返回不同类型属性的校验器。
2025-05-28 09:41:02 +08:00
37f4af67cd feat: 添加 MapValidator#ruleForComparable 2025-05-28 09:40:00 +08:00
6cd47e369e test: 添加 BasePropertyValidator#withRule 的反用例 2025-05-28 09:38:48 +08:00
15 changed files with 280 additions and 40 deletions

View File

@@ -122,31 +122,31 @@ public abstract class BasePropertyValidator<T, TProperty, TPropertyValidator ext
// ================================
// ================================
// #region - equals
// #region - equalTo
// ================================
public TPropertyValidator equalsThat(Object that) {
return equalsThat(that,
public TPropertyValidator equalTo(Object that) {
return equalTo(that,
value -> new IllegalArgumentException(String.format("The input must be equal to '%s'.", that)));
}
public TPropertyValidator equalsThat(Object that, String errMsg) {
return equalsThat(that, convertExceptionCreator(errMsg));
public TPropertyValidator equalTo(Object that, String errMsg) {
return equalTo(that, convertExceptionCreator(errMsg));
}
public <E extends RuntimeException> TPropertyValidator equalsThat(
public <E extends RuntimeException> TPropertyValidator equalTo(
Object that, Supplier<E> exceptionCreator) {
return equalsThat(that, convertExceptionCreator(exceptionCreator));
return equalTo(that, convertExceptionCreator(exceptionCreator));
}
public <E extends RuntimeException> TPropertyValidator equalsThat(
public <E extends RuntimeException> TPropertyValidator equalTo(
Object that, Function<TProperty, E> exceptionCreator) {
withRule(value -> Objects.equals(value, that), exceptionCreator);
return thisObject();
}
// ================================
// #endregion - equals
// #endregion - equalTo
// ================================
// ================================

View File

@@ -24,6 +24,8 @@ import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import xyz.zhouxy.plusone.validator.function.*;
/**
* BaseValidator
*
@@ -79,30 +81,60 @@ public abstract class BaseValidator<T> {
return validator;
}
protected final IntPropertyValidator<T> ruleFor(ToIntegerFunction<T> getter) {
IntPropertyValidator<T> validator = new IntPropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
protected final LongPropertyValidator<T> ruleForLong(Function<T, Long> getter) {
LongPropertyValidator<T> validator = new LongPropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
protected final LongPropertyValidator<T> ruleFor(ToLongObjectFunction<T> getter) {
LongPropertyValidator<T> validator = new LongPropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
protected final DoublePropertyValidator<T> ruleForDouble(Function<T, Double> getter) {
DoublePropertyValidator<T> validator = new DoublePropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
protected final DoublePropertyValidator<T> ruleFor(ToDoubleObjectFunction<T> getter) {
DoublePropertyValidator<T> validator = new DoublePropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
protected final BoolPropertyValidator<T> ruleForBool(Function<T, Boolean> getter) {
BoolPropertyValidator<T> validator = new BoolPropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
protected final BoolPropertyValidator<T> ruleFor(ToBoolObjectFunction<T> getter) {
BoolPropertyValidator<T> validator = new BoolPropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
protected final StringPropertyValidator<T> ruleForString(Function<T, String> getter) {
StringPropertyValidator<T> validator = new StringPropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
protected final StringPropertyValidator<T> ruleFor(ToStringFunction<T> getter) {
StringPropertyValidator<T> validator = new StringPropertyValidator<>(getter);
this.rules.add(validator::validate);
return validator;
}
protected final <E> CollectionPropertyValidator<T, E> ruleForCollection(Function<T, Collection<E>> getter) {
CollectionPropertyValidator<T, E> validator = new CollectionPropertyValidator<>(getter);
this.rules.add(validator::validate);

View File

@@ -21,7 +21,6 @@ package xyz.zhouxy.plusone.validator;
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*
* @see ValidTools
* @see BaseValidator
*/
public interface IValidateRequired {

View File

@@ -60,7 +60,8 @@ public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
// ========== ruleFor ==========
protected final ObjectPropertyValidator<Map<K, V>, V> ruleFor(K key) {
return ruleFor(m -> m.get(key));
final Function<Map<K, V>, V> func = m -> m.get(key);
return ruleFor(func);
}
protected final IntPropertyValidator<Map<K, V>> ruleForInt(K key) {
@@ -83,6 +84,12 @@ public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
return ruleForString(m -> (String) m.get(key));
}
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);
}
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);

View File

@@ -269,8 +269,8 @@ public class StringPropertyValidator<T> extends BaseComparablePropertyValidator<
public <E extends RuntimeException> StringPropertyValidator<T> length(int min, int max,
Function<String, E> exceptionCreator) {
AssertTools.checkArgument(min >= 0, "The 'min' must be greater than or equal to 0.");
AssertTools.checkArgument(min <= max, "The 'min' must be less than or equal to the 'max'.");
AssertTools.checkArgument(min >= 0, "min must be non-negative.");
AssertTools.checkArgument(min <= max, "min must be less than or equal to max.");
withRule(s -> length(s, min, max), exceptionCreator);
return this;
}

View File

@@ -35,22 +35,16 @@ import java.util.function.Supplier;
* </pre>
*
* <p>
* 然后通过校验器的 {@link #validate} 方法,或
* {@link ValidTools#validate(Object, Validator)} 对指定对象进行校验。
* 然后通过校验器的 {@link #validate} 方法对指定对象进行校验。
* </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> {

View File

@@ -0,0 +1,23 @@
/*
* 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;
@FunctionalInterface
public interface ToBoolObjectFunction<T> extends Function<T, Boolean>, Serializable {
}

View File

@@ -0,0 +1,23 @@
/*
* 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;
@FunctionalInterface
public interface ToDoubleObjectFunction<T> extends Function<T, Double>, Serializable {
}

View File

@@ -0,0 +1,23 @@
/*
* 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;
@FunctionalInterface
public interface ToIntegerFunction<T> extends Function<T, Integer>, Serializable {
}

View File

@@ -0,0 +1,23 @@
/*
* 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;
@FunctionalInterface
public interface ToLongObjectFunction<T> extends Function<T, Long>, Serializable {
}

View File

@@ -0,0 +1,23 @@
/*
* 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;
@FunctionalInterface
public interface ToStringFunction<T> extends Function<T, String>, Serializable {
}

View File

@@ -1,3 +1,19 @@
/*
* 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.*;

View File

@@ -18,6 +18,7 @@ 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.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.time.DateTimeException;
@@ -44,12 +45,12 @@ public class ObjectPropertyValidatorTests {
// ================================
@Test
void withRule() {
void withRule_validInput() {
BaseValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getBoolProperty)
.notNull("The boolProperty cannot be null.")
.withRule(Boolean.TRUE::equals, "The boolProperty should be true.");
.withRule(Boolean.TRUE::equals);
ruleFor(ExampleCommand::getIntProperty)
.withRule(intProperty -> intProperty > 0, "The intProperty should be greater than 0.");
@@ -99,6 +100,50 @@ public class ObjectPropertyValidatorTests {
assertDoesNotThrow(() -> validator.validate(command));
}
@Test
void withRule_invalidInputs() {
ExampleCommand command = new ExampleCommand();
BaseValidator<ExampleCommand> ruleWithDefaultMessage = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getObjectProperty)
.withRule(x -> false);
}
};
IllegalArgumentException eWithDefaultMessage = assertThrows(
IllegalArgumentException.class, () -> ruleWithDefaultMessage.validate(command));
assertNull(eWithDefaultMessage.getMessage());
BaseValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getObjectProperty)
.withRule(x -> false, "invalid input.");
}
};
IllegalArgumentException eWithMessage = assertThrows(
IllegalArgumentException.class, () -> ruleWithMessage.validate(command));
assertEquals("invalid input.", eWithMessage.getMessage());
BaseValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getObjectProperty)
.withRule(x -> false, () -> ExampleException.withMessage("invalid input."));
}
};
ExampleException specifiedException = assertThrows(
ExampleException.class, () -> ruleWithExceptionSupplier.validate(command));
assertEquals("invalid input.", specifiedException.getMessage());
BaseValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleFor(ExampleCommand::getObjectProperty)
.withRule(x -> false, x -> ExampleException.withMessage("invalid input: [%s].", x));
}
};
ExampleException specifiedException2 = assertThrows(
ExampleException.class, () -> ruleWithExceptionFunction.validate(command));
assertEquals("invalid input: [null].", specifiedException2.getMessage());
}
// ================================
// #endregion - withRule
// ================================
@@ -273,19 +318,19 @@ public class ObjectPropertyValidatorTests {
// ================================
// ================================
// #region - equalsThat
// #region - equalTo
// ================================
@Test
void equalsThat_validInput() {
void equalTo_validInput() {
BaseValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty)
.equalsThat("Foo")
.equalsThat("Foo", "The stringProperty should be equal to 'Foo'.")
.equalsThat("Foo", () ->
.equalTo("Foo")
.equalTo("Foo", "The stringProperty should be equal to 'Foo'.")
.equalTo("Foo", () ->
ExampleException.withMessage("The stringProperty should be equal to 'Foo'."))
.equalsThat("Foo", str ->
.equalTo("Foo", str ->
ExampleException.withMessage("The stringProperty should be equal to 'Foo', but is was '%s'.", str));
}
};
@@ -296,13 +341,13 @@ public class ObjectPropertyValidatorTests {
}
@Test
void equalsThat_invalidInput() {
void equalTo_invalidInput() {
ExampleCommand command = new ExampleCommand();
command.setStringProperty("Bar");
BaseValidator<ExampleCommand> defaultRule = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalsThat("Foo");
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo");
}
};
IllegalArgumentException eWithDefaultMessage = assertThrows(
@@ -311,7 +356,7 @@ public class ObjectPropertyValidatorTests {
BaseValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalsThat("Foo",
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
"The stringProperty should be equal to 'Foo'.");
}
};
@@ -321,7 +366,7 @@ public class ObjectPropertyValidatorTests {
BaseValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalsThat("Foo",
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
() -> ExampleException.withMessage("The stringProperty should be equal to 'Foo'."));
}
};
@@ -331,7 +376,7 @@ public class ObjectPropertyValidatorTests {
BaseValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalsThat("Foo",
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
str -> ExampleException.withMessage("The stringProperty should be equal to 'Foo', but is was '%s'.", str));
}
};
@@ -341,12 +386,12 @@ public class ObjectPropertyValidatorTests {
}
@Test
void equalsThat_nullInput() {
void equalTo_nullInput() {
ExampleCommand command = new ExampleCommand();
BaseValidator<ExampleCommand> defaultRule = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalsThat("Foo");
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo");
}
};
IllegalArgumentException eWithDefaultMessage = assertThrows(
@@ -355,7 +400,7 @@ public class ObjectPropertyValidatorTests {
BaseValidator<ExampleCommand> ruleWithMessage = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalsThat("Foo",
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
"The stringProperty should be equal to 'Foo'.");
}
};
@@ -365,7 +410,7 @@ public class ObjectPropertyValidatorTests {
BaseValidator<ExampleCommand> ruleWithExceptionSupplier = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalsThat("Foo",
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
() -> ExampleException.withMessage("The stringProperty should be equal to 'Foo'."));
}
};
@@ -375,7 +420,7 @@ public class ObjectPropertyValidatorTests {
BaseValidator<ExampleCommand> ruleWithExceptionFunction = new BaseValidator<ExampleCommand>() {
{
ruleForString(ExampleCommand::getStringProperty).equalsThat("Foo",
ruleForString(ExampleCommand::getStringProperty).equalTo("Foo",
str -> ExampleException.withMessage("The stringProperty should be equal to 'Foo', but is was '%s'.", str));
}
};
@@ -385,7 +430,7 @@ public class ObjectPropertyValidatorTests {
}
// ================================
// #endregion - equalsThat
// #endregion - equalTo
// ================================
// ================================

View File

@@ -1,3 +1,19 @@
/*
* 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.example.validator;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;

View File

@@ -1,3 +1,19 @@
/*
* 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.*;
@@ -102,7 +118,7 @@ class ParamsValidator extends MapValidator<String, Object> {
.notNull(d -> ExampleException.withMessage("The doubleProperty cannot be null, but it was %s", d));
ruleForString(STRING_PROPERTY)
.notNull();
ruleFor(DATE_TIME_PROPERTY)
ruleForComparable(DATE_TIME_PROPERTY)
.notNull("The dateTimeProperty cannot be null");
ruleFor(OBJECT_PROPERTY)
.notNull(() -> ExampleException.withMessage("The objectProperty cannot be null"));