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

feat(exception): Supported ConfigExceptionHandler for holders.

This commit is contained in:
2025-03-17 01:06:57 +08:00
parent 65f3cc1b3d
commit 82cca5eca2
18 changed files with 190 additions and 131 deletions
@@ -1,21 +0,0 @@
package cc.carm.lib.configuration.annotation;
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
public class Ex {
static void init(ConfigurationInitializer initializer) {
initializer.appendFieldInitializer((holder, path, field, value) -> {
ValueRange range = field.getAnnotation(ValueRange.class);
if (range == null) return;
value.validate((h, v) -> {
if (!(v instanceof Number)) return;
Number number = (Number) v;
if (number.doubleValue() >= range.min() && number.doubleValue() <= range.max()) {
throw new IllegalArgumentException(range.message());
}
});
});
}
}
@@ -29,7 +29,7 @@ public abstract class AbstractConfigBuilder<
protected @Nullable HOLDER holder; protected @Nullable HOLDER holder;
protected @Nullable String path; protected @Nullable String path;
protected @NotNull ValueValidator<? super UNIT> valueValidator = ValueValidator.none(); protected @NotNull ValueValidator<UNIT> valueValidator = ValueValidator.none();
protected @NotNull Supplier<@Nullable TYPE> defaultValueSupplier = () -> null; protected @NotNull Supplier<@Nullable TYPE> defaultValueSupplier = () -> null;
protected @NotNull BiConsumer<ConfigurationHolder<?>, String> initializer = (h, p) -> { protected @NotNull BiConsumer<ConfigurationHolder<?>, String> initializer = (h, p) -> {
}; };
@@ -63,7 +63,7 @@ public abstract class AbstractConfigBuilder<
* @param validator The validator to set. * @param validator The validator to set.
* @return this builder * @return this builder
*/ */
public SELF validator(@NotNull ValueValidator<? super UNIT> validator) { public SELF validator(@NotNull ValueValidator<UNIT> validator) {
this.valueValidator = validator; this.valueValidator = validator;
return self(); return self();
} }
@@ -81,20 +81,17 @@ public abstract class AbstractConfigBuilder<
/** /**
* Validate the value with the specified condition. * Validate the value with the specified condition.
* *
* @param validator The validator to set. * @param validator The validator to append.
* @return this builder * @return this builder
*/ */
public SELF validate(@NotNull ValueValidator<? super UNIT> validator) { public SELF validate(@NotNull ValueValidator<? super UNIT> validator) {
return validator((h, v) -> { return validator(this.valueValidator.and(validator));
this.valueValidator.validate(h, v);
validator.validate(h, v);
});
} }
/** /**
* Validate the value with the specified condition. * Validate the value with the specified condition.
* *
* @param validator The validator to set. * @param validator The validator to append.
* @return this builder * @return this builder
*/ */
public SELF validate(@NotNull DataValidator<? super UNIT> validator) { public SELF validate(@NotNull DataValidator<? super UNIT> validator) {
@@ -0,0 +1,22 @@
package cc.carm.lib.configuration.function;
import org.jetbrains.annotations.NotNull;
@FunctionalInterface
public interface ConfigExceptionHandler {
void handle(@NotNull String path, @NotNull Throwable throwable);
static @NotNull ConfigExceptionHandler silence() {
return (path, throwable) -> {
};
}
static @NotNull ConfigExceptionHandler print() {
return (path, throwable) -> {
System.err.println("Error occurred at path: " + path);
throwable.printStackTrace();
};
}
}
@@ -9,7 +9,7 @@ public interface ValueValidator<T> {
void validate(@NotNull ConfigurationHolder<?> holder, @Nullable T value) throws Exception; void validate(@NotNull ConfigurationHolder<?> holder, @Nullable T value) throws Exception;
default ValueValidator<T> compose(ValueValidator<? super T> other) { default ValueValidator<T> and(ValueValidator<? super T> other) {
return (holder, value) -> { return (holder, value) -> {
validate(holder, value); validate(holder, value);
other.validate(holder, value); other.validate(holder, value);
@@ -2,7 +2,9 @@ package cc.carm.lib.configuration.source;
import cc.carm.lib.configuration.adapter.*; import cc.carm.lib.configuration.adapter.*;
import cc.carm.lib.configuration.adapter.strandard.StandardAdapters; import cc.carm.lib.configuration.adapter.strandard.StandardAdapters;
import cc.carm.lib.configuration.function.ConfigExceptionHandler;
import cc.carm.lib.configuration.function.DataFunction; import cc.carm.lib.configuration.function.DataFunction;
import cc.carm.lib.configuration.function.ValueValidator;
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer; import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
import cc.carm.lib.configuration.source.loader.PathGenerator; import cc.carm.lib.configuration.source.loader.PathGenerator;
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder; import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
@@ -33,10 +35,11 @@ public abstract class ConfigurationFactory<
SELF SELF
> { > {
protected ValueAdapterRegistry adapters = new ValueAdapterRegistry(); protected @NotNull ValueAdapterRegistry adapters = new ValueAdapterRegistry();
protected ConfigurationOptionHolder options = new ConfigurationOptionHolder(); protected @NotNull ConfigurationOptionHolder options = new ConfigurationOptionHolder();
protected @NotNull Map<String, ConfigurationMetaHolder> metadata = new HashMap<>(); protected @NotNull Map<String, ConfigurationMetaHolder> metadata = new HashMap<>();
protected ConfigurationInitializer initializer = new ConfigurationInitializer(); protected @NotNull ConfigurationInitializer initializer = new ConfigurationInitializer();
protected @NotNull ConfigExceptionHandler exceptionHandler = ConfigExceptionHandler.print();
protected ConfigurationFactory() { protected ConfigurationFactory() {
this.adapters.register(StandardAdapters.PRIMITIVES); this.adapters.register(StandardAdapters.PRIMITIVES);
@@ -147,6 +150,11 @@ public abstract class ConfigurationFactory<
return self(); return self();
} }
public SELF exceptionally(@NotNull ConfigExceptionHandler handler) {
this.exceptionHandler = handler;
return self();
}
/** /**
* Supply the base path generator for this configuration holder * Supply the base path generator for this configuration holder
* *
@@ -154,9 +162,7 @@ public abstract class ConfigurationFactory<
* @return this * @return this
*/ */
public SELF pathGenerator(PathGenerator generator) { public SELF pathGenerator(PathGenerator generator) {
return initializer(loader -> { return initializer(loader -> loader.pathGenerator(generator));
loader.pathGenerator(generator);
});
} }
/** /**
@@ -175,6 +181,19 @@ public abstract class ConfigurationFactory<
return initializer(loader -> loader.registerAnnotation(annotation, metadata, extractor)); return initializer(loader -> loader.registerAnnotation(annotation, metadata, extractor));
} }
/**
* Register a new annotation for {@link ValueValidator} to the configuration loader
*
* @param annotation The {@link Annotation}
* @param builder The {@link Function} to build the {@link ValueValidator} from the annotation
* @param <A> The annotation type
* @return this
*/
public <A extends Annotation> SELF validAnnotation(@NotNull Class<A> annotation,
@NotNull Function<A, ValueValidator<Object>> builder) {
return initializer(loader -> loader.registerValidAnnotation(annotation, builder));
}
/** /**
* Build the configuration holder. * Build the configuration holder.
* *
@@ -3,6 +3,7 @@ package cc.carm.lib.configuration.source;
import cc.carm.lib.configuration.Configuration; import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry; import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
import cc.carm.lib.configuration.adapter.ValueType; import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.function.ConfigExceptionHandler;
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer; import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder; import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata; import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
@@ -31,14 +32,25 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
protected final @NotNull ConfigurationInitializer initializer; protected final @NotNull ConfigurationInitializer initializer;
protected @NotNull ConfigExceptionHandler exceptionHandler;
public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters, public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters,
@NotNull ConfigurationOptionHolder options, @NotNull ConfigurationOptionHolder options,
@NotNull Map<String, ConfigurationMetaHolder> metadata, @NotNull Map<String, ConfigurationMetaHolder> metadata,
@NotNull ConfigurationInitializer initializer) { @NotNull ConfigurationInitializer initializer) {
this(adapters, options, metadata, initializer, ConfigExceptionHandler.print());
}
public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters,
@NotNull ConfigurationOptionHolder options,
@NotNull Map<String, ConfigurationMetaHolder> metadata,
@NotNull ConfigurationInitializer initializer,
@NotNull ConfigExceptionHandler exceptionHandler) {
this.initializer = initializer; this.initializer = initializer;
this.adapters = adapters; this.adapters = adapters;
this.options = options; this.options = options;
this.metadata = metadata; this.metadata = metadata;
this.exceptionHandler = exceptionHandler;
} }
public abstract @NotNull SOURCE config(); public abstract @NotNull SOURCE config();
@@ -117,7 +129,7 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
try { try {
initializer.initialize(this, configClass); initializer.initialize(this, configClass);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throwing(configClass.getName(), e);
} }
} }
@@ -125,7 +137,7 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
try { try {
initializer.initialize(this, config); initializer.initialize(this, config);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throwing(config.getClass().getName(), e);
} }
} }
@@ -133,4 +145,12 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
value.holder(this); value.holder(this);
} }
public void throwing(@NotNull String path, @NotNull Throwable e) {
this.exceptionHandler.handle(path, e);
}
public void exceptionally(@NotNull ConfigExceptionHandler handler) {
this.exceptionHandler = handler;
}
} }
@@ -134,7 +134,7 @@ public class ConfigurationInitializer {
try { try {
this.classInitializer.whenInitialize(holder, path, root.getClass(), root); this.classInitializer.whenInitialize(holder, path, root.getClass(), root);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); holder.throwing(path, e);
} }
Arrays.stream(root.getClass().getDeclaredFields()).forEach(field -> initializeField(holder, root, field, path)); Arrays.stream(root.getClass().getDeclaredFields()).forEach(field -> initializeField(holder, root, field, path));
} }
@@ -151,7 +151,7 @@ public class ConfigurationInitializer {
try { try {
this.classInitializer.whenInitialize(holder, path, (Class<? extends Configuration>) clazz, configField); this.classInitializer.whenInitialize(holder, path, (Class<? extends Configuration>) clazz, configField);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); holder.throwing(path, e);
} }
for (Field field : clazz.getDeclaredFields()) { for (Field field : clazz.getDeclaredFields()) {
@@ -185,7 +185,7 @@ public class ConfigurationInitializer {
try { try {
this.valueInitializer.whenInitialize(holder, path, field, value); this.valueInitializer.whenInitialize(holder, path, field, value);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); holder.throwing(path, e);
} }
if (holder.option(StandardOptions.PRELOAD)) { if (holder.option(StandardOptions.PRELOAD)) {
value.get(); // Preload the value by calling #get method. value.get(); // Preload the value by calling #get method.
@@ -20,7 +20,7 @@ public class ValueManifest<TYPE, UNIT> {
protected @Nullable ConfigurationHolder<?> holder; protected @Nullable ConfigurationHolder<?> holder;
protected @Nullable String path; // Section path protected @Nullable String path; // Section path
protected @NotNull ValueValidator<? super UNIT> validator; protected @NotNull ValueValidator<UNIT> validator;
protected @NotNull Supplier<@Nullable TYPE> defaultSupplier; protected @NotNull Supplier<@Nullable TYPE> defaultSupplier;
public ValueManifest(@NotNull ValueType<TYPE> type) { public ValueManifest(@NotNull ValueType<TYPE> type) {
@@ -37,19 +37,19 @@ public class ValueManifest<TYPE, UNIT> {
public ValueManifest(@NotNull ValueType<TYPE> type, public ValueManifest(@NotNull ValueType<TYPE> type,
@NotNull Supplier<@Nullable TYPE> defaultSupplier, @NotNull Supplier<@Nullable TYPE> defaultSupplier,
@NotNull ValueValidator<? super UNIT> validator) { @NotNull ValueValidator<UNIT> validator) {
this(type, defaultSupplier, validator, EMPTY_INITIALIZER, null, null); this(type, defaultSupplier, validator, EMPTY_INITIALIZER, null, null);
} }
public ValueManifest(@NotNull ValueType<TYPE> type, @NotNull Supplier<@Nullable TYPE> defaultSupplier, public ValueManifest(@NotNull ValueType<TYPE> type, @NotNull Supplier<@Nullable TYPE> defaultSupplier,
@NotNull ValueValidator<? super UNIT> validator, @NotNull ValueValidator<UNIT> validator,
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer) { @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer) {
this(type, defaultSupplier, validator, initializer, null, null); this(type, defaultSupplier, validator, initializer, null, null);
} }
public ValueManifest(@NotNull ValueType<TYPE> type, public ValueManifest(@NotNull ValueType<TYPE> type,
@NotNull Supplier<@Nullable TYPE> defaultSupplier, @NotNull Supplier<@Nullable TYPE> defaultSupplier,
@NotNull ValueValidator<? super UNIT> validator, @NotNull ValueValidator<UNIT> validator,
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer, @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer,
@Nullable ConfigurationHolder<?> holder, @Nullable String path) { @Nullable ConfigurationHolder<?> holder, @Nullable String path) {
this.type = type; this.type = type;
@@ -103,19 +103,16 @@ public class ValueManifest<TYPE, UNIT> {
return defaults() != null; return defaults() != null;
} }
public @NotNull ValueValidator<? super UNIT> validator() { public @NotNull ValueValidator<UNIT> validator() {
return this.validator; return this.validator;
} }
public void validator(@NotNull ValueValidator<? super UNIT> validator) { public void validator(@NotNull ValueValidator<UNIT> validator) {
this.validator = validator; this.validator = validator;
} }
public void validate(@NotNull ValueValidator<? super UNIT> validator) { public void validate(@NotNull ValueValidator<UNIT> validator) {
validator((h, v) -> { validator(this.validator.and(validator));
this.validator.validate(h, v);
validator.validate(h, v);
});
} }
protected UNIT withValidated(@Nullable UNIT value) throws Exception { protected UNIT withValidated(@Nullable UNIT value) throws Exception {
@@ -151,6 +148,15 @@ public class ValueManifest<TYPE, UNIT> {
config().set(path(), value); config().set(path(), value);
} }
protected void throwing(@NotNull Throwable throwable) {
throwing(path, throwable);
}
protected void throwing(@NotNull String path, @NotNull Throwable throwable) {
if (holder == null) throwable.printStackTrace();
else holder.throwing(path, throwable);
}
private static final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> EMPTY_INITIALIZER = (provider, valuePath) -> { private static final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> EMPTY_INITIALIZER = (provider, valuePath) -> {
}; };
@@ -87,19 +87,24 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>, V> implements
if (!cacheExpired()) return getCachedOrDefault(createList()); if (!cacheExpired()) return getCachedOrDefault(createList());
// Data that is outdated and needs to be parsed again. // Data that is outdated and needs to be parsed again.
List<V> list = createList(); List<V> list = createList();
List<?> data = config().contains(path()) ? config().getList(path()) : null; try {
if (data == null) return getDefaultFirst(list); List<?> data = config().contains(path()) ? config().getList(path()) : null;
if (data == null) return getDefaultFirst(list);
ValueParser<V> parser = parser(); ValueParser<V> parser = parser();
if (parser == null) return getDefaultFirst(list); if (parser == null) return getDefaultFirst(list);
for (Object dataVal : data) { int i = 0;
if (dataVal == null) continue; for (Object dataVal : data) {
try { if (dataVal == null) continue;
list.add(withValidated(parser.parse(holder(), paramType(), dataVal))); try {
} catch (Exception e) { list.add(withValidated(parser.parse(holder(), paramType(), dataVal)));
e.printStackTrace(); } catch (Exception e) {
throwing(path + "[" + i + "]", e);
}
} }
} catch (Exception ex) {
throwing(ex);
} }
return updateCache(list); return updateCache(list);
} }
@@ -121,7 +126,7 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>, V> implements
try { try {
data.add(serializer.serialize(holder(), paramType(), withValidated(val))); data.add(serializer.serialize(holder(), paramType(), withValidated(val)));
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); throwing(ex);
} }
} }
setData(data); setData(data);
@@ -77,27 +77,31 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>, V> impleme
// If the value is expired, we need to update it // If the value is expired, we need to update it
Map<K, V> map = createMap(); Map<K, V> map = createMap();
ConfigureSection section = config().getSection(path()); try {
if (section == null) return getDefaultFirst(map); ConfigureSection section = config().getSection(path());
if (section == null) return getDefaultFirst(map);
Set<String> keys = section.getKeys(false); Set<String> keys = section.getKeys(false);
if (keys.isEmpty()) return getDefaultFirst(map); if (keys.isEmpty()) return getDefaultFirst(map);
ValueParser<K> keyParser = parserFor(keyAdapter); ValueParser<K> keyParser = parserFor(keyAdapter);
if (keyParser == null) return getDefaultFirst(map); if (keyParser == null) return getDefaultFirst(map);
ValueParser<V> valueParser = parserFor(valueAdapter); ValueParser<V> valueParser = parserFor(valueAdapter);
if (valueParser == null) return getDefaultFirst(map); if (valueParser == null) return getDefaultFirst(map);
for (String dataKey : keys) { for (String dataKey : keys) {
Object dataVal = section.get(dataKey); Object dataVal = section.get(dataKey);
if (dataVal == null) continue; if (dataVal == null) continue;
try { try {
K key = keyParser.parse(holder(), keyType(), dataKey); K key = keyParser.parse(holder(), keyType(), dataKey);
V value = valueParser.parse(holder(), valueType(), dataVal); V value = valueParser.parse(holder(), valueType(), dataVal);
map.put(key, withValidated(value)); map.put(key, withValidated(value));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throwing(path + "." + dataKey, e);
}
} }
} catch (Exception ex) {
throwing(ex);
} }
return updateCache(map); return updateCache(map);
@@ -120,24 +124,28 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>, V> impleme
return; return;
} }
ValueSerializer<K> keySerializer = serializerFor(keyAdapter); try {
if (keySerializer == null) return; ValueSerializer<K> keySerializer = serializerFor(keyAdapter);
ValueSerializer<V> valueSerializer = serializerFor(valueAdapter); if (keySerializer == null) return;
if (valueSerializer == null) return; ValueSerializer<V> valueSerializer = serializerFor(valueAdapter);
if (valueSerializer == null) return;
Map<Object, Object> data = new LinkedHashMap<>(); Map<Object, Object> data = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : value.entrySet()) { for (Map.Entry<K, V> entry : value.entrySet()) {
try { try {
data.put( data.put(
keySerializer.serialize(holder(), keyType(), entry.getKey()), keySerializer.serialize(holder(), keyType(), entry.getKey()),
valueSerializer.serialize(holder(), valueType(), withValidated(entry.getValue())) valueSerializer.serialize(holder(), valueType(), withValidated(entry.getValue()))
); );
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throwing(path + "." + entry.getKey(), e);
}
} }
setData(data);
} catch (Exception ex) {
throwing(ex);
} }
setData(data);
} }
public <T> @NotNull T handle(Function<Map<K, V>, T> function) { public <T> @NotNull T handle(Function<Map<K, V>, T> function) {
@@ -137,20 +137,19 @@ public class ConfiguredValue<V> extends CachedConfigValue<V, V> {
if (!cacheExpired()) return getCachedOrDefault(); if (!cacheExpired()) return getCachedOrDefault();
// Data that is outdated and needs to be parsed again. // Data that is outdated and needs to be parsed again.
Object data = getData();
if (data == null) return defaults();
ValueParser<V> parser = parser();
if (parser == null) return defaults(); // No parser, return default value.
try { try {
Object data = getData();
if (data == null) return defaults();
ValueParser<V> parser = parser();
if (parser == null) return defaults(); // No parser, return default value.
// If there are no errors, update the cache and return. // If there are no errors, update the cache and return.
V parsed = parser.parse(holder(), type(), data); V parsed = parser.parse(holder(), type(), data);
return updateCache(withValidated(parsed)); return updateCache(withValidated(parsed));
} catch (Exception e) { } catch (Exception e) {
// There was a validate or parsing error, prompted and returned the default value. // There was a validate or parsing error, prompted and returned the default value.
e.printStackTrace(); throwing(e);
return defaults(); return defaults();
} }
@@ -170,13 +169,13 @@ public class ConfiguredValue<V> extends CachedConfigValue<V, V> {
return; return;
} }
ValueSerializer<V> serializer = serializer();
if (serializer == null) return; // No serializer, do nothing.
try { try {
ValueSerializer<V> serializer = serializer();
if (serializer == null) return; // No serializer, do nothing.
setData(serializer.serialize(holder(), type(), withValidated(value))); setData(serializer.serialize(holder(), type(), withValidated(value)));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throwing(e);
} }
} }
+8
View File
@@ -13,6 +13,7 @@
<maven.compiler.target>${project.jdk.version}</maven.compiler.target> <maven.compiler.target>${project.jdk.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding> <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties> </properties>
<artifactId>configured-demo</artifactId> <artifactId>configured-demo</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -40,6 +41,13 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>configured-feature-validators</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@@ -3,7 +3,6 @@ package cc.carm.lib.configuration.demo;
import cc.carm.lib.configuration.Configuration; import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.annotation.ConfigPath; import cc.carm.lib.configuration.annotation.ConfigPath;
import cc.carm.lib.configuration.annotation.HeaderComments; import cc.carm.lib.configuration.annotation.HeaderComments;
import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.standard.ConfiguredValue; import cc.carm.lib.configuration.value.standard.ConfiguredValue;
@HeaderComments({"", "数据库配置", " 用于提供数据库连接,进行数据库操作。"}) @HeaderComments({"", "数据库配置", " 用于提供数据库连接,进行数据库操作。"})
@@ -16,17 +15,17 @@ public interface DatabaseConfiguration extends Configuration {
"- MySQL(新): com.mysql.cj.jdbc.Driver", "- MySQL(新): com.mysql.cj.jdbc.Driver",
"- MariaDB(推荐): org.mariadb.jdbc.Driver", "- MariaDB(推荐): org.mariadb.jdbc.Driver",
}) })
ConfigValue<String> DRIVER_NAME = ConfiguredValue.of( ConfiguredValue<String> DRIVER_NAME = ConfiguredValue.of(
String.class, "com.mysql.cj.jdbc.Driver" String.class, "com.mysql.cj.jdbc.Driver"
); );
ConfigValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1"); ConfiguredValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
ConfigValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306); ConfiguredValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
ConfigValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft"); ConfiguredValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
ConfigValue<String> USERNAME = ConfiguredValue.of(String.class, "root"); ConfiguredValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
ConfigValue<String> PASSWORD = ConfiguredValue.of(String.class, "password"); ConfiguredValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false"); ConfiguredValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
static String buildJDBC() { static String buildJDBC() {
return String.format("jdbc:mysql://%s:%s/%s%s", HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get()); return String.format("jdbc:mysql://%s:%s/%s%s", HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get());
@@ -29,10 +29,7 @@ public interface DemoConfiguration extends Configuration {
@ConfigPath(root = true) @ConfigPath(root = true)
@FooterComments({"此处内容将显示在配置条目的下方", "可用于补充说明,但一般不建议使用"}) @FooterComments({"此处内容将显示在配置条目的下方", "可用于补充说明,但一般不建议使用"})
ConfiguredValue<Long> TEST_NUMBER = ConfiguredValue.with(Long.class) ConfiguredValue<Long> TEST_NUMBER = ConfiguredValue.with(Long.class).defaults(123456789L).build();
.validate(l -> l > 100, "数值必须大于100")
.validate(l -> l < 100000000, "数值必须小于100000000")
.defaults(123456789L).build();
@HeaderComments({"枚举类型测试"}) @HeaderComments({"枚举类型测试"})
@FooterComments({"上述的枚举内容本质上是通过STRING解析的"}) @FooterComments({"上述的枚举内容本质上是通过STRING解析的"})
@@ -2,11 +2,13 @@ package cc.carm.lib.configuration.demo.tests.conf;
import cc.carm.lib.configuration.Configuration; import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.annotation.HeaderComments; import cc.carm.lib.configuration.annotation.HeaderComments;
import cc.carm.lib.configuration.annotation.ValueRange;
import cc.carm.lib.configuration.value.standard.ConfiguredValue; import cc.carm.lib.configuration.value.standard.ConfiguredValue;
@HeaderComments("Inner Test") @HeaderComments("service")
public class InstanceConfig implements Configuration { public class InstanceConfig implements Configuration {
@ValueRange(min = 0, max = 100, message = "The value must be between 0 and 100")
public final ConfiguredValue<Double> STATUS = ConfiguredValue.of(1.0D); public final ConfiguredValue<Double> STATUS = ConfiguredValue.of(1.0D);
} }
@@ -11,7 +11,11 @@ import java.util.regex.Pattern;
public class Validators { public class Validators {
public static void initialize(ConfigurationHolder<?> holder) { private Validators() {
throw new UnsupportedOperationException("API Register.");
}
public static void activate(ConfigurationHolder<?> holder) {
holder.initializer().registerValidAnnotation(ValueRange.class, r -> (ho, value) -> { holder.initializer().registerValidAnnotation(ValueRange.class, r -> (ho, value) -> {
if (!(value instanceof Number)) { if (!(value instanceof Number)) {
throw new IllegalArgumentException("Value is not a number: " + value); throw new IllegalArgumentException("Value is not a number: " + value);
@@ -1,10 +1,8 @@
package config; package config;
import cc.carm.lib.configuration.demo.tests.ConfigurationTest; import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
import cc.carm.lib.configuration.source.json.JSONConfigFactory;
import cc.carm.lib.configuration.source.ConfigurationHolder; import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.value.ConfigValue; import cc.carm.lib.configuration.source.json.JSONConfigFactory;
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
import org.junit.Test; import org.junit.Test;
import java.io.File; import java.io.File;
@@ -18,12 +16,6 @@ public class JSONConfigTest {
@Test @Test
public void onTest() { public void onTest() {
ConfigValue<Boolean> EXAMPLE = ConfiguredValue.of(false);
EXAMPLE.initialize(this.holder, "example");
System.out.println("Example: " + EXAMPLE.get());
ConfigurationTest.testDemo(this.holder); ConfigurationTest.testDemo(this.holder);
ConfigurationTest.testInner(this.holder); ConfigurationTest.testInner(this.holder);
@@ -1,11 +1,11 @@
package yaml.test; package yaml.test;
import cc.carm.lib.configuration.commentable.Commentable;
import cc.carm.lib.configuration.commentable.CommentableMeta; import cc.carm.lib.configuration.commentable.CommentableMeta;
import cc.carm.lib.configuration.demo.tests.ConfigurationTest; import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
import cc.carm.lib.configuration.source.ConfigurationHolder; import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.yaml.YAMLConfigFactory; import cc.carm.lib.configuration.source.yaml.YAMLConfigFactory;
import cc.carm.lib.configuration.source.yaml.YAMLSource; import cc.carm.lib.configuration.source.yaml.YAMLSource;
import cc.carm.lib.configuration.validators.Validators;
import org.junit.Test; import org.junit.Test;
import java.util.List; import java.util.List;
@@ -19,6 +19,8 @@ public class YamlTests {
ConfigurationHolder<YAMLSource> holder = YAMLConfigFactory.from("target/tests.yml") ConfigurationHolder<YAMLSource> holder = YAMLConfigFactory.from("target/tests.yml")
.resourcePath("configs/sample.yml").build(); .resourcePath("configs/sample.yml").build();
Validators.activate(holder);
ConfigurationTest.testDemo(holder); ConfigurationTest.testDemo(holder);
ConfigurationTest.testInner(holder); ConfigurationTest.testInner(holder);