-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
32 changed files
with
1,471 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
name: run mvn test | ||
|
||
on: [ push, pull_request, workflow_dispatch ] | ||
|
||
jobs: | ||
run-mvn-test: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-java@v4 | ||
with: | ||
distribution: 'zulu' | ||
java-version: '8' | ||
cache: maven | ||
|
||
- run: | | ||
java -version | ||
mvn -v | ||
- run: mvn verify | ||
- run: mvn clean test jacoco:report coveralls:report -DrepoToken="${{secrets.COVERALLS_TOKEN}}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<component name="ProjectRunConfigurationManager"> | ||
<configuration default="false" name="jacoco:report" type="MavenRunConfiguration" factoryName="Maven"> | ||
<MavenSettings> | ||
<option name="myGeneralSettings"/> | ||
<option name="myRunnerSettings"/> | ||
<option name="myRunnerParameters"> | ||
<MavenRunnerParameters> | ||
<option name="cmdOptions"/> | ||
<option name="profiles"> | ||
<set/> | ||
</option> | ||
<option name="goals"> | ||
<list> | ||
<option value="clean"/> | ||
<option value="test"/> | ||
<option value="jacoco:report"/> | ||
</list> | ||
</option> | ||
<option name="multimoduleDir"/> | ||
<option name="pomFileName" value="pom.xml"/> | ||
<option name="profilesMap"> | ||
<map> | ||
<entry key="release" value="false"/> | ||
</map> | ||
</option> | ||
<option name="projectsCmdOptionValues"> | ||
<list/> | ||
</option> | ||
<option name="resolveToWorkspace" value="false"/> | ||
<option name="workingDirPath" value="$PROJECT_DIR$"/> | ||
</MavenRunnerParameters> | ||
</option> | ||
</MavenSettings> | ||
<extension name="net.ashald.envfile"> | ||
<option name="IS_ENABLED" value="false"/> | ||
<option name="IS_SUBST" value="false"/> | ||
<option name="IS_PATH_MACRO_SUPPORTED" value="false"/> | ||
<option name="IS_IGNORE_MISSING_FILES" value="false"/> | ||
<option name="IS_ENABLE_EXPERIMENTAL_INTEGRATIONS" value="false"/> | ||
<ENTRIES> | ||
<ENTRY IS_ENABLED="true" PARSER="runconfig"/> | ||
</ENTRIES> | ||
</extension> | ||
<method v="2"/> | ||
</configuration> | ||
</component> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
src/main/java/cn/sticki/validator/spel/constrain/SpelMax.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package cn.sticki.validator.spel.constrain; | ||
|
||
import cn.sticki.validator.spel.SpelConstraint; | ||
import cn.sticki.validator.spel.SpelValid; | ||
import cn.sticki.validator.spel.constraintvalidator.SpelMaxValidator; | ||
import org.intellij.lang.annotations.Language; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.Repeatable; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.Target; | ||
|
||
import static java.lang.annotation.ElementType.FIELD; | ||
import static java.lang.annotation.RetentionPolicy.RUNTIME; | ||
|
||
/** | ||
* 被标记的元素值必须小于或等于指定的最小值。{@code null} 元素被认为是有效的。 | ||
* <p> | ||
* 支持所有 {@link Number} 类型及它们的基本数据类型。 | ||
* | ||
* @author 阿杆 | ||
* @version 1.0 | ||
* @since 2024/9/29 | ||
*/ | ||
@Documented | ||
@Retention(RUNTIME) | ||
@Target(FIELD) | ||
@Repeatable(SpelMax.List.class) | ||
@SpelConstraint(validatedBy = SpelMaxValidator.class) | ||
public @interface SpelMax { | ||
|
||
/** | ||
* 校验失败时的错误消息。 | ||
*/ | ||
String message() default "必须小于或等于 {value}"; | ||
|
||
/** | ||
* 约束开启条件,必须为合法的SpEL表达式,计算结果必须为boolean类型。 | ||
* <p> | ||
* 当 表达式为空 或 计算结果为true 时,会对带注解的元素进行校验。 | ||
* <p> | ||
* 默认情况下,开启校验。 | ||
*/ | ||
@Language("SpEL") | ||
String condition() default ""; | ||
|
||
/** | ||
* 分组条件,必须为合法的SpEL表达式。 | ||
* <p> | ||
* 当分组信息不为空时,只有当 {@link SpelValid#spelGroups()} 中的分组信息与此处的分组信息有交集时,才会对带注解的元素进行校验。 | ||
* <p> | ||
* 其计算结果可以是任何类型,但只有两个计算结果完全相等时,才被认为是相等的。 | ||
*/ | ||
@Language("SpEL") | ||
String[] group() default {}; | ||
|
||
/** | ||
* 指定元素最大值。必须为合法的SpEL表达式, | ||
* <p> | ||
* 表达式的计算结果必须为 {@link Number} 类型。 | ||
*/ | ||
@Language("SpEL") | ||
String value() default "0"; | ||
|
||
@Documented | ||
@Target(FIELD) | ||
@Retention(RUNTIME) | ||
@interface List { | ||
|
||
SpelMax[] value(); | ||
|
||
} | ||
|
||
} |
73 changes: 73 additions & 0 deletions
73
src/main/java/cn/sticki/validator/spel/constrain/SpelMin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package cn.sticki.validator.spel.constrain; | ||
|
||
import cn.sticki.validator.spel.SpelConstraint; | ||
import cn.sticki.validator.spel.SpelValid; | ||
import cn.sticki.validator.spel.constraintvalidator.SpelMinValidator; | ||
import org.intellij.lang.annotations.Language; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.Repeatable; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.Target; | ||
|
||
import static java.lang.annotation.ElementType.FIELD; | ||
import static java.lang.annotation.RetentionPolicy.RUNTIME; | ||
|
||
/** | ||
* 被标记的元素值必须大于或等于指定的最小值。{@code null} 元素被认为是有效的。 | ||
* <p> | ||
* 支持所有 {@link Number} 类型及它们的基本数据类型。 | ||
* | ||
* @author oddfar、阿杆 | ||
* @version 1.0 | ||
* @since 2024/8/25 | ||
*/ | ||
@Documented | ||
@Retention(RUNTIME) | ||
@Target(FIELD) | ||
@Repeatable(SpelMin.List.class) | ||
@SpelConstraint(validatedBy = SpelMinValidator.class) | ||
public @interface SpelMin { | ||
|
||
/** | ||
* 校验失败时的错误消息。 | ||
*/ | ||
String message() default "必须大于或等于 {value}"; | ||
|
||
/** | ||
* 约束开启条件,必须为合法的SpEL表达式,计算结果必须为boolean类型。 | ||
* <p> | ||
* 当 表达式为空 或 计算结果为true 时,会对带注解的元素进行校验。 | ||
* <p> | ||
* 默认情况下,开启校验。 | ||
*/ | ||
@Language("SpEL") | ||
String condition() default ""; | ||
|
||
/** | ||
* 分组条件,必须为合法的SpEL表达式。 | ||
* <p> | ||
* 当分组信息不为空时,只有当 {@link SpelValid#spelGroups()} 中的分组信息与此处的分组信息有交集时,才会对带注解的元素进行校验。 | ||
* <p> | ||
* 其计算结果可以是任何类型,但只有两个计算结果完全相等时,才被认为是相等的。 | ||
*/ | ||
@Language("SpEL") | ||
String[] group() default {}; | ||
|
||
/** | ||
* 指定元素最小值。必须为合法的SpEL表达式, | ||
* <p> | ||
* 表达式的计算结果必须为 {@link Number} 类型。 | ||
*/ | ||
@Language("SpEL") | ||
String value() default "0"; | ||
|
||
@Documented | ||
@Target(FIELD) | ||
@Retention(RUNTIME) | ||
@interface List { | ||
|
||
SpelMin[] value(); | ||
|
||
} | ||
} |
71 changes: 71 additions & 0 deletions
71
...java/cn/sticki/validator/spel/constraintvalidator/AbstractSpelNumberCompareValidator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package cn.sticki.validator.spel.constraintvalidator; | ||
|
||
import cn.sticki.validator.spel.SpelConstraintValidator; | ||
import cn.sticki.validator.spel.exception.SpelParserException; | ||
import cn.sticki.validator.spel.parse.SpelParser; | ||
import cn.sticki.validator.spel.result.FieldValidResult; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.util.Collections; | ||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
/** | ||
* 约束注解 Max、Min 的抽象校验器。 | ||
* | ||
* @author oddfar、阿杆 | ||
* @version 1.0 | ||
* @since 2024/8/25 | ||
*/ | ||
public abstract class AbstractSpelNumberCompareValidator<T extends Annotation> implements SpelConstraintValidator<T> { | ||
|
||
public FieldValidResult isValid(Number fieldValue, String spel, String errorMessage, Object obj) { | ||
// 元素为null是被允许的 | ||
if (fieldValue == null) { | ||
return FieldValidResult.success(); | ||
} | ||
// 计算表达式的值,基本数据类型会自动装箱 | ||
Object minValue = SpelParser.parse(spel, obj); | ||
if (!(minValue instanceof Number)) { | ||
throw new SpelParserException("Expression [" + spel + "] calculate result must be Number."); | ||
} | ||
// 比较大小,其中一个是Not-a-Number (NaN)默认失败 | ||
if (!this.compare(fieldValue, (Number) minValue)) { | ||
// todo 目前对Double的边界值处理不太友好,message的展示类似为:不能小于等于 NaN。后续考虑去掉对Double Float类型的支持,或者对边界值抛出异常。 | ||
// 构建错误信息 | ||
String replacedMessage = errorMessage.replace("{value}", String.valueOf(minValue)); | ||
return new FieldValidResult(false, replacedMessage); | ||
} | ||
|
||
return FieldValidResult.success(); | ||
} | ||
|
||
/** | ||
* 比较两个数值的大小,返回比较结果。 | ||
* | ||
* @param fieldValue 当前元素的值 | ||
* @param compareValue 比较的值,最大值或最小值 | ||
* @return 成功时返回true,失败时返回false | ||
*/ | ||
protected abstract boolean compare(Number fieldValue, Number compareValue); | ||
|
||
static final Set<Class<?>> SUPPORT_TYPE; | ||
|
||
static { | ||
HashSet<Class<?>> hashSet = new HashSet<>(); | ||
hashSet.add(Number.class); | ||
hashSet.add(int.class); | ||
hashSet.add(long.class); | ||
hashSet.add(float.class); | ||
hashSet.add(double.class); | ||
hashSet.add(short.class); | ||
hashSet.add(byte.class); | ||
SUPPORT_TYPE = Collections.unmodifiableSet(hashSet); | ||
} | ||
|
||
@Override | ||
public Set<Class<?>> supportType() { | ||
return SUPPORT_TYPE; | ||
} | ||
|
||
} |
28 changes: 28 additions & 0 deletions
28
src/main/java/cn/sticki/validator/spel/constraintvalidator/SpelMaxValidator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package cn.sticki.validator.spel.constraintvalidator; | ||
|
||
import cn.sticki.validator.spel.constrain.SpelMax; | ||
import cn.sticki.validator.spel.result.FieldValidResult; | ||
import cn.sticki.validator.spel.util.NumberComparatorUtil; | ||
|
||
import java.lang.reflect.Field; | ||
|
||
/** | ||
* {@link SpelMax} 注解校验器。 | ||
* | ||
* @author 阿杆 | ||
* @version 1.0 | ||
* @since 2024/9/29 | ||
*/ | ||
public class SpelMaxValidator extends AbstractSpelNumberCompareValidator<SpelMax> { | ||
|
||
@Override | ||
protected boolean compare(Number fieldValue, Number compareValue) { | ||
return NumberComparatorUtil.compare(fieldValue, compareValue, NumberComparatorUtil.GREATER_THAN) <= 0; | ||
} | ||
|
||
@Override | ||
public FieldValidResult isValid(SpelMax annotation, Object obj, Field field) throws IllegalAccessException { | ||
return super.isValid((Number) field.get(obj), annotation.value(), annotation.message(), obj); | ||
} | ||
|
||
} |
Oops, something went wrong.