mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 10:38:19 +08:00
feat(json): Implement json sources
This commit is contained in:
@@ -55,13 +55,13 @@ public class ValueAdapter<TYPE>
|
|||||||
@Override
|
@Override
|
||||||
public Object serialize(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<? super TYPE> type, @NotNull TYPE value) throws Exception {
|
public Object serialize(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<? super TYPE> type, @NotNull TYPE value) throws Exception {
|
||||||
if (serializer == null) throw new UnsupportedOperationException("Serializer is not supported");
|
if (serializer == null) throw new UnsupportedOperationException("Serializer is not supported");
|
||||||
return serializer.serialize(provider, type, value);
|
return serializer.serialize(holder, type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TYPE parse(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<? super TYPE> type, @NotNull Object value) throws Exception {
|
public TYPE parse(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<? super TYPE> type, @NotNull Object value) throws Exception {
|
||||||
if (deserializer == null) throw new UnsupportedOperationException("Deserializer is not supported");
|
if (deserializer == null) throw new UnsupportedOperationException("Deserializer is not supported");
|
||||||
return deserializer.parse(provider, type, value);
|
return deserializer.parse(holder, type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class ValueAdapterRegistry {
|
|||||||
|
|
||||||
@Contract("_,_,null -> null")
|
@Contract("_,_,null -> null")
|
||||||
public <T> T deserialize(@NotNull ConfigurationHolder<?> holder, @NotNull Class<T> type, @Nullable Object source) throws Exception {
|
public <T> T deserialize(@NotNull ConfigurationHolder<?> holder, @NotNull Class<T> type, @Nullable Object source) throws Exception {
|
||||||
return deserialize(provider, ValueType.of(type), source);
|
return deserialize(holder, ValueType.of(type), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_,_,null -> null")
|
@Contract("_,_,null -> null")
|
||||||
@@ -110,7 +110,7 @@ public class ValueAdapterRegistry {
|
|||||||
if (type.isInstance(source)) return type.cast(source); // Not required to deserialize
|
if (type.isInstance(source)) return type.cast(source); // Not required to deserialize
|
||||||
ValueAdapter<T> adapter = adapterOf(type);
|
ValueAdapter<T> adapter = adapterOf(type);
|
||||||
if (adapter == null) throw new RuntimeException("No adapter for type " + type);
|
if (adapter == null) throw new RuntimeException("No adapter for type " + type);
|
||||||
return adapter.parse(provider, type, source);
|
return adapter.parse(holder, type, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("_,null -> null")
|
@Contract("_,null -> null")
|
||||||
@@ -119,7 +119,7 @@ public class ValueAdapterRegistry {
|
|||||||
ValueType<T> type = ValueType.of(value);
|
ValueType<T> type = ValueType.of(value);
|
||||||
ValueAdapter<T> adapter = adapterOf(type);
|
ValueAdapter<T> adapter = adapterOf(type);
|
||||||
if (adapter == null) return value; // No adapters, try to return the original value
|
if (adapter == null) return value; // No adapters, try to return the original value
|
||||||
return adapter.serialize(provider, type, value);
|
return adapter.serialize(holder, type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package cc.carm.lib.configuration.adapter;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@@ -12,12 +11,45 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
public abstract class ValueType<T> {
|
public abstract class ValueType<T> {
|
||||||
|
|
||||||
|
public static final ValueType<String> STRING = ofPrimitiveType(String.class);
|
||||||
|
public static final ValueType<Integer> INTEGER = ofPrimitiveType(Integer.class);
|
||||||
|
public static final ValueType<Integer> INTEGER_TYPE = ofPrimitiveType(int.class);
|
||||||
|
public static final ValueType<Long> LONG = ofPrimitiveType(Long.class);
|
||||||
|
public static final ValueType<Long> LONG_TYPE = ofPrimitiveType(long.class);
|
||||||
|
public static final ValueType<Double> DOUBLE = ofPrimitiveType(Double.class);
|
||||||
|
public static final ValueType<Double> DOUBLE_TYPE = ofPrimitiveType(double.class);
|
||||||
|
public static final ValueType<Float> FLOAT = ofPrimitiveType(Float.class);
|
||||||
|
public static final ValueType<Float> FLOAT_TYPE = ofPrimitiveType(float.class);
|
||||||
|
public static final ValueType<Boolean> BOOLEAN = ofPrimitiveType(Boolean.class);
|
||||||
|
public static final ValueType<Boolean> BOOLEAN_TYPE = ofPrimitiveType(boolean.class);
|
||||||
|
public static final ValueType<Byte> BYTE = ofPrimitiveType(Byte.class);
|
||||||
|
public static final ValueType<Byte> BYTE_TYPE = ofPrimitiveType(byte.class);
|
||||||
|
public static final ValueType<Short> SHORT = ofPrimitiveType(Short.class);
|
||||||
|
public static final ValueType<Short> SHORT_TYPE = ofPrimitiveType(short.class);
|
||||||
|
public static final ValueType<Character> CHAR = ofPrimitiveType(Character.class);
|
||||||
|
public static final ValueType<Character> CHAR_TYPE = ofPrimitiveType(char.class);
|
||||||
|
|
||||||
|
public static final ValueType<?>[] PRIMITIVE_TYPES = {
|
||||||
|
STRING, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, BYTE, SHORT, CHAR,
|
||||||
|
INTEGER_TYPE, LONG_TYPE, DOUBLE_TYPE, FLOAT_TYPE, BOOLEAN_TYPE, BYTE_TYPE, SHORT_TYPE, CHAR_TYPE
|
||||||
|
};
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> ValueType<T> of(@NotNull T value) {
|
public static <T> ValueType<T> of(@NotNull T value) {
|
||||||
return of((Class<T>) value.getClass());
|
return of((Class<T>) value.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> ValueType<T> of(final Type type) {
|
public static <T> ValueType<T> of(final Type type) {
|
||||||
|
if (type == null) throw new NullPointerException("Type cannot be null");
|
||||||
|
if (type instanceof Class<?>) { // Try handle primitive types
|
||||||
|
Class<?> clazz = (Class<?>) type;
|
||||||
|
for (ValueType<?> valueType : PRIMITIVE_TYPES) {
|
||||||
|
if (valueType.getRawType() == clazz) {
|
||||||
|
return (ValueType<T>) valueType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return new ValueType<T>(type) {
|
return new ValueType<T>(type) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -54,6 +86,11 @@ public abstract class ValueType<T> {
|
|||||||
return of(parameterizedType);
|
return of(parameterizedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <T> ValueType<T> ofPrimitiveType(Class<T> clazz) {
|
||||||
|
return new ValueType<T>(clazz) {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private final Type type;
|
private final Type type;
|
||||||
|
|
||||||
protected ValueType() {
|
protected ValueType() {
|
||||||
@@ -139,6 +176,9 @@ public abstract class ValueType<T> {
|
|||||||
if (obj instanceof ValueType) {
|
if (obj instanceof ValueType) {
|
||||||
return Objects.equals(type, ((ValueType<?>) obj).type);
|
return Objects.equals(type, ((ValueType<?>) obj).type);
|
||||||
}
|
}
|
||||||
|
if (obj instanceof Type) {
|
||||||
|
return Objects.equals(type, obj);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -2,16 +2,16 @@ 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.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
|
|
||||||
public interface StandardAdapters {
|
public interface StandardAdapters {
|
||||||
|
|
||||||
ValueAdapter<ConfigurationSection> SECTION_ADAPTER = new ValueAdapter<>(
|
ValueAdapter<ConfigureSection> SECTION_ADAPTER = new ValueAdapter<>(
|
||||||
ValueType.of(ConfigurationSection.class),
|
ValueType.of(ConfigureSection.class),
|
||||||
(provider, type, value) -> value,
|
(provider, type, value) -> value,
|
||||||
(provider, type, value) -> {
|
(provider, type, value) -> {
|
||||||
if (value instanceof ConfigurationSection) {
|
if (value instanceof ConfigureSection) {
|
||||||
return (ConfigurationSection) value;
|
return (ConfigureSection) value;
|
||||||
} else throw new IllegalArgumentException("Value is not a ConfigurationSection");
|
} else throw new IllegalArgumentException("Value is not a ConfigurationSection");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
+13
-13
@@ -5,7 +5,7 @@ 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.DataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import cc.carm.lib.configuration.function.ValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
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,39 +21,39 @@ public abstract class AbstractSectionBuilder<
|
|||||||
|
|
||||||
protected final @NotNull ValueType<PARAM> paramType;
|
protected final @NotNull ValueType<PARAM> paramType;
|
||||||
|
|
||||||
protected @NotNull ValueHandler<ConfigurationSection, PARAM> parser;
|
protected @NotNull ValueHandler<ConfigureSection, PARAM> parser;
|
||||||
protected @NotNull ValueHandler<PARAM, ? extends Map<Object, Object>> serializer;
|
protected @NotNull ValueHandler<PARAM, ? extends Map<String, Object>> serializer;
|
||||||
|
|
||||||
public AbstractSectionBuilder(@NotNull ValueType<TYPE> type, @NotNull ValueType<PARAM> paramType,
|
public AbstractSectionBuilder(@NotNull ValueType<TYPE> type, @NotNull ValueType<PARAM> paramType,
|
||||||
@NotNull ValueHandler<ConfigurationSection, PARAM> parser,
|
@NotNull ValueHandler<ConfigureSection, PARAM> parser,
|
||||||
@NotNull ValueHandler<PARAM, ? extends Map<Object, Object>> serializer) {
|
@NotNull ValueHandler<PARAM, ? extends Map<String, 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(DataFunction<ConfigurationSection, PARAM> valueParser) {
|
public @NotNull SELF parse(DataFunction<ConfigureSection, PARAM> valueParser) {
|
||||||
return parse((p, section) -> valueParser.handle(section));
|
return parse((p, section) -> valueParser.handle(section));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(ValueHandler<ConfigurationSection, PARAM> valueParser) {
|
public @NotNull SELF parse(ValueHandler<ConfigureSection, PARAM> valueParser) {
|
||||||
this.parser = valueParser;
|
this.parser = valueParser;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(DataFunction<PARAM, ? extends Map<Object, Object>> serializer) {
|
public @NotNull SELF serialize(DataFunction<PARAM, ? extends Map<String, Object>> serializer) {
|
||||||
return serialize((p, value) -> serializer.handle(value));
|
return serialize((p, value) -> serializer.handle(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(ValueHandler<PARAM, ? extends Map<Object, Object>> serializer) {
|
public @NotNull SELF serialize(ValueHandler<PARAM, ? extends Map<String, Object>> serializer) {
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(Consumer<Map<Object, Object>> serializer) {
|
public @NotNull SELF serialize(Consumer<Map<String, Object>> serializer) {
|
||||||
return serialize((p, value) -> {
|
return serialize((p, value) -> {
|
||||||
Map<Object, Object> map = new LinkedHashMap<>();
|
Map<String, Object> map = new LinkedHashMap<>();
|
||||||
serializer.accept(map);
|
serializer.accept(map);
|
||||||
return map;
|
return map;
|
||||||
});
|
});
|
||||||
@@ -62,12 +62,12 @@ public abstract class AbstractSectionBuilder<
|
|||||||
protected ValueAdapter<PARAM> buildAdapter() {
|
protected ValueAdapter<PARAM> buildAdapter() {
|
||||||
return new ValueAdapter<>(this.paramType)
|
return new ValueAdapter<>(this.paramType)
|
||||||
.parser((p, type, data) -> {
|
.parser((p, type, data) -> {
|
||||||
ConfigurationSection section = p.deserialize(ConfigurationSection.class, data);
|
ConfigureSection section = p.deserialize(ConfigureSection.class, data);
|
||||||
if (section == null) return null;
|
if (section == null) return null;
|
||||||
return this.parser.handle(p, section);
|
return this.parser.handle(p, section);
|
||||||
})
|
})
|
||||||
.serializer((p, type, data) -> {
|
.serializer((p, type, data) -> {
|
||||||
Map<Object, Object> map = this.serializer.handle(p, data);
|
Map<String, Object> map = this.serializer.handle(p, data);
|
||||||
return map == null || map.isEmpty() ? null : map;
|
return map == null || map.isEmpty() ? null : map;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -49,13 +49,13 @@ public abstract class AbstractSourceBuilder<
|
|||||||
|
|
||||||
protected ValueAdapter<PARAM> buildAdapter() {
|
protected ValueAdapter<PARAM> buildAdapter() {
|
||||||
return new ValueAdapter<>(this.paramType)
|
return new ValueAdapter<>(this.paramType)
|
||||||
.parser((p, type, data) -> {
|
.parser((holder, type, data) -> {
|
||||||
SOURCE source = p.deserialize(this.sourceType, data);
|
SOURCE source = holder.deserialize(this.sourceType, data);
|
||||||
return this.valueParser.handle(p, source);
|
return this.valueParser.handle(holder, source);
|
||||||
})
|
})
|
||||||
.serializer((p, type, data) -> {
|
.serializer((holder, type, data) -> {
|
||||||
SOURCE source = this.valueSerializer.handle(p, data);
|
SOURCE source = this.valueSerializer.handle(holder, data);
|
||||||
return p.serialize(source);
|
return holder.serialize(source);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class ConfigListBuilder<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SourceListBuilder<String, V> fromString() {
|
public @NotNull SourceListBuilder<String, V> fromString() {
|
||||||
return from(String.class);
|
return new SourceListBuilder<>(ValueType.STRING, type, ValueHandler.required(), ValueHandler.stringValue(), ArrayList::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionListBuilder<V> fromSection() {
|
public @NotNull SectionListBuilder<V> fromSection() {
|
||||||
|
|||||||
@@ -3,7 +3,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.ValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
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 ValueHandler<ConfigurationSection, V> parser,
|
@NotNull ValueHandler<ConfigureSection, V> parser,
|
||||||
@NotNull ValueHandler<V, ? extends Map<Object, Object>> serializer,
|
@NotNull ValueHandler<V, ? extends Map<String, 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.value;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.function.ValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -30,7 +30,7 @@ public class ConfigValueBuilder<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SourceValueBuilder<String, V> fromString() {
|
public @NotNull SourceValueBuilder<String, V> fromString() {
|
||||||
return from(String.class);
|
return from(ValueType.STRING, ValueHandler.required(), ValueHandler.stringValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionValueBuilder<V> fromSection() {
|
public @NotNull SectionValueBuilder<V> fromSection() {
|
||||||
@@ -38,8 +38,8 @@ public class ConfigValueBuilder<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionValueBuilder<V> fromSection(
|
public @NotNull SectionValueBuilder<V> fromSection(
|
||||||
@NotNull ValueHandler<ConfigurationSection, V> valueParser,
|
@NotNull ValueHandler<ConfigureSection, V> valueParser,
|
||||||
@NotNull ValueHandler<V, ? extends Map<Object, Object>> valueSerializer
|
@NotNull ValueHandler<V, ? extends Map<String, Object>> valueSerializer
|
||||||
) {
|
) {
|
||||||
return new SectionValueBuilder<>(this.type, valueParser, valueSerializer);
|
return new SectionValueBuilder<>(this.type, valueParser, valueSerializer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,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.ValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
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 ValueHandler<ConfigurationSection, V> parser,
|
@NotNull ValueHandler<ConfigureSection, V> parser,
|
||||||
@NotNull ValueHandler<V, ? extends Map<Object, Object>> serializer) {
|
@NotNull ValueHandler<V, ? extends Map<String, Object>> serializer) {
|
||||||
super(type, type, parser, serializer);
|
super(type, type, parser, serializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ public interface ValueHandler<T, R> {
|
|||||||
return ConfigurationHolder::serialize;
|
return ConfigurationHolder::serialize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Contract(pure = true)
|
||||||
|
static <T> @NotNull ValueHandler<T, String> stringValue() {
|
||||||
|
return (provider, input) -> String.valueOf(input);
|
||||||
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T> @NotNull ValueHandler<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);
|
||||||
|
|||||||
@@ -1,46 +1,38 @@
|
|||||||
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.*;
|
||||||
|
import cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapter;
|
||||||
|
import cc.carm.lib.configuration.adapter.strandard.StandardAdapters;
|
||||||
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||||
import cc.carm.lib.configuration.source.loader.PathGenerator;
|
import cc.carm.lib.configuration.source.loader.PathGenerator;
|
||||||
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
||||||
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;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSource;
|
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public abstract class ConfigurationFactory<SOURCE extends ConfigurationSource<SOURCE, ?>, PROVIDER extends ConfigurationHolder<SOURCE>, SELF> {
|
public abstract class ConfigurationFactory<
|
||||||
|
SOURCE extends ConfigureSource<?, ?, SOURCE>,
|
||||||
protected Function<PROVIDER, ConfigurationInitializer> loaderFunction = PROVIDER -> new ConfigurationInitializer();
|
HOLDER extends ConfigurationHolder<SOURCE>,
|
||||||
protected Consumer<ConfigurationInitializer> loaderConsumer = loader -> {
|
SELF
|
||||||
};
|
> {
|
||||||
|
|
||||||
protected ValueAdapterRegistry adapters = new ValueAdapterRegistry();
|
protected ValueAdapterRegistry adapters = new ValueAdapterRegistry();
|
||||||
protected ConfigurationOptionHolder options = new ConfigurationOptionHolder();
|
protected ConfigurationOptionHolder options = new ConfigurationOptionHolder();
|
||||||
|
protected ConfigurationInitializer initializer = new ConfigurationInitializer();
|
||||||
|
|
||||||
|
public ConfigurationFactory() {
|
||||||
|
this.adapters.register(PrimitiveAdapter.ADAPTERS);
|
||||||
|
this.adapters.register(StandardAdapters.SECTION_ADAPTER);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract SELF self();
|
public abstract SELF self();
|
||||||
|
|
||||||
public SELF loader(Function<PROVIDER, ConfigurationInitializer> loaderFunction) {
|
|
||||||
this.loaderFunction = loaderFunction;
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SELF loader(ConfigurationInitializer loader) {
|
|
||||||
return loader(PROVIDER -> loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SELF loader(Consumer<ConfigurationInitializer> loaderConsumer) {
|
|
||||||
this.loaderConsumer = this.loaderConsumer.andThen(loaderConsumer);
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SELF pathGenerator(PathGenerator generator) {
|
|
||||||
return loader(loader -> {
|
|
||||||
loader.pathGenerator(generator);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public SELF adapters(ValueAdapterRegistry adapters) {
|
public SELF adapters(ValueAdapterRegistry adapters) {
|
||||||
this.adapters = adapters;
|
this.adapters = adapters;
|
||||||
@@ -52,18 +44,37 @@ public abstract class ConfigurationFactory<SOURCE extends ConfigurationSource<SO
|
|||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
// public SELF adapter(@NotNull ValueAdapter<?, ?> adapter) {
|
public <T> SELF adapter(@NotNull ValueAdapter<T> adapter) {
|
||||||
// return adapter(a -> a.register(adapter));
|
return adapter(a -> a.register(adapter));
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// public <T> SELF adapter(Class<T> clazz, @NotNull ValueAdapter<?, T> adapter) {
|
public <T> SELF adapter(@NotNull ValueType<T> type, @NotNull ValueSerializer<T> serializer) {
|
||||||
// return adapter(a -> a.register(clazz, adapter));
|
return adapter(a -> a.register(type, serializer));
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// public <B, V> SELF adapter(Class<B> baseClass, Class<V> valueClass,
|
public <T> SELF adapter(@NotNull ValueType<T> type, @NotNull ValueParser<T> parser) {
|
||||||
// ConfigDataFunction<B, V> parser, ConfigDataFunction<V, B> serializer) {
|
return adapter(a -> a.register(type, parser));
|
||||||
// return adapter(a -> a.register(baseClass, valueClass, parser, serializer));
|
}
|
||||||
// }
|
|
||||||
|
public <FROM, TO> SELF adapter(@NotNull Class<FROM> from, @NotNull Class<TO> to,
|
||||||
|
@NotNull DataFunction<FROM, TO> parser,
|
||||||
|
@NotNull DataFunction<TO, FROM> serializer) {
|
||||||
|
return adapter(a -> a.register(from, to, parser, serializer));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <FROM, TO> SELF adapter(@NotNull ValueType<FROM> from, @NotNull ValueType<TO> to,
|
||||||
|
@NotNull DataFunction<FROM, TO> parser,
|
||||||
|
@NotNull DataFunction<TO, FROM> serializer) {
|
||||||
|
return adapter(a -> a.register(from, to, parser, serializer));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> SELF adapter(@NotNull ValueType<T> type, @NotNull ValueSerializer<T> serializer, @NotNull ValueParser<T> parser) {
|
||||||
|
return adapter(a -> a.register(type, serializer, parser));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> SELF adapter(@NotNull Class<T> type, @NotNull ValueSerializer<T> serializer, @NotNull ValueParser<T> parser) {
|
||||||
|
return adapter(ValueType.of(type), serializer, parser);
|
||||||
|
}
|
||||||
|
|
||||||
public SELF options(ConfigurationOptionHolder options) {
|
public SELF options(ConfigurationOptionHolder options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
@@ -79,6 +90,29 @@ public abstract class ConfigurationFactory<SOURCE extends ConfigurationSource<SO
|
|||||||
return option(o -> o.set(option, value));
|
return option(o -> o.set(option, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract @NotNull PROVIDER build();
|
|
||||||
|
public SELF initializer(ConfigurationInitializer initializer) {
|
||||||
|
this.initializer = initializer;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF initializer(Consumer<ConfigurationInitializer> initializerConsumer) {
|
||||||
|
initializerConsumer.accept(initializer);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF pathGenerator(PathGenerator generator) {
|
||||||
|
return initializer(loader -> {
|
||||||
|
loader.pathGenerator(generator);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public <M, A extends Annotation> SELF metaAnnotation(@NotNull Class<A> annotation,
|
||||||
|
@NotNull ConfigurationMetadata<M> metadata,
|
||||||
|
@NotNull Function<A, M> extractor) {
|
||||||
|
return initializer(loader -> loader.registerAnnotation(annotation, metadata, extractor));
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract @NotNull HOLDER build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,15 @@ import cc.carm.lib.configuration.adapter.ValueType;
|
|||||||
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||||
import cc.carm.lib.configuration.source.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.ConfigureSource;
|
||||||
import cc.carm.lib.configuration.value.ValueManifest;
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
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;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class ConfigurationHolder<S extends ConfigurationSource<S, ?>> {
|
public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, SOURCE>> {
|
||||||
|
|
||||||
protected final @NotNull ValueAdapterRegistry adapters;
|
protected final @NotNull ValueAdapterRegistry adapters;
|
||||||
protected final @NotNull ConfigurationOptionHolder options;
|
protected final @NotNull ConfigurationOptionHolder options;
|
||||||
@@ -23,8 +22,6 @@ public class ConfigurationHolder<S extends ConfigurationSource<S, ?>> {
|
|||||||
|
|
||||||
protected final @NotNull ConfigurationInitializer initializer;
|
protected final @NotNull ConfigurationInitializer initializer;
|
||||||
|
|
||||||
protected @Nullable S source;
|
|
||||||
|
|
||||||
public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters,
|
public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters,
|
||||||
@NotNull ConfigurationOptionHolder options,
|
@NotNull ConfigurationOptionHolder options,
|
||||||
@NotNull Map<String, ConfigurationMetaHolder> metadata,
|
@NotNull Map<String, ConfigurationMetaHolder> metadata,
|
||||||
@@ -35,16 +32,14 @@ public class ConfigurationHolder<S extends ConfigurationSource<S, ?>> {
|
|||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull S source() {
|
public abstract @NotNull SOURCE config();
|
||||||
return Objects.requireNonNull(source, "Source is not initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reload() throws Exception {
|
public void reload() throws Exception {
|
||||||
source().reload();
|
config().reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save() throws Exception {
|
public void save() throws Exception {
|
||||||
source().save();
|
config().save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigurationOptionHolder options() {
|
public ConfigurationOptionHolder options() {
|
||||||
@@ -83,7 +78,7 @@ public class ConfigurationHolder<S extends ConfigurationSource<S, ?>> {
|
|||||||
return adapters().serialize(this, value);
|
return adapters().serialize(this, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load(Class<? extends Configuration> configClass) {
|
public void initialize(Class<? extends Configuration> configClass) {
|
||||||
try {
|
try {
|
||||||
initializer.initialize(this, configClass);
|
initializer.initialize(this, configClass);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -91,7 +86,7 @@ public class ConfigurationHolder<S extends ConfigurationSource<S, ?>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load(@NotNull Configuration config) {
|
public void initialize(@NotNull Configuration config) {
|
||||||
try {
|
try {
|
||||||
initializer.initialize(this, config);
|
initializer.initialize(this, config);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -99,7 +94,7 @@ public class ConfigurationHolder<S extends ConfigurationSource<S, ?>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load(@NotNull ValueManifest<?> value) {
|
public void initialize(@NotNull ValueManifest<?> value) {
|
||||||
value.holder(this);
|
value.holder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-23
@@ -70,49 +70,49 @@ public class ConfigurationInitializer {
|
|||||||
public <T, A extends Annotation> void registerAnnotation(@NotNull Class<A> annotation,
|
public <T, A extends Annotation> void registerAnnotation(@NotNull Class<A> annotation,
|
||||||
@NotNull ConfigurationMetadata<T> metadata,
|
@NotNull ConfigurationMetadata<T> metadata,
|
||||||
@NotNull Function<A, T> extractor) {
|
@NotNull Function<A, T> extractor) {
|
||||||
appendFieldInitializer((provider, path, field) -> {
|
appendFieldInitializer((holder, path, field) -> {
|
||||||
A data = field.getAnnotation(annotation);
|
A data = field.getAnnotation(annotation);
|
||||||
if (data == null) return;
|
if (data == null) return;
|
||||||
provider.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
holder.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
||||||
});
|
});
|
||||||
appendClassInitializer((provider, path, clazz) -> {
|
appendClassInitializer((holder, path, clazz) -> {
|
||||||
A data = clazz.getAnnotation(annotation);
|
A data = clazz.getAnnotation(annotation);
|
||||||
if (data == null) return;
|
if (data == null) return;
|
||||||
provider.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
holder.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public @Nullable String getFieldPath(ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) {
|
public @Nullable String getFieldPath(ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) {
|
||||||
return pathGenerator.getFieldPath(provider, parentPath, field);
|
return pathGenerator.getFieldPath(holder, parentPath, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable String getClassPath(ConfigurationHolder<?> holder, @Nullable String parentPath,
|
public @Nullable String getClassPath(ConfigurationHolder<?> holder, @Nullable String parentPath,
|
||||||
@NotNull Class<?> clazz, @Nullable Field clazzField) {
|
@NotNull Class<?> clazz, @Nullable Field clazzField) {
|
||||||
return pathGenerator.getClassPath(provider, parentPath, clazz, clazzField);
|
return pathGenerator.getClassPath(holder, parentPath, clazz, clazzField);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(ConfigurationHolder<?> holder, @NotNull Configuration config) throws Exception {
|
public void initialize(ConfigurationHolder<?> holder, @NotNull Configuration config) throws Exception {
|
||||||
initializeInstance(provider, config, null, null);
|
initializeInstance(holder, config, null, null);
|
||||||
if (provider.options().get(StandardOptions.SET_DEFAULTS)) provider.save();
|
if (holder.options().get(StandardOptions.SET_DEFAULTS)) holder.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(ConfigurationHolder<?> holder, @NotNull Class<? extends Configuration> clazz) throws Exception {
|
public void initialize(ConfigurationHolder<?> holder, @NotNull Class<? extends Configuration> clazz) throws Exception {
|
||||||
initializeStaticClass(provider, clazz, null, null);
|
initializeStaticClass(holder, clazz, null, null);
|
||||||
if (provider.options().get(StandardOptions.SET_DEFAULTS)) provider.save();
|
if (holder.options().get(StandardOptions.SET_DEFAULTS)) holder.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 针对实例类的初始化方法
|
// 针对实例类的初始化方法
|
||||||
protected void initializeInstance(@NotNull ConfigurationHolder<?> holder,
|
protected void initializeInstance(@NotNull ConfigurationHolder<?> holder,
|
||||||
@NotNull Configuration root, @Nullable String parentPath, @Nullable Field configField) {
|
@NotNull Configuration root, @Nullable String parentPath, @Nullable Field configField) {
|
||||||
String path = getClassPath(provider, parentPath, root.getClass(), configField);
|
String path = getClassPath(holder, parentPath, root.getClass(), configField);
|
||||||
try {
|
try {
|
||||||
this.classInitializer.whenInitialize(provider, path, root.getClass());
|
this.classInitializer.whenInitialize(holder, path, root.getClass());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
Arrays.stream(root.getClass().getDeclaredFields()).forEach(field -> initializeField(provider, root, field, path));
|
Arrays.stream(root.getClass().getDeclaredFields()).forEach(field -> initializeField(holder, root, field, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 针对静态类的初始化方法
|
// 针对静态类的初始化方法
|
||||||
@@ -121,22 +121,22 @@ public class ConfigurationInitializer {
|
|||||||
@NotNull Class<?> clazz, @Nullable String parentPath, @Nullable Field configField) {
|
@NotNull Class<?> clazz, @Nullable String parentPath, @Nullable Field configField) {
|
||||||
if (!Configuration.class.isAssignableFrom(clazz)) return; // 只解析继承了 ConfigurationRoot 的类
|
if (!Configuration.class.isAssignableFrom(clazz)) return; // 只解析继承了 ConfigurationRoot 的类
|
||||||
|
|
||||||
String path = getClassPath(provider, parentPath, clazz, configField);
|
String path = getClassPath(holder, parentPath, clazz, configField);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.classInitializer.whenInitialize(provider, path, (Class<? extends Configuration>) clazz);
|
this.classInitializer.whenInitialize(holder, path, (Class<? extends Configuration>) clazz);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Field field : clazz.getDeclaredFields()) {
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
initializeField(provider, clazz, field, path);
|
initializeField(holder, clazz, field, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (provider.options().get(StandardOptions.LOAD_SUB_CLASSES)) {
|
if (holder.options().get(StandardOptions.LOAD_SUB_CLASSES)) {
|
||||||
Class<?>[] classes = clazz.getDeclaredClasses();
|
Class<?>[] classes = clazz.getDeclaredClasses();
|
||||||
for (int i = classes.length - 1; i >= 0; i--) { // 逆向加载,保持顺序。
|
for (int i = classes.length - 1; i >= 0; i--) { // 逆向加载,保持顺序。
|
||||||
initializeStaticClass(provider, classes[i], path, null);
|
initializeStaticClass(holder, classes[i], path, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,20 +150,20 @@ public class ConfigurationInitializer {
|
|||||||
if (object instanceof ConfigValue<?>) {
|
if (object instanceof ConfigValue<?>) {
|
||||||
// 目标是 ConfigValue 实例,进行具体的初始化注入
|
// 目标是 ConfigValue 实例,进行具体的初始化注入
|
||||||
ConfigValue<?> value = (ConfigValue<?>) object;
|
ConfigValue<?> value = (ConfigValue<?>) object;
|
||||||
String path = getFieldPath(provider, parent, field);
|
String path = getFieldPath(holder, parent, field);
|
||||||
if (path == null) return;
|
if (path == null) return;
|
||||||
value.initialize(provider, path);
|
value.initialize(holder, path);
|
||||||
try {
|
try {
|
||||||
this.fieldInitializer.whenInitialize(provider, path, field);
|
this.fieldInitializer.whenInitialize(holder, path, field);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} else if (source instanceof Configuration && object instanceof Configuration) {
|
} else if (source instanceof Configuration && object instanceof Configuration) {
|
||||||
// 当且仅当 源字段与字段 均为Configuration实例时,才对目标字段进行下一步初始化加载。
|
// 当且仅当 源字段与字段 均为Configuration实例时,才对目标字段进行下一步初始化加载。
|
||||||
initializeInstance(provider, (Configuration) object, parent, field);
|
initializeInstance(holder, (Configuration) object, parent, field);
|
||||||
} else if (source instanceof Class<?> && object instanceof Class<?>) {
|
} else if (source instanceof Class<?> && object instanceof Class<?>) {
|
||||||
// 当且仅当 源字段与字段 均为静态类时,才对目标字段进行下一步初始化加载。
|
// 当且仅当 源字段与字段 均为静态类时,才对目标字段进行下一步初始化加载。
|
||||||
initializeStaticClass(provider, (Class<?>) object, parent, field);
|
initializeStaticClass(holder, (Class<?>) object, parent, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 以上判断实现以下规范:
|
// 以上判断实现以下规范:
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ public class PathGenerator {
|
|||||||
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder,
|
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder,
|
||||||
@Nullable String parentPath, @NotNull Field field) {
|
@Nullable String parentPath, @NotNull Field field) {
|
||||||
ConfigPath path = field.getAnnotation(ConfigPath.class);
|
ConfigPath path = field.getAnnotation(ConfigPath.class);
|
||||||
if (path == null) return link(provider, parentPath, false, field.getName()); // No annotation, use field name.
|
if (path == null) return link(holder, parentPath, false, field.getName()); // No annotation, use field name.
|
||||||
else return link(provider, parentPath, path.root(), select(path.value(), field.getName()));
|
else return link(holder, parentPath, path.root(), select(path.value(), field.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable String getClassPath(@NotNull ConfigurationHolder<?> holder,
|
public @Nullable String getClassPath(@NotNull ConfigurationHolder<?> holder,
|
||||||
@@ -52,14 +52,14 @@ public class PathGenerator {
|
|||||||
// and use filed information.
|
// and use filed information.
|
||||||
ConfigPath clazzPath = clazz.getAnnotation(ConfigPath.class);
|
ConfigPath clazzPath = clazz.getAnnotation(ConfigPath.class);
|
||||||
|
|
||||||
if (clazzPath != null) return link(provider, parentPath, clazzPath.root(), clazzPath.value());
|
if (clazzPath != null) return link(holder, parentPath, clazzPath.root(), clazzPath.value());
|
||||||
if (clazzField == null) {
|
if (clazzField == null) {
|
||||||
return link(provider, parentPath, false, clazz.getSimpleName()); // No field, use class name.
|
return link(holder, parentPath, false, clazz.getSimpleName()); // No field, use class name.
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigPath fieldPath = clazzField.getAnnotation(ConfigPath.class);
|
ConfigPath fieldPath = clazzField.getAnnotation(ConfigPath.class);
|
||||||
if (fieldPath == null) return link(provider, parentPath, false, clazzField.getName());
|
if (fieldPath == null) return link(holder, parentPath, false, clazzField.getName());
|
||||||
else return getFieldPath(provider, parentPath, clazzField);
|
else return getFieldPath(holder, parentPath, clazzField);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String select(String path, String defaultValue) {
|
protected String select(String path, String defaultValue) {
|
||||||
@@ -70,7 +70,7 @@ public class PathGenerator {
|
|||||||
protected @Nullable String link(@NotNull ConfigurationHolder<?> holder,
|
protected @Nullable String link(@NotNull ConfigurationHolder<?> holder,
|
||||||
@Nullable String parent, boolean root, @Nullable String path) {
|
@Nullable String parent, boolean root, @Nullable String path) {
|
||||||
if (path == null || path.isEmpty()) return root ? null : parent;
|
if (path == null || path.isEmpty()) return root ? null : parent;
|
||||||
return root || parent == null ? covertPath(path) : parent + pathSeparator(provider) + covertPath(path);
|
return root || parent == null ? covertPath(path) : parent + pathSeparator(holder) + covertPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isBlank(String path) {
|
public static boolean isBlank(String path) {
|
||||||
@@ -78,7 +78,7 @@ public class PathGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static char pathSeparator(ConfigurationHolder<?> holder) {
|
public static char pathSeparator(ConfigurationHolder<?> holder) {
|
||||||
return provider.options().get(StandardOptions.PATH_SEPARATOR);
|
return holder.options().get(StandardOptions.PATH_SEPARATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public interface StandardOptions {
|
|||||||
* <br> if false, the values will be parsed when calling
|
* <br> if false, the values will be parsed when calling
|
||||||
* {@link cc.carm.lib.configuration.value.ConfigValue#get()}
|
* {@link cc.carm.lib.configuration.value.ConfigValue#get()}
|
||||||
* <br> if true, the values will be parsed when
|
* <br> if true, the values will be parsed when
|
||||||
* {@link ConfigurationHolder#load(Configuration)}.
|
* {@link ConfigurationHolder#initialize(Configuration)}.
|
||||||
*/
|
*/
|
||||||
ConfigurationOption<Boolean> PRELOAD = of(false);
|
ConfigurationOption<Boolean> PRELOAD = of(false);
|
||||||
|
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.source.section;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public abstract class ConfigurationSource<SELF extends ConfigurationSource<SELF, ORIGINAL>, ORIGINAL>
|
|
||||||
implements ConfigurationSection {
|
|
||||||
|
|
||||||
protected final @NotNull ConfigurationHolder<? extends SELF> holder;
|
|
||||||
protected long lastUpdateMillis;
|
|
||||||
|
|
||||||
protected ConfigurationSource(@NotNull ConfigurationHolder<? extends SELF> holder,
|
|
||||||
long lastUpdateMillis) {
|
|
||||||
this.holder = holder;
|
|
||||||
this.lastUpdateMillis = lastUpdateMillis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull ConfigurationHolder<? extends SELF> holder() {
|
|
||||||
return holder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reload() throws Exception {
|
|
||||||
onReload(); // 调用重写的Reload方法
|
|
||||||
this.lastUpdateMillis = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract SELF self();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Original configuration object
|
|
||||||
*/
|
|
||||||
public abstract @NotNull ORIGINAL original();
|
|
||||||
|
|
||||||
public abstract void save() throws Exception;
|
|
||||||
|
|
||||||
protected abstract void onReload() throws Exception;
|
|
||||||
|
|
||||||
public long getLastUpdateMillis() {
|
|
||||||
return this.lastUpdateMillis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExpired(long parsedTime) {
|
|
||||||
return getLastUpdateMillis() > parsedTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+9
-2
@@ -1,6 +1,7 @@
|
|||||||
package cc.carm.lib.configuration.source.section;
|
package cc.carm.lib.configuration.source.section;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.function.DataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
|
import cc.carm.lib.configuration.source.option.StandardOptions;
|
||||||
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;
|
||||||
@@ -8,7 +9,13 @@ import org.jetbrains.annotations.Unmodifiable;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public interface ConfigurationSection {
|
public interface ConfigureSection {
|
||||||
|
|
||||||
|
@NotNull ConfigureSource<?, ?, ?> source();
|
||||||
|
|
||||||
|
default char separator() {
|
||||||
|
return source().holder().options().get(StandardOptions.PATH_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
default Set<String> getKeys(boolean deep) {
|
default Set<String> getKeys(boolean deep) {
|
||||||
@@ -33,7 +40,7 @@ public interface ConfigurationSection {
|
|||||||
boolean isSection(@NotNull String path);
|
boolean isSection(@NotNull String path);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
ConfigurationSection getSection(@NotNull String path);
|
ConfigureSection getSection(@NotNull String path);
|
||||||
|
|
||||||
@Nullable Object get(@NotNull String path);
|
@Nullable Object get(@NotNull String path);
|
||||||
|
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package cc.carm.lib.configuration.source.section;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract class ConfigureSource<
|
||||||
|
SECTION extends ConfigureSection, ORIGINAL,
|
||||||
|
SELF extends ConfigureSource<SECTION, ORIGINAL, SELF>>
|
||||||
|
implements ConfigureSection {
|
||||||
|
|
||||||
|
protected final @NotNull ConfigurationHolder<? extends SELF> holder;
|
||||||
|
protected long lastUpdateMillis;
|
||||||
|
|
||||||
|
protected ConfigureSource(@NotNull ConfigurationHolder<? extends SELF> holder, long lastUpdateMillis) {
|
||||||
|
this.holder = holder;
|
||||||
|
this.lastUpdateMillis = lastUpdateMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull ConfigurationHolder<? extends SELF> holder() {
|
||||||
|
return holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void reload() throws Exception {
|
||||||
|
onReload(); // 调用重写的Reload方法
|
||||||
|
this.lastUpdateMillis = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract SELF self();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Original configuration object
|
||||||
|
*/
|
||||||
|
public abstract @NotNull ORIGINAL original();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Configuration section
|
||||||
|
*/
|
||||||
|
public abstract @NotNull SECTION section();
|
||||||
|
|
||||||
|
public abstract void save() throws Exception;
|
||||||
|
|
||||||
|
protected abstract void onReload() throws Exception;
|
||||||
|
|
||||||
|
public long getLastUpdateMillis() {
|
||||||
|
return this.lastUpdateMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExpired(long parsedTime) {
|
||||||
|
return getLastUpdateMillis() > parsedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Map<String, Object> getValues(boolean deep) {
|
||||||
|
return section().getValues(deep);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(@NotNull String path, @Nullable Object value) {
|
||||||
|
section().set(path, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(@NotNull String path) {
|
||||||
|
return section().contains(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isList(@NotNull String path) {
|
||||||
|
return section().isList(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<?> getList(@NotNull String path) {
|
||||||
|
return section().getList(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSection(@NotNull String path) {
|
||||||
|
return section().isSection(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable ConfigureSection getSection(@NotNull String path) {
|
||||||
|
return section().getSection(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Object get(@NotNull String path) {
|
||||||
|
return section().get(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ 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.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSource;
|
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -101,8 +101,8 @@ public class ValueManifest<T> {
|
|||||||
throw new IllegalStateException("Value does not have a provider.");
|
throw new IllegalStateException("Value does not have a provider.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ConfigurationSource<?, ?> config() {
|
public @NotNull ConfigureSource<?, ?, ?> config() {
|
||||||
return holder().source();
|
return holder().config();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigurationMetaHolder metadata() {
|
public ConfigurationMetaHolder metadata() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ 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.ValueSerializer;
|
import cc.carm.lib.configuration.adapter.ValueSerializer;
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
import cc.carm.lib.configuration.value.ValueManifest;
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
|
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -58,7 +58,7 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
|
|||||||
// If the value is expired, we need to update it
|
// If the value is expired, we need to update it
|
||||||
Map<K, V> map = createMap();
|
Map<K, V> map = createMap();
|
||||||
|
|
||||||
ConfigurationSection section = config().getSection(path());
|
ConfigureSection section = config().getSection(path());
|
||||||
if (section == null) return getDefaultFirst(map);
|
if (section == null) return getDefaultFirst(map);
|
||||||
|
|
||||||
Set<String> keys = section.getKeys(false);
|
Set<String> keys = section.getKeys(false);
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
|||||||
return of(ValueType.of(type), () -> null);
|
return of(ValueType.of(type), () -> null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <V> ConfiguredValue<V> of(@NotNull Class<V> type, @NotNull V defaults) {
|
||||||
|
return of(ValueType.of(type), () -> defaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static <V> ConfiguredValue<V> of(@NotNull Class<V> type, @NotNull Supplier<@Nullable V> defaultSupplier) {
|
public static <V> ConfiguredValue<V> of(@NotNull Class<V> type, @NotNull Supplier<@Nullable V> defaultSupplier) {
|
||||||
return of(ValueType.of(type), defaultSupplier);
|
return of(ValueType.of(type), defaultSupplier);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import cc.carm.lib.configuration.source.ConfigurationHolder;
|
|||||||
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
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.test.config.TestSource;
|
import cc.carm.test.config.TestSource;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
@@ -28,10 +29,17 @@ public class AdaptTest {
|
|||||||
data -> Duration.between(LocalTime.now(), data)
|
data -> Duration.between(LocalTime.now(), data)
|
||||||
);
|
);
|
||||||
|
|
||||||
ConfigurationHolder<TestSource> provider = new ConfigurationHolder<>(
|
ConfigurationHolder<TestSource> provider = new ConfigurationHolder<TestSource>(
|
||||||
new TestSource(), registry, new ConfigurationOptionHolder(),
|
registry, new ConfigurationOptionHolder(),
|
||||||
new ConcurrentHashMap<>(), new ConfigurationInitializer()
|
new ConcurrentHashMap<>(), new ConfigurationInitializer()
|
||||||
);
|
) {
|
||||||
|
final TestSource source = new TestSource(this, System.currentTimeMillis());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull TestSource config() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
LocalTime v = registry.deserialize(provider, LocalTime.class, 600000L);
|
LocalTime v = registry.deserialize(provider, LocalTime.class, 600000L);
|
||||||
Object d = registry.serialize(provider, v);
|
Object d = registry.serialize(provider, v);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import cc.carm.lib.configuration.source.loader.PathGenerator;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class NameTest {
|
public class NameTest {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import cc.carm.lib.configuration.Configuration;
|
|||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
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.jetbrains.annotations.NotNull;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@@ -14,10 +15,17 @@ public class LoaderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() throws Exception {
|
public void test() throws Exception {
|
||||||
ConfigurationHolder<TestSource> provider = new ConfigurationHolder<>(
|
ConfigurationHolder<TestSource> provider = new ConfigurationHolder<TestSource>(
|
||||||
new TestSource(), new ValueAdapterRegistry(), new ConfigurationOptionHolder(),
|
new ValueAdapterRegistry(), new ConfigurationOptionHolder(),
|
||||||
new ConcurrentHashMap<>(), new ConfigurationInitializer()
|
new ConcurrentHashMap<>(), new ConfigurationInitializer()
|
||||||
);
|
) {
|
||||||
|
final TestSource source = new TestSource(this, System.currentTimeMillis());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull TestSource config() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ConfigurationInitializer loader = new ConfigurationInitializer();
|
ConfigurationInitializer loader = new ConfigurationInitializer();
|
||||||
loader.initialize(provider, ROOT.class);
|
loader.initialize(provider, ROOT.class);
|
||||||
|
|||||||
+9
-5
@@ -1,6 +1,7 @@
|
|||||||
package cc.carm.lib.configuration.json;
|
package cc.carm.test.config;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -8,8 +9,11 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class JSONConfigurationSection implements ConfigurationSection {
|
public class TestSection implements ConfigureSection {
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfigureSource<?, ?, ?> source() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Map<String, Object> getValues(boolean deep) {
|
public @NotNull Map<String, Object> getValues(boolean deep) {
|
||||||
@@ -42,7 +46,7 @@ public class JSONConfigurationSection implements ConfigurationSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable ConfigurationSection getSection(@NotNull String path) {
|
public @Nullable ConfigureSection getSection(@NotNull String path) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,18 +1,16 @@
|
|||||||
package cc.carm.test.config;
|
package cc.carm.test.config;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSource;
|
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class TestSource extends ConfigurationSource<TestSource, Map<String, String>> {
|
public class TestSource extends ConfigureSource<TestSection, Map<String, String>, TestSource> {
|
||||||
|
|
||||||
public TestSource() {
|
|
||||||
super(System.currentTimeMillis());
|
public TestSource(@NotNull ConfigurationHolder<? extends TestSource> holder, long lastUpdateMillis) {
|
||||||
|
super(holder, lastUpdateMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -36,47 +34,12 @@ public class TestSource extends ConfigurationSource<TestSource, Map<String, Stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Set<String> getKeys(boolean deep) {
|
public @NotNull TestSection section() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Map<String, Object> getValues(boolean deep) {
|
public @NotNull ConfigureSource<?, ?, ?> source() {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Object get(@NotNull String path) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(@NotNull String path, @Nullable Object value) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(@NotNull String path) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isList(@NotNull String path) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable List<?> getList(@NotNull String path) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSection(@NotNull String path) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable ConfigurationSection getSection(@NotNull String path) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,13 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>easyconfiguration-feature-commentable</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.demo;
|
package cc.carm.lib.configuration.demo;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
import cc.carm.lib.configuration.annotation.ConfigPath;
|
import cc.carm.lib.configuration.annotation.ConfigPath;
|
||||||
import cc.carm.lib.configuration.annotation.HeaderComment;
|
import cc.carm.lib.configuration.annotation.HeaderComment;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package cc.carm.lib.configuration.demo.tests;
|
|||||||
import cc.carm.lib.configuration.demo.tests.conf.DemoConfiguration;
|
import cc.carm.lib.configuration.demo.tests.conf.DemoConfiguration;
|
||||||
import cc.carm.lib.configuration.demo.tests.conf.TestConfiguration;
|
import cc.carm.lib.configuration.demo.tests.conf.TestConfiguration;
|
||||||
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import org.jetbrains.annotations.TestOnly;
|
import org.jetbrains.annotations.TestOnly;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -14,8 +14,12 @@ import java.util.stream.IntStream;
|
|||||||
public class ConfigurationTest {
|
public class ConfigurationTest {
|
||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
public static void testDemo(ConfigurationProvider<?> provider) {
|
public static void testDemo(ConfigurationHolder<?> holder) {
|
||||||
provider.initialize(DemoConfiguration.class);
|
try {
|
||||||
|
holder.initializer().initialize(holder, DemoConfiguration.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
System.out.println("----------------------------------------------------");
|
System.out.println("----------------------------------------------------");
|
||||||
|
|
||||||
@@ -48,21 +52,21 @@ public class ConfigurationTest {
|
|||||||
System.out.println(DemoConfiguration.MODEL_TEST.get());
|
System.out.println(DemoConfiguration.MODEL_TEST.get());
|
||||||
DemoConfiguration.MODEL_TEST.set(TestModel.random());
|
DemoConfiguration.MODEL_TEST.set(TestModel.random());
|
||||||
|
|
||||||
System.out.println("> Test Maps:");
|
// System.out.println("> Test Maps:");
|
||||||
DemoConfiguration.USERS.forEach((k, v) -> System.out.println(k + ": " + v));
|
// DemoConfiguration.USERS.forEach((k, v) -> System.out.println(k + ": " + v));
|
||||||
LinkedHashMap<Integer, UUID> data = new LinkedHashMap<>();
|
// LinkedHashMap<Integer, UUID> data = new LinkedHashMap<>();
|
||||||
for (int i = 1; i <= 5; i++) {
|
// for (int i = 1; i <= 5; i++) {
|
||||||
data.put(i, UUID.randomUUID());
|
// data.put(i, UUID.randomUUID());
|
||||||
}
|
// }
|
||||||
DemoConfiguration.USERS.set(data);
|
// DemoConfiguration.USERS.set(data);
|
||||||
System.out.println("----------------------------------------------------");
|
System.out.println("----------------------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void testInner(ConfigurationProvider<?> provider) {
|
public static void testInner(ConfigurationHolder<?> provider) {
|
||||||
|
|
||||||
TestConfiguration TEST = new TestConfiguration();
|
TestConfiguration TEST = new TestConfiguration();
|
||||||
|
|
||||||
provider.initialize(TEST, true);
|
provider.initialize(TEST);
|
||||||
|
|
||||||
System.out.println("> Test Inner value before:");
|
System.out.println("> Test Inner value before:");
|
||||||
System.out.println(TEST.INNER.INNER_VALUE.getNotNull());
|
System.out.println(TEST.INNER.INNER_VALUE.getNotNull());
|
||||||
@@ -76,7 +80,7 @@ public class ConfigurationTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void save(ConfigurationProvider<?> provider) {
|
public static void save(ConfigurationHolder<?> provider) {
|
||||||
try {
|
try {
|
||||||
provider.save();
|
provider.save();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
+14
-16
@@ -1,15 +1,13 @@
|
|||||||
package cc.carm.lib.configuration.demo.tests.conf;
|
package cc.carm.lib.configuration.demo.tests.conf;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
import cc.carm.lib.configuration.annotation.ConfigPath;
|
import cc.carm.lib.configuration.annotation.ConfigPath;
|
||||||
import cc.carm.lib.configuration.annotation.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.demo.tests.model.TestModel;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredMap;
|
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredSection;
|
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
|
||||||
|
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -37,22 +35,22 @@ public interface DemoConfiguration extends Configuration {
|
|||||||
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||||
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||||
@InlineComment("Section数据也支持InlineComment注释")
|
@InlineComment("Section数据也支持InlineComment注释")
|
||||||
ConfigValue<TestModel> MODEL_TEST = ConfiguredSection.builderOf(TestModel.class)
|
ConfigValue<TestModel> MODEL_TEST = ConfiguredValue.builderOf(TestModel.class).fromSection()
|
||||||
.defaults(new TestModel("Carm", UUID.randomUUID()))
|
.defaults(new TestModel("Carm", UUID.randomUUID()))
|
||||||
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
|
.parse((holder, section) -> TestModel.deserialize(section))
|
||||||
.serializeValue(TestModel::serialize).build();
|
.serialize(TestModel::serialize).build();
|
||||||
|
|
||||||
@HeaderComment({"[ID - UUID]对照表", "", "用于测试Map类型的解析与序列化保存"})
|
// @HeaderComment({"[ID - UUID]对照表", "", "用于测试Map类型的解析与序列化保存"})
|
||||||
ConfiguredMap<Integer, UUID> USERS = ConfiguredMap.builderOf(Integer.class, UUID.class)
|
// ConfiguredMap<Integer, UUID> USERS = ConfiguredMap.builderOf(Integer.class, UUID.class)
|
||||||
.asLinkedMap().fromString()
|
// .asLinkedMap().fromString()
|
||||||
.parseKey(Integer::parseInt)
|
// .parseKey(Integer::parseInt)
|
||||||
.parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
|
// .parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
|
||||||
.build();
|
// .build();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支持内部类的直接注册。
|
* 支持内部类的直接注册。
|
||||||
* 注意,需要使用 {@link ConfigInitializer#initialize(Class, boolean, boolean)} 方法,并设定第三个参数为 true。
|
* 注意,需要启用 {@link cc.carm.lib.configuration.source.option.StandardOptions#LOAD_SUB_CLASSES}
|
||||||
*/
|
*/
|
||||||
class Sub implements Configuration {
|
class Sub implements Configuration {
|
||||||
|
|
||||||
@@ -60,14 +58,14 @@ public interface DemoConfiguration extends Configuration {
|
|||||||
@InlineComment("This is an inline comment")
|
@InlineComment("This is an inline comment")
|
||||||
public static final ConfigValue<UUID> UUID_CONFIG_VALUE = ConfiguredValue
|
public static final ConfigValue<UUID> UUID_CONFIG_VALUE = ConfiguredValue
|
||||||
.builderOf(UUID.class).fromString()
|
.builderOf(UUID.class).fromString()
|
||||||
.parseValue((data, defaultValue) -> UUID.fromString(data))
|
.parse((holder, data) -> UUID.fromString(data))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static class That implements Configuration {
|
public static class That implements Configuration {
|
||||||
|
|
||||||
public static final ConfiguredList<UUID> OPERATORS = ConfiguredList
|
public static final ConfiguredList<UUID> OPERATORS = ConfiguredList
|
||||||
.builderOf(UUID.class).fromString()
|
.builderOf(UUID.class).fromString()
|
||||||
.parseValue(s -> Objects.requireNonNull(UUID.fromString(s)))
|
.parse(s -> Objects.requireNonNull(UUID.fromString(s)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package cc.carm.lib.configuration.demo.tests.conf;
|
package cc.carm.lib.configuration.demo.tests.conf;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
import cc.carm.lib.configuration.annotation.ConfigPath;
|
import cc.carm.lib.configuration.annotation.ConfigPath;
|
||||||
import cc.carm.lib.configuration.annotation.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.value.ConfigValue;
|
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredSection;
|
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
|
||||||
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
||||||
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -15,16 +14,15 @@ public class TestConfiguration implements Configuration {
|
|||||||
|
|
||||||
public final TestInnerConfiguration INNER = new TestInnerConfiguration();
|
public final TestInnerConfiguration INNER = new TestInnerConfiguration();
|
||||||
|
|
||||||
public final ConfigValue<Double> CLASS_VALUE = ConfiguredValue.of(Double.class, 1.0D);
|
public final ConfigValue<Double> CLASS_VALUE = ConfiguredValue.of(1.0D);
|
||||||
|
|
||||||
@ConfigPath("test.user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
@ConfigPath("test.user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||||
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||||
@InlineComment("Section数据也支持InlineComment注释")
|
@InlineComment("Section数据也支持InlineComment注释")
|
||||||
public final ConfigValue<TestModel> TEST_MODEL = ConfiguredSection
|
public final ConfigValue<TestModel> TEST_MODEL = ConfiguredValue.builderOf(TestModel.class).fromSection()
|
||||||
.builderOf(TestModel.class)
|
|
||||||
.defaults(new TestModel("Carm", UUID.randomUUID()))
|
.defaults(new TestModel("Carm", UUID.randomUUID()))
|
||||||
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
|
.parse((holder, section) -> TestModel.deserialize(section))
|
||||||
.serializeValue(TestModel::serialize).build();
|
.serialize((holder, data) -> data.serialize()).build();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.demo.tests.conf;
|
package cc.carm.lib.configuration.demo.tests.conf;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
import cc.carm.lib.configuration.annotation.HeaderComment;
|
import cc.carm.lib.configuration.annotation.HeaderComment;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
@@ -8,6 +8,6 @@ import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
|||||||
@HeaderComment("Inner Test")
|
@HeaderComment("Inner Test")
|
||||||
public class TestInnerConfiguration implements Configuration {
|
public class TestInnerConfiguration implements Configuration {
|
||||||
|
|
||||||
public final ConfigValue<Double> INNER_VALUE = ConfiguredValue.of(Double.class, 1.0D);
|
public final ConfigValue<Double> INNER_VALUE = ConfiguredValue.of(1.0D);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.demo.tests.model;
|
package cc.carm.lib.configuration.demo.tests.model;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -32,7 +33,7 @@ public class TestModel extends AbstractModel {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TestModel deserialize(ConfigurationWrapper<?> section) {
|
public static TestModel deserialize(ConfigureSection section) {
|
||||||
String name = section.getString("name");
|
String name = section.getString("name");
|
||||||
if (name == null) throw new NullPointerException("name is null");
|
if (name == null) throw new NullPointerException("name is null");
|
||||||
String uuidString = section.getString("info.uuid");
|
String uuidString = section.getString("info.uuid");
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package cc.carm.lib.configuration.source;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public abstract class FileConfigFactory<SOURCE extends FileConfigSource<?, ?, SOURCE>,
|
||||||
|
HOLDER extends ConfigurationHolder<SOURCE>, SELF extends FileConfigFactory<SOURCE, HOLDER, SELF>>
|
||||||
|
extends ConfigurationFactory<SOURCE, HOLDER, SELF> {
|
||||||
|
|
||||||
|
|
||||||
|
protected @NotNull File file;
|
||||||
|
protected @Nullable String resourcePath;
|
||||||
|
|
||||||
|
public FileConfigFactory(@NotNull File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF file(@NotNull File file) {
|
||||||
|
this.file = file;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF file(@NotNull Path path) {
|
||||||
|
return file(path.toFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF file(@NotNull File parent, @NotNull String fileName) {
|
||||||
|
return file(new File(parent, fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SELF resourcePath(@Nullable String resourcePath) {
|
||||||
|
this.resourcePath = resourcePath;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+11
-14
@@ -2,7 +2,8 @@ package cc.carm.lib.configuration.source;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.function.DataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import cc.carm.lib.configuration.option.FileConfigOptions;
|
import cc.carm.lib.configuration.option.FileConfigOptions;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSource;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -14,8 +15,8 @@ import java.nio.file.Files;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public abstract class FileConfigSource<SELF extends FileConfigSource<SELF, ORIGINAL>, ORIGINAL>
|
public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINAL, SELF extends FileConfigSource<SECTION, ORIGINAL, SELF>>
|
||||||
extends ConfigurationSource<SELF, ORIGINAL> {
|
extends ConfigureSource<SECTION, ORIGINAL, SELF> {
|
||||||
|
|
||||||
protected final @NotNull File file;
|
protected final @NotNull File file;
|
||||||
protected final @Nullable String resourcePath;
|
protected final @Nullable String resourcePath;
|
||||||
@@ -27,6 +28,7 @@ public abstract class FileConfigSource<SELF extends FileConfigSource<SELF, ORIGI
|
|||||||
this.resourcePath = resourcePath;
|
this.resourcePath = resourcePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Charset charset() {
|
public Charset charset() {
|
||||||
return holder().options().get(FileConfigOptions.CHARSET);
|
return holder().options().get(FileConfigOptions.CHARSET);
|
||||||
}
|
}
|
||||||
@@ -56,28 +58,23 @@ public abstract class FileConfigSource<SELF extends FileConfigSource<SELF, ORIGI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <R> R fileInputStream(@NotNull DataFunction<InputStream, R> loader) {
|
protected <R> R fileInputStream(@NotNull DataFunction<InputStream, R> loader) throws Exception {
|
||||||
try (FileInputStream is = new FileInputStream(file)) {
|
try (InputStream is = Files.newInputStream(file.toPath())) {
|
||||||
return loader.handle(is);
|
return loader.handle(is);
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <R> R fileReader(@NotNull DataFunction<Reader, R> loader) {
|
protected <R> R fileReader(@NotNull DataFunction<Reader, R> loader) throws Exception {
|
||||||
return fileInputStream(is -> loader.handle(new InputStreamReader(is, charset())));
|
return fileInputStream(is -> loader.handle(new InputStreamReader(is, charset())));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fileOutputStream(@NotNull Consumer<FileOutputStream> stream) {
|
protected void fileOutputStream(@NotNull Consumer<OutputStream> stream) throws Exception {
|
||||||
try (FileOutputStream os = new FileOutputStream(file)) {
|
try (OutputStream os = Files.newOutputStream(file.toPath())) {
|
||||||
stream.accept(os);
|
stream.accept(os);
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fileWriter(@NotNull Consumer<Writer> writer) {
|
protected void fileWriter(@NotNull Consumer<Writer> writer) throws Exception {
|
||||||
fileOutputStream(os -> writer.accept(new OutputStreamWriter(os, charset())));
|
fileOutputStream(os -> writer.accept(new OutputStreamWriter(os, charset())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,12 @@
|
|||||||
<module>features/commentable</module>
|
<module>features/commentable</module>
|
||||||
<module>features/file</module>
|
<module>features/file</module>
|
||||||
|
|
||||||
<!-- <module>demo</module>-->
|
<!-- <module>providers/yaml</module>-->
|
||||||
<!-- <module>providers/yaml</module>-->
|
|
||||||
<module>providers/gson</module>
|
<module>providers/gson</module>
|
||||||
<!-- <module>providers/sql</module>-->
|
<!-- <module>providers/sql</module>-->
|
||||||
<!-- <module>providers/hocon</module>-->
|
<!-- <module>providers/hocon</module>-->
|
||||||
|
|
||||||
|
<module>demo</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<name>EasyConfiguration</name>
|
<name>EasyConfiguration</name>
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
package cc.carm.lib.configuration;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.json.JSONConfigProvider;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class EasyConfiguration {
|
|
||||||
|
|
||||||
private EasyConfiguration() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JSONConfigProvider from(File file, String source) {
|
|
||||||
JSONConfigProvider provider = new JSONConfigProvider(file);
|
|
||||||
try {
|
|
||||||
provider.initializeFile(source);
|
|
||||||
provider.initializeConfig();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JSONConfigProvider from(File file) {
|
|
||||||
return from(file, file.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JSONConfigProvider from(String fileName) {
|
|
||||||
return from(fileName, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JSONConfigProvider from(String fileName, String source) {
|
|
||||||
return from(new File(fileName), source);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package cc.carm.lib.configuration.json;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import cc.carm.lib.configuration.source.FileConfigFactory;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class JSONConfigFactory extends FileConfigFactory<JSONSource, ConfigurationHolder<JSONSource>, JSONConfigFactory> {
|
||||||
|
|
||||||
|
public static JSONConfigFactory from(@NotNull File file) {
|
||||||
|
return new JSONConfigFactory(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSONConfigFactory from(@NotNull File parent, @NotNull String configName) {
|
||||||
|
return new JSONConfigFactory(new File(parent, configName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Supplier<Gson> gsonSupplier = () -> JSONSource.DEFAULT_GSON;
|
||||||
|
|
||||||
|
public JSONConfigFactory(@NotNull File file) {
|
||||||
|
super(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONConfigFactory self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONConfigFactory gson(@NotNull Supplier<Gson> gsonSupplier) {
|
||||||
|
this.gsonSupplier = gsonSupplier;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONConfigFactory gson(@NotNull Gson gson) {
|
||||||
|
return gson(() -> gson);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONConfigFactory gson(@NotNull Consumer<GsonBuilder> builder) {
|
||||||
|
return gson(() -> {
|
||||||
|
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||||
|
builder.accept(gsonBuilder);
|
||||||
|
return gsonBuilder.create();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfigurationHolder<JSONSource> build() {
|
||||||
|
Gson gson = gsonSupplier.get();
|
||||||
|
if (gson == null) throw new NullPointerException("No Gson instance provided.");
|
||||||
|
|
||||||
|
File configFile = this.file;
|
||||||
|
String sourcePath = this.resourcePath;
|
||||||
|
|
||||||
|
return new ConfigurationHolder<JSONSource>(this.adapters, this.options, new ConcurrentHashMap<>(), this.initializer) {
|
||||||
|
final JSONSource source = new JSONSource(this, 0, configFile, sourcePath, gson);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull JSONSource config() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.json;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.comment.ConfigurationComments;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.JsonSerializer;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Some code comes from BungeeCord's implementation of the JsonConfiguration.
|
|
||||||
*
|
|
||||||
* @author md_5, CarmJos
|
|
||||||
*/
|
|
||||||
public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected JSONConfigWrapper configuration;
|
|
||||||
protected ConfigInitializer<JSONConfigProvider> initializer;
|
|
||||||
|
|
||||||
public JSONConfigProvider(@NotNull File file) {
|
|
||||||
super(file);
|
|
||||||
this.initializer = new ConfigInitializer<>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initializeConfig() {
|
|
||||||
onReload();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull JSONConfigWrapper getConfiguration() {
|
|
||||||
return this.configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onReload() {
|
|
||||||
LinkedHashMap<?, ?> map = null;
|
|
||||||
|
|
||||||
try (FileInputStream is = new FileInputStream(file)) {
|
|
||||||
map = gson.fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), LinkedHashMap.class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map == null) map = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
this.configuration = new JSONConfigWrapper(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable ConfigurationComments getComments() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save() throws Exception {
|
|
||||||
try (Writer writer = new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8)) {
|
|
||||||
gson.toJson(configuration.data, writer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ConfigInitializer<? extends ConfigurationProvider<JSONConfigWrapper>> getInitializer() {
|
|
||||||
return this.initializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.json;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
|
||||||
import cc.carm.lib.configuration.source.FileConfigSource;
|
|
||||||
import cc.carm.lib.configuration.source.section.ConfigurationSection;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonSerializer;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class JSONConfigSource extends FileConfigSource<JSONConfigSource, JsonObject> {
|
|
||||||
|
|
||||||
public static final @NotNull Gson DEFAULT_GSON = new GsonBuilder()
|
|
||||||
.serializeNulls().disableHtmlEscaping().setPrettyPrinting()
|
|
||||||
.registerTypeAdapter(
|
|
||||||
JSONConfigWrapper.class,
|
|
||||||
(JsonSerializer<JSONConfigWrapper>) (src, typeOfSrc, context) -> context.serialize(src.data)
|
|
||||||
).create();
|
|
||||||
|
|
||||||
protected final @NotNull Gson gson;
|
|
||||||
|
|
||||||
protected @Nullable JsonObject original;
|
|
||||||
|
|
||||||
protected JSONConfigSource(@NotNull ConfigurationHolder<? extends JSONConfigSource> holder, long lastUpdateMillis,
|
|
||||||
@NotNull File file, @Nullable String resourcePath, @NotNull Gson gson) {
|
|
||||||
super(holder, lastUpdateMillis, file, resourcePath);
|
|
||||||
this.gson = gson;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initialize() {
|
|
||||||
try {
|
|
||||||
initializeFile();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initializeJson() {
|
|
||||||
this.original = fileReader(reader -> gson.fromJson(reader, JsonObject.class));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JSONConfigSource self() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull JsonObject original() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onReload() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Map<String, Object> getValues(boolean deep) {
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(@NotNull String path, @Nullable Object value) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(@NotNull String path) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isList(@NotNull String path) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable List<?> getList(@NotNull String path) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSection(@NotNull String path) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable ConfigurationSection getSection(@NotNull String path) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Object get(@NotNull String path) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+32
-32
@@ -1,31 +1,27 @@
|
|||||||
package cc.carm.lib.configuration.json;
|
package cc.carm.lib.configuration.json;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
public class JSONSection implements ConfigureSection {
|
||||||
* Some code comes from BungeeCord's implementation of the JsonConfiguration.
|
|
||||||
*
|
|
||||||
* @author md_5, CarmJos
|
|
||||||
*/
|
|
||||||
public class JSONConfigWrapper implements ConfigurationWrapper<Map<String, Object>> {
|
|
||||||
|
|
||||||
private static final char SEPARATOR = '.';
|
protected final ConfigureSource<? extends JSONSection, ?, ?> source;
|
||||||
protected final Map<String, Object> data;
|
protected final Map<String, Object> data;
|
||||||
|
|
||||||
JSONConfigWrapper(Map<?, ?> map) {
|
public JSONSection(@NotNull ConfigureSource<? extends JSONSection, ?, ?> source,
|
||||||
|
@NotNull Map<?, ?> data) {
|
||||||
|
this.source = source;
|
||||||
this.data = new LinkedHashMap<>();
|
this.data = new LinkedHashMap<>();
|
||||||
|
|
||||||
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
for (Map.Entry<?, ?> entry : data.entrySet()) {
|
||||||
String key = (entry.getKey() == null) ? "null" : entry.getKey().toString();
|
String key = (entry.getKey() == null) ? "null" : entry.getKey().toString();
|
||||||
|
|
||||||
if (entry.getValue() instanceof Map) {
|
if (entry.getValue() instanceof Map) {
|
||||||
this.data.put(key, new JSONConfigWrapper((Map<?, ?>) entry.getValue()));
|
this.data.put(key, new JSONSection(source, (Map<?, ?>) entry.getValue()));
|
||||||
} else {
|
} else {
|
||||||
this.data.put(key, entry.getValue());
|
this.data.put(key, entry.getValue());
|
||||||
}
|
}
|
||||||
@@ -33,7 +29,11 @@ public class JSONConfigWrapper implements ConfigurationWrapper<Map<String, Objec
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Map<String, Object> getSource() {
|
public @NotNull ConfigureSource<? extends JSONSection, ?, ?> source() {
|
||||||
|
return this.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> data() {
|
||||||
return this.data;
|
return this.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,10 +54,10 @@ public class JSONConfigWrapper implements ConfigurationWrapper<Map<String, Objec
|
|||||||
@Override
|
@Override
|
||||||
public void set(@NotNull String path, @Nullable Object value) {
|
public void set(@NotNull String path, @Nullable Object value) {
|
||||||
if (value instanceof Map) {
|
if (value instanceof Map) {
|
||||||
value = new JSONConfigWrapper((Map<?, ?>) value);
|
value = new JSONSection(source(), (Map<?, ?>) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONConfigWrapper section = getSectionFor(path);
|
JSONSection section = getSectionFor(path);
|
||||||
if (section == this) {
|
if (section == this) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
this.data.remove(path);
|
this.data.remove(path);
|
||||||
@@ -76,7 +76,7 @@ public class JSONConfigWrapper implements ConfigurationWrapper<Map<String, Objec
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Object get(@NotNull String path) {
|
public @Nullable Object get(@NotNull String path) {
|
||||||
JSONConfigWrapper section = getSectionFor(path);
|
JSONSection section = getSectionFor(path);
|
||||||
return section == this ? data.get(path) : section.get(getChild(path));
|
return section == this ? data.get(path) : section.get(getChild(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,44 +92,44 @@ public class JSONConfigWrapper implements ConfigurationWrapper<Map<String, Objec
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isConfigurationSection(@NotNull String path) {
|
public boolean isSection(@NotNull String path) {
|
||||||
return get(path) instanceof JSONConfigWrapper;
|
return get(path) instanceof JSONSection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable JSONConfigWrapper getConfigurationSection(@NotNull String path) {
|
public @Nullable ConfigureSection getSection(@NotNull String path) {
|
||||||
Object val = get(path);
|
Object val = get(path);
|
||||||
return (val instanceof JSONConfigWrapper) ? (JSONConfigWrapper) val : null;
|
return (val instanceof ConfigureSection) ? (ConfigureSection) val : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JSONConfigWrapper getSectionFor(String path) {
|
private JSONSection getSectionFor(String path) {
|
||||||
int index = path.indexOf(SEPARATOR);
|
int index = path.indexOf(separator());
|
||||||
if (index == -1) return this;
|
if (index == -1) return this;
|
||||||
|
|
||||||
String root = path.substring(0, index);
|
String root = path.substring(0, index);
|
||||||
Object section = this.data.get(root);
|
Object section = this.data.get(root);
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
section = new JSONConfigWrapper(new LinkedHashMap<>());
|
section = new JSONSection(source(), new LinkedHashMap<>());
|
||||||
this.data.put(root, section);
|
this.data.put(root, section);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (JSONConfigWrapper) section;
|
return (JSONSection) section;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getChild(String path) {
|
private String getChild(String path) {
|
||||||
int index = path.indexOf(SEPARATOR);
|
int index = path.indexOf(separator());
|
||||||
return (index == -1) ? path : path.substring(index + 1);
|
return (index == -1) ? path : path.substring(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void mapChildrenValues(@NotNull Map<String, Object> output, @NotNull JSONConfigWrapper section,
|
protected void mapChildrenValues(@NotNull Map<String, Object> output, @NotNull JSONSection section,
|
||||||
@Nullable String parent, boolean deep) {
|
@Nullable String parent, boolean deep) {
|
||||||
for (Map.Entry<String, Object> entry : section.data.entrySet()) {
|
for (Map.Entry<String, Object> entry : section.data().entrySet()) {
|
||||||
String path = (parent == null ? "" : parent + ".") + entry.getKey();
|
String path = (parent == null ? "" : parent + separator()) + entry.getKey();
|
||||||
output.remove(path);
|
output.remove(path);
|
||||||
output.put(path, entry.getValue());
|
output.put(path, entry.getValue());
|
||||||
if (deep && entry.getValue() instanceof JSONConfigWrapper) {
|
if (deep && entry.getValue() instanceof JSONSection) {
|
||||||
this.mapChildrenValues(output, (JSONConfigWrapper) entry.getValue(), path, true);
|
this.mapChildrenValues(output, (JSONSection) entry.getValue(), path, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package cc.carm.lib.configuration.json;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import cc.carm.lib.configuration.source.FileConfigSource;
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class JSONSource extends FileConfigSource<JSONSection, Map<?, ?>, JSONSource> {
|
||||||
|
|
||||||
|
public static final @NotNull Gson DEFAULT_GSON = new GsonBuilder()
|
||||||
|
.serializeNulls().disableHtmlEscaping().setPrettyPrinting()
|
||||||
|
.registerTypeAdapter(
|
||||||
|
JSONSection.class,
|
||||||
|
(JsonSerializer<JSONSection>) (src, typeOfSrc, context) -> context.serialize(src.data)
|
||||||
|
).create();
|
||||||
|
|
||||||
|
protected final @NotNull Gson gson;
|
||||||
|
protected @Nullable JSONSection section;
|
||||||
|
|
||||||
|
protected JSONSource(@NotNull ConfigurationHolder<? extends JSONSource> holder, long lastUpdateMillis,
|
||||||
|
@NotNull File file, @Nullable String resourcePath) {
|
||||||
|
this(holder, lastUpdateMillis, file, resourcePath, DEFAULT_GSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JSONSource(@NotNull ConfigurationHolder<? extends JSONSource> holder, long lastUpdateMillis,
|
||||||
|
@NotNull File file, @Nullable String resourcePath, @NotNull Gson gson) {
|
||||||
|
super(holder, lastUpdateMillis, file, resourcePath);
|
||||||
|
this.gson = gson;
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
try {
|
||||||
|
initializeFile();
|
||||||
|
onReload();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JSONSource self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfigureSource<?, ?, ?> source() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Map<?, ?> original() {
|
||||||
|
return section().data();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull JSONSection section() {
|
||||||
|
return Objects.requireNonNull(this.section, "Section is not initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() throws Exception {
|
||||||
|
fileWriter(writer -> gson.toJson(original(), writer));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onReload() throws Exception {
|
||||||
|
Map<?, ?> data = fileReader(reader -> gson.fromJson(reader, LinkedHashMap.class));
|
||||||
|
if (data == null) data = new LinkedHashMap<>();
|
||||||
|
this.section = new JSONSection(this, data);
|
||||||
|
this.lastUpdateMillis = System.currentTimeMillis(); // 更新时间
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,26 @@
|
|||||||
package config;
|
package config;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.EasyConfiguration;
|
|
||||||
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||||
import cc.carm.lib.configuration.json.JSONConfigProvider;
|
import cc.carm.lib.configuration.json.JSONConfigFactory;
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import cc.carm.lib.configuration.source.option.StandardOptions;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
public class JSONConfigTest {
|
public class JSONConfigTest {
|
||||||
|
|
||||||
protected final JSONConfigProvider provider = EasyConfiguration.from("target/config.json", "config.json");
|
protected final ConfigurationHolder<?> holder = JSONConfigFactory
|
||||||
|
.from(new File("target"), "config.json")
|
||||||
|
.option(StandardOptions.PATH_SEPARATOR, '-')
|
||||||
|
.build();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onTest() {
|
public void onTest() {
|
||||||
|
ConfigurationTest.testDemo(this.holder);
|
||||||
|
ConfigurationTest.testInner(this.holder);
|
||||||
|
|
||||||
ConfigurationTest.testDemo(this.provider);
|
ConfigurationTest.save(this.holder);
|
||||||
ConfigurationTest.testInner(this.provider);
|
|
||||||
|
|
||||||
System.out.println("----------------------------------------------------");
|
|
||||||
provider.getConfiguration().getValues(true).forEach((k, v) -> System.out.println(k + ": " + v));
|
|
||||||
System.out.println("----------------------------------------------------");
|
|
||||||
provider.getConfiguration().getValues(false).forEach((k, v) -> System.out.println(k + ": " + v));
|
|
||||||
System.out.println("----------------------------------------------------");
|
|
||||||
|
|
||||||
ConfigurationTest.save(this.provider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user