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:
@@ -15,6 +15,7 @@ public class ValueAdapter<TYPE>
|
||||
implements ValueSerializer<TYPE>, ValueParser<TYPE> {
|
||||
|
||||
protected final @NotNull ValueType<TYPE> type;
|
||||
|
||||
protected @Nullable ValueSerializer<TYPE> serializer;
|
||||
protected @Nullable ValueParser<TYPE> deserializer;
|
||||
|
||||
@@ -53,13 +54,17 @@ public class ValueAdapter<TYPE>
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object serialize(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<? super TYPE> type, @NotNull TYPE value) throws Exception {
|
||||
public @Nullable Object serialize(
|
||||
@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<? super TYPE> type,
|
||||
@NotNull TYPE value) throws Exception {
|
||||
if (serializer == null) throw new UnsupportedOperationException("Serializer is not supported");
|
||||
return serializer.serialize(holder, type, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TYPE parse(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<? super TYPE> type, @NotNull Object value) throws Exception {
|
||||
public @Nullable TYPE parse(
|
||||
@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<? super TYPE> type,
|
||||
@NotNull Object value) throws Exception {
|
||||
if (deserializer == null) throw new UnsupportedOperationException("Deserializer is not supported");
|
||||
return deserializer.parse(holder, type, value);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,9 @@ public class ValueAdapterRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void register(@NotNull ValueType<T> type, @Nullable ValueSerializer<T> serializer, @Nullable ValueParser<T> deserializer) {
|
||||
public <T> void register(@NotNull ValueType<T> type,
|
||||
@Nullable ValueSerializer<T> serializer,
|
||||
@Nullable ValueParser<T> deserializer) {
|
||||
if (serializer == null && deserializer == null) return;
|
||||
ValueAdapter<T> existing = adapterOf(type);
|
||||
if (existing != null) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package cc.carm.lib.configuration.adapter;
|
||||
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Value deserializer, convert base data to target value.
|
||||
@@ -11,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
@FunctionalInterface
|
||||
public interface ValueParser<TYPE> {
|
||||
|
||||
TYPE parse(
|
||||
@Nullable TYPE parse(
|
||||
@NotNull ConfigurationHolder<?> holder,
|
||||
@NotNull ValueType<? super TYPE> type, @NotNull Object data
|
||||
) throws Exception;
|
||||
|
||||
@@ -2,6 +2,7 @@ package cc.carm.lib.configuration.adapter;
|
||||
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Value serializer, convert target value to base data.
|
||||
@@ -11,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
@FunctionalInterface
|
||||
public interface ValueSerializer<TYPE> {
|
||||
|
||||
Object serialize(
|
||||
@Nullable Object serialize(
|
||||
@NotNull ConfigurationHolder<?> holder,
|
||||
@NotNull ValueType<? super TYPE> type, @NotNull TYPE value
|
||||
) throws Exception;
|
||||
|
||||
@@ -5,6 +5,8 @@ import cc.carm.lib.configuration.adapter.ValueType;
|
||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapter.*;
|
||||
|
||||
public interface StandardAdapters {
|
||||
@@ -17,6 +19,12 @@ public interface StandardAdapters {
|
||||
|
||||
@NotNull ValueAdapter<Enum<?>> ENUMS = PrimitiveAdapter.ofEnum();
|
||||
|
||||
@NotNull ValueAdapter<UUID> UUID = new ValueAdapter<>(
|
||||
ValueType.of(UUID.class),
|
||||
(provider, type, value) -> value.toString(),
|
||||
(provider, type, value) -> java.util.UUID.fromString(value.toString())
|
||||
);
|
||||
|
||||
@NotNull ValueAdapter<ConfigureSection> SECTIONS = new ValueAdapter<>(
|
||||
ValueType.of(ConfigureSection.class),
|
||||
(provider, type, value) -> value,
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
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());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +1,26 @@
|
||||
package cc.carm.lib.configuration.builder;
|
||||
|
||||
import cc.carm.lib.configuration.adapter.ValueType;
|
||||
import cc.carm.lib.configuration.function.DataValidator;
|
||||
import cc.carm.lib.configuration.function.ValueValidator;
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
||||
import cc.carm.lib.configuration.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.value.ValueManifest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.NotNullByDefault;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@NotNullByDefault
|
||||
public abstract class AbstractConfigBuilder<
|
||||
TYPE, RESULT extends ConfigValue<TYPE>, HOLDER extends ConfigurationHolder<?>,
|
||||
SELF extends AbstractConfigBuilder<TYPE, RESULT, HOLDER, SELF>
|
||||
TYPE, UNIT, RESULT extends ConfigValue<TYPE, UNIT>, HOLDER extends ConfigurationHolder<?>,
|
||||
SELF extends AbstractConfigBuilder<TYPE, UNIT, RESULT, HOLDER, SELF>
|
||||
> {
|
||||
|
||||
protected final Class<? super HOLDER> providerClass;
|
||||
@@ -24,6 +29,7 @@ public abstract class AbstractConfigBuilder<
|
||||
protected @Nullable HOLDER holder;
|
||||
protected @Nullable String path;
|
||||
|
||||
protected @NotNull ValueValidator<? super UNIT> valueValidator = ValueValidator.none();
|
||||
protected @NotNull Supplier<@Nullable TYPE> defaultValueSupplier = () -> null;
|
||||
protected @NotNull BiConsumer<ConfigurationHolder<?>, String> initializer = (h, p) -> {
|
||||
};
|
||||
@@ -37,54 +43,124 @@ public abstract class AbstractConfigBuilder<
|
||||
return type;
|
||||
}
|
||||
|
||||
protected abstract @NotNull SELF self();
|
||||
protected abstract SELF self();
|
||||
|
||||
public abstract @NotNull RESULT build();
|
||||
|
||||
public @NotNull SELF holder(@Nullable HOLDER holder) {
|
||||
public SELF holder(@Nullable HOLDER holder) {
|
||||
this.holder = holder;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull SELF path(@Nullable String path) {
|
||||
public SELF path(@Nullable String path) {
|
||||
this.path = path;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull SELF initializer(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
|
||||
/**
|
||||
* Set the {@link ValueValidator} for the value.
|
||||
*
|
||||
* @param validator The validator to set.
|
||||
* @return this builder
|
||||
*/
|
||||
public SELF validator(@NotNull ValueValidator<? super UNIT> validator) {
|
||||
this.valueValidator = validator;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link DataValidator} for the value.
|
||||
*
|
||||
* @param validator The validator to set.
|
||||
* @return this builder
|
||||
*/
|
||||
public SELF validator(@NotNull DataValidator<? super UNIT> validator) {
|
||||
return validator((h, value) -> validator.validate(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the value with the specified condition.
|
||||
*
|
||||
* @param validator The validator to set.
|
||||
* @return this builder
|
||||
*/
|
||||
public SELF validate(@NotNull ValueValidator<? super UNIT> validator) {
|
||||
return validator((h, v) -> {
|
||||
this.valueValidator.validate(h, v);
|
||||
validator.validate(h, v);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the value with the specified condition.
|
||||
*
|
||||
* @param validator The validator to set.
|
||||
* @return this builder
|
||||
*/
|
||||
public SELF validate(@NotNull DataValidator<? super UNIT> validator) {
|
||||
return validate((h, value) -> validator.validate(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the value with the specified condition.
|
||||
*
|
||||
* @param condition The condition to check, if the condition is false, an exception will be thrown.
|
||||
* @param exception The exception to throw if the condition is false.
|
||||
* @return this builder
|
||||
*/
|
||||
public SELF validate(@NotNull Predicate<? super UNIT> condition, @NotNull Exception exception) {
|
||||
return validate((h, value) -> {
|
||||
if (!condition.test(value)) throw exception;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the value with the specified condition.
|
||||
*
|
||||
* @param condition The condition to check, if the condition is false, an exception will be thrown.
|
||||
* @param msg The message to throw if the condition is false.
|
||||
* @return this builder
|
||||
*/
|
||||
public SELF validate(@NotNull Predicate<? super UNIT> condition, @NotNull String msg) {
|
||||
return validate((h, value) -> {
|
||||
if (!condition.test(value)) throw new IllegalArgumentException(msg);
|
||||
});
|
||||
}
|
||||
|
||||
public SELF initializer(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
|
||||
this.initializer = initializer;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull SELF append(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
|
||||
public SELF append(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
|
||||
return initializer(initializer.andThen(initializer));
|
||||
}
|
||||
|
||||
public @NotNull SELF append(@NotNull Consumer<ConfigurationHolder<?>> initializer) {
|
||||
public SELF append(@NotNull Consumer<ConfigurationHolder<?>> initializer) {
|
||||
return append((provider, valuePath) -> initializer.accept(provider));
|
||||
}
|
||||
|
||||
public @NotNull SELF defaults(@Nullable TYPE defaultValue) {
|
||||
public SELF defaults(@Nullable TYPE defaultValue) {
|
||||
return defaults(() -> defaultValue);
|
||||
}
|
||||
|
||||
public @NotNull SELF defaults(@NotNull Supplier<@Nullable TYPE> supplier) {
|
||||
public SELF defaults(@NotNull Supplier<@Nullable TYPE> supplier) {
|
||||
this.defaultValueSupplier = supplier;
|
||||
return self();
|
||||
}
|
||||
|
||||
public <M> @NotNull SELF meta(@NotNull Consumer<@NotNull ConfigurationMetaHolder> metaConsumer) {
|
||||
public SELF meta(@NotNull Consumer<@NotNull ConfigurationMetaHolder> metaConsumer) {
|
||||
return append((h, p) -> metaConsumer.accept(h.metadata(p)));
|
||||
}
|
||||
|
||||
public <M> @NotNull SELF meta(@NotNull ConfigurationMetadata<M> type, @Nullable M value) {
|
||||
public <M> SELF meta(@NotNull ConfigurationMetadata<M> type, @Nullable M value) {
|
||||
return meta(h -> h.set(type, value));
|
||||
}
|
||||
|
||||
protected @NotNull ValueManifest<TYPE> buildManifest() {
|
||||
protected @NotNull ValueManifest<TYPE, UNIT> buildManifest() {
|
||||
return new ValueManifest<>(
|
||||
type(), this.defaultValueSupplier, this.initializer,
|
||||
this.holder, this.path
|
||||
type(), this.defaultValueSupplier, this.valueValidator,
|
||||
this.initializer, this.holder, this.path
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,11 @@ import cc.carm.lib.configuration.adapter.ValueType;
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import cc.carm.lib.configuration.value.ConfigValue;
|
||||
|
||||
public abstract class CommonConfigBuilder<TYPE, RESULT extends ConfigValue<TYPE>, SELF extends CommonConfigBuilder<TYPE, RESULT, SELF>>
|
||||
extends AbstractConfigBuilder<TYPE, RESULT, ConfigurationHolder<?>, SELF> {
|
||||
public abstract class CommonConfigBuilder<
|
||||
TYPE, UNIT,
|
||||
RESULT extends ConfigValue<TYPE, UNIT>,
|
||||
SELF extends CommonConfigBuilder<TYPE, UNIT, RESULT, SELF>
|
||||
> extends AbstractConfigBuilder<TYPE, UNIT, RESULT, ConfigurationHolder<?>, SELF> {
|
||||
|
||||
protected CommonConfigBuilder(ValueType<TYPE> type) {
|
||||
super(ConfigurationHolder.class, type);
|
||||
|
||||
+17
-17
@@ -4,7 +4,7 @@ import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||
import cc.carm.lib.configuration.adapter.ValueType;
|
||||
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
||||
import cc.carm.lib.configuration.function.DataFunction;
|
||||
import cc.carm.lib.configuration.function.ValueConsumer;
|
||||
import cc.carm.lib.configuration.function.ValueComposer;
|
||||
import cc.carm.lib.configuration.function.ValueHandler;
|
||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||
import cc.carm.lib.configuration.value.ConfigValue;
|
||||
@@ -14,45 +14,45 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class AbstractSectionBuilder<
|
||||
TYPE, PARAM,
|
||||
RESULT extends ConfigValue<TYPE>,
|
||||
SELF extends AbstractSectionBuilder<TYPE, PARAM, RESULT, SELF>
|
||||
> extends CommonConfigBuilder<TYPE, RESULT, SELF> {
|
||||
TYPE, UNIT,
|
||||
RESULT extends ConfigValue<TYPE, UNIT>,
|
||||
SELF extends AbstractSectionBuilder<TYPE, UNIT, RESULT, SELF>
|
||||
> extends CommonConfigBuilder<TYPE, UNIT, RESULT, SELF> {
|
||||
|
||||
|
||||
protected final @NotNull ValueType<PARAM> paramType;
|
||||
protected final @NotNull ValueType<UNIT> paramType;
|
||||
|
||||
protected @NotNull ValueHandler<ConfigureSection, PARAM> parser;
|
||||
protected @NotNull ValueHandler<PARAM, ? extends Map<String, Object>> serializer;
|
||||
protected @NotNull ValueHandler<ConfigureSection, UNIT> parser;
|
||||
protected @NotNull ValueHandler<UNIT, ? extends Map<String, Object>> serializer;
|
||||
|
||||
protected AbstractSectionBuilder(@NotNull ValueType<TYPE> type, @NotNull ValueType<PARAM> paramType,
|
||||
@NotNull ValueHandler<ConfigureSection, PARAM> parser,
|
||||
@NotNull ValueHandler<PARAM, ? extends Map<String, Object>> serializer) {
|
||||
protected AbstractSectionBuilder(@NotNull ValueType<TYPE> type, @NotNull ValueType<UNIT> paramType,
|
||||
@NotNull ValueHandler<ConfigureSection, UNIT> parser,
|
||||
@NotNull ValueHandler<UNIT, ? extends Map<String, Object>> serializer) {
|
||||
super(type);
|
||||
this.paramType = paramType;
|
||||
this.parser = parser;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
public @NotNull SELF parse(@NotNull DataFunction<ConfigureSection, PARAM> valueParser) {
|
||||
public @NotNull SELF parse(@NotNull DataFunction<ConfigureSection, UNIT> valueParser) {
|
||||
return parse((p, section) -> valueParser.handle(section));
|
||||
}
|
||||
|
||||
public @NotNull SELF parse(@NotNull ValueHandler<ConfigureSection, PARAM> valueParser) {
|
||||
public @NotNull SELF parse(@NotNull ValueHandler<ConfigureSection, UNIT> valueParser) {
|
||||
this.parser = valueParser;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull SELF serialize(@NotNull ValueHandler<PARAM, ? extends Map<String, Object>> serializer) {
|
||||
public @NotNull SELF serialize(@NotNull ValueHandler<UNIT, ? extends Map<String, Object>> serializer) {
|
||||
this.serializer = serializer;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull SELF serialize(@NotNull DataFunction<PARAM, ? extends Map<String, Object>> serializer) {
|
||||
public @NotNull SELF serialize(@NotNull DataFunction<UNIT, ? extends Map<String, Object>> serializer) {
|
||||
return serialize((p, value) -> serializer.handle(value));
|
||||
}
|
||||
|
||||
public @NotNull SELF serialize(@NotNull ValueConsumer<Map<String, Object>, PARAM> serializer) {
|
||||
public @NotNull SELF serialize(@NotNull ValueComposer<Map<String, Object>, UNIT> serializer) {
|
||||
return serialize((h, value) -> {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
serializer.accept(h, map, value);
|
||||
@@ -60,7 +60,7 @@ public abstract class AbstractSectionBuilder<
|
||||
});
|
||||
}
|
||||
|
||||
protected ValueAdapter<PARAM> buildAdapter() {
|
||||
protected ValueAdapter<UNIT> buildAdapter() {
|
||||
return new ValueAdapter<>(this.paramType)
|
||||
.parser((p, type, data) -> {
|
||||
ConfigureSection section = p.deserialize(ConfigureSection.class, data);
|
||||
|
||||
+14
-14
@@ -9,19 +9,19 @@ import cc.carm.lib.configuration.value.ConfigValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class AbstractSourceBuilder<
|
||||
V, SOURCE, PARAM, RESULT extends ConfigValue<V>,
|
||||
SELF extends AbstractSourceBuilder<V, SOURCE, PARAM, RESULT, SELF>
|
||||
> extends CommonConfigBuilder<V, RESULT, SELF> {
|
||||
V, SOURCE, UNIT, RESULT extends ConfigValue<V, UNIT>,
|
||||
SELF extends AbstractSourceBuilder<V, SOURCE, UNIT, RESULT, SELF>
|
||||
> extends CommonConfigBuilder<V, UNIT, RESULT, SELF> {
|
||||
|
||||
protected final @NotNull ValueType<SOURCE> sourceType;
|
||||
protected final @NotNull ValueType<PARAM> paramType;
|
||||
protected @NotNull ValueHandler<SOURCE, PARAM> valueParser;
|
||||
protected @NotNull ValueHandler<PARAM, SOURCE> valueSerializer;
|
||||
protected final @NotNull ValueType<UNIT> paramType;
|
||||
protected @NotNull ValueHandler<SOURCE, UNIT> valueParser;
|
||||
protected @NotNull ValueHandler<UNIT, SOURCE> valueSerializer;
|
||||
|
||||
protected AbstractSourceBuilder(@NotNull ValueType<V> type,
|
||||
@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<PARAM> paramType,
|
||||
@NotNull ValueHandler<SOURCE, PARAM> parser,
|
||||
@NotNull ValueHandler<PARAM, SOURCE> serializer) {
|
||||
@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<UNIT> paramType,
|
||||
@NotNull ValueHandler<SOURCE, UNIT> parser,
|
||||
@NotNull ValueHandler<UNIT, SOURCE> serializer) {
|
||||
super(type);
|
||||
this.sourceType = sourceType;
|
||||
this.paramType = paramType;
|
||||
@@ -29,25 +29,25 @@ public abstract class AbstractSourceBuilder<
|
||||
this.valueSerializer = serializer;
|
||||
}
|
||||
|
||||
public @NotNull SELF parse(@NotNull DataFunction<SOURCE, PARAM> parser) {
|
||||
public @NotNull SELF parse(@NotNull DataFunction<SOURCE, UNIT> parser) {
|
||||
return parse((p, source) -> parser.handle(source));
|
||||
}
|
||||
|
||||
public @NotNull SELF parse(@NotNull ValueHandler<SOURCE, PARAM> parser) {
|
||||
public @NotNull SELF parse(@NotNull ValueHandler<SOURCE, UNIT> parser) {
|
||||
this.valueParser = parser;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull SELF serialize(@NotNull ValueHandler<PARAM, SOURCE> serializer) {
|
||||
public @NotNull SELF serialize(@NotNull ValueHandler<UNIT, SOURCE> serializer) {
|
||||
this.valueSerializer = serializer;
|
||||
return self();
|
||||
}
|
||||
|
||||
public @NotNull SELF serialize(@NotNull DataFunction<PARAM, SOURCE> serializer) {
|
||||
public @NotNull SELF serialize(@NotNull DataFunction<UNIT, SOURCE> serializer) {
|
||||
return serialize((p, value) -> serializer.handle(value));
|
||||
}
|
||||
|
||||
protected ValueAdapter<PARAM> buildAdapter() {
|
||||
protected ValueAdapter<UNIT> buildAdapter() {
|
||||
return new ValueAdapter<>(this.paramType)
|
||||
.parser((holder, type, data) -> {
|
||||
SOURCE source = holder.deserialize(this.sourceType, data);
|
||||
|
||||
@@ -8,9 +8,11 @@ import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SectionListBuilder<V> extends AbstractSectionBuilder<List<V>, V, ConfiguredList<V>, SectionListBuilder<V>> {
|
||||
public class SectionListBuilder<V>
|
||||
extends AbstractSectionBuilder<List<V>, V, ConfiguredList<V>, SectionListBuilder<V>> {
|
||||
|
||||
protected @NotNull Supplier<? extends List<V>> constructor;
|
||||
|
||||
@@ -32,6 +34,14 @@ public class SectionListBuilder<V> extends AbstractSectionBuilder<List<V>, V, Co
|
||||
return defaults(new ArrayList<>(values));
|
||||
}
|
||||
|
||||
public final @NotNull SectionListBuilder<V> defaults(@NotNull Consumer<List<V>> constructor) {
|
||||
return defaults(() -> {
|
||||
List<V> list = new ArrayList<>();
|
||||
constructor.accept(list);
|
||||
return list;
|
||||
});
|
||||
}
|
||||
|
||||
public SectionListBuilder<V> constructor(@NotNull Supplier<? extends List<V>> constructor) {
|
||||
this.constructor = constructor;
|
||||
return this;
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SourceListBuilder<SOURCE, V>
|
||||
@@ -34,6 +35,23 @@ public class SourceListBuilder<SOURCE, V>
|
||||
return defaults(new ArrayList<>(values));
|
||||
}
|
||||
|
||||
public final @NotNull SourceListBuilder<SOURCE, V> defaults(@NotNull Consumer<List<V>> constructor) {
|
||||
return defaults(() -> {
|
||||
List<V> list = new ArrayList<>();
|
||||
constructor.accept(list);
|
||||
return list;
|
||||
});
|
||||
}
|
||||
|
||||
public SourceListBuilder<SOURCE, V> constructor(@NotNull Supplier<? extends List<V>> constructor) {
|
||||
this.constructor = constructor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public <LIST extends List<V>> SourceListBuilder<SOURCE, V> construct(@NotNull LIST list) {
|
||||
return constructor(() -> list);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull SourceListBuilder<SOURCE, V> self() {
|
||||
return this;
|
||||
|
||||
@@ -14,10 +14,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SectionMapBuilder<MAP extends Map<K, V>, K, V>
|
||||
extends AbstractSectionBuilder<
|
||||
Map<K, V>, V, ConfiguredMap<K, V>,
|
||||
SectionMapBuilder<MAP, K, V>
|
||||
> {
|
||||
extends AbstractSectionBuilder<Map<K, V>, V, ConfiguredMap<K, V>, SectionMapBuilder<MAP, K, V>> {
|
||||
|
||||
protected final @NotNull ValueType<K> keyType;
|
||||
|
||||
|
||||
@@ -13,10 +13,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SourceMapBuilder<MAP extends Map<K, V>, SOURCE, K, V>
|
||||
extends AbstractSourceBuilder<
|
||||
Map<K, V>, SOURCE, V, ConfiguredMap<K, V>,
|
||||
SourceMapBuilder<MAP, SOURCE, K, V>
|
||||
> {
|
||||
extends AbstractSourceBuilder<Map<K, V>, SOURCE, V, ConfiguredMap<K, V>, SourceMapBuilder<MAP, SOURCE, K, V>> {
|
||||
|
||||
protected final @NotNull ValueType<K> keyType;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package cc.carm.lib.configuration.builder.value;
|
||||
|
||||
import cc.carm.lib.configuration.adapter.ValueType;
|
||||
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
|
||||
import cc.carm.lib.configuration.function.ValueHandler;
|
||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -6,7 +6,8 @@ import cc.carm.lib.configuration.function.ValueHandler;
|
||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SourceValueBuilder<S, V> extends AbstractSourceBuilder<V, S, V, ConfiguredValue<V>, SourceValueBuilder<S, V>> {
|
||||
public class SourceValueBuilder<S, V>
|
||||
extends AbstractSourceBuilder<V, S, V, ConfiguredValue<V>, SourceValueBuilder<S, V>> {
|
||||
|
||||
|
||||
public SourceValueBuilder(@NotNull ValueType<S> sourceType, @NotNull ValueType<V> valueType,
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package cc.carm.lib.configuration.function;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface DataValidator<T> {
|
||||
|
||||
void validate(@Nullable T value) throws Exception;
|
||||
|
||||
default DataValidator<T> compose(DataValidator<? super T> other) {
|
||||
return value -> {
|
||||
validate(value);
|
||||
other.validate(value);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cc.carm.lib.configuration.function;
|
||||
|
||||
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ValueComposer<T, U> {
|
||||
|
||||
/**
|
||||
* Accept the value and the data, and then compose the value.
|
||||
*
|
||||
* @param holder The configuration holder
|
||||
* @param type The value type, e.g. {@link java.util.List}, {@link java.util.Map}, etc.
|
||||
* @param data The unit data
|
||||
* @throws Exception If an error occurs
|
||||
*/
|
||||
void accept(@NotNull ConfigurationHolder<?> holder, @NotNull T type, @NotNull U data) throws Exception;
|
||||
|
||||
default ValueComposer<T, U> andThen(ValueComposer<? super T, ? super U> after) {
|
||||
return (holder, unit, data) -> {
|
||||
accept(holder, unit, data);
|
||||
after.accept(holder, unit, data);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package cc.carm.lib.configuration.function;
|
||||
|
||||
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ValueConsumer<U, T> {
|
||||
|
||||
void accept(@NotNull ConfigurationHolder<?> holder, @NotNull U unit, @NotNull T data) throws Exception;
|
||||
|
||||
default ValueConsumer<U, T> andThen(ValueConsumer<? super U, ? super T> after) {
|
||||
return (holder, unit, data) -> {
|
||||
accept(holder, unit, data);
|
||||
after.accept(holder, unit, data);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package cc.carm.lib.configuration.function;
|
||||
|
||||
public interface ValueSupplier {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package cc.carm.lib.configuration.function;
|
||||
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ValueValidator<T> {
|
||||
|
||||
void validate(@NotNull ConfigurationHolder<?> holder, @Nullable T value) throws Exception;
|
||||
|
||||
default ValueValidator<T> compose(ValueValidator<? super T> other) {
|
||||
return (holder, value) -> {
|
||||
validate(holder, value);
|
||||
other.validate(holder, value);
|
||||
};
|
||||
}
|
||||
|
||||
static <V> ValueValidator<V> none() {
|
||||
return (holder, data) -> {
|
||||
};
|
||||
}
|
||||
|
||||
static <V> ValueValidator<V> nonnull() {
|
||||
return nonnull("Value cannot be null");
|
||||
}
|
||||
|
||||
static <V> ValueValidator<V> nonnull(String message) {
|
||||
return (holder, data) -> {
|
||||
if (data == null) throw new IllegalArgumentException(message);
|
||||
};
|
||||
}
|
||||
|
||||
static <V extends Number> ValueValidator<V> range(V min, V max) {
|
||||
return range(min, max, "Value must be in range [" + min + ", " + max + "]");
|
||||
}
|
||||
|
||||
static <V extends Number> ValueValidator<V> range(V min, V max, String message) {
|
||||
return (holder, data) -> {
|
||||
if (data.doubleValue() < min.doubleValue() || data.doubleValue() > max.doubleValue()) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -38,10 +38,11 @@ public abstract class ConfigurationFactory<
|
||||
protected @NotNull Map<String, ConfigurationMetaHolder> metadata = new HashMap<>();
|
||||
protected ConfigurationInitializer initializer = new ConfigurationInitializer();
|
||||
|
||||
public ConfigurationFactory() {
|
||||
protected ConfigurationFactory() {
|
||||
this.adapters.register(StandardAdapters.PRIMITIVES);
|
||||
this.adapters.register(StandardAdapters.SECTIONS);
|
||||
this.adapters.register(StandardAdapters.ENUMS);
|
||||
this.adapters.register(StandardAdapters.UUID);
|
||||
}
|
||||
|
||||
protected abstract SELF self();
|
||||
|
||||
@@ -86,7 +86,7 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
|
||||
|
||||
@NotNull
|
||||
@UnmodifiableView
|
||||
public Map<String, ConfigValue<?>> registeredValues() {
|
||||
public Map<String, ConfigValue<?, ?>> registeredValues() {
|
||||
return extractMetadata(StandardMeta.VALUE);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
|
||||
}
|
||||
}
|
||||
|
||||
public void initialize(@NotNull ValueManifest<?> value) {
|
||||
public void initialize(@NotNull ValueManifest<?, ?> value) {
|
||||
value.holder(this);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public interface ConfigInitializeHandler<T, V> {
|
||||
|
||||
static <T, V> ConfigInitializeHandler<T, V> start() {
|
||||
return (provider, path, value, instace) -> {
|
||||
return (provider, path, value, instance) -> {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+7
-7
@@ -21,7 +21,7 @@ import java.util.function.Function;
|
||||
public class ConfigurationInitializer {
|
||||
|
||||
protected @NotNull PathGenerator pathGenerator;
|
||||
protected @NotNull ConfigInitializeHandler<Field, ConfigValue<?>> valueInitializer;
|
||||
protected @NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> valueInitializer;
|
||||
protected @NotNull ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer;
|
||||
|
||||
public ConfigurationInitializer() {
|
||||
@@ -29,7 +29,7 @@ public class ConfigurationInitializer {
|
||||
}
|
||||
|
||||
public ConfigurationInitializer(@NotNull PathGenerator pathGenerator,
|
||||
@NotNull ConfigInitializeHandler<Field, ConfigValue<?>> valueInitializer,
|
||||
@NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> valueInitializer,
|
||||
@NotNull ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer) {
|
||||
this.pathGenerator = pathGenerator;
|
||||
this.valueInitializer = valueInitializer;
|
||||
@@ -44,11 +44,11 @@ public class ConfigurationInitializer {
|
||||
return pathGenerator;
|
||||
}
|
||||
|
||||
public ConfigInitializeHandler<Field, ConfigValue<?>> fieldInitializer() {
|
||||
public ConfigInitializeHandler<Field, ConfigValue<?, ?>> fieldInitializer() {
|
||||
return valueInitializer;
|
||||
}
|
||||
|
||||
public void fieldInitializer(@NotNull ConfigInitializeHandler<Field, ConfigValue<?>> fieldInitializer) {
|
||||
public void fieldInitializer(@NotNull ConfigInitializeHandler<Field, ConfigValue<?,?>> fieldInitializer) {
|
||||
this.valueInitializer = fieldInitializer;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class ConfigurationInitializer {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -163,9 +163,9 @@ public class ConfigurationInitializer {
|
||||
field.setAccessible(true);
|
||||
Object object = field.get(source);
|
||||
//
|
||||
if (object instanceof ConfigValue<?>) {
|
||||
if (object instanceof ConfigValue<?,?>) {
|
||||
// 目标是 ConfigValue 实例,进行具体的初始化注入
|
||||
ConfigValue<?> value = (ConfigValue<?>) object;
|
||||
ConfigValue<?,?> value = (ConfigValue<?,?>) object;
|
||||
String path = getFieldPath(holder, parent, field);
|
||||
if (path == null) return;
|
||||
value.initialize(holder, path);
|
||||
|
||||
@@ -7,6 +7,6 @@ public interface StandardMeta {
|
||||
/**
|
||||
* To mark the {@link ConfigValue} instance of specific path.
|
||||
*/
|
||||
ConfigurationMetadata<ConfigValue<?>> VALUE = ConfigurationMetadata.of();
|
||||
ConfigurationMetadata<ConfigValue<?, ?>> VALUE = ConfigurationMetadata.of();
|
||||
|
||||
}
|
||||
|
||||
@@ -33,9 +33,9 @@ import java.util.Optional;
|
||||
* @see ValueManifest Base class providing metadata and default value handling
|
||||
* @see ConfigurationHolder Responsible for configuration source persistence
|
||||
*/
|
||||
public abstract class ConfigValue<T> extends ValueManifest<T> {
|
||||
public abstract class ConfigValue<T, U> extends ValueManifest<T, U> {
|
||||
|
||||
protected ConfigValue(@NotNull ValueManifest<T> manifest) {
|
||||
protected ConfigValue(@NotNull ValueManifest<T, U> manifest) {
|
||||
super(manifest);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cc.carm.lib.configuration.value;
|
||||
|
||||
import cc.carm.lib.configuration.adapter.ValueType;
|
||||
import cc.carm.lib.configuration.function.ValueValidator;
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||
@@ -11,37 +12,48 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ValueManifest<T> {
|
||||
public class ValueManifest<TYPE, UNIT> {
|
||||
|
||||
protected final @NotNull ValueType<T> type;
|
||||
protected final @NotNull ValueType<TYPE> type;
|
||||
protected final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer;
|
||||
|
||||
protected @Nullable ConfigurationHolder<?> holder;
|
||||
protected @Nullable String path; // Section path
|
||||
|
||||
protected @NotNull Supplier<@Nullable T> defaultSupplier;
|
||||
protected @NotNull ValueValidator<? super UNIT> validator;
|
||||
protected @NotNull Supplier<@Nullable TYPE> defaultSupplier;
|
||||
|
||||
public ValueManifest(@NotNull ValueType<T> type) {
|
||||
this(type, () -> null, EMPTY_INITIALIZER, null, null);
|
||||
public ValueManifest(@NotNull ValueType<TYPE> type) {
|
||||
this(type, () -> null, ValueValidator.none(), EMPTY_INITIALIZER, null, null);
|
||||
}
|
||||
|
||||
public ValueManifest(@NotNull T defaultValue) {
|
||||
public ValueManifest(@NotNull TYPE defaultValue) {
|
||||
this(ValueType.of(defaultValue), () -> defaultValue);
|
||||
}
|
||||
|
||||
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier) {
|
||||
this(type, defaultSupplier, EMPTY_INITIALIZER, null, null);
|
||||
public ValueManifest(@NotNull ValueType<TYPE> type, @NotNull Supplier<@Nullable TYPE> defaultSupplier) {
|
||||
this(type, defaultSupplier, ValueValidator.none(), EMPTY_INITIALIZER, null, null);
|
||||
}
|
||||
|
||||
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier,
|
||||
public ValueManifest(@NotNull ValueType<TYPE> type,
|
||||
@NotNull Supplier<@Nullable TYPE> defaultSupplier,
|
||||
@NotNull ValueValidator<? super UNIT> validator) {
|
||||
this(type, defaultSupplier, validator, EMPTY_INITIALIZER, null, null);
|
||||
}
|
||||
|
||||
public ValueManifest(@NotNull ValueType<TYPE> type, @NotNull Supplier<@Nullable TYPE> defaultSupplier,
|
||||
@NotNull ValueValidator<? super UNIT> validator,
|
||||
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer) {
|
||||
this(type, defaultSupplier, initializer, null, null);
|
||||
this(type, defaultSupplier, validator, initializer, null, null);
|
||||
}
|
||||
|
||||
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier,
|
||||
public ValueManifest(@NotNull ValueType<TYPE> type,
|
||||
@NotNull Supplier<@Nullable TYPE> defaultSupplier,
|
||||
@NotNull ValueValidator<? super UNIT> validator,
|
||||
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer,
|
||||
@Nullable ConfigurationHolder<?> holder, @Nullable String path) {
|
||||
this.type = type;
|
||||
this.validator = validator;
|
||||
this.initializer = initializer;
|
||||
this.defaultSupplier = defaultSupplier;
|
||||
this.holder = holder;
|
||||
@@ -49,8 +61,8 @@ public class ValueManifest<T> {
|
||||
initialize();
|
||||
}
|
||||
|
||||
protected ValueManifest(@NotNull ValueManifest<T> manifest) {
|
||||
this(manifest.type, manifest.defaultSupplier, manifest.initializer, manifest.holder, manifest.path);
|
||||
protected ValueManifest(@NotNull ValueManifest<TYPE, UNIT> manifest) {
|
||||
this(manifest.type, manifest.defaultSupplier, manifest.validator, manifest.initializer, manifest.holder, manifest.path);
|
||||
}
|
||||
|
||||
public void initialize(@NotNull ConfigurationHolder<?> holder, @NotNull String path) {
|
||||
@@ -63,7 +75,7 @@ public class ValueManifest<T> {
|
||||
if (holder != null && path != null) this.initializer.accept(holder, path);
|
||||
}
|
||||
|
||||
public @NotNull ValueType<T> type() {
|
||||
public @NotNull ValueType<TYPE> type() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@@ -75,20 +87,40 @@ public class ValueManifest<T> {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public @Nullable T defaults() {
|
||||
public @Nullable TYPE defaults() {
|
||||
return this.defaultSupplier.get();
|
||||
}
|
||||
|
||||
public void defaults(@Nullable T defaultValue) {
|
||||
public void defaults(@Nullable TYPE defaultValue) {
|
||||
defaults(() -> defaultValue);
|
||||
}
|
||||
|
||||
public void defaults(@NotNull Supplier<@Nullable T> defaultValue) {
|
||||
public void defaults(@NotNull Supplier<@Nullable TYPE> defaultValue) {
|
||||
this.defaultSupplier = defaultValue;
|
||||
}
|
||||
|
||||
public boolean hasDefaults() {
|
||||
return this.defaultSupplier.get() != null;
|
||||
return defaults() != null;
|
||||
}
|
||||
|
||||
public @NotNull ValueValidator<? super UNIT> validator() {
|
||||
return this.validator;
|
||||
}
|
||||
|
||||
public void validator(@NotNull ValueValidator<? super UNIT> validator) {
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
public void validate(@NotNull ValueValidator<? super UNIT> validator) {
|
||||
validator((h, v) -> {
|
||||
this.validator.validate(h, v);
|
||||
validator.validate(h, v);
|
||||
});
|
||||
}
|
||||
|
||||
protected UNIT withValidated(@Nullable UNIT value) throws Exception {
|
||||
validator.validate(holder(), value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public @NotNull String path() {
|
||||
@@ -105,7 +137,7 @@ public class ValueManifest<T> {
|
||||
return holder().config();
|
||||
}
|
||||
|
||||
public ConfigurationMetaHolder metadata() {
|
||||
public @NotNull ConfigurationMetaHolder metadata() {
|
||||
return holder().metadata(path());
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class CachedConfigValue<T> extends ConfigValue<T> {
|
||||
public abstract class CachedConfigValue<T, U> extends ConfigValue<T, U> {
|
||||
|
||||
protected @Nullable T cachedValue;
|
||||
protected long parsedTime = -1;
|
||||
|
||||
protected CachedConfigValue(@NotNull ValueManifest<T> manifest) {
|
||||
protected CachedConfigValue(@NotNull ValueManifest<T, U> manifest) {
|
||||
super(manifest);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import cc.carm.lib.configuration.adapter.ValueParser;
|
||||
import cc.carm.lib.configuration.adapter.ValueSerializer;
|
||||
import cc.carm.lib.configuration.adapter.ValueType;
|
||||
import cc.carm.lib.configuration.builder.list.ConfigListBuilder;
|
||||
import cc.carm.lib.configuration.builder.list.SourceListBuilder;
|
||||
import cc.carm.lib.configuration.value.ValueManifest;
|
||||
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -15,7 +16,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements List<V> {
|
||||
public class ConfiguredList<V> extends CachedConfigValue<List<V>, V> implements List<V> {
|
||||
|
||||
public static <T> @NotNull ConfigListBuilder<T> builderOf(@NotNull Class<T> type) {
|
||||
return builderOf(ValueType.of(type));
|
||||
@@ -25,10 +26,26 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
|
||||
return new ConfigListBuilder<>(type);
|
||||
}
|
||||
|
||||
public static <T> @NotNull SourceListBuilder<T, T> with(@NotNull Class<T> registeredType) {
|
||||
return with(ValueType.of(registeredType));
|
||||
}
|
||||
|
||||
public static <T> @NotNull SourceListBuilder<T, T> with(@NotNull ValueType<T> registeredType) {
|
||||
return new ConfigListBuilder<>(registeredType).from(registeredType);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <T> @NotNull ConfiguredList<T> of(@NotNull T value, @NotNull T... values) {
|
||||
List<T> list = new ArrayList<>();
|
||||
list.add(value);
|
||||
Collections.addAll(list, values);
|
||||
return with(ValueType.of(value)).defaults(list).build();
|
||||
}
|
||||
|
||||
protected final @NotNull Supplier<? extends List<V>> constructor;
|
||||
protected final @NotNull ValueAdapter<V> paramAdapter;
|
||||
|
||||
public ConfiguredList(@NotNull ValueManifest<List<V>> manifest,
|
||||
public ConfiguredList(@NotNull ValueManifest<List<V>, V> manifest,
|
||||
@NotNull Supplier<? extends List<V>> constructor,
|
||||
@NotNull ValueAdapter<V> paramAdapter) {
|
||||
super(manifest);
|
||||
@@ -79,7 +96,7 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
|
||||
for (Object dataVal : data) {
|
||||
if (dataVal == null) continue;
|
||||
try {
|
||||
list.add(parser.parse(holder(), paramType(), dataVal));
|
||||
list.add(withValidated(parser.parse(holder(), paramType(), dataVal)));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -88,20 +105,21 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(@Nullable List<V> value) {
|
||||
updateCache(value);
|
||||
if (value == null) {
|
||||
public void set(@Nullable List<V> list) {
|
||||
updateCache(list);
|
||||
if (list == null) {
|
||||
setData(null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ValueSerializer<V> serializer = serializer();
|
||||
if (serializer == null) return;
|
||||
|
||||
List<Object> data = new ArrayList<>();
|
||||
for (V val : value) {
|
||||
for (V val : list) {
|
||||
if (val == null) continue;
|
||||
try {
|
||||
data.add(serializer.serialize(holder(), paramType(), val));
|
||||
data.add(serializer.serialize(holder(), paramType(), withValidated(val)));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,11 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements Map<K, V> {
|
||||
public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>, V> implements Map<K, V> {
|
||||
|
||||
public static <V> ConfigMapCreator<String, V> builderOf(@NotNull Class<V> valueType) {
|
||||
return builderOf(String.class, valueType);
|
||||
}
|
||||
|
||||
public static <K, V> ConfigMapCreator<K, V> builderOf(@NotNull ValueType<K> keyType, @NotNull ValueType<V> valueType) {
|
||||
return new ConfigMapCreator<>(keyType, valueType);
|
||||
@@ -38,7 +42,7 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
|
||||
protected final @NotNull ValueAdapter<K> keyAdapter;
|
||||
protected final @NotNull ValueAdapter<V> valueAdapter;
|
||||
|
||||
public ConfiguredMap(@NotNull ValueManifest<Map<K, V>> manifest,
|
||||
public ConfiguredMap(@NotNull ValueManifest<Map<K, V>, V> manifest,
|
||||
@NotNull Supplier<? extends Map<K, V>> constructor,
|
||||
@NotNull ValueAdapter<K> keyAdapter, @NotNull ValueAdapter<V> valueAdapter) {
|
||||
super(manifest);
|
||||
@@ -80,8 +84,9 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
|
||||
if (keys.isEmpty()) return getDefaultFirst(map);
|
||||
|
||||
ValueParser<K> keyParser = parserFor(keyAdapter);
|
||||
if (keyParser == null) return getDefaultFirst(map);
|
||||
ValueParser<V> valueParser = parserFor(valueAdapter);
|
||||
if (keyParser == null || valueParser == null) return getDefaultFirst(map);
|
||||
if (valueParser == null) return getDefaultFirst(map);
|
||||
|
||||
for (String dataKey : keys) {
|
||||
Object dataVal = section.get(dataKey);
|
||||
@@ -89,7 +94,7 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
|
||||
try {
|
||||
K key = keyParser.parse(holder(), keyType(), dataKey);
|
||||
V value = valueParser.parse(holder(), valueType(), dataVal);
|
||||
map.put(key, value);
|
||||
map.put(key, withValidated(value));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -116,8 +121,9 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
|
||||
}
|
||||
|
||||
ValueSerializer<K> keySerializer = serializerFor(keyAdapter);
|
||||
if (keySerializer == null) return;
|
||||
ValueSerializer<V> valueSerializer = serializerFor(valueAdapter);
|
||||
if (keySerializer == null || valueSerializer == null) return;
|
||||
if (valueSerializer == null) return;
|
||||
|
||||
Map<Object, Object> data = new LinkedHashMap<>();
|
||||
|
||||
@@ -125,7 +131,7 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
|
||||
try {
|
||||
data.put(
|
||||
keySerializer.serialize(holder(), keyType(), entry.getKey()),
|
||||
valueSerializer.serialize(holder(), valueType(), entry.getValue())
|
||||
valueSerializer.serialize(holder(), valueType(), withValidated(entry.getValue()))
|
||||
);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -5,6 +5,8 @@ import cc.carm.lib.configuration.adapter.ValueParser;
|
||||
import cc.carm.lib.configuration.adapter.ValueSerializer;
|
||||
import cc.carm.lib.configuration.adapter.ValueType;
|
||||
import cc.carm.lib.configuration.builder.value.ConfigValueBuilder;
|
||||
import cc.carm.lib.configuration.builder.value.SourceValueBuilder;
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import cc.carm.lib.configuration.value.ValueManifest;
|
||||
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -12,16 +14,54 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
||||
public class ConfiguredValue<V> extends CachedConfigValue<V, V> {
|
||||
|
||||
/**
|
||||
* Create a new value builder.
|
||||
*
|
||||
* @param type The type of the value.
|
||||
* @param <V> The type of the value.
|
||||
* @return a {@link ConfigValueBuilder} with the specified type.
|
||||
*/
|
||||
public static <V> ConfigValueBuilder<V> builderOf(@NotNull Class<V> type) {
|
||||
return new ConfigValueBuilder<>(ValueType.of(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new value builder.
|
||||
*
|
||||
* @param type The type of the value.
|
||||
* @param <V> The type of the value.
|
||||
* @return a {@link ConfigValueBuilder} with the specified type.
|
||||
*/
|
||||
public static <V> ConfigValueBuilder<V> builderOf(@NotNull ValueType<V> type) {
|
||||
return new ConfigValueBuilder<>(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new value builder with the specified {@link ConfigurationHolder#registeredValues()} type.
|
||||
*
|
||||
* @param registeredType The type of the value.
|
||||
* @param <V> The type of the value.
|
||||
* @return a {@link SourceValueBuilder} with the specified registered type.
|
||||
* @see ValueAdapter
|
||||
*/
|
||||
public static <V> SourceValueBuilder<V, V> with(@NotNull Class<V> registeredType) {
|
||||
return with(ValueType.of(registeredType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new value builder with the specified {@link ConfigurationHolder#registeredValues()} type.
|
||||
*
|
||||
* @param registeredType The type of the value.
|
||||
* @param <V> The type of the value.
|
||||
* @return a {@link SourceValueBuilder} with the specified registered type.
|
||||
* @see ValueAdapter
|
||||
*/
|
||||
public static <V> SourceValueBuilder<V, V> with(@NotNull ValueType<V> registeredType) {
|
||||
return new ConfigValueBuilder<>(registeredType).from(registeredType);
|
||||
}
|
||||
|
||||
public static <V> ConfiguredValue<V> of(@NotNull V defaults) {
|
||||
return of(ValueType.of(defaults), () -> defaults);
|
||||
}
|
||||
@@ -51,7 +91,7 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
||||
);
|
||||
}
|
||||
|
||||
public static <V> ConfiguredValue<V> of(@NotNull ValueManifest<V> manifest,
|
||||
public static <V> ConfiguredValue<V> of(@NotNull ValueManifest<V, V> manifest,
|
||||
@Nullable ValueParser<V> parser,
|
||||
@Nullable ValueSerializer<V> serializer) {
|
||||
ValueAdapter<V> adapter = new ValueAdapter<>(manifest.type());
|
||||
@@ -60,13 +100,13 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
||||
return of(manifest, adapter);
|
||||
}
|
||||
|
||||
public static <V> ConfiguredValue<V> of(@NotNull ValueManifest<V> manifest, @NotNull ValueAdapter<V> adapter) {
|
||||
public static <V> ConfiguredValue<V> of(@NotNull ValueManifest<V, V> manifest, @NotNull ValueAdapter<V> adapter) {
|
||||
return new ConfiguredValue<>(manifest, adapter);
|
||||
}
|
||||
|
||||
protected final @NotNull ValueAdapter<V> adapter;
|
||||
|
||||
public ConfiguredValue(@NotNull ValueManifest<V> manifest, @NotNull ValueAdapter<V> adapter) {
|
||||
public ConfiguredValue(@NotNull ValueManifest<V, V> manifest, @NotNull ValueAdapter<V> adapter) {
|
||||
super(manifest);
|
||||
this.adapter = adapter;
|
||||
}
|
||||
@@ -103,11 +143,13 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
||||
ValueParser<V> parser = parser();
|
||||
if (parser == null) return defaults(); // No parser, return default value.
|
||||
|
||||
|
||||
try {
|
||||
// If there are no errors, update the cache and return.
|
||||
return updateCache(parser.parse(holder(), type(), data));
|
||||
V parsed = parser.parse(holder(), type(), data);
|
||||
return updateCache(withValidated(parsed));
|
||||
} catch (Exception e) {
|
||||
// There was a parsing error, prompted and returned the default value.
|
||||
// There was a validate or parsing error, prompted and returned the default value.
|
||||
e.printStackTrace();
|
||||
return defaults();
|
||||
}
|
||||
@@ -121,18 +163,18 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
||||
* @param value The value to be set
|
||||
*/
|
||||
@Override
|
||||
public void set(V value) {
|
||||
public void set(@Nullable V value) {
|
||||
updateCache(value); // Update cache
|
||||
if (value == null) {
|
||||
setData(null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ValueSerializer<V> serializer = serializer();
|
||||
if (serializer == null) return; // No serializer, do nothing.
|
||||
|
||||
try {
|
||||
setData(serializer.serialize(holder(), type(), value));
|
||||
setData(serializer.serialize(holder(), type(), withValidated(value)));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user