Compare commits

...

2 Commits

5 changed files with 93 additions and 134 deletions

View File

@ -9,18 +9,18 @@ import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
public class BaseValidator<T> { public class BaseValidator<T> {
private final List<Consumer<T>> rules = new ArrayList<>(); private final List<Consumer<? super T>> rules = new ArrayList<>();
protected void withRule(final Predicate<T> rule, final String errorMessage) { protected void withRule(final Predicate<T> rule, final String errorMessage) {
withRule(rule, () -> new IllegalArgumentException(errorMessage)); withRule(rule, () -> new IllegalArgumentException(errorMessage));
} }
protected <E extends RuntimeException> void withRule(Predicate<T> rule, Supplier<E> exceptionBuilder) { protected <E extends RuntimeException> void withRule(Predicate<? super T> rule, Supplier<E> exceptionBuilder) {
withRule(rule, value -> exceptionBuilder.get()); withRule(rule, value -> exceptionBuilder.get());
} }
protected <E extends RuntimeException> void withRule( protected <E extends RuntimeException> void withRule(
Predicate<T> condition, Function<T, E> exceptionBuilder) { Predicate<? super T> condition, Function<T, E> exceptionBuilder) {
withRule(value -> { withRule(value -> {
if (!condition.test(value)) { if (!condition.test(value)) {
throw exceptionBuilder.apply(value); throw exceptionBuilder.apply(value);
@ -28,7 +28,7 @@ public class BaseValidator<T> {
}); });
} }
protected void withRule(Consumer<T> rule) { protected void withRule(Consumer<? super T> rule) {
this.rules.add(rule); this.rules.add(rule);
} }

View File

@ -0,0 +1,71 @@
package xyz.zhouxy.plusone.validator;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
private final Set<K> keys;
protected MapValidator(K[] keys) {
this(Arrays.asList(keys));
}
protected MapValidator(Collection<K> keys) {
this.keys = keys.stream().collect(Collectors.toSet());
}
// ========== validate & validateAndCopy ==========
public final Map<K, V> validateAndCopy(Map<K, V> obj) {
return validateAndCopyInternal(obj, this.keys);
}
public final Map<K, V> validateAndCopy(Map<K, V> obj, Collection<K> keys) {
return validateAndCopyInternal(obj, keys);
}
@SafeVarargs
public final Map<K, V> validateAndCopy(Map<K, V> obj, K... keys) {
return validateAndCopyInternal(obj, Arrays.asList(keys));
}
private final Map<K, V> validateAndCopyInternal(Map<K, V> obj, Collection<K> keys) {
validate(obj);
return obj.entrySet().stream()
.filter(kv -> keys.contains(kv.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
// ========== ruleFor ==========
protected final ObjectValidator<Map<K, V>, V> ruleFor(K key) {
return ruleFor(m -> m.get(key));
}
protected final IntValidator<Map<K, V>> ruleForInt(K key) {
return ruleForInt(m -> (Integer) m.get(key));
}
protected final DoubleValidator<Map<K, V>> ruleForDouble(K key) {
return ruleForDouble(m -> (Double) m.get(key));
}
protected final BoolValidator<Map<K, V>> ruleForBool(K key) {
return ruleForBool(m -> (Boolean) m.get(key));
}
protected final StringValidator<Map<K, V>> ruleForString(K key) {
return ruleForString(m -> (String) m.get(key));
}
protected final <E> CollectionValidator<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);
}
}

View File

@ -1,22 +0,0 @@
package xyz.zhouxy.plusone.validator.map;
import java.util.Map;
import xyz.zhouxy.plusone.validator.BasePropertyValidator;
public class EntryValidator<K, V>
extends BasePropertyValidator<Map<K, ? super V>, V, EntryValidator<K, V>> {
public EntryValidator(K key) {
super(m -> {
@SuppressWarnings("unchecked")
V v = (V) m.get(key);
return v;
});
}
@Override
protected EntryValidator<K, V> thisObject() {
return this;
}
}

View File

@ -1,83 +0,0 @@
package xyz.zhouxy.plusone.validator.map;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public abstract class MapValidator<K, V> {
private final List<Consumer<Map<K, V>>> consumers = new LinkedList<>();
private final Set<K> keys;
protected MapValidator(K[] keys) {
this(Arrays.asList(keys));
}
protected MapValidator(Collection<K> keys) {
this.keys = keys.stream().collect(Collectors.toSet());
}
public final Map<K, V> validateAndCopy(Map<K, V> obj) {
return validateAndCopyInternal(obj, this.keys);
}
public final Map<K, V> validateAndCopy(Map<K, V> obj, Collection<K> keys) {
return validateAndCopyInternal(obj, keys);
}
@SafeVarargs
public final Map<K, V> validateAndCopy(Map<K, V> obj, K... keys) {
return validateAndCopyInternal(obj, Arrays.asList(keys));
}
private final Map<K, V> validateAndCopyInternal(Map<K, V> obj, Collection<K> keys) {
validate(obj);
return obj.entrySet().stream()
.filter(kv -> keys.contains(kv.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
public final void validate(Map<K, V> obj) {
this.consumers.forEach(consumer -> consumer.accept(obj));
}
@SuppressWarnings("unused")
protected final <VV extends V> EntryValidator<K, VV> checkValue(K key, Class<VV> clazz) {
return checkValue(key);
}
protected final <VV extends V> EntryValidator<K, VV> checkValue(K key) {
EntryValidator<K, VV> validator = new EntryValidator<>(key);
this.consumers.add(validator::validate);
return validator;
}
protected final void withRule(Predicate<? super Map<K, V>> rule, String errMsg) {
withRule(rule, map -> new IllegalArgumentException(errMsg));
}
protected final void withRule(Predicate<? super Map<K, V>> rule, String errMsgFormat, Object... args) {
withRule(rule, map -> new IllegalArgumentException(String.format(errMsgFormat, args)));
}
protected final <E extends RuntimeException> void withRule(Predicate<? super Map<K, V>> rule, Supplier<E> e) {
withRule(rule, map -> e.get());
}
protected final <E extends RuntimeException> void withRule(Predicate<? super Map<K, V>> rule, Function<Map<K, V>, E> e) {
this.consumers.add(map -> {
if (!rule.test(map)) {
throw e.apply(map);
}
});
}
}

View File

@ -3,7 +3,6 @@ package xyz.zhouxy.plusone.validator.map.test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -12,11 +11,8 @@ import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import xyz.zhouxy.plusone.commons.collection.CollectionTools;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.commons.constant.PatternConsts;
import xyz.zhouxy.plusone.commons.function.PredicateTools; import xyz.zhouxy.plusone.validator.MapValidator;
import xyz.zhouxy.plusone.commons.util.RegexTools;
import xyz.zhouxy.plusone.validator.map.MapValidator;
public // public //
class MapValidatorTests { class MapValidatorTests {
@ -52,36 +48,33 @@ class ParamsValidator extends MapValidator<String, Object> {
private ParamsValidator() { private ParamsValidator() {
super(new String[] { USERNAME, ACCOUNT, PASSWORD, AGE, BOOLEAN, ROLE_LIST }); super(new String[] { USERNAME, ACCOUNT, PASSWORD, AGE, BOOLEAN, ROLE_LIST });
checkValue(USERNAME, String.class).withRule( ruleForString(USERNAME)
PredicateTools.from(StringUtils::isNotBlank) .notBlank("用户名不能为空")
.and(username -> RegexTools.matches(username, PatternConsts.USERNAME)), .matches(PatternConsts.USERNAME,
username -> new IllegalArgumentException(String.format("用户名【%s】不符合规范", username))); username -> new IllegalArgumentException(String.format("用户名【%s】不符合规范", username)));
checkValue(ACCOUNT, String.class).withRule( ruleForString(ACCOUNT)
PredicateTools.from(StringUtils::isNotBlank) .notBlank("账号不能为空")
.and(account -> RegexTools.matchesOne(account, .matchesOne(new Pattern[] { PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE }, "请输入正确的邮箱地址或手机号");
new Pattern[] { PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE })),
"请输入正确的邮箱地址或手机号");
checkValue(PASSWORD, String.class) ruleForString(PASSWORD)
.withRule(StringUtils::isNotEmpty, "密码不能为空") .notEmpty("密码不能为空")
.withRule(pwd -> RegexTools.matches(pwd, PatternConsts.PASSWORD), "密码不符合规范"); .matches(PatternConsts.PASSWORD, "密码不符合规范");
// 校验到多个属性,只能针对 map 本身进行校验 // 校验到多个属性,只能针对 map 本身进行校验
withRule(m -> Objects.equals(m.get(PASSWORD), m.get(PASSWORD2)), withRule(m -> Objects.equals(m.get(PASSWORD), m.get(PASSWORD2)),
"两次输入的密码不一样!"); "两次输入的密码不一样!");
// 通过泛型方式调用方法,指定数据类型 ruleForInt(AGE)
this.<Integer>checkValue(AGE)
.withRule(Objects::nonNull) .withRule(Objects::nonNull)
.withRule(age -> (18 <= age && 60 >= age)); .between(18, 61);
checkValue(BOOLEAN, Boolean.class) ruleForBool(BOOLEAN)
.withRule(Objects::nonNull, "Boolean property could not be null.") .notNull("Boolean property could not be null.")
.withRule(b -> b, "Boolean property must be true."); .isTrue("Boolean property must be true.");
this.<Collection<String>>checkValue(ROLE_LIST) this.<String>ruleForCollection(ROLE_LIST)
.withRule(CollectionTools::isNotEmpty, "角色列表不能为空!") .notEmpty("角色列表不能为空!")
.withRule(l -> l.stream().allMatch(StringUtils::isNotBlank), .withRule(l -> l.stream().allMatch(StringUtils::isNotBlank),
() -> new IllegalArgumentException("角色标识不能为空!")); () -> new IllegalArgumentException("角色标识不能为空!"));
} }