1
mirror of https://github.com/CarmJos/EasyConfiguration.git synced 2026-06-04 18:48:20 +08:00

feat(validator): Support validators for config values.

BREAKING CHANGE: `ValueManifest` and `ConfigValue` added a new type "UNIT" to mark the minimal unit value of this instance.

link #132
This commit is contained in:
2025-03-17 00:26:47 +08:00
parent fae048dd69
commit 65f3cc1b3d
3 changed files with 53 additions and 12 deletions
@@ -1,6 +1,7 @@
package cc.carm.lib.configuration.source.loader; package cc.carm.lib.configuration.source.loader;
import cc.carm.lib.configuration.Configuration; import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.function.ValueValidator;
import cc.carm.lib.configuration.source.ConfigurationHolder; import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata; import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
import cc.carm.lib.configuration.source.meta.StandardMeta; import cc.carm.lib.configuration.source.meta.StandardMeta;
@@ -48,7 +49,7 @@ public class ConfigurationInitializer {
return valueInitializer; return valueInitializer;
} }
public void fieldInitializer(@NotNull ConfigInitializeHandler<Field, ConfigValue<?,?>> fieldInitializer) { public void fieldInitializer(@NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> fieldInitializer) {
this.valueInitializer = fieldInitializer; this.valueInitializer = fieldInitializer;
} }
@@ -60,7 +61,7 @@ public class ConfigurationInitializer {
this.classInitializer = classInitializer; this.classInitializer = classInitializer;
} }
public void appendFieldInitializer(@NotNull ConfigInitializeHandler<Field, ConfigValue<?,?>> fieldInitializer) { public void appendFieldInitializer(@NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> fieldInitializer) {
this.valueInitializer = this.valueInitializer.andThen(fieldInitializer); this.valueInitializer = this.valueInitializer.andThen(fieldInitializer);
} }
@@ -95,6 +96,14 @@ public class ConfigurationInitializer {
registerFieldAnnotation(annotation, metadata, extractor); registerFieldAnnotation(annotation, metadata, extractor);
} }
public <A extends Annotation> void registerValidAnnotation(@NotNull Class<A> annotation,
@NotNull Function<A, ValueValidator<Object>> builder) {
appendFieldInitializer((holder, path, field, instance) -> {
A data = field.getAnnotation(annotation);
if (data == null) return;
instance.validate((h, t) -> builder.apply(data).validate(h, t));
});
}
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) { public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) {
return pathGenerator.getFieldPath(holder, parentPath, field); return pathGenerator.getFieldPath(holder, parentPath, field);
@@ -163,9 +172,9 @@ public class ConfigurationInitializer {
field.setAccessible(true); field.setAccessible(true);
Object object = field.get(source); Object object = field.get(source);
// //
if (object instanceof ConfigValue<?,?>) { if (object instanceof ConfigValue<?, ?>) {
// 目标是 ConfigValue 实例,进行具体的初始化注入 // 目标是 ConfigValue 实例,进行具体的初始化注入
ConfigValue<?,?> value = (ConfigValue<?,?>) object; ConfigValue<?, ?> value = (ConfigValue<?, ?>) object;
String path = getFieldPath(holder, parent, field); String path = getFieldPath(holder, parent, field);
if (path == null) return; if (path == null) return;
value.initialize(holder, path); value.initialize(holder, path);
@@ -1,8 +0,0 @@
package cc.carm.lib.configuration.validators;
public class StandardValidators {
}
@@ -0,0 +1,40 @@
package cc.carm.lib.configuration.validators;
import cc.carm.lib.configuration.annotation.ValuePattern;
import cc.carm.lib.configuration.annotation.ValueRange;
import cc.carm.lib.configuration.function.ValueValidator;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.regex.Pattern;
public class Validators {
public static void initialize(ConfigurationHolder<?> holder) {
holder.initializer().registerValidAnnotation(ValueRange.class, r -> (ho, value) -> {
if (!(value instanceof Number)) {
throw new IllegalArgumentException("Value is not a number: " + value);
}
Number number = (Number) value;
if (number.doubleValue() < r.min() || number.doubleValue() > r.max()) {
throw new IllegalArgumentException(r.message());
}
});
holder.initializer().registerValidAnnotation(ValuePattern.class, r -> new ValueValidator<Object>() {
private final Pattern pattern = Pattern.compile(r.value());
@Override
public void validate(@NotNull ConfigurationHolder<?> holder, @Nullable Object value) throws Exception {
if (value == null) return;
if (!pattern.matcher(value.toString()).matches()) {
throw new IllegalArgumentException(r.message());
}
}
});
}
}