mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 10:38:19 +08:00
feat!(core): Finished the design of core module
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.adapter;
|
package cc.carm.lib.configuration.adapter;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -15,14 +15,14 @@ public class ValueAdapterRegistry {
|
|||||||
protected final Set<ValueAdapter<?>> adapters = new HashSet<>();
|
protected final Set<ValueAdapter<?>> adapters = new HashSet<>();
|
||||||
|
|
||||||
public <FROM, TO> void register(@NotNull Class<FROM> from, @NotNull Class<TO> to,
|
public <FROM, TO> void register(@NotNull Class<FROM> from, @NotNull Class<TO> to,
|
||||||
@Nullable ConfigDataFunction<FROM, TO> parser,
|
@Nullable DataFunction<FROM, TO> parser,
|
||||||
@Nullable ConfigDataFunction<TO, FROM> serializer) {
|
@Nullable DataFunction<TO, FROM> serializer) {
|
||||||
register(ValueType.of(from), ValueType.of(to), parser, serializer);
|
register(ValueType.of(from), ValueType.of(to), parser, serializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <FROM, TO> void register(@NotNull ValueType<FROM> from, @NotNull ValueType<TO> to,
|
public <FROM, TO> void register(@NotNull ValueType<FROM> from, @NotNull ValueType<TO> to,
|
||||||
@Nullable ConfigDataFunction<FROM, TO> parser,
|
@Nullable DataFunction<FROM, TO> parser,
|
||||||
@Nullable ConfigDataFunction<TO, FROM> serializer) {
|
@Nullable DataFunction<TO, FROM> serializer) {
|
||||||
ValueAdapter<FROM> fromAdapter = adapterOf(from);
|
ValueAdapter<FROM> fromAdapter = adapterOf(from);
|
||||||
if (fromAdapter == null) throw new IllegalArgumentException("No adapter for type " + from);
|
if (fromAdapter == null) throw new IllegalArgumentException("No adapter for type " + from);
|
||||||
register(to,
|
register(to,
|
||||||
|
|||||||
+44
-28
@@ -3,17 +3,27 @@ package cc.carm.lib.configuration.adapter.strandard;
|
|||||||
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||||
import cc.carm.lib.configuration.adapter.ValueParser;
|
import cc.carm.lib.configuration.adapter.ValueParser;
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class PrimitiveAdapters<T> extends ValueAdapter<T> {
|
import java.util.Arrays;
|
||||||
|
|
||||||
public static final PrimitiveAdapters<?>[] ADAPTERS = new PrimitiveAdapters[]{
|
public class PrimitiveAdapter<T> extends ValueAdapter<T> {
|
||||||
|
|
||||||
|
public static final PrimitiveAdapter<?>[] ADAPTERS = new PrimitiveAdapter[]{
|
||||||
ofString(), ofBoolean(), ofBooleanType(), ofCharacter(), ofCharacterType(),
|
ofString(), ofBoolean(), ofBooleanType(), ofCharacter(), ofCharacterType(),
|
||||||
ofInteger(), ofIntegerType(), ofLong(), ofLongType(), ofDouble(), ofDoubleType(),
|
ofInteger(), ofIntegerType(), ofLong(), ofLongType(), ofDouble(), ofDoubleType(),
|
||||||
ofFloat(), ofFloatType(), ofShort(), ofShortType(), ofByte(), ofByteType()
|
ofFloat(), ofFloatType(), ofShort(), ofShortType(), ofByte(), ofByteType()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static final String[] TRUE_VALUES = new String[]{
|
||||||
|
"true", "yes", "on", "1", "enabled", "enable", "active"
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final String[] FALSE_VALUES = new String[]{
|
||||||
|
"false", "no", "off", "0", "disabled", "disable", "inactive"
|
||||||
|
};
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
public static ValueAdapter<Enum<?>> ofEnum() {
|
public static ValueAdapter<Enum<?>> ofEnum() {
|
||||||
ValueAdapter<Enum<?>> adapter = new ValueAdapter<>(new ValueType<Enum<?>>() {
|
ValueAdapter<Enum<?>> adapter = new ValueAdapter<>(new ValueType<Enum<?>>() {
|
||||||
@@ -23,86 +33,92 @@ public class PrimitiveAdapters<T> extends ValueAdapter<T> {
|
|||||||
return adapter;
|
return adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<String> ofString() {
|
public static PrimitiveAdapter<String> ofString() {
|
||||||
return of(String.class, o -> o instanceof String ? (String) o : o.toString());
|
return of(String.class, o -> o instanceof String ? (String) o : o.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Boolean> ofBoolean() {
|
public static PrimitiveAdapter<Boolean> ofBoolean() {
|
||||||
return of(Boolean.class, o -> o instanceof Boolean ? (Boolean) o : Boolean.parseBoolean(o.toString()));
|
return of(Boolean.class, data -> {
|
||||||
|
if (data instanceof Boolean) return (Boolean) data;
|
||||||
|
String v = data.toString().trim();
|
||||||
|
if (Arrays.stream(TRUE_VALUES).anyMatch(v::equalsIgnoreCase)) return true;
|
||||||
|
else if (Arrays.stream(FALSE_VALUES).anyMatch(v::equalsIgnoreCase)) return false;
|
||||||
|
else throw new IllegalArgumentException("Cannot parse boolean from " + data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Boolean> ofBooleanType() {
|
public static PrimitiveAdapter<Boolean> ofBooleanType() {
|
||||||
return of(boolean.class, o -> o instanceof Boolean ? (Boolean) o : Boolean.parseBoolean(o.toString()));
|
return of(boolean.class, o -> o instanceof Boolean ? (Boolean) o : Boolean.parseBoolean(o.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Character> ofCharacter() {
|
public static PrimitiveAdapter<Character> ofCharacter() {
|
||||||
return of(Character.class, o -> o instanceof Character ? (Character) o : o.toString().charAt(0));
|
return of(Character.class, o -> o instanceof Character ? (Character) o : o.toString().charAt(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Character> ofCharacterType() {
|
public static PrimitiveAdapter<Character> ofCharacterType() {
|
||||||
return of(char.class, o -> o instanceof Character ? (Character) o : o.toString().charAt(0));
|
return of(char.class, o -> o instanceof Character ? (Character) o : o.toString().charAt(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Integer> ofInteger() {
|
public static PrimitiveAdapter<Integer> ofInteger() {
|
||||||
return ofNumber(Integer.class, Number::intValue, Integer::parseInt);
|
return ofNumber(Integer.class, Number::intValue, Integer::parseInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Integer> ofIntegerType() {
|
public static PrimitiveAdapter<Integer> ofIntegerType() {
|
||||||
return ofNumber(int.class, Number::intValue, Integer::parseInt);
|
return ofNumber(int.class, Number::intValue, Integer::parseInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Long> ofLong() {
|
public static PrimitiveAdapter<Long> ofLong() {
|
||||||
return ofNumber(Long.class, Number::longValue, Long::parseLong);
|
return ofNumber(Long.class, Number::longValue, Long::parseLong);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Long> ofLongType() {
|
public static PrimitiveAdapter<Long> ofLongType() {
|
||||||
return ofNumber(long.class, Number::longValue, Long::parseLong);
|
return ofNumber(long.class, Number::longValue, Long::parseLong);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Double> ofDouble() {
|
public static PrimitiveAdapter<Double> ofDouble() {
|
||||||
return ofNumber(Double.class, Number::doubleValue, Double::parseDouble);
|
return ofNumber(Double.class, Number::doubleValue, Double::parseDouble);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Double> ofDoubleType() {
|
public static PrimitiveAdapter<Double> ofDoubleType() {
|
||||||
return ofNumber(double.class, Number::doubleValue, Double::parseDouble);
|
return ofNumber(double.class, Number::doubleValue, Double::parseDouble);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Float> ofFloat() {
|
public static PrimitiveAdapter<Float> ofFloat() {
|
||||||
return ofNumber(Float.class, Number::floatValue, Float::parseFloat);
|
return ofNumber(Float.class, Number::floatValue, Float::parseFloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Float> ofFloatType() {
|
public static PrimitiveAdapter<Float> ofFloatType() {
|
||||||
return ofNumber(float.class, Number::floatValue, Float::parseFloat);
|
return ofNumber(float.class, Number::floatValue, Float::parseFloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Short> ofShort() {
|
public static PrimitiveAdapter<Short> ofShort() {
|
||||||
return ofNumber(Short.class, Number::shortValue, Short::parseShort);
|
return ofNumber(Short.class, Number::shortValue, Short::parseShort);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Short> ofShortType() {
|
public static PrimitiveAdapter<Short> ofShortType() {
|
||||||
return ofNumber(short.class, Number::shortValue, Short::parseShort);
|
return ofNumber(short.class, Number::shortValue, Short::parseShort);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Byte> ofByte() {
|
public static PrimitiveAdapter<Byte> ofByte() {
|
||||||
return ofNumber(Byte.class, Number::byteValue, Byte::parseByte);
|
return ofNumber(Byte.class, Number::byteValue, Byte::parseByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveAdapters<Byte> ofByteType() {
|
public static PrimitiveAdapter<Byte> ofByteType() {
|
||||||
return ofNumber(byte.class, Number::byteValue, Byte::parseByte);
|
return ofNumber(byte.class, Number::byteValue, Byte::parseByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> PrimitiveAdapters<T> of(@NotNull Class<T> clazz,
|
public static <T> PrimitiveAdapter<T> of(@NotNull Class<T> clazz,
|
||||||
@NotNull ConfigDataFunction<Object, T> function) {
|
@NotNull DataFunction<Object, T> function) {
|
||||||
return new PrimitiveAdapters<>(clazz, (p, type, data) -> function.handle(data));
|
return new PrimitiveAdapter<>(clazz, (p, type, data) -> function.handle(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Number> PrimitiveAdapters<T> ofNumber(@NotNull Class<T> numberClass,
|
public static <T extends Number> PrimitiveAdapter<T> ofNumber(@NotNull Class<T> numberClass,
|
||||||
@NotNull ConfigDataFunction<Number, T> castFunction,
|
@NotNull DataFunction<Number, T> castFunction,
|
||||||
@NotNull ConfigDataFunction<String, T> parseFunction) {
|
@NotNull DataFunction<String, T> parseFunction) {
|
||||||
return of(numberClass, o -> o instanceof Number ? castFunction.handle((Number) o) : parseFunction.handle(o.toString()));
|
return of(numberClass, o -> o instanceof Number ? castFunction.handle((Number) o) : parseFunction.handle(o.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PrimitiveAdapters(@NotNull Class<T> valueType, @NotNull ValueParser<T> deserializer) {
|
protected PrimitiveAdapter(@NotNull Class<T> valueType, @NotNull ValueParser<T> deserializer) {
|
||||||
super(ValueType.of(valueType), (provider, type, value) -> value, deserializer);
|
super(ValueType.of(valueType), (provider, type, value) -> value, deserializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
package cc.carm.lib.configuration.annotation;
|
package cc.carm.lib.configuration.annotation;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.loader.PathGenerator;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|||||||
@@ -2,11 +2,15 @@ package cc.carm.lib.configuration.builder;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
||||||
|
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.ConfigValue;
|
||||||
import cc.carm.lib.configuration.value.ValueManifest;
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public abstract class AbstractConfigBuilder<
|
public abstract class AbstractConfigBuilder<
|
||||||
@@ -21,6 +25,8 @@ public abstract class AbstractConfigBuilder<
|
|||||||
protected @Nullable String path;
|
protected @Nullable String path;
|
||||||
|
|
||||||
protected @NotNull Supplier<TYPE> defaultValueSupplier = () -> null;
|
protected @NotNull Supplier<TYPE> defaultValueSupplier = () -> null;
|
||||||
|
protected @NotNull BiConsumer<ConfigurationProvider<?>, String> initializer = (provider, path) -> {
|
||||||
|
};
|
||||||
|
|
||||||
protected AbstractConfigBuilder(Class<? super PROVIDER> providerClass, ValueType<TYPE> type) {
|
protected AbstractConfigBuilder(Class<? super PROVIDER> providerClass, ValueType<TYPE> type) {
|
||||||
this.providerClass = providerClass;
|
this.providerClass = providerClass;
|
||||||
@@ -35,7 +41,7 @@ public abstract class AbstractConfigBuilder<
|
|||||||
|
|
||||||
public abstract @NotNull RESULT build();
|
public abstract @NotNull RESULT build();
|
||||||
|
|
||||||
public @NotNull SELF from(@Nullable PROVIDER provider) {
|
public @NotNull SELF provider(@Nullable PROVIDER provider) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
@@ -45,6 +51,19 @@ public abstract class AbstractConfigBuilder<
|
|||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF initializer(@NotNull BiConsumer<ConfigurationProvider<?>, String> initializer) {
|
||||||
|
this.initializer = initializer;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF append(@NotNull BiConsumer<ConfigurationProvider<?>, String> initializer) {
|
||||||
|
return initializer(initializer.andThen(initializer));
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF append(@NotNull Consumer<ConfigurationProvider<?>> initializer) {
|
||||||
|
return append((provider, path) -> initializer.accept(provider));
|
||||||
|
}
|
||||||
|
|
||||||
public @NotNull SELF defaults(@Nullable TYPE defaultValue) {
|
public @NotNull SELF defaults(@Nullable TYPE defaultValue) {
|
||||||
return defaults(() -> defaultValue);
|
return defaults(() -> defaultValue);
|
||||||
}
|
}
|
||||||
@@ -54,8 +73,19 @@ public abstract class AbstractConfigBuilder<
|
|||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <M> @NotNull SELF meta(@NotNull Consumer<@NotNull ConfigurationMetaHolder> metaConsumer) {
|
||||||
|
return append((provider, path) -> metaConsumer.accept(provider.metadata(path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <M> @NotNull SELF meta(@NotNull ConfigurationMetadata<M> type, @Nullable M value) {
|
||||||
|
return meta(holder -> holder.set(type, value));
|
||||||
|
}
|
||||||
|
|
||||||
protected @NotNull ValueManifest<TYPE> buildManifest() {
|
protected @NotNull ValueManifest<TYPE> buildManifest() {
|
||||||
return new ValueManifest<>(type(), this.provider, this.path, this.defaultValueSupplier);
|
return new ValueManifest<>(
|
||||||
|
type(), this.defaultValueSupplier, this.initializer,
|
||||||
|
this.provider, this.path
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -3,8 +3,8 @@ package cc.carm.lib.configuration.builder.impl;
|
|||||||
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
||||||
import cc.carm.lib.configuration.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import cc.carm.lib.configuration.function.ConfigValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -21,32 +21,32 @@ public abstract class AbstractSectionBuilder<
|
|||||||
|
|
||||||
protected final @NotNull ValueType<PARAM> paramType;
|
protected final @NotNull ValueType<PARAM> paramType;
|
||||||
|
|
||||||
protected @NotNull ConfigValueHandler<ConfigurationSection, PARAM> parser;
|
protected @NotNull ValueHandler<ConfigurationSection, PARAM> parser;
|
||||||
protected @NotNull ConfigValueHandler<PARAM, ? extends Map<Object, Object>> serializer;
|
protected @NotNull ValueHandler<PARAM, ? extends Map<Object, Object>> serializer;
|
||||||
|
|
||||||
public AbstractSectionBuilder(@NotNull ValueType<TYPE> type, @NotNull ValueType<PARAM> paramType,
|
public AbstractSectionBuilder(@NotNull ValueType<TYPE> type, @NotNull ValueType<PARAM> paramType,
|
||||||
@NotNull ConfigValueHandler<ConfigurationSection, PARAM> parser,
|
@NotNull ValueHandler<ConfigurationSection, PARAM> parser,
|
||||||
@NotNull ConfigValueHandler<PARAM, ? extends Map<Object, Object>> serializer) {
|
@NotNull ValueHandler<PARAM, ? extends Map<Object, Object>> serializer) {
|
||||||
super(type);
|
super(type);
|
||||||
this.paramType = paramType;
|
this.paramType = paramType;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(ConfigDataFunction<ConfigurationSection, PARAM> valueParser) {
|
public @NotNull SELF parse(DataFunction<ConfigurationSection, PARAM> valueParser) {
|
||||||
return parse((p, section) -> valueParser.handle(section));
|
return parse((p, section) -> valueParser.handle(section));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(ConfigValueHandler<ConfigurationSection, PARAM> valueParser) {
|
public @NotNull SELF parse(ValueHandler<ConfigurationSection, PARAM> valueParser) {
|
||||||
this.parser = valueParser;
|
this.parser = valueParser;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(ConfigDataFunction<PARAM, ? extends Map<Object, Object>> serializer) {
|
public @NotNull SELF serialize(DataFunction<PARAM, ? extends Map<Object, Object>> serializer) {
|
||||||
return serialize((p, value) -> serializer.handle(value));
|
return serialize((p, value) -> serializer.handle(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(ConfigValueHandler<PARAM, ? extends Map<Object, Object>> serializer) {
|
public @NotNull SELF serialize(ValueHandler<PARAM, ? extends Map<Object, Object>> serializer) {
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -3,8 +3,8 @@ package cc.carm.lib.configuration.builder.impl;
|
|||||||
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
||||||
import cc.carm.lib.configuration.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import cc.carm.lib.configuration.function.ConfigValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -15,13 +15,13 @@ public abstract class AbstractSourceBuilder<
|
|||||||
|
|
||||||
protected final @NotNull ValueType<SOURCE> sourceType;
|
protected final @NotNull ValueType<SOURCE> sourceType;
|
||||||
protected final @NotNull ValueType<PARAM> paramType;
|
protected final @NotNull ValueType<PARAM> paramType;
|
||||||
protected @NotNull ConfigValueHandler<SOURCE, PARAM> valueParser;
|
protected @NotNull ValueHandler<SOURCE, PARAM> valueParser;
|
||||||
protected @NotNull ConfigValueHandler<PARAM, SOURCE> valueSerializer;
|
protected @NotNull ValueHandler<PARAM, SOURCE> valueSerializer;
|
||||||
|
|
||||||
public AbstractSourceBuilder(@NotNull ValueType<V> type,
|
public AbstractSourceBuilder(@NotNull ValueType<V> type,
|
||||||
@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<PARAM> paramType,
|
@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<PARAM> paramType,
|
||||||
@NotNull ConfigValueHandler<SOURCE, PARAM> parser,
|
@NotNull ValueHandler<SOURCE, PARAM> parser,
|
||||||
@NotNull ConfigValueHandler<PARAM, SOURCE> serializer) {
|
@NotNull ValueHandler<PARAM, SOURCE> serializer) {
|
||||||
super(type);
|
super(type);
|
||||||
this.sourceType = sourceType;
|
this.sourceType = sourceType;
|
||||||
this.paramType = paramType;
|
this.paramType = paramType;
|
||||||
@@ -29,21 +29,21 @@ public abstract class AbstractSourceBuilder<
|
|||||||
this.valueSerializer = serializer;
|
this.valueSerializer = serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(ConfigDataFunction<SOURCE, PARAM> parser) {
|
public @NotNull SELF parse(DataFunction<SOURCE, PARAM> parser) {
|
||||||
return parse((p, source) -> parser.handle(source));
|
return parse((p, source) -> parser.handle(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(@NotNull ConfigValueHandler<SOURCE, PARAM> parser) {
|
public @NotNull SELF parse(@NotNull ValueHandler<SOURCE, PARAM> parser) {
|
||||||
this.valueParser = parser;
|
this.valueParser = parser;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(@NotNull ConfigValueHandler<PARAM, SOURCE> serializer) {
|
public @NotNull SELF serialize(@NotNull ValueHandler<PARAM, SOURCE> serializer) {
|
||||||
this.valueSerializer = serializer;
|
this.valueSerializer = serializer;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(@NotNull ConfigDataFunction<PARAM, SOURCE> serializer) {
|
public @NotNull SELF serialize(@NotNull DataFunction<PARAM, SOURCE> serializer) {
|
||||||
return serialize((p, value) -> serializer.handle(value));
|
return serialize((p, value) -> serializer.handle(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package cc.carm.lib.configuration.builder.list;
|
package cc.carm.lib.configuration.builder.list;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.function.ConfigValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -19,7 +19,7 @@ public class ConfigListBuilder<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <S> @NotNull SourceListBuilder<S, V> from(@NotNull ValueType<S> sourceType) {
|
public <S> @NotNull SourceListBuilder<S, V> from(@NotNull ValueType<S> sourceType) {
|
||||||
return new SourceListBuilder<>(sourceType, type, ConfigValueHandler.required(), ConfigValueHandler.required(), ArrayList::new);
|
return new SourceListBuilder<>(sourceType, type, ValueHandler.required(), ValueHandler.required(), ArrayList::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SourceListBuilder<String, V> fromString() {
|
public @NotNull SourceListBuilder<String, V> fromString() {
|
||||||
@@ -27,7 +27,7 @@ public class ConfigListBuilder<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionListBuilder<V> fromSection() {
|
public @NotNull SectionListBuilder<V> fromSection() {
|
||||||
return new SectionListBuilder<>(type, ConfigValueHandler.required(), ConfigValueHandler.required(), ArrayList::new);
|
return new SectionListBuilder<>(type, ValueHandler.required(), ValueHandler.required(), ArrayList::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package cc.carm.lib.configuration.builder.list;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
|
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
|
||||||
import cc.carm.lib.configuration.function.ConfigValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -15,8 +15,8 @@ public class SectionListBuilder<V> extends AbstractSectionBuilder<List<V>, V, Co
|
|||||||
protected @NotNull Supplier<? extends List<V>> constructor;
|
protected @NotNull Supplier<? extends List<V>> constructor;
|
||||||
|
|
||||||
public SectionListBuilder(@NotNull ValueType<V> paramType,
|
public SectionListBuilder(@NotNull ValueType<V> paramType,
|
||||||
@NotNull ConfigValueHandler<ConfigurationSection, V> parser,
|
@NotNull ValueHandler<ConfigurationSection, V> parser,
|
||||||
@NotNull ConfigValueHandler<V, ? extends Map<Object, Object>> serializer,
|
@NotNull ValueHandler<V, ? extends Map<Object, Object>> serializer,
|
||||||
@NotNull Supplier<? extends List<V>> constructor) {
|
@NotNull Supplier<? extends List<V>> constructor) {
|
||||||
super(new ValueType<List<V>>() {
|
super(new ValueType<List<V>>() {
|
||||||
}, paramType, parser, serializer);
|
}, paramType, parser, serializer);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package cc.carm.lib.configuration.builder.list;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.impl.AbstractSourceBuilder;
|
import cc.carm.lib.configuration.builder.impl.AbstractSourceBuilder;
|
||||||
import cc.carm.lib.configuration.function.ConfigValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ public class SourceListBuilder<SOURCE, V>
|
|||||||
protected @NotNull Supplier<? extends List<V>> constructor;
|
protected @NotNull Supplier<? extends List<V>> constructor;
|
||||||
|
|
||||||
public SourceListBuilder(@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<V> paramType,
|
public SourceListBuilder(@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<V> paramType,
|
||||||
@NotNull ConfigValueHandler<SOURCE, V> parser, @NotNull ConfigValueHandler<V, SOURCE> serializer,
|
@NotNull ValueHandler<SOURCE, V> parser, @NotNull ValueHandler<V, SOURCE> serializer,
|
||||||
@NotNull Supplier<? extends List<V>> constructor) {
|
@NotNull Supplier<? extends List<V>> constructor) {
|
||||||
super(new ValueType<List<V>>() {
|
super(new ValueType<List<V>>() {
|
||||||
}, sourceType, paramType, parser, serializer);
|
}, sourceType, paramType, parser, serializer);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package cc.carm.lib.configuration.builder.value;
|
package cc.carm.lib.configuration.builder.value;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.function.ConfigValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -20,12 +20,12 @@ public class ConfigValueBuilder<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull <S> SourceValueBuilder<S, V> from(@NotNull ValueType<S> sourceType) {
|
public @NotNull <S> SourceValueBuilder<S, V> from(@NotNull ValueType<S> sourceType) {
|
||||||
return from(sourceType, ConfigValueHandler.required(), ConfigValueHandler.required());
|
return from(sourceType, ValueHandler.required(), ValueHandler.required());
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull <S> SourceValueBuilder<S, V> from(@NotNull ValueType<S> sourceType,
|
public @NotNull <S> SourceValueBuilder<S, V> from(@NotNull ValueType<S> sourceType,
|
||||||
@NotNull ConfigValueHandler<S, V> valueParser,
|
@NotNull ValueHandler<S, V> valueParser,
|
||||||
@NotNull ConfigValueHandler<V, S> valueSerializer) {
|
@NotNull ValueHandler<V, S> valueSerializer) {
|
||||||
return new SourceValueBuilder<>(sourceType, this.type, valueParser, valueSerializer);
|
return new SourceValueBuilder<>(sourceType, this.type, valueParser, valueSerializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,12 +34,12 @@ public class ConfigValueBuilder<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionValueBuilder<V> fromSection() {
|
public @NotNull SectionValueBuilder<V> fromSection() {
|
||||||
return fromSection(ConfigValueHandler.required(), ConfigValueHandler.required());
|
return fromSection(ValueHandler.required(), ValueHandler.required());
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionValueBuilder<V> fromSection(
|
public @NotNull SectionValueBuilder<V> fromSection(
|
||||||
@NotNull ConfigValueHandler<ConfigurationSection, V> valueParser,
|
@NotNull ValueHandler<ConfigurationSection, V> valueParser,
|
||||||
@NotNull ConfigValueHandler<V, ? extends Map<Object, Object>> valueSerializer
|
@NotNull ValueHandler<V, ? extends Map<Object, Object>> valueSerializer
|
||||||
) {
|
) {
|
||||||
return new SectionValueBuilder<>(this.type, valueParser, valueSerializer);
|
return new SectionValueBuilder<>(this.type, valueParser, valueSerializer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package cc.carm.lib.configuration.builder.value;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
|
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
|
||||||
import cc.carm.lib.configuration.function.ConfigValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -12,8 +12,8 @@ import java.util.Map;
|
|||||||
public class SectionValueBuilder<V> extends AbstractSectionBuilder<V, V, ConfiguredValue<V>, SectionValueBuilder<V>> {
|
public class SectionValueBuilder<V> extends AbstractSectionBuilder<V, V, ConfiguredValue<V>, SectionValueBuilder<V>> {
|
||||||
|
|
||||||
public SectionValueBuilder(@NotNull ValueType<V> type,
|
public SectionValueBuilder(@NotNull ValueType<V> type,
|
||||||
@NotNull ConfigValueHandler<ConfigurationSection, V> parser,
|
@NotNull ValueHandler<ConfigurationSection, V> parser,
|
||||||
@NotNull ConfigValueHandler<V, ? extends Map<Object, Object>> serializer) {
|
@NotNull ValueHandler<V, ? extends Map<Object, Object>> serializer) {
|
||||||
super(type, type, parser, serializer);
|
super(type, type, parser, serializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package cc.carm.lib.configuration.builder.value;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.impl.AbstractSourceBuilder;
|
import cc.carm.lib.configuration.builder.impl.AbstractSourceBuilder;
|
||||||
import cc.carm.lib.configuration.function.ConfigValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ public class SourceValueBuilder<S, V> extends AbstractSourceBuilder<V, S, V, Con
|
|||||||
|
|
||||||
|
|
||||||
public SourceValueBuilder(@NotNull ValueType<S> sourceType, @NotNull ValueType<V> valueType,
|
public SourceValueBuilder(@NotNull ValueType<S> sourceType, @NotNull ValueType<V> valueType,
|
||||||
@NotNull ConfigValueHandler<S, V> parser, @NotNull ConfigValueHandler<V, S> serializer) {
|
@NotNull ValueHandler<S, V> parser, @NotNull ValueHandler<V, S> serializer) {
|
||||||
super(valueType, sourceType, valueType, parser, serializer);
|
super(valueType, sourceType, valueType, parser, serializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-17
@@ -7,39 +7,39 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ConfigDataFunction<T, R> {
|
public interface DataFunction<T, R> {
|
||||||
|
|
||||||
@NotNull R handle(@NotNull T data) throws Exception;
|
@NotNull R handle(@NotNull T data) throws Exception;
|
||||||
|
|
||||||
default <V> @NotNull ConfigDataFunction<T, V> andThen(@NotNull ConfigDataFunction<? super R, V> after) {
|
default <V> @NotNull DataFunction<T, V> andThen(@NotNull DataFunction<? super R, V> after) {
|
||||||
Objects.requireNonNull(after);
|
Objects.requireNonNull(after);
|
||||||
return data -> after.handle(handle(data));
|
return data -> after.handle(handle(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T> @NotNull ConfigDataFunction<T, T> identity() {
|
static <T> @NotNull DataFunction<T, T> identity() {
|
||||||
return input -> input;
|
return input -> input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T> @NotNull ConfigDataFunction<T, T> identity(Class<T> type) {
|
static <T> @NotNull DataFunction<T, T> identity(Class<T> type) {
|
||||||
return input -> input;
|
return input -> input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T, V> @NotNull ConfigDataFunction<T, V> required() {
|
static <T, V> @NotNull DataFunction<T, V> required() {
|
||||||
return input -> {
|
return input -> {
|
||||||
throw new IllegalArgumentException("Please specify the value parser.");
|
throw new IllegalArgumentException("Please specify the value parser.");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T> @NotNull ConfigDataFunction<T, Object> toObject() {
|
static <T> @NotNull DataFunction<T, Object> toObject() {
|
||||||
return input -> input;
|
return input -> input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <V> @NotNull ConfigDataFunction<Object, V> castObject(Class<V> valueClass) {
|
static <V> @NotNull DataFunction<Object, V> castObject(Class<V> valueClass) {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (valueClass.isInstance(input)) return valueClass.cast(input);
|
if (valueClass.isInstance(input)) return valueClass.cast(input);
|
||||||
else throw new IllegalArgumentException("Cannot cast value to " + valueClass.getName());
|
else throw new IllegalArgumentException("Cannot cast value to " + valueClass.getName());
|
||||||
@@ -47,7 +47,7 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <V> @NotNull ConfigDataFunction<String, V> castFromString(Class<V> valueClass) {
|
static <V> @NotNull DataFunction<String, V> castFromString(Class<V> valueClass) {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (valueClass.isInstance(input)) return valueClass.cast(input);
|
if (valueClass.isInstance(input)) return valueClass.cast(input);
|
||||||
else throw new IllegalArgumentException("Cannot cast string to " + valueClass.getName());
|
else throw new IllegalArgumentException("Cannot cast string to " + valueClass.getName());
|
||||||
@@ -55,7 +55,7 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T> @NotNull ConfigDataFunction<T, String> castToString() {
|
static <T> @NotNull DataFunction<T, String> castToString() {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (input instanceof String) return (String) input;
|
if (input instanceof String) return (String) input;
|
||||||
else if (input instanceof Enum<?>) return ((Enum<?>) input).name();
|
else if (input instanceof Enum<?>) return ((Enum<?>) input).name();
|
||||||
@@ -64,7 +64,7 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <V> @NotNull ConfigDataFunction<String, V> parseString(Class<V> valueClass) {
|
static <V> @NotNull DataFunction<String, V> parseString(Class<V> valueClass) {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (valueClass.isInstance(input)) return valueClass.cast(input);
|
if (valueClass.isInstance(input)) return valueClass.cast(input);
|
||||||
else throw new IllegalArgumentException("Cannot cast string to " + valueClass.getName());
|
else throw new IllegalArgumentException("Cannot cast string to " + valueClass.getName());
|
||||||
@@ -72,7 +72,7 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static @NotNull ConfigDataFunction<Object, Integer> intValue() {
|
static @NotNull DataFunction<Object, Integer> intValue() {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (input instanceof Integer) {
|
if (input instanceof Integer) {
|
||||||
return (Integer) input;
|
return (Integer) input;
|
||||||
@@ -83,7 +83,7 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static @NotNull ConfigDataFunction<Object, Short> shortValue() {
|
static @NotNull DataFunction<Object, Short> shortValue() {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (input instanceof Short) {
|
if (input instanceof Short) {
|
||||||
return (Short) input;
|
return (Short) input;
|
||||||
@@ -94,7 +94,7 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static @NotNull ConfigDataFunction<Object, Double> doubleValue() {
|
static @NotNull DataFunction<Object, Double> doubleValue() {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (input instanceof Double) {
|
if (input instanceof Double) {
|
||||||
return (Double) input;
|
return (Double) input;
|
||||||
@@ -105,7 +105,7 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static @NotNull ConfigDataFunction<Object, Byte> byteValue() {
|
static @NotNull DataFunction<Object, Byte> byteValue() {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (input instanceof Byte) {
|
if (input instanceof Byte) {
|
||||||
return (Byte) input;
|
return (Byte) input;
|
||||||
@@ -116,7 +116,7 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static @NotNull ConfigDataFunction<Object, Float> floatValue() {
|
static @NotNull DataFunction<Object, Float> floatValue() {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (input instanceof Float) {
|
if (input instanceof Float) {
|
||||||
return (Float) input;
|
return (Float) input;
|
||||||
@@ -127,7 +127,7 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static @NotNull ConfigDataFunction<Object, Long> longValue() {
|
static @NotNull DataFunction<Object, Long> longValue() {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (input instanceof Long) {
|
if (input instanceof Long) {
|
||||||
return (Long) input;
|
return (Long) input;
|
||||||
@@ -138,7 +138,7 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static @NotNull ConfigDataFunction<Object, Boolean> booleanValue() {
|
static @NotNull DataFunction<Object, Boolean> booleanValue() {
|
||||||
return input -> {
|
return input -> {
|
||||||
if (input instanceof Boolean) {
|
if (input instanceof Boolean) {
|
||||||
return (Boolean) input;
|
return (Boolean) input;
|
||||||
+8
-8
@@ -10,11 +10,11 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ConfigValueHandler<T, R> {
|
public interface ValueHandler<T, R> {
|
||||||
|
|
||||||
@Nullable R handle(@NotNull ConfigurationProvider<?> provider, @NotNull T data) throws Exception;
|
@Nullable R handle(@NotNull ConfigurationProvider<?> provider, @NotNull T data) throws Exception;
|
||||||
|
|
||||||
default <V> ConfigValueHandler<T, V> andThen(@NotNull ConfigValueHandler<R, V> after) {
|
default <V> ValueHandler<T, V> andThen(@NotNull ValueHandler<R, V> after) {
|
||||||
Objects.requireNonNull(after);
|
Objects.requireNonNull(after);
|
||||||
return ((provider, data) -> {
|
return ((provider, data) -> {
|
||||||
R result = handle(provider, data);
|
R result = handle(provider, data);
|
||||||
@@ -23,7 +23,7 @@ public interface ConfigValueHandler<T, R> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
default <V> ConfigValueHandler<V, R> compose(@NotNull ConfigValueHandler<? super V, ? extends T> before) {
|
default <V> ValueHandler<V, R> compose(@NotNull ValueHandler<? super V, ? extends T> before) {
|
||||||
Objects.requireNonNull(before);
|
Objects.requireNonNull(before);
|
||||||
return ((provider, data) -> {
|
return ((provider, data) -> {
|
||||||
T result = before.handle(provider, data);
|
T result = before.handle(provider, data);
|
||||||
@@ -32,7 +32,7 @@ public interface ConfigValueHandler<T, R> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
default <V> ConfigValueHandler<V, R> compose(@NotNull ConfigDataFunction<? super V, ? extends T> before) {
|
default <V> ValueHandler<V, R> compose(@NotNull DataFunction<? super V, ? extends T> before) {
|
||||||
Objects.requireNonNull(before);
|
Objects.requireNonNull(before);
|
||||||
return ((provider, data) -> {
|
return ((provider, data) -> {
|
||||||
T result = before.handle(data);
|
T result = before.handle(data);
|
||||||
@@ -41,23 +41,23 @@ public interface ConfigValueHandler<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T> @NotNull ConfigValueHandler<T, T> identity() {
|
static <T> @NotNull ValueHandler<T, T> identity() {
|
||||||
return (provider, input) -> input;
|
return (provider, input) -> input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T> @NotNull ConfigValueHandler<T, Object> toObject() {
|
static <T> @NotNull ValueHandler<T, Object> toObject() {
|
||||||
return ConfigurationProvider::serialize;
|
return ConfigurationProvider::serialize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T> @NotNull ConfigValueHandler<Object, T> fromObject(ValueType<T> type) {
|
static <T> @NotNull ValueHandler<Object, T> fromObject(ValueType<T> type) {
|
||||||
return (provider, input) -> provider.deserialize(type, input);
|
return (provider, input) -> provider.deserialize(type, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T, V> @NotNull ConfigValueHandler<T, V> required() {
|
static <T, V> @NotNull ValueHandler<T, V> required() {
|
||||||
return (provider, input) -> {
|
return (provider, input) -> {
|
||||||
throw new IllegalArgumentException("Please specify the value parser.");
|
throw new IllegalArgumentException("Please specify the value parser.");
|
||||||
};
|
};
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.meta;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public class PathMetadata<T> {
|
|
||||||
|
|
||||||
public static <T> PathMetadata<T> of() {
|
|
||||||
return of(() -> null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> PathMetadata<T> of(T defaults) {
|
|
||||||
return of(() -> defaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> PathMetadata<T> of(@NotNull Supplier<@Nullable T> defaults) {
|
|
||||||
return of(v -> defaults.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> PathMetadata<T> of(@NotNull Function<String, @Nullable T> defaults) {
|
|
||||||
return new PathMetadata<>(defaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Function<String, @Nullable T> defaultFunction;
|
|
||||||
|
|
||||||
public PathMetadata(@NotNull Function<String, @Nullable T> defaults) {
|
|
||||||
this.defaultFunction = defaults;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDefault(String path, @NotNull T value) {
|
|
||||||
return value.equals(defaults(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasDefaults(String path) {
|
|
||||||
return defaults(path) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getDefault(String path, @Nullable T suppliedValue) {
|
|
||||||
T defaults = defaults(path);
|
|
||||||
return defaults == null ? suppliedValue : defaults;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable T defaults(String path) {
|
|
||||||
return defaultFunction.apply(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaults(Function<String, T> defaultFunction) {
|
|
||||||
this.defaultFunction = defaultFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaults(T value) {
|
|
||||||
setDefaults((v) -> value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package cc.carm.lib.configuration.source;
|
package cc.carm.lib.configuration.source;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
|
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationLoader;
|
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.option.ConfigurationOption;
|
import cc.carm.lib.configuration.source.option.ConfigurationOption;
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
||||||
@@ -13,8 +13,8 @@ import java.util.function.Function;
|
|||||||
|
|
||||||
public abstract class ConfigurationFactory<SOURCE extends ConfigurationSource<SOURCE, ?>, PROVIDER extends ConfigurationProvider<SOURCE>, SELF> {
|
public abstract class ConfigurationFactory<SOURCE extends ConfigurationSource<SOURCE, ?>, PROVIDER extends ConfigurationProvider<SOURCE>, SELF> {
|
||||||
|
|
||||||
protected Function<PROVIDER, ConfigurationLoader> loaderFunction = PROVIDER -> new ConfigurationLoader();
|
protected Function<PROVIDER, ConfigurationInitializer> loaderFunction = PROVIDER -> new ConfigurationInitializer();
|
||||||
protected Consumer<ConfigurationLoader> loaderConsumer = loader -> {
|
protected Consumer<ConfigurationInitializer> loaderConsumer = loader -> {
|
||||||
};
|
};
|
||||||
|
|
||||||
protected ValueAdapterRegistry adapters = new ValueAdapterRegistry();
|
protected ValueAdapterRegistry adapters = new ValueAdapterRegistry();
|
||||||
@@ -22,23 +22,23 @@ public abstract class ConfigurationFactory<SOURCE extends ConfigurationSource<SO
|
|||||||
|
|
||||||
public abstract SELF self();
|
public abstract SELF self();
|
||||||
|
|
||||||
public SELF loader(Function<PROVIDER, ConfigurationLoader> loaderFunction) {
|
public SELF loader(Function<PROVIDER, ConfigurationInitializer> loaderFunction) {
|
||||||
this.loaderFunction = loaderFunction;
|
this.loaderFunction = loaderFunction;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SELF loader(ConfigurationLoader loader) {
|
public SELF loader(ConfigurationInitializer loader) {
|
||||||
return loader(PROVIDER -> loader);
|
return loader(PROVIDER -> loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SELF loader(Consumer<ConfigurationLoader> loaderConsumer) {
|
public SELF loader(Consumer<ConfigurationInitializer> loaderConsumer) {
|
||||||
this.loaderConsumer = this.loaderConsumer.andThen(loaderConsumer);
|
this.loaderConsumer = this.loaderConsumer.andThen(loaderConsumer);
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SELF pathGenerator(PathGenerator pathGenerator) {
|
public SELF pathGenerator(PathGenerator generator) {
|
||||||
return loader(loader -> {
|
return loader(loader -> {
|
||||||
loader.setPathGenerator(pathGenerator);
|
loader.pathGenerator(generator);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,8 @@ 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.meta.PathMetadata;
|
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationLoader;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOption;
|
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSource;
|
import cc.carm.lib.configuration.source.section.ConfigurationSource;
|
||||||
import cc.carm.lib.configuration.value.ValueManifest;
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
@@ -18,20 +17,22 @@ import java.util.Map;
|
|||||||
public class ConfigurationProvider<S extends ConfigurationSource<S, ?>> {
|
public class ConfigurationProvider<S extends ConfigurationSource<S, ?>> {
|
||||||
|
|
||||||
protected final @NotNull S source;
|
protected final @NotNull S source;
|
||||||
protected final @NotNull ConfigurationLoader loader;
|
|
||||||
protected final @NotNull ValueAdapterRegistry adapters;
|
protected final @NotNull ValueAdapterRegistry adapters;
|
||||||
protected final @NotNull ConfigurationOptionHolder options;
|
protected final @NotNull ConfigurationOptionHolder options;
|
||||||
protected final @NotNull Map<String, Map<PathMetadata<?>, Object>> pathMetadata;
|
protected final @NotNull Map<String, ConfigurationMetaHolder> metadata;
|
||||||
|
|
||||||
public ConfigurationProvider(@NotNull S source, @NotNull ConfigurationLoader loader,
|
protected final @NotNull ConfigurationInitializer initializer;
|
||||||
|
|
||||||
|
public ConfigurationProvider(@NotNull S source,
|
||||||
@NotNull ValueAdapterRegistry adapters,
|
@NotNull ValueAdapterRegistry adapters,
|
||||||
@NotNull ConfigurationOptionHolder options,
|
@NotNull ConfigurationOptionHolder options,
|
||||||
@NotNull Map<String, Map<PathMetadata<?>, Object>> pathMetadata) {
|
@NotNull Map<String, ConfigurationMetaHolder> metadata,
|
||||||
|
@NotNull ConfigurationInitializer initializer) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.loader = loader;
|
this.initializer = initializer;
|
||||||
this.adapters = adapters;
|
this.adapters = adapters;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.pathMetadata = pathMetadata;
|
this.metadata = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull S source() {
|
public @NotNull S source() {
|
||||||
@@ -50,112 +51,21 @@ public class ConfigurationProvider<S extends ConfigurationSource<S, ?>> {
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> @NotNull T option(@NotNull ConfigurationOption<T> option) {
|
public @NotNull Map<String, ConfigurationMetaHolder> metadata() {
|
||||||
return options.get(option);
|
return this.metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void option(@NotNull ConfigurationOption<T> option, @NotNull T value) {
|
public @NotNull ConfigurationMetaHolder metadata(@Nullable String path) {
|
||||||
options.set(option, value);
|
return metadata().computeIfAbsent(path, k -> new ConfigurationMetaHolder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ValueAdapterRegistry adapters() {
|
public ValueAdapterRegistry adapters() {
|
||||||
return this.adapters;
|
return this.adapters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigurationLoader loader() {
|
public ConfigurationInitializer initializer() {
|
||||||
return loader;
|
return initializer;
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull Map<String, Map<PathMetadata<?>, Object>> pathMetadata() {
|
|
||||||
return pathMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull Map<PathMetadata<?>, Object> metadata(@NotNull String path) {
|
|
||||||
return pathMetadata().computeIfAbsent(path, k -> new java.util.HashMap<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the value of option.
|
|
||||||
*
|
|
||||||
* @param type {@link PathMetadata}
|
|
||||||
* @param defaultValue Default value if the value of option is not set.
|
|
||||||
* @param <V> Value type
|
|
||||||
* @return Value of option
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Contract("_,_, !null -> !null")
|
|
||||||
public <V> @Nullable V meta(@NotNull String path,
|
|
||||||
@NotNull PathMetadata<V> type, @Nullable V defaultValue) {
|
|
||||||
return (V) metadata(path).getOrDefault(type, type.getDefault(path, defaultValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the value of option.
|
|
||||||
*
|
|
||||||
* @param type {@link PathMetadata}
|
|
||||||
* @param <V> Value type
|
|
||||||
* @return Value of option
|
|
||||||
*/
|
|
||||||
public <V> @Nullable V meta(@NotNull String path, @NotNull PathMetadata<V> type) {
|
|
||||||
return meta(path, type, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasMeta(@NotNull String path, @NotNull PathMetadata<?> type) {
|
|
||||||
return metadata(path).containsKey(type) || type.hasDefaults(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value of meta, if the value is null, the meta will be removed.
|
|
||||||
* <br> Will only be changed in current holder.
|
|
||||||
*
|
|
||||||
* @param type {@link PathMetadata}
|
|
||||||
* @param value Value of meta
|
|
||||||
* @param <V> Value type
|
|
||||||
* @return Previous value of meta
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <V> @Nullable V setMeta(@NotNull String path, @NotNull PathMetadata<V> type, @Nullable V value) {
|
|
||||||
if (value == null || type.isDefault(path, value)) {
|
|
||||||
return (V) metadata(path).remove(type);
|
|
||||||
} else {
|
|
||||||
return (V) metadata(path).put(type, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value of meta, if the value is null, the meta will not be changed.
|
|
||||||
* <br> Will only be changed in current holder.
|
|
||||||
*
|
|
||||||
* @param type {@link PathMetadata}
|
|
||||||
* @param value Value of meta
|
|
||||||
* @param <V> Value type
|
|
||||||
*/
|
|
||||||
public <V> void setMetaIfAbsent(@NotNull String path, @NotNull PathMetadata<V> type, @Nullable V value) {
|
|
||||||
if (value == null || type.isDefault(path, value)) {
|
|
||||||
metadata(path).remove(type);
|
|
||||||
} else {
|
|
||||||
metadata(path).putIfAbsent(type, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value of meta, if the value is null, the meta will not be changed.
|
|
||||||
* <br> Will only be changed in current holder.
|
|
||||||
*
|
|
||||||
* @param type {@link PathMetadata}
|
|
||||||
* @param value Value of meta
|
|
||||||
* @param <V> Value type
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <V> @Nullable V setMetaIfPresent(@NotNull String path, @NotNull PathMetadata<V> type, @Nullable V value) {
|
|
||||||
Object exists = metadata(path).get(type);
|
|
||||||
if (exists == null) return null;
|
|
||||||
|
|
||||||
if (value == null || type.isDefault(path, value)) {
|
|
||||||
return (V) metadata(path).remove(type);
|
|
||||||
} else {
|
|
||||||
return (V) metadata(path).put(type, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_,null -> null")
|
@Contract("_,null -> null")
|
||||||
@@ -167,7 +77,7 @@ public class ConfigurationProvider<S extends ConfigurationSource<S, ?>> {
|
|||||||
public <T> T deserialize(@NotNull ValueType<T> type, @Nullable Object source) throws Exception {
|
public <T> T deserialize(@NotNull ValueType<T> type, @Nullable Object source) throws Exception {
|
||||||
return adapters().deserialize(this, type, source);
|
return adapters().deserialize(this, type, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("null -> null")
|
@Contract("null -> null")
|
||||||
public <T> Object serialize(@Nullable T value) throws Exception {
|
public <T> Object serialize(@Nullable T value) throws Exception {
|
||||||
return adapters().serialize(this, value);
|
return adapters().serialize(this, value);
|
||||||
@@ -175,7 +85,7 @@ public class ConfigurationProvider<S extends ConfigurationSource<S, ?>> {
|
|||||||
|
|
||||||
public void load(Class<? extends Configuration> configClass) {
|
public void load(Class<? extends Configuration> configClass) {
|
||||||
try {
|
try {
|
||||||
loader.load(this, configClass);
|
initializer.initialize(this, configClass);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -183,7 +93,7 @@ public class ConfigurationProvider<S extends ConfigurationSource<S, ?>> {
|
|||||||
|
|
||||||
public void load(@NotNull Configuration config) {
|
public void load(@NotNull Configuration config) {
|
||||||
try {
|
try {
|
||||||
loader.load(this, config);
|
initializer.initialize(this, config);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package cc.carm.lib.configuration.source.loader;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ConfigInitializeHandler<T> {
|
||||||
|
|
||||||
|
static <T> ConfigInitializeHandler<T> start() {
|
||||||
|
return (provider, path, value) -> {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void whenInitialize(@NotNull ConfigurationProvider<?> provider, @Nullable String path, @NotNull T value) throws Exception;
|
||||||
|
|
||||||
|
default ConfigInitializeHandler<T> andThen(ConfigInitializeHandler<T> after) {
|
||||||
|
return (provider, path, value) -> {
|
||||||
|
whenInitialize(provider, path, value);
|
||||||
|
after.whenInitialize(provider, path, value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default ConfigInitializeHandler<T> compose(ConfigInitializeHandler<T> before) {
|
||||||
|
return (provider, path, value) -> {
|
||||||
|
before.whenInitialize(provider, path, value);
|
||||||
|
whenInitialize(provider, path, value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+177
@@ -0,0 +1,177 @@
|
|||||||
|
package cc.carm.lib.configuration.source.loader;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.Configuration;
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
||||||
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
||||||
|
import cc.carm.lib.configuration.source.option.StandardOptions;
|
||||||
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration initializer,
|
||||||
|
* used to initialize {@link ConfigValue}s from {@link Configuration} classes.
|
||||||
|
*/
|
||||||
|
public class ConfigurationInitializer {
|
||||||
|
|
||||||
|
protected @NotNull PathGenerator pathGenerator;
|
||||||
|
protected @NotNull ConfigInitializeHandler<Field> fieldInitializer;
|
||||||
|
protected @NotNull ConfigInitializeHandler<Class<? extends Configuration>> classInitializer;
|
||||||
|
|
||||||
|
public ConfigurationInitializer() {
|
||||||
|
this(PathGenerator.of(), ConfigInitializeHandler.start(), ConfigInitializeHandler.start());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigurationInitializer(@NotNull PathGenerator pathGenerator,
|
||||||
|
@NotNull ConfigInitializeHandler<Field> fieldInitializer,
|
||||||
|
@NotNull ConfigInitializeHandler<Class<? extends Configuration>> classInitializer) {
|
||||||
|
this.pathGenerator = pathGenerator;
|
||||||
|
this.fieldInitializer = fieldInitializer;
|
||||||
|
this.classInitializer = classInitializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pathGenerator(@NotNull PathGenerator pathGenerator) {
|
||||||
|
this.pathGenerator = pathGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull PathGenerator pathGenerator() {
|
||||||
|
return pathGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigInitializeHandler<Field> fieldInitializer() {
|
||||||
|
return fieldInitializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fieldInitializer(@NotNull ConfigInitializeHandler<Field> fieldInitializer) {
|
||||||
|
this.fieldInitializer = fieldInitializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigInitializeHandler<Class<? extends Configuration>> classInitializer() {
|
||||||
|
return classInitializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void classInitializer(@NotNull ConfigInitializeHandler<Class<? extends Configuration>> classInitializer) {
|
||||||
|
this.classInitializer = classInitializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendFieldInitializer(@NotNull ConfigInitializeHandler<Field> fieldInitializer) {
|
||||||
|
this.fieldInitializer = this.fieldInitializer.andThen(fieldInitializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendClassInitializer(@NotNull ConfigInitializeHandler<Class<? extends Configuration>> classInitializer) {
|
||||||
|
this.classInitializer = this.classInitializer.andThen(classInitializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T, A extends Annotation> void registerAnnotation(@NotNull Class<A> annotation,
|
||||||
|
@NotNull ConfigurationMetadata<T> metadata,
|
||||||
|
@NotNull Function<A, T> extractor) {
|
||||||
|
appendFieldInitializer((provider, path, field) -> {
|
||||||
|
A data = field.getAnnotation(annotation);
|
||||||
|
if (data == null) return;
|
||||||
|
provider.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
||||||
|
});
|
||||||
|
appendClassInitializer((provider, path, clazz) -> {
|
||||||
|
A data = clazz.getAnnotation(annotation);
|
||||||
|
if (data == null) return;
|
||||||
|
provider.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public @Nullable String getFieldPath(ConfigurationProvider<?> provider, @Nullable String parentPath, @NotNull Field field) {
|
||||||
|
return pathGenerator.getFieldPath(provider, parentPath, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getClassPath(ConfigurationProvider<?> provider, @Nullable String parentPath,
|
||||||
|
@NotNull Class<?> clazz, @Nullable Field clazzField) {
|
||||||
|
return pathGenerator.getClassPath(provider, parentPath, clazz, clazzField);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize(ConfigurationProvider<?> provider, @NotNull Configuration config) throws Exception {
|
||||||
|
initializeInstance(provider, config, null, null);
|
||||||
|
if (provider.options().get(StandardOptions.SET_DEFAULTS)) provider.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize(ConfigurationProvider<?> provider, @NotNull Class<? extends Configuration> clazz) throws Exception {
|
||||||
|
initializeStaticClass(provider, clazz, null, null);
|
||||||
|
if (provider.options().get(StandardOptions.SET_DEFAULTS)) provider.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 针对实例类的初始化方法
|
||||||
|
protected void initializeInstance(@NotNull ConfigurationProvider<?> provider,
|
||||||
|
@NotNull Configuration root, @Nullable String parentPath, @Nullable Field configField) {
|
||||||
|
String path = getClassPath(provider, parentPath, root.getClass(), configField);
|
||||||
|
try {
|
||||||
|
this.classInitializer.whenInitialize(provider, path, root.getClass());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
Arrays.stream(root.getClass().getDeclaredFields()).forEach(field -> initializeField(provider, root, field, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 针对静态类的初始化方法
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void initializeStaticClass(@NotNull ConfigurationProvider<?> provider,
|
||||||
|
@NotNull Class<?> clazz, @Nullable String parentPath, @Nullable Field configField) {
|
||||||
|
if (!Configuration.class.isAssignableFrom(clazz)) return; // 只解析继承了 ConfigurationRoot 的类
|
||||||
|
|
||||||
|
String path = getClassPath(provider, parentPath, clazz, configField);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.classInitializer.whenInitialize(provider, path, (Class<? extends Configuration>) clazz);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
|
initializeField(provider, clazz, field, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provider.options().get(StandardOptions.LOAD_SUB_CLASSES)) {
|
||||||
|
Class<?>[] classes = clazz.getDeclaredClasses();
|
||||||
|
for (int i = classes.length - 1; i >= 0; i--) { // 逆向加载,保持顺序。
|
||||||
|
initializeStaticClass(provider, classes[i], path, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initializeField(@NotNull ConfigurationProvider<?> provider,
|
||||||
|
@NotNull Object source, @NotNull Field field, @Nullable String parent) {
|
||||||
|
try {
|
||||||
|
field.setAccessible(true);
|
||||||
|
Object object = field.get(source);
|
||||||
|
//
|
||||||
|
if (object instanceof ConfigValue<?>) {
|
||||||
|
// 目标是 ConfigValue 实例,进行具体的初始化注入
|
||||||
|
ConfigValue<?> value = (ConfigValue<?>) object;
|
||||||
|
String path = getFieldPath(provider, parent, field);
|
||||||
|
if (path == null) return;
|
||||||
|
value.initialize(provider, path);
|
||||||
|
try {
|
||||||
|
this.fieldInitializer.whenInitialize(provider, path, field);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else if (source instanceof Configuration && object instanceof Configuration) {
|
||||||
|
// 当且仅当 源字段与字段 均为Configuration实例时,才对目标字段进行下一步初始化加载。
|
||||||
|
initializeInstance(provider, (Configuration) object, parent, field);
|
||||||
|
} else if (source instanceof Class<?> && object instanceof Class<?>) {
|
||||||
|
// 当且仅当 源字段与字段 均为静态类时,才对目标字段进行下一步初始化加载。
|
||||||
|
initializeStaticClass(provider, (Class<?>) object, parent, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 以上判断实现以下规范:
|
||||||
|
// - 实例类中仅加载 ConfigValue实例 与 Configuration实例
|
||||||
|
// - 静态类中仅加载 静态ConfigValue实例 与 静态Configuration类
|
||||||
|
|
||||||
|
} catch (IllegalAccessException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.source.loader;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.Configuration;
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOptions;
|
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
|
||||||
import cc.carm.lib.configuration.value.ValueManifest;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration loader,
|
|
||||||
* used to load configuration values from {@link Configuration} classes.
|
|
||||||
*/
|
|
||||||
public class ConfigurationLoader {
|
|
||||||
|
|
||||||
public static final Field PATH_FIELD;
|
|
||||||
public static final Field PROVIDER_FIELD;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
PATH_FIELD = ValueManifest.class.getDeclaredField("path");
|
|
||||||
PATH_FIELD.setAccessible(true);
|
|
||||||
PROVIDER_FIELD = ValueManifest.class.getDeclaredField("provider");
|
|
||||||
PROVIDER_FIELD.setAccessible(true);
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected PathGenerator pathGenerator;
|
|
||||||
|
|
||||||
public ConfigurationLoader() {
|
|
||||||
this(StandardPathGenerator.of());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigurationLoader(PathGenerator pathGenerator) {
|
|
||||||
this.pathGenerator = pathGenerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPathGenerator(PathGenerator pathGenerator) {
|
|
||||||
this.pathGenerator = pathGenerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PathGenerator getPathGenerator() {
|
|
||||||
return pathGenerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable String getFieldPath(ConfigurationProvider<?> provider, @Nullable String parentPath, @NotNull Field field) {
|
|
||||||
return pathGenerator.getFieldPath(provider, parentPath, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable String getClassPath(ConfigurationProvider<?> provider, @Nullable String parentPath,
|
|
||||||
@NotNull Class<?> clazz, @Nullable Field clazzField) {
|
|
||||||
return pathGenerator.getClassPath(provider, parentPath, clazz, clazzField);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(ConfigurationProvider<?> provider, @NotNull Configuration config) throws Exception {
|
|
||||||
initializeInstance(provider, config, null, null);
|
|
||||||
if (provider.option(ConfigurationOptions.SET_DEFAULTS)) provider.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(ConfigurationProvider<?> provider, @NotNull Class<? extends Configuration> clazz) throws Exception {
|
|
||||||
initializeStaticClass(provider, clazz, null, null);
|
|
||||||
if (provider.option(ConfigurationOptions.SET_DEFAULTS)) provider.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 针对实例类的初始化方法
|
|
||||||
private void initializeInstance(@NotNull ConfigurationProvider<?> provider,
|
|
||||||
@NotNull Configuration root, @Nullable String parentPath, @Nullable Field configField) {
|
|
||||||
String path = getClassPath(provider, parentPath, root.getClass(), configField);
|
|
||||||
Arrays.stream(root.getClass().getDeclaredFields()).forEach(field -> initializeField(provider, root, field, path));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 针对静态类的初始化方法
|
|
||||||
private void initializeStaticClass(@NotNull ConfigurationProvider<?> provider,
|
|
||||||
@NotNull Class<?> clazz, @Nullable String parentPath, @Nullable Field configField) {
|
|
||||||
if (!Configuration.class.isAssignableFrom(clazz)) return; // 只解析继承了 ConfigurationRoot 的类
|
|
||||||
String path = getClassPath(provider, parentPath, clazz, configField);
|
|
||||||
|
|
||||||
for (Field field : clazz.getDeclaredFields()) {
|
|
||||||
initializeField(provider, clazz, field, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!provider.option(ConfigurationOptions.LOAD_SUB_CLASSES)) return;
|
|
||||||
Class<?>[] classes = clazz.getDeclaredClasses();
|
|
||||||
for (int i = classes.length - 1; i >= 0; i--) { // 逆向加载,保持顺序。
|
|
||||||
initializeStaticClass(provider, classes[i], path, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeField(@NotNull ConfigurationProvider<?> provider,
|
|
||||||
@NotNull Object source, @NotNull Field field, @Nullable String parent) {
|
|
||||||
try {
|
|
||||||
field.setAccessible(true);
|
|
||||||
Object object = field.get(source);
|
|
||||||
//
|
|
||||||
if (object instanceof ConfigValue<?>) {
|
|
||||||
// 目标是 ConfigValue 实例,进行具体的初始化注入
|
|
||||||
ConfigValue<?> value = (ConfigValue<?>) object;
|
|
||||||
String path = getFieldPath(provider, parent, field);
|
|
||||||
if (path == null) return;
|
|
||||||
insertIfAbsent(value, PATH_FIELD, path);
|
|
||||||
insertIfAbsent(value, PROVIDER_FIELD, provider);
|
|
||||||
} else if (source instanceof Configuration && object instanceof Configuration) {
|
|
||||||
// 当且仅当 源字段与字段 均为Configuration实例时,才对目标字段进行下一步初始化加载。
|
|
||||||
initializeInstance(provider, (Configuration) object, parent, field);
|
|
||||||
} else if (source instanceof Class<?> && object instanceof Class<?>) {
|
|
||||||
// 当且仅当 源字段与字段 均为静态类时,才对目标字段进行下一步初始化加载。
|
|
||||||
initializeStaticClass(provider, (Class<?>) object, parent, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 以上判断实现以下规范:
|
|
||||||
// - 实例类中仅加载 ConfigValue实例 与 Configuration实例
|
|
||||||
// - 静态类中仅加载 静态ConfigValue实例 与 静态Configuration类
|
|
||||||
|
|
||||||
} catch (IllegalAccessException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void insertIfAbsent(@NotNull ValueManifest<?> value, @NotNull Field field, @NotNull Object obj) {
|
|
||||||
try {
|
|
||||||
if (field.get(obj) == null) field.set(obj, value);
|
|
||||||
} catch (IllegalAccessException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,27 +1,96 @@
|
|||||||
package cc.carm.lib.configuration.source.loader;
|
package cc.carm.lib.configuration.source.loader;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.annotation.ConfigPath;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
||||||
|
import cc.carm.lib.configuration.source.option.StandardOptions;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
public interface PathGenerator {
|
public class PathGenerator {
|
||||||
|
|
||||||
@Nullable String getFieldPath(@NotNull ConfigurationProvider<?> provider,
|
public static PathGenerator of() {
|
||||||
@Nullable String parentPath, @NotNull Field field);
|
return of(PathGenerator::covertPathName);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable String getClassPath(@NotNull ConfigurationProvider<?> provider,
|
public static PathGenerator of(UnaryOperator<String> pathConverter) {
|
||||||
@Nullable String parentPath, @NotNull Class<?> clazz, @Nullable Field clazzField);
|
return new PathGenerator(pathConverter);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected UnaryOperator<String> pathConverter;
|
||||||
|
|
||||||
|
public PathGenerator(UnaryOperator<String> pathConverter) {
|
||||||
|
this.pathConverter = pathConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull UnaryOperator<String> getPathConverter() {
|
||||||
|
return pathConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPathConverter(UnaryOperator<String> pathConverter) {
|
||||||
|
this.pathConverter = pathConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String covertPath(String name) {
|
||||||
|
return pathConverter.apply(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getFieldPath(@NotNull ConfigurationProvider<?> provider,
|
||||||
|
@Nullable String parentPath, @NotNull Field field) {
|
||||||
|
ConfigPath path = field.getAnnotation(ConfigPath.class);
|
||||||
|
if (path == null) return link(provider, parentPath, false, field.getName()); // No annotation, use field name.
|
||||||
|
else return link(provider, parentPath, path.root(), select(path.value(), field.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getClassPath(@NotNull ConfigurationProvider<?> provider,
|
||||||
|
@Nullable String parentPath, @NotNull Class<?> clazz, @Nullable Field clazzField) {
|
||||||
|
// For standard path generator, we generate path following by:
|
||||||
|
// 1. Check if the class has a ConfigPath annotation, if so, use the root and value as the path.
|
||||||
|
// 2. If the class defined as a field, check if the field has a ConfigPath annotation,
|
||||||
|
// and use filed information.
|
||||||
|
ConfigPath clazzPath = clazz.getAnnotation(ConfigPath.class);
|
||||||
|
|
||||||
|
if (clazzPath != null) return link(provider, parentPath, clazzPath.root(), clazzPath.value());
|
||||||
|
if (clazzField == null) {
|
||||||
|
return link(provider, parentPath, false, clazz.getSimpleName()); // No field, use class name.
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigPath fieldPath = clazzField.getAnnotation(ConfigPath.class);
|
||||||
|
if (fieldPath == null) return link(provider, parentPath, false, clazzField.getName());
|
||||||
|
else return getFieldPath(provider, parentPath, clazzField);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String select(String path, String defaultValue) {
|
||||||
|
if (path == null || path.isEmpty()) return defaultValue;
|
||||||
|
else return isBlank(path) ? null : path;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected @Nullable String link(@NotNull ConfigurationProvider<?> provider,
|
||||||
|
@Nullable String parent, boolean root, @Nullable String path) {
|
||||||
|
if (path == null || path.isEmpty()) return root ? null : parent;
|
||||||
|
return root || parent == null ? covertPath(path) : parent + pathSeparator(provider) + covertPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isBlank(String path) {
|
||||||
|
return path == null || path.replace(" ", "").isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static char pathSeparator(ConfigurationProvider<?> provider) {
|
||||||
|
return provider.options().get(StandardOptions.PATH_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the configuration name of the specified element.
|
* Get the configuration name of the specified element.
|
||||||
* Use the naming convention of all lowercase and "-" links.
|
* Use the naming convention of all lowercase and "-" links.
|
||||||
|
* <p>
|
||||||
|
* e.g. "SOME_NAME" -> "some-name"
|
||||||
*
|
*
|
||||||
* @param name source name
|
* @param name source name
|
||||||
* @return the final path
|
* @return the final path
|
||||||
*/
|
*/
|
||||||
static String covertPathName(String name) {
|
public static String covertPathName(String name) {
|
||||||
return name
|
return name
|
||||||
// Replace all uppercase letters with dashes
|
// Replace all uppercase letters with dashes
|
||||||
.replaceAll("[A-Z]", "-$0")
|
.replaceAll("[A-Z]", "-$0")
|
||||||
@@ -40,4 +109,5 @@ public interface PathGenerator {
|
|||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.source.loader;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.annotation.ConfigPath;
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOptions;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.function.UnaryOperator;
|
|
||||||
|
|
||||||
public class StandardPathGenerator implements PathGenerator {
|
|
||||||
|
|
||||||
public static StandardPathGenerator of() {
|
|
||||||
return of(PathGenerator::covertPathName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static StandardPathGenerator of(UnaryOperator<String> pathConverter) {
|
|
||||||
return new StandardPathGenerator(pathConverter);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected UnaryOperator<String> pathConverter;
|
|
||||||
|
|
||||||
public StandardPathGenerator(UnaryOperator<String> pathConverter) {
|
|
||||||
this.pathConverter = pathConverter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull UnaryOperator<String> getPathConverter() {
|
|
||||||
return pathConverter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPathConverter(UnaryOperator<String> pathConverter) {
|
|
||||||
this.pathConverter = pathConverter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String covertPath(String name) {
|
|
||||||
return pathConverter.apply(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public char pathSeparator(ConfigurationProvider<?> provider) {
|
|
||||||
return provider.option(ConfigurationOptions.PATH_SEPARATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable String getFieldPath(@NotNull ConfigurationProvider<?> provider,
|
|
||||||
@Nullable String parentPath, @NotNull Field field) {
|
|
||||||
ConfigPath path = field.getAnnotation(ConfigPath.class);
|
|
||||||
if (path == null) return link(provider, parentPath, false, field.getName()); // No annotation, use field name.
|
|
||||||
else return link(provider, parentPath, path.root(), select(path.value(), field.getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable String getClassPath(@NotNull ConfigurationProvider<?> provider,
|
|
||||||
@Nullable String parentPath, @NotNull Class<?> clazz, @Nullable Field clazzField) {
|
|
||||||
// For standard path generator, we generate path following by:
|
|
||||||
// 1. Check if the class has a ConfigPath annotation, if so, use the root and value as the path.
|
|
||||||
// 2. If the class defined as a field, check if the field has a ConfigPath annotation,
|
|
||||||
// and use filed information.
|
|
||||||
ConfigPath clazzPath = clazz.getAnnotation(ConfigPath.class);
|
|
||||||
|
|
||||||
if (clazzPath != null) return link(provider, parentPath, clazzPath.root(), clazzPath.value());
|
|
||||||
if (clazzField == null) {
|
|
||||||
return link(provider, parentPath, false, clazz.getSimpleName()); // No field, use class name.
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigPath fieldPath = clazzField.getAnnotation(ConfigPath.class);
|
|
||||||
if (fieldPath == null) return link(provider, parentPath, false, clazzField.getName());
|
|
||||||
else return getFieldPath(provider, parentPath, clazzField);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String select(String path, String defaultValue) {
|
|
||||||
if (path == null || path.isEmpty()) return defaultValue;
|
|
||||||
else return isBlank(path) ? null : path;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isBlank(String path) {
|
|
||||||
return path == null || path.replace(" ", "").isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected @Nullable String link(@NotNull ConfigurationProvider<?> provider, @Nullable String parent, boolean root, @Nullable String path) {
|
|
||||||
if (path == null || path.isEmpty()) return root ? null : parent;
|
|
||||||
return root || parent == null ? covertPath(path) : parent + pathSeparator(provider) + covertPath(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
+124
@@ -0,0 +1,124 @@
|
|||||||
|
package cc.carm.lib.configuration.source.meta;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class ConfigurationMetaHolder {
|
||||||
|
|
||||||
|
protected final @NotNull Map<ConfigurationMetadata<?>, Object> values;
|
||||||
|
|
||||||
|
public ConfigurationMetaHolder() {
|
||||||
|
this(new ConcurrentHashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigurationMetaHolder(@NotNull Map<ConfigurationMetadata<?>, Object> values) {
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull Map<ConfigurationMetadata<?>, Object> values() {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of option.
|
||||||
|
*
|
||||||
|
* @param type {@link ConfigurationMetadata}
|
||||||
|
* @param defaultValue Default value if the value of option is not set.
|
||||||
|
* @param <V> Value type
|
||||||
|
* @return Value of option
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Contract("_,!null -> !null")
|
||||||
|
public <V> @Nullable V get(@NotNull ConfigurationMetadata<V> type, @Nullable V defaultValue) {
|
||||||
|
return (V) values().getOrDefault(type, type.defaultOrSupply(defaultValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of option.
|
||||||
|
*
|
||||||
|
* @param type {@link ConfigurationMetadata}
|
||||||
|
* @param defaultValue Default value if the value of option is not set.
|
||||||
|
* @param <V> Value type
|
||||||
|
* @return Value of option
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Contract("_,!null -> !null")
|
||||||
|
public <V> @Nullable V get(@NotNull ConfigurationMetadata<V> type, Supplier<@Nullable V> defaultValue) {
|
||||||
|
return (V) values().getOrDefault(type, type.defaultOrSupply(defaultValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of option.
|
||||||
|
*
|
||||||
|
* @param type {@link ConfigurationMetadata}
|
||||||
|
* @param <V> Value type
|
||||||
|
* @return Value of option
|
||||||
|
*/
|
||||||
|
public <V> @Nullable V get(@NotNull ConfigurationMetadata<V> type) {
|
||||||
|
return get(type, (V) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(@NotNull ConfigurationMetadata<?> type) {
|
||||||
|
return values().containsKey(type) || type.hasDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of meta, if the value is null, the meta will be removed.
|
||||||
|
* <br> Will only be changed in current holder.
|
||||||
|
*
|
||||||
|
* @param type {@link ConfigurationMetadata}
|
||||||
|
* @param value Value of meta
|
||||||
|
* @param <V> Value type
|
||||||
|
* @return Previous value of meta
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <V> @Nullable V set(@NotNull ConfigurationMetadata<V> type, @Nullable V value) {
|
||||||
|
if (value == null || type.isDefault(value)) {
|
||||||
|
return (V) values().remove(type);
|
||||||
|
} else {
|
||||||
|
return (V) values().put(type, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of meta, if the value is null, the meta will not be changed.
|
||||||
|
* <br> Will only be changed in current holder.
|
||||||
|
*
|
||||||
|
* @param type {@link ConfigurationMetadata}
|
||||||
|
* @param value Value of meta
|
||||||
|
* @param <V> Value type
|
||||||
|
*/
|
||||||
|
public <V> void setIfAbsent(@NotNull ConfigurationMetadata<V> type, @Nullable V value) {
|
||||||
|
if (value == null || type.isDefault(value)) {
|
||||||
|
values().remove(type);
|
||||||
|
} else {
|
||||||
|
values().putIfAbsent(type, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of meta, if the value is null, the meta will not be changed.
|
||||||
|
* <br> Will only be changed in current holder.
|
||||||
|
*
|
||||||
|
* @param type {@link ConfigurationMetadata}
|
||||||
|
* @param value Value of meta
|
||||||
|
* @param <V> Value type
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <V> @Nullable V setIfPresent(@NotNull ConfigurationMetadata<V> type, @Nullable V value) {
|
||||||
|
Object exists = values().get(type);
|
||||||
|
if (exists == null) return null;
|
||||||
|
|
||||||
|
if (value == null || type.isDefault(value)) {
|
||||||
|
return (V) values().remove(type);
|
||||||
|
} else {
|
||||||
|
return (V) values().put(type, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package cc.carm.lib.configuration.source.meta;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class ConfigurationMetadata<T> {
|
||||||
|
|
||||||
|
public static <T> ConfigurationMetadata<T> of() {
|
||||||
|
return of(() -> null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ConfigurationMetadata<T> of(T defaults) {
|
||||||
|
return of(() -> defaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ConfigurationMetadata<T> of(@NotNull Supplier<@Nullable T> defaults) {
|
||||||
|
return new ConfigurationMetadata<>(defaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Supplier<@Nullable T> defaultsSupplier;
|
||||||
|
|
||||||
|
public ConfigurationMetadata(@NotNull Supplier<@Nullable T> defaults) {
|
||||||
|
this.defaultsSupplier = defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDefault(@NotNull T value) {
|
||||||
|
return value.equals(defaults());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasDefaults() {
|
||||||
|
return defaults() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T defaultOrSupply(@Nullable T suppliedValue) {
|
||||||
|
return defaultOrSupply(() -> suppliedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T defaultOrSupply(Supplier<@Nullable T> suppliedValue) {
|
||||||
|
T defaults = defaults();
|
||||||
|
return defaults == null ? suppliedValue.get() : defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable T defaults() {
|
||||||
|
return defaultsSupplier.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaults(Supplier<T> defaultFunction) {
|
||||||
|
this.defaultsSupplier = defaultFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaults(T value) {
|
||||||
|
setDefaults(() -> value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+5
-5
@@ -9,7 +9,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
|
|
||||||
public class ConfigurationOptionHolder {
|
public class ConfigurationOptionHolder {
|
||||||
|
|
||||||
public static <V> @NotNull ConfigurationOptionHolder of(@NotNull Map<ConfigurationOption<V>, V> options) {
|
public static @NotNull ConfigurationOptionHolder of(@NotNull Map<ConfigurationOption<?>, Object> options) {
|
||||||
return new ConfigurationOptionHolder(new ConcurrentHashMap<>(options));
|
return new ConfigurationOptionHolder(new ConcurrentHashMap<>(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ public class ConfigurationOptionHolder {
|
|||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Map<ConfigurationOption<?>, Object> options() {
|
public @NotNull Map<ConfigurationOption<?>, Object> values() {
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ public class ConfigurationOptionHolder {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <V> @NotNull V get(@NotNull ConfigurationOption<V> type) {
|
public <V> @NotNull V get(@NotNull ConfigurationOption<V> type) {
|
||||||
return Optional.ofNullable(options().get(type)).map(v -> (V) v).orElseGet(type::defaults);
|
return Optional.ofNullable(values().get(type)).map(v -> (V) v).orElseGet(type::defaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,9 +50,9 @@ public class ConfigurationOptionHolder {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <V> @Nullable V set(@NotNull ConfigurationOption<V> type, @Nullable V value) {
|
public <V> @Nullable V set(@NotNull ConfigurationOption<V> type, @Nullable V value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return (V) options().remove(type);
|
return (V) values().remove(type);
|
||||||
} else {
|
} else {
|
||||||
return (V) options().put(type, value);
|
return (V) values().put(type, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import cc.carm.lib.configuration.Configuration;
|
|||||||
|
|
||||||
import static cc.carm.lib.configuration.source.option.ConfigurationOption.of;
|
import static cc.carm.lib.configuration.source.option.ConfigurationOption.of;
|
||||||
|
|
||||||
public interface ConfigurationOptions {
|
public interface StandardOptions {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration path separator.
|
* The configuration path separator.
|
||||||
+20
-20
@@ -1,6 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.source.section;
|
package cc.carm.lib.configuration.source.section;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -41,18 +41,18 @@ public interface ConfigurationSection {
|
|||||||
return get(path, null, clazz);
|
return get(path, null, clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
default @Nullable <T> T get(@NotNull String path, @NotNull ConfigDataFunction<Object, T> parser) {
|
default @Nullable <T> T get(@NotNull String path, @NotNull DataFunction<Object, T> parser) {
|
||||||
return get(path, null, parser);
|
return get(path, null, parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_,!null,_->!null")
|
@Contract("_,!null,_->!null")
|
||||||
default @Nullable <T> T get(@NotNull String path, @Nullable T defaultValue, @NotNull Class<T> clazz) {
|
default @Nullable <T> T get(@NotNull String path, @Nullable T defaultValue, @NotNull Class<T> clazz) {
|
||||||
return get(path, defaultValue, ConfigDataFunction.castObject(clazz));
|
return get(path, defaultValue, DataFunction.castObject(clazz));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_,!null,_->!null")
|
@Contract("_,!null,_->!null")
|
||||||
default @Nullable <T> T get(@NotNull String path, @Nullable T defaultValue,
|
default @Nullable <T> T get(@NotNull String path, @Nullable T defaultValue,
|
||||||
@NotNull ConfigDataFunction<Object, T> parser) {
|
@NotNull DataFunction<Object, T> parser) {
|
||||||
Object value = get(path);
|
Object value = get(path);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
try {
|
try {
|
||||||
@@ -75,7 +75,7 @@ public interface ConfigurationSection {
|
|||||||
|
|
||||||
@Contract("_, !null -> !null")
|
@Contract("_, !null -> !null")
|
||||||
default @Nullable Boolean getBoolean(@NotNull String path, @Nullable Boolean def) {
|
default @Nullable Boolean getBoolean(@NotNull String path, @Nullable Boolean def) {
|
||||||
return get(path, def, ConfigDataFunction.booleanValue());
|
return get(path, def, DataFunction.booleanValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
default @Nullable Boolean isByte(@NotNull String path) {
|
default @Nullable Boolean isByte(@NotNull String path) {
|
||||||
@@ -88,7 +88,7 @@ public interface ConfigurationSection {
|
|||||||
|
|
||||||
@Contract("_, !null -> !null")
|
@Contract("_, !null -> !null")
|
||||||
default @Nullable Byte getByte(@NotNull String path, @Nullable Byte def) {
|
default @Nullable Byte getByte(@NotNull String path, @Nullable Byte def) {
|
||||||
return get(path, def, ConfigDataFunction.byteValue());
|
return get(path, def, DataFunction.byteValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean isShort(@NotNull String path) {
|
default boolean isShort(@NotNull String path) {
|
||||||
@@ -101,7 +101,7 @@ public interface ConfigurationSection {
|
|||||||
|
|
||||||
@Contract("_, !null -> !null")
|
@Contract("_, !null -> !null")
|
||||||
default @Nullable Short getShort(@NotNull String path, @Nullable Short def) {
|
default @Nullable Short getShort(@NotNull String path, @Nullable Short def) {
|
||||||
return get(path, def, ConfigDataFunction.shortValue());
|
return get(path, def, DataFunction.shortValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ public interface ConfigurationSection {
|
|||||||
|
|
||||||
@Contract("_, !null -> !null")
|
@Contract("_, !null -> !null")
|
||||||
default @Nullable Integer getInt(@NotNull String path, @Nullable Integer def) {
|
default @Nullable Integer getInt(@NotNull String path, @Nullable Integer def) {
|
||||||
return get(path, def, ConfigDataFunction.intValue());
|
return get(path, def, DataFunction.intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ public interface ConfigurationSection {
|
|||||||
|
|
||||||
@Contract("_, !null -> !null")
|
@Contract("_, !null -> !null")
|
||||||
default @Nullable Long getLong(@NotNull String path, @Nullable Long def) {
|
default @Nullable Long getLong(@NotNull String path, @Nullable Long def) {
|
||||||
return get(path, def, ConfigDataFunction.longValue());
|
return get(path, def, DataFunction.longValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ public interface ConfigurationSection {
|
|||||||
|
|
||||||
@Contract("_, !null -> !null")
|
@Contract("_, !null -> !null")
|
||||||
default @Nullable Float getFloat(@NotNull String path, @Nullable Float def) {
|
default @Nullable Float getFloat(@NotNull String path, @Nullable Float def) {
|
||||||
return get(path, def, ConfigDataFunction.floatValue());
|
return get(path, def, DataFunction.floatValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ public interface ConfigurationSection {
|
|||||||
|
|
||||||
@Contract("_, !null -> !null")
|
@Contract("_, !null -> !null")
|
||||||
default @Nullable Double getDouble(@NotNull String path, @Nullable Double def) {
|
default @Nullable Double getDouble(@NotNull String path, @Nullable Double def) {
|
||||||
return get(path, def, ConfigDataFunction.doubleValue());
|
return get(path, def, DataFunction.doubleValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -188,47 +188,47 @@ public interface ConfigurationSection {
|
|||||||
return get(path, def, String.class);
|
return get(path, def, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
default <V> @NotNull List<V> getList(@NotNull String path, @NotNull ConfigDataFunction<Object, V> parser) {
|
default <V> @NotNull List<V> getList(@NotNull String path, @NotNull DataFunction<Object, V> parser) {
|
||||||
return parseList(getList(path), parser);
|
return parseList(getList(path), parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unmodifiable
|
@Unmodifiable
|
||||||
default @NotNull List<String> getStringList(@NotNull String path) {
|
default @NotNull List<String> getStringList(@NotNull String path) {
|
||||||
return getList(path, ConfigDataFunction.castToString());
|
return getList(path, DataFunction.castToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unmodifiable
|
@Unmodifiable
|
||||||
default @NotNull List<Integer> getIntegerList(@NotNull String path) {
|
default @NotNull List<Integer> getIntegerList(@NotNull String path) {
|
||||||
return getList(path, ConfigDataFunction.intValue());
|
return getList(path, DataFunction.intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unmodifiable
|
@Unmodifiable
|
||||||
default @NotNull List<Long> getLongList(@NotNull String path) {
|
default @NotNull List<Long> getLongList(@NotNull String path) {
|
||||||
return getList(path, ConfigDataFunction.longValue());
|
return getList(path, DataFunction.longValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unmodifiable
|
@Unmodifiable
|
||||||
default @NotNull List<Double> getDoubleList(@NotNull String path) {
|
default @NotNull List<Double> getDoubleList(@NotNull String path) {
|
||||||
return getList(path, ConfigDataFunction.doubleValue());
|
return getList(path, DataFunction.doubleValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unmodifiable
|
@Unmodifiable
|
||||||
default @NotNull List<Float> getFloatList(@NotNull String path) {
|
default @NotNull List<Float> getFloatList(@NotNull String path) {
|
||||||
return getList(path, ConfigDataFunction.floatValue());
|
return getList(path, DataFunction.floatValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unmodifiable
|
@Unmodifiable
|
||||||
default @NotNull List<Byte> getByteList(@NotNull String path) {
|
default @NotNull List<Byte> getByteList(@NotNull String path) {
|
||||||
return getList(path, ConfigDataFunction.byteValue());
|
return getList(path, DataFunction.byteValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unmodifiable
|
@Unmodifiable
|
||||||
default @NotNull List<Character> getCharList(@NotNull String path) {
|
default @NotNull List<Character> getCharList(@NotNull String path) {
|
||||||
return getList(path, ConfigDataFunction.castObject(Character.class));
|
return getList(path, DataFunction.castObject(Character.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unmodifiable
|
@Unmodifiable
|
||||||
static <T> @NotNull List<T> parseList(@Nullable List<?> list, ConfigDataFunction<Object, T> parser) {
|
static <T> @NotNull List<T> parseList(@Nullable List<?> list, DataFunction<Object, T> parser) {
|
||||||
if (list == null) return Collections.emptyList();
|
if (list == null) return Collections.emptyList();
|
||||||
List<T> values = new ArrayList<>();
|
List<T> values = new ArrayList<>();
|
||||||
for (Object o : list) {
|
for (Object o : list) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.Optional;
|
|||||||
public abstract class ConfigValue<T> extends ValueManifest<T> {
|
public abstract class ConfigValue<T> extends ValueManifest<T> {
|
||||||
|
|
||||||
protected ConfigValue(@NotNull ValueManifest<T> manifest) {
|
protected ConfigValue(@NotNull ValueManifest<T> manifest) {
|
||||||
super(manifest.type, manifest.provider, manifest.path, manifest.defaultSupplier);
|
super(manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,7 +37,7 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
|
|||||||
* @throws NullPointerException 对应数据为空时抛出
|
* @throws NullPointerException 对应数据为空时抛出
|
||||||
*/
|
*/
|
||||||
public @NotNull T getNotNull() {
|
public @NotNull T getNotNull() {
|
||||||
return Objects.requireNonNull(getOrDefault(), "Value(" + path() + ") [" + type() + "] is null.");
|
return Objects.requireNonNull(getOrDefault(), "Value(" + type() + ") @[" + path() + "] is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Optional<@Nullable T> optional() {
|
public @NotNull Optional<@Nullable T> optional() {
|
||||||
@@ -80,4 +80,16 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
|
|||||||
return Objects.equals(defaults(), get());
|
return Objects.equals(defaults(), get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to save the configuration.
|
||||||
|
* <br>To save multiple modifications,
|
||||||
|
* it is recommended to call {@link ConfigurationProvider#save()}
|
||||||
|
* after all modifications are completed instead of this.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void save() throws Exception {
|
||||||
|
provider().save();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,41 +2,65 @@ package cc.carm.lib.configuration.value;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
||||||
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSource;
|
import cc.carm.lib.configuration.source.section.ConfigurationSource;
|
||||||
import cc.carm.lib.configuration.meta.PathMetadata;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ValueManifest<T> {
|
public class ValueManifest<T> {
|
||||||
|
|
||||||
protected final @NotNull ValueType<T> type;
|
protected final @NotNull ValueType<T> type;
|
||||||
|
protected final @NotNull BiConsumer<@NotNull ConfigurationProvider<?>, @NotNull String> initializer;
|
||||||
|
|
||||||
protected @Nullable ConfigurationProvider<?> provider;
|
protected @Nullable ConfigurationProvider<?> provider;
|
||||||
protected @Nullable String path; // Section path
|
protected @Nullable String path; // Section path
|
||||||
|
|
||||||
protected @NotNull Supplier<@Nullable T> defaultSupplier;
|
protected @NotNull Supplier<@Nullable T> defaultSupplier;
|
||||||
|
|
||||||
public ValueManifest(ValueType<T> type) {
|
|
||||||
this(type, null, null, () -> null);
|
public ValueManifest(@NotNull ValueType<T> type) {
|
||||||
|
this(type, () -> null, EMPTY_INITIALIZER, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueManifest(@NotNull T defaultValue) {
|
public ValueManifest(@NotNull T defaultValue) {
|
||||||
this(ValueType.of(defaultValue), null, null, () -> defaultValue);
|
this(ValueType.of(defaultValue), () -> defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier) {
|
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier) {
|
||||||
this(type, null, null, defaultSupplier);
|
this(type, defaultSupplier, EMPTY_INITIALIZER, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueManifest(@NotNull ValueType<T> type,
|
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier,
|
||||||
@Nullable ConfigurationProvider<?> provider, @Nullable String path,
|
@NotNull BiConsumer<@NotNull ConfigurationProvider<?>, @NotNull String> initializer) {
|
||||||
@NotNull Supplier<@Nullable T> defaultSupplier) {
|
this(type, defaultSupplier, initializer, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier,
|
||||||
|
@NotNull BiConsumer<@NotNull ConfigurationProvider<?>, @NotNull String> initializer,
|
||||||
|
@Nullable ConfigurationProvider<?> provider, @Nullable String path) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.initializer = initializer;
|
||||||
|
this.defaultSupplier = defaultSupplier;
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.defaultSupplier = defaultSupplier;
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ValueManifest(@NotNull ValueManifest<T> manifest) {
|
||||||
|
this(manifest.type, manifest.defaultSupplier, manifest.initializer, manifest.provider, manifest.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize(@NotNull ConfigurationProvider<?> provider, @NotNull String path) {
|
||||||
|
this.provider = provider;
|
||||||
|
this.path = path;
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initialize() {
|
||||||
|
if (provider != null && path != null) this.initializer.accept(provider, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ValueType<T> type() {
|
public @NotNull ValueType<T> type() {
|
||||||
@@ -81,6 +105,10 @@ public class ValueManifest<T> {
|
|||||||
return provider().source();
|
return provider().source();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConfigurationMetaHolder metadata() {
|
||||||
|
return provider().metadata(path());
|
||||||
|
}
|
||||||
|
|
||||||
protected Object getData() {
|
protected Object getData() {
|
||||||
return config().get(path());
|
return config().get(path());
|
||||||
}
|
}
|
||||||
@@ -89,8 +117,8 @@ public class ValueManifest<T> {
|
|||||||
config().set(path(), value);
|
config().set(path(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<PathMetadata<?>, Object> metadata() {
|
|
||||||
return provider().metadata(path());
|
private static final @NotNull BiConsumer<@NotNull ConfigurationProvider<?>, @NotNull String> EMPTY_INITIALIZER = (provider, path) -> {
|
||||||
}
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
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.adapter.strandard.PrimitiveAdapters;
|
import cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapter;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationLoader;
|
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
|
||||||
import cc.carm.test.config.TestSource;
|
import cc.carm.test.config.TestSource;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class AdaptTest {
|
public class AdaptTest {
|
||||||
@@ -20,8 +17,8 @@ public class AdaptTest {
|
|||||||
public void test() throws Exception {
|
public void test() throws Exception {
|
||||||
|
|
||||||
ValueAdapterRegistry registry = new ValueAdapterRegistry();
|
ValueAdapterRegistry registry = new ValueAdapterRegistry();
|
||||||
registry.register(PrimitiveAdapters.ADAPTERS);
|
registry.register(PrimitiveAdapter.ADAPTERS);
|
||||||
registry.register(PrimitiveAdapters.ofEnum());
|
registry.register(PrimitiveAdapter.ofEnum());
|
||||||
|
|
||||||
|
|
||||||
registry.register(ValueType.of(Long.class), ValueType.of(Duration.class), Duration::ofMillis, Duration::toMillis);
|
registry.register(ValueType.of(Long.class), ValueType.of(Duration.class), Duration::ofMillis, Duration::toMillis);
|
||||||
@@ -32,8 +29,8 @@ public class AdaptTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
ConfigurationProvider<TestSource> provider = new ConfigurationProvider<>(
|
ConfigurationProvider<TestSource> provider = new ConfigurationProvider<>(
|
||||||
new TestSource(), new ConfigurationLoader(),
|
new TestSource(), registry, new ConfigurationOptionHolder(),
|
||||||
registry, new ConfigurationOptionHolder(), new ConcurrentHashMap<>()
|
new ConcurrentHashMap<>(), new ConfigurationInitializer()
|
||||||
);
|
);
|
||||||
|
|
||||||
LocalTime v = registry.deserialize(provider, LocalTime.class, 600000L);
|
LocalTime v = registry.deserialize(provider, LocalTime.class, 600000L);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import cc.carm.lib.configuration.source.loader.PathGenerator;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class NameTest {
|
public class NameTest {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
|
|||||||
import cc.carm.lib.configuration.annotation.ConfigPath;
|
import cc.carm.lib.configuration.annotation.ConfigPath;
|
||||||
import cc.carm.lib.configuration.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationLoader;
|
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -14,10 +14,13 @@ public class LoaderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() throws Exception {
|
public void test() throws Exception {
|
||||||
ConfigurationProvider<TestSource> provider = new ConfigurationProvider<>(new TestSource(), new ConfigurationLoader(), new ValueAdapterRegistry(), new ConfigurationOptionHolder(), new ConcurrentHashMap<>());
|
ConfigurationProvider<TestSource> provider = new ConfigurationProvider<>(
|
||||||
|
new TestSource(), new ValueAdapterRegistry(), new ConfigurationOptionHolder(),
|
||||||
|
new ConcurrentHashMap<>(), new ConfigurationInitializer()
|
||||||
|
);
|
||||||
|
|
||||||
ConfigurationLoader loader = new ConfigurationLoader();
|
ConfigurationInitializer loader = new ConfigurationInitializer();
|
||||||
loader.load(provider, ROOT.class);
|
loader.initialize(provider, ROOT.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ROOT extends Configuration {
|
interface ROOT extends Configuration {
|
||||||
|
|||||||
+20
-3
@@ -2,8 +2,12 @@ package cc.carm.lib.configuration.commentable;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.annotation.HeaderComment;
|
import cc.carm.lib.configuration.annotation.HeaderComment;
|
||||||
import cc.carm.lib.configuration.annotation.InlineComment;
|
import cc.carm.lib.configuration.annotation.InlineComment;
|
||||||
import cc.carm.lib.configuration.meta.PathMetadata;
|
import cc.carm.lib.configuration.source.ConfigurationProvider;
|
||||||
|
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||||
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -12,11 +16,24 @@ public interface CommentableMetaTypes {
|
|||||||
/**
|
/**
|
||||||
* Configuration's {@link HeaderComment}
|
* Configuration's {@link HeaderComment}
|
||||||
*/
|
*/
|
||||||
PathMetadata<List<String>> HEADER_COMMENTS = PathMetadata.of(Collections.emptyList());
|
ConfigurationMetadata<List<String>> HEADER_COMMENTS = ConfigurationMetadata.of(Collections.emptyList());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration's {@link InlineComment}
|
* Configuration's {@link InlineComment}
|
||||||
*/
|
*/
|
||||||
PathMetadata<String> INLINE_COMMENT_VALUE = PathMetadata.of();
|
ConfigurationMetadata<String> INLINE_COMMENT = ConfigurationMetadata.of();
|
||||||
|
|
||||||
|
|
||||||
|
static void register(@NotNull ConfigurationProvider<?> provider) {
|
||||||
|
register(provider.initializer());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void register(@NotNull ConfigurationInitializer initializer) {
|
||||||
|
initializer.registerAnnotation(
|
||||||
|
HeaderComment.class, HEADER_COMMENTS,
|
||||||
|
a -> Arrays.asList(a.value())
|
||||||
|
);
|
||||||
|
initializer.registerAnnotation(InlineComment.class, INLINE_COMMENT, InlineComment::value);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-48
@@ -1,48 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.commentable;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.annotations.Unmodifiable;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class ConfigurationComments {
|
|
||||||
|
|
||||||
protected final @NotNull Map<String, List<String>> headerComments = new HashMap<>();
|
|
||||||
protected final @NotNull Map<String, String> inlineComments = new HashMap<>();
|
|
||||||
|
|
||||||
protected @NotNull Map<String, List<String>> getHeaderComments() {
|
|
||||||
return headerComments;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected @NotNull Map<String, String> getInlineComments() {
|
|
||||||
return inlineComments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeaderComments(@Nullable String path, @Nullable List<String> comments) {
|
|
||||||
if (comments == null) {
|
|
||||||
getHeaderComments().remove(path);
|
|
||||||
} else {
|
|
||||||
getHeaderComments().put(path, comments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInlineComment(@NotNull String path, @Nullable String comment) {
|
|
||||||
if (comment == null) {
|
|
||||||
getInlineComments().remove(path);
|
|
||||||
} else {
|
|
||||||
getInlineComments().put(path, comment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Unmodifiable
|
|
||||||
public List<String> getHeaderComment(@Nullable String path) {
|
|
||||||
return Optional.ofNullable(getHeaderComments().get(path)).map(Collections::unmodifiableList).orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable String getInlineComment(@NotNull String path) {
|
|
||||||
return getInlineComments().get(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package cc.carm.lib.configuration.source;
|
package cc.carm.lib.configuration.source;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
|
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
|
||||||
import cc.carm.lib.configuration.meta.PathMetadata;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationLoader;
|
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSource;
|
import cc.carm.lib.configuration.source.section.ConfigurationSource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -11,9 +11,9 @@ import java.util.Map;
|
|||||||
|
|
||||||
public abstract class FileProvider<S extends ConfigurationSource<S, ?>> extends ConfigurationProvider<S> {
|
public abstract class FileProvider<S extends ConfigurationSource<S, ?>> extends ConfigurationProvider<S> {
|
||||||
|
|
||||||
public FileProvider(@NotNull S source, @NotNull ConfigurationLoader loader,
|
public FileProvider(@NotNull S source, @NotNull ConfigurationInitializer loader,
|
||||||
@NotNull ValueAdapterRegistry adapters, @NotNull ConfigurationOptionHolder options,
|
@NotNull ValueAdapterRegistry adapters, @NotNull ConfigurationOptionHolder options,
|
||||||
@NotNull Map<String, Map<PathMetadata<?>, Object>> pathMetadata) {
|
@NotNull Map<String, Map<ConfigurationMetadata<?>, Object>> pathMetadata) {
|
||||||
super(source, loader, adapters, options, pathMetadata);
|
super(source, loader, adapters, options, pathMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user