|
| 1 | +package cn.sticki.validator.spel.constraintvalidator; |
| 2 | + |
| 3 | +import cn.sticki.validator.spel.SpelConstraintValidator; |
| 4 | +import cn.sticki.validator.spel.exception.SpelParserException; |
| 5 | +import cn.sticki.validator.spel.parse.SpelParser; |
| 6 | +import cn.sticki.validator.spel.result.FieldValidResult; |
| 7 | + |
| 8 | +import java.lang.annotation.Annotation; |
| 9 | +import java.util.Collections; |
| 10 | +import java.util.HashSet; |
| 11 | +import java.util.Set; |
| 12 | + |
| 13 | +/** |
| 14 | + * 约束注解 Max、Min 的抽象校验器。 |
| 15 | + * |
| 16 | + * @author oddfar、阿杆 |
| 17 | + * @version 1.0 |
| 18 | + * @since 2024/8/25 |
| 19 | + */ |
| 20 | +public abstract class AbstractSpelNumberCompareValidator<T extends Annotation> implements SpelConstraintValidator<T> { |
| 21 | + |
| 22 | + public FieldValidResult isValid(Number fieldValue, String spel, String errorMessage, Object obj) { |
| 23 | + // 元素为null是被允许的 |
| 24 | + if (fieldValue == null) { |
| 25 | + return FieldValidResult.success(); |
| 26 | + } |
| 27 | + // 计算表达式的值,基本数据类型会自动装箱 |
| 28 | + Object minValue = SpelParser.parse(spel, obj); |
| 29 | + if (!(minValue instanceof Number)) { |
| 30 | + throw new SpelParserException("Expression [" + spel + "] calculate result must be Number."); |
| 31 | + } |
| 32 | + // 比较大小,其中一个是Not-a-Number (NaN)默认失败 |
| 33 | + if (!this.compare(fieldValue, (Number) minValue)) { |
| 34 | + // todo 目前对Double的边界值处理不太友好,message的展示类似为:不能小于等于 NaN。后续考虑去掉对Double Float类型的支持,或者对边界值抛出异常。 |
| 35 | + // 构建错误信息 |
| 36 | + String replacedMessage = errorMessage.replace("{value}", String.valueOf(minValue)); |
| 37 | + return new FieldValidResult(false, replacedMessage); |
| 38 | + } |
| 39 | + |
| 40 | + return FieldValidResult.success(); |
| 41 | + } |
| 42 | + |
| 43 | + /** |
| 44 | + * 比较两个数值的大小,返回比较结果。 |
| 45 | + * |
| 46 | + * @param fieldValue 当前元素的值 |
| 47 | + * @param compareValue 比较的值,最大值或最小值 |
| 48 | + * @return 成功时返回true,失败时返回false |
| 49 | + */ |
| 50 | + protected abstract boolean compare(Number fieldValue, Number compareValue); |
| 51 | + |
| 52 | + static final Set<Class<?>> SUPPORT_TYPE; |
| 53 | + |
| 54 | + static { |
| 55 | + HashSet<Class<?>> hashSet = new HashSet<>(); |
| 56 | + hashSet.add(Number.class); |
| 57 | + hashSet.add(int.class); |
| 58 | + hashSet.add(long.class); |
| 59 | + hashSet.add(float.class); |
| 60 | + hashSet.add(double.class); |
| 61 | + hashSet.add(short.class); |
| 62 | + hashSet.add(byte.class); |
| 63 | + SUPPORT_TYPE = Collections.unmodifiableSet(hashSet); |
| 64 | + } |
| 65 | + |
| 66 | + @Override |
| 67 | + public Set<Class<?>> supportType() { |
| 68 | + return SUPPORT_TYPE; |
| 69 | + } |
| 70 | + |
| 71 | +} |
0 commit comments