mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 18:48:20 +08:00
feat(yaml): Finished YAML Provider
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
package cc.carm.lib.configuration.function;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface DataConsumer<T> {
|
||||||
|
|
||||||
|
void accept(@NotNull T data) throws Exception;
|
||||||
|
|
||||||
|
default DataConsumer<T> andThen(DataConsumer<? super T> after) {
|
||||||
|
return (T t) -> {
|
||||||
|
accept(t);
|
||||||
|
after.accept(t);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.lang.annotation.Annotation;
|
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;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public abstract class ConfigurationFactory<
|
public abstract class ConfigurationFactory<
|
||||||
SOURCE extends ConfigureSource<?, ?, SOURCE>,
|
SOURCE extends ConfigureSource<?, ?, SOURCE>,
|
||||||
@@ -31,8 +32,7 @@ public abstract class ConfigurationFactory<
|
|||||||
this.adapters.register(StandardAdapters.SECTION_ADAPTER);
|
this.adapters.register(StandardAdapters.SECTION_ADAPTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract SELF self();
|
protected abstract SELF self();
|
||||||
|
|
||||||
|
|
||||||
public SELF adapters(ValueAdapterRegistry adapters) {
|
public SELF adapters(ValueAdapterRegistry adapters) {
|
||||||
this.adapters = adapters;
|
this.adapters = adapters;
|
||||||
@@ -81,13 +81,25 @@ public abstract class ConfigurationFactory<
|
|||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SELF option(Consumer<ConfigurationOptionHolder> optionsConsumer) {
|
public SELF option(Consumer<ConfigurationOptionHolder> modifier) {
|
||||||
optionsConsumer.accept(options);
|
modifier.accept(options);
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public <O> SELF option(ConfigurationOption<O> option, O value) {
|
public <O> SELF option(ConfigurationOption<O> type, O value) {
|
||||||
return option(o -> o.set(option, value));
|
return option(o -> o.set(type, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <O> SELF option(ConfigurationOption<O> type, Supplier<O> value) {
|
||||||
|
return option(type, value.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public <O> SELF option(ConfigurationOption<O> type, Consumer<O> modifier) {
|
||||||
|
return option(holder -> {
|
||||||
|
O current = holder.get(type);
|
||||||
|
modifier.accept(current);
|
||||||
|
holder.set(type, current);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+20
-8
@@ -67,14 +67,9 @@ public class ConfigurationInitializer {
|
|||||||
this.classInitializer = this.classInitializer.andThen(classInitializer);
|
this.classInitializer = this.classInitializer.andThen(classInitializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T, A extends Annotation> void registerAnnotation(@NotNull Class<A> annotation,
|
public <T, A extends Annotation> void registerClassAnnotation(@NotNull Class<A> annotation,
|
||||||
@NotNull ConfigurationMetadata<T> metadata,
|
@NotNull ConfigurationMetadata<T> metadata,
|
||||||
@NotNull Function<A, T> extractor) {
|
@NotNull Function<A, T> extractor) {
|
||||||
appendFieldInitializer((holder, path, field) -> {
|
|
||||||
A data = field.getAnnotation(annotation);
|
|
||||||
if (data == null) return;
|
|
||||||
holder.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
|
||||||
});
|
|
||||||
appendClassInitializer((holder, path, clazz) -> {
|
appendClassInitializer((holder, path, clazz) -> {
|
||||||
A data = clazz.getAnnotation(annotation);
|
A data = clazz.getAnnotation(annotation);
|
||||||
if (data == null) return;
|
if (data == null) return;
|
||||||
@@ -82,6 +77,23 @@ public class ConfigurationInitializer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T, A extends Annotation> void registerFieldAnnotation(@NotNull Class<A> annotation,
|
||||||
|
@NotNull ConfigurationMetadata<T> metadata,
|
||||||
|
@NotNull Function<A, T> extractor) {
|
||||||
|
appendFieldInitializer((holder, path, field) -> {
|
||||||
|
A data = field.getAnnotation(annotation);
|
||||||
|
if (data == null) return;
|
||||||
|
holder.metadata(path).setIfAbsent(metadata, extractor.apply(data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T, A extends Annotation> void registerAnnotation(@NotNull Class<A> annotation,
|
||||||
|
@NotNull ConfigurationMetadata<T> metadata,
|
||||||
|
@NotNull Function<A, T> extractor) {
|
||||||
|
registerClassAnnotation(annotation, metadata, extractor);
|
||||||
|
registerFieldAnnotation(annotation, metadata, extractor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) {
|
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) {
|
||||||
return pathGenerator.getFieldPath(holder, parentPath, field);
|
return pathGenerator.getFieldPath(holder, parentPath, field);
|
||||||
|
|||||||
@@ -54,13 +54,14 @@ public class PathGenerator {
|
|||||||
ConfigPath clazzPath = clazz.getAnnotation(ConfigPath.class);
|
ConfigPath clazzPath = clazz.getAnnotation(ConfigPath.class);
|
||||||
if (clazzPath != null) return link(holder, parentPath, clazzPath.root(), clazzPath.value());
|
if (clazzPath != null) return link(holder, parentPath, clazzPath.root(), clazzPath.value());
|
||||||
|
|
||||||
if (clazzField == null) {
|
if (clazzField != null) {
|
||||||
return link(holder, parentPath, false, parentPath == null ? null : covertPath(clazz.getSimpleName())); // No field, use class name.
|
ConfigPath fieldPath = clazzField.getAnnotation(ConfigPath.class);
|
||||||
|
if (fieldPath == null) return link(holder, parentPath, false, covertPath(clazzField.getName()));
|
||||||
|
else return getFieldPath(holder, parentPath, clazzField);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigPath fieldPath = clazzField.getAnnotation(ConfigPath.class);
|
return link(holder, parentPath, false, covertPath(clazz.getSimpleName())); // No field, use class name.
|
||||||
if (fieldPath == null) return link(holder, parentPath, false, covertPath(clazzField.getName()));
|
|
||||||
else return getFieldPath(holder, parentPath, clazzField);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String select(String path, String defaultValue) {
|
protected String select(String path, String defaultValue) {
|
||||||
@@ -71,7 +72,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 ? path : parent + pathSeparator(holder) + path;
|
return (root || parent == null) ? path : (parent + pathSeparator(holder) + path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isBlank(String path) {
|
public static boolean isBlank(String path) {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package cc.carm.lib.configuration.source.option;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class ConfigurationOption<V> {
|
public class ConfigurationOption<V> {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -13,6 +15,10 @@ public class ConfigurationOption<V> {
|
|||||||
return new ConfigurationOption<>(valueClazz, defaultValue);
|
return new ConfigurationOption<>(valueClazz, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> ConfigurationOption<T> of(@NotNull Supplier<T> defaultValue) {
|
||||||
|
return of(defaultValue.get());
|
||||||
|
}
|
||||||
|
|
||||||
private final @NotNull Class<V> valueClazz;
|
private final @NotNull Class<V> valueClazz;
|
||||||
private @NotNull V defaultValue;
|
private @NotNull V defaultValue;
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,11 @@ public abstract class ConfigureSource<
|
|||||||
return null; // Source also represents the root section, so it has no parent
|
return null; // Source also represents the root section, so it has no parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfigureSource<?, ?, ?> source() {
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Map<String, Object> getValues(boolean deep) {
|
public @NotNull Map<String, Object> getValues(boolean deep) {
|
||||||
return section().getValues(deep);
|
return section().getValues(deep);
|
||||||
|
|||||||
@@ -7,6 +7,32 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a configurable value with type safety and null-handling capabilities.
|
||||||
|
* <p>
|
||||||
|
* This abstract class provides core functionalities for managing configuration values,
|
||||||
|
* including value retrieval with fallback defaults, null safety enforcement, and value
|
||||||
|
* persistence controls. It serves as the foundation for type-specific configuration
|
||||||
|
* implementations.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <h3>Functions:</h3>
|
||||||
|
* <ul>
|
||||||
|
* <li>Type-safe value access through {@link #get()} and {@link #optional()}</li>
|
||||||
|
* <li>Default value fallback via {@link #getOrDefault()}</li>
|
||||||
|
* <li>Null-safety enforcement with {@link #resolve()} and {@link #getNotNull()}</li>
|
||||||
|
* <li>Default value initialization through {@link #setDefault()}</li>
|
||||||
|
* <li>Value comparison with {@link #isDefault()}</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <h3>Persistence Behavior:</h3>
|
||||||
|
* Value modifications via {@link #set(Object)} or {@link #setDefault()} methods
|
||||||
|
* <b>do NOT automatically persist</b> to configuration sources. Explicit calls to
|
||||||
|
* {@link ConfigurationHolder#save()} are required for permanent storage.
|
||||||
|
*
|
||||||
|
* @see ValueManifest Base class providing metadata and default value handling
|
||||||
|
* @see ConfigurationHolder Responsible for configuration source persistence
|
||||||
|
*/
|
||||||
public abstract class ConfigValue<T> extends ValueManifest<T> {
|
public abstract class ConfigValue<T> extends ValueManifest<T> {
|
||||||
|
|
||||||
protected ConfigValue(@NotNull ValueManifest<T> manifest) {
|
protected ConfigValue(@NotNull ValueManifest<T> manifest) {
|
||||||
@@ -14,57 +40,77 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 得到该配置的设定值(即读取到的值)。
|
* Gets the configured value (i.e., the value read from the source).
|
||||||
* <br> 若初始化时未写入默认值,则可以通过 {@link #getOrDefault()} 方法在该设定值为空时获取默认值。
|
* <br> If no default value was written during initialization, you can use
|
||||||
|
* the {@link #getOrDefault()} method to obtain the default value when this value is empty.
|
||||||
*
|
*
|
||||||
* @return 设定值
|
* @return Configured value
|
||||||
*/
|
*/
|
||||||
public abstract @Nullable T get();
|
public abstract @Nullable T get();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 得到该配置的设定值,若不存在,则返回默认值。
|
* Gets the configured value, or returns the default value if not present.
|
||||||
*
|
*
|
||||||
* @return 设定值或默认值
|
* @return Configured value or default value
|
||||||
*/
|
*/
|
||||||
public T getOrDefault() {
|
public T getOrDefault() {
|
||||||
return optional().orElse(defaults());
|
return optional().orElse(defaults());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 得到该配置的非空值。
|
* Gets the non-null value of this configuration.
|
||||||
*
|
*
|
||||||
* @return 非空值
|
* @return Non-null value
|
||||||
* @throws NullPointerException 对应数据为空时抛出
|
* @throws NullPointerException Thrown when the corresponding data is null
|
||||||
*/
|
*/
|
||||||
public @NotNull T getNotNull() {
|
public @NotNull T resolve() {
|
||||||
return Objects.requireNonNull(getOrDefault(), "Value(" + type() + ") @[" + path() + "] is null.");
|
return Objects.requireNonNull(getOrDefault(), "Value(" + type() + ") @[" + path() + "] is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the non-null value of this configuration.
|
||||||
|
*
|
||||||
|
* @return Non-null value
|
||||||
|
* @throws NullPointerException Thrown when the corresponding data is null
|
||||||
|
* @see #resolve()
|
||||||
|
*/
|
||||||
|
public @NotNull T getNotNull() {
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of this configuration as an {@link Optional}.
|
||||||
|
*
|
||||||
|
* @return {@link Optional} value
|
||||||
|
*/
|
||||||
public @NotNull Optional<@Nullable T> optional() {
|
public @NotNull Optional<@Nullable T> optional() {
|
||||||
return Optional.ofNullable(get());
|
return Optional.ofNullable(get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设定该配置的值。
|
* Sets the value of this configuration.
|
||||||
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationHolder#save()} 方法。
|
* <br> After setting, the configuration file will NOT be saved automatically.
|
||||||
|
* To save, call {@link ConfigurationHolder#save()}.
|
||||||
*
|
*
|
||||||
* @param value 配置的值
|
* @param value The value to set
|
||||||
*/
|
*/
|
||||||
public abstract void set(@Nullable T value);
|
public abstract void set(@Nullable T value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化该配置的默认值。
|
* Initializes the default value for this configuration.
|
||||||
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationHolder#save()} 方法。
|
* <br> After setting, the configuration file will NOT be saved automatically.
|
||||||
|
* To save, call {@link ConfigurationHolder#save()}.
|
||||||
*/
|
*/
|
||||||
public void setDefault() {
|
public void setDefault() {
|
||||||
setDefault(false);
|
setDefault(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将该配置的值设置为默认值。
|
* Sets the configuration value to its default.
|
||||||
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationHolder#save()} 方法。
|
* <br> After setting, the configuration file will NOT be saved automatically.
|
||||||
|
* To save, call {@link ConfigurationHolder#save()}.
|
||||||
*
|
*
|
||||||
* @param override 是否覆盖已设定的值
|
* @param override Whether to overwrite existing configured value
|
||||||
*/
|
*/
|
||||||
public void setDefault(boolean override) {
|
public void setDefault(boolean override) {
|
||||||
if (!override && config().contains(path())) return;
|
if (!override && config().contains(path())) return;
|
||||||
@@ -72,9 +118,9 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断加载的配置是否与默认值相同。
|
* Checks if the loaded configuration value matches the default value.
|
||||||
*
|
*
|
||||||
* @return 获取当前值是否为默认值。
|
* @return Whether the current value is the default value
|
||||||
*/
|
*/
|
||||||
public boolean isDefault() {
|
public boolean isDefault() {
|
||||||
return Objects.equals(defaults(), get());
|
return Objects.equals(defaults(), get());
|
||||||
@@ -86,10 +132,10 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
|
|||||||
* it is recommended to call {@link ConfigurationHolder#save()}
|
* it is recommended to call {@link ConfigurationHolder#save()}
|
||||||
* after all modifications are completed instead of this.
|
* after all modifications are completed instead of this.
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception Thrown when an error occurs during saving
|
||||||
*/
|
*/
|
||||||
public void save() throws Exception {
|
public void save() throws Exception {
|
||||||
holder().save();
|
holder().save();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -111,22 +111,22 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public V get(int index) {
|
public V get(int index) {
|
||||||
return getNotNull().get(index);
|
return resolve().get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull List<V> copy() {
|
public @NotNull List<V> copy() {
|
||||||
return new ArrayList<>(getNotNull());
|
return new ArrayList<>(resolve());
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> @NotNull T handle(Function<List<V>, T> function) {
|
public <T> @NotNull T handle(Function<List<V>, T> function) {
|
||||||
List<V> list = getNotNull();
|
List<V> list = resolve();
|
||||||
T result = function.apply(list);
|
T result = function.apply(list);
|
||||||
set(list);
|
set(list);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ConfiguredList<V> modify(Consumer<List<V>> consumer) {
|
public @NotNull ConfiguredList<V> modify(Consumer<List<V>> consumer) {
|
||||||
List<V> list = getNotNull();
|
List<V> list = resolve();
|
||||||
consumer.accept(list);
|
consumer.accept(list);
|
||||||
set(list);
|
set(list);
|
||||||
return this;
|
return this;
|
||||||
@@ -139,40 +139,40 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return getNotNull().size();
|
return resolve().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return getNotNull().isEmpty();
|
return resolve().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(Object o) {
|
public boolean contains(Object o) {
|
||||||
return getNotNull().contains(o);
|
return resolve().contains(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Iterator<V> iterator() {
|
public Iterator<V> iterator() {
|
||||||
return getNotNull().iterator();
|
return resolve().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Object @NotNull [] toArray() {
|
public Object @NotNull [] toArray() {
|
||||||
return getNotNull().toArray();
|
return resolve().toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public <T> T @NotNull [] toArray(@NotNull T[] a) {
|
public <T> T @NotNull [] toArray(@NotNull T[] a) {
|
||||||
return getNotNull().toArray(a);
|
return resolve().toArray(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsAll(@NotNull Collection<?> c) {
|
public boolean containsAll(@NotNull Collection<?> c) {
|
||||||
return new HashSet<>(getNotNull()).containsAll(c);
|
return new HashSet<>(resolve()).containsAll(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -223,30 +223,30 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int indexOf(Object o) {
|
public int indexOf(Object o) {
|
||||||
return getNotNull().indexOf(o);
|
return resolve().indexOf(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int lastIndexOf(Object o) {
|
public int lastIndexOf(Object o) {
|
||||||
return getNotNull().lastIndexOf(o);
|
return resolve().lastIndexOf(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ListIterator<V> listIterator() {
|
public ListIterator<V> listIterator() {
|
||||||
return getNotNull().listIterator();
|
return resolve().listIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ListIterator<V> listIterator(int index) {
|
public ListIterator<V> listIterator(int index) {
|
||||||
return getNotNull().listIterator(index);
|
return resolve().listIterator(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<V> subList(int fromIndex, int toIndex) {
|
public List<V> subList(int fromIndex, int toIndex) {
|
||||||
return getNotNull().subList(fromIndex, toIndex);
|
return resolve().subList(fromIndex, toIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
|
||||||
import cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapter;
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
|
||||||
import cc.carm.test.config.TestSource;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.time.LocalTime;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
public class AdaptTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
|
|
||||||
ValueAdapterRegistry registry = new ValueAdapterRegistry();
|
|
||||||
registry.register(PrimitiveAdapter.ADAPTERS);
|
|
||||||
registry.register(PrimitiveAdapter.ofEnum());
|
|
||||||
|
|
||||||
|
|
||||||
registry.register(ValueType.of(Long.class), ValueType.of(Duration.class), Duration::ofMillis, Duration::toMillis);
|
|
||||||
registry.register(
|
|
||||||
ValueType.of(Duration.class), ValueType.of(LocalTime.class),
|
|
||||||
duration -> LocalTime.now().plus(duration),
|
|
||||||
data -> Duration.between(LocalTime.now(), data)
|
|
||||||
);
|
|
||||||
|
|
||||||
ConfigurationHolder<TestSource> provider = new ConfigurationHolder<TestSource>(
|
|
||||||
registry, new ConfigurationOptionHolder(),
|
|
||||||
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);
|
|
||||||
Object d = registry.serialize(provider, v);
|
|
||||||
|
|
||||||
System.out.println(v);
|
|
||||||
System.out.println(d);
|
|
||||||
System.out.println(registry.deserialize(provider, TestEnum.class, "C"));
|
|
||||||
System.out.println(registry.serialize(provider, TestEnum.C).getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TestEnum {
|
|
||||||
A, b, C
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package cc.carm.test.config;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
|
|
||||||
import cc.carm.lib.configuration.annotation.ConfigPath;
|
|
||||||
import cc.carm.lib.configuration.Configuration;
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
|
||||||
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
public class LoaderTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws Exception {
|
|
||||||
ConfigurationHolder<TestSource> provider = new ConfigurationHolder<TestSource>(
|
|
||||||
new ValueAdapterRegistry(), new ConfigurationOptionHolder(),
|
|
||||||
new ConcurrentHashMap<>(), new ConfigurationInitializer()
|
|
||||||
) {
|
|
||||||
final TestSource source = new TestSource(this, System.currentTimeMillis());
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull TestSource config() {
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ConfigurationInitializer loader = new ConfigurationInitializer();
|
|
||||||
loader.initialize(provider, ROOT.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ROOT extends Configuration {
|
|
||||||
|
|
||||||
interface SUB extends Configuration {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ConfigPath(root = true)
|
|
||||||
interface EXTERNAL extends Configuration {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ConfigPath("NO")
|
|
||||||
interface YES extends Configuration {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
package cc.carm.test.config;
|
|
||||||
|
|
||||||
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.Nullable;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class TestSection implements ConfigureSection {
|
|
||||||
@Override
|
|
||||||
public @NotNull ConfigureSource<?, ?, ?> source() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 ConfigureSection getSection(@NotNull String path) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Object get(@NotNull String path) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package cc.carm.test.config;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
|
||||||
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class TestSource extends ConfigureSource<TestSection, Map<String, String>, TestSource> {
|
|
||||||
|
|
||||||
|
|
||||||
public TestSource(@NotNull ConfigurationHolder<? extends TestSource> holder, long lastUpdateMillis) {
|
|
||||||
super(holder, lastUpdateMillis);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TestSource self() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onReload() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Map<String, String> original() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull TestSection section() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ConfigureSource<?, ?, ?> source() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -69,14 +69,14 @@ public class ConfigurationTest {
|
|||||||
provider.initialize(TEST);
|
provider.initialize(TEST);
|
||||||
|
|
||||||
System.out.println("> Test Inner value before:");
|
System.out.println("> Test Inner value before:");
|
||||||
System.out.println(TEST.INSTANCE.INNER_VALUE.getNotNull());
|
System.out.println(TEST.INSTANCE.INNER_VALUE.resolve());
|
||||||
|
|
||||||
double after = Math.random() * 200D;
|
double after = Math.random() * 200D;
|
||||||
System.out.println("> Test Inner value -> " + after);
|
System.out.println("> Test Inner value -> " + after);
|
||||||
TEST.INSTANCE.INNER_VALUE.set(after);
|
TEST.INSTANCE.INNER_VALUE.set(after);
|
||||||
|
|
||||||
System.out.println("> Test Inner value after:");
|
System.out.println("> Test Inner value after:");
|
||||||
System.out.println(TEST.INSTANCE.INNER_VALUE.getNotNull());
|
System.out.println(TEST.INSTANCE.INNER_VALUE.resolve());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+31
-4
@@ -1,5 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.source.file;
|
package cc.carm.lib.configuration.source.file;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.function.DataConsumer;
|
||||||
import cc.carm.lib.configuration.function.DataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.option.FileConfigOptions;
|
import cc.carm.lib.configuration.source.option.FileConfigOptions;
|
||||||
@@ -14,7 +15,6 @@ import java.net.URLConnection;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINAL, SELF extends FileConfigSource<SECTION, ORIGINAL, SELF>>
|
public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINAL, SELF extends FileConfigSource<SECTION, ORIGINAL, SELF>>
|
||||||
extends ConfigureSource<SECTION, ORIGINAL, SELF> {
|
extends ConfigureSource<SECTION, ORIGINAL, SELF> {
|
||||||
@@ -38,7 +38,6 @@ public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINA
|
|||||||
return holder().options().get(FileConfigOptions.COPY_DEFAULTS);
|
return holder().options().get(FileConfigOptions.COPY_DEFAULTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void initializeFile() throws IOException {
|
public void initializeFile() throws IOException {
|
||||||
if (this.file.exists()) return;
|
if (this.file.exists()) return;
|
||||||
|
|
||||||
@@ -74,13 +73,41 @@ public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fileOutputStream(@NotNull Consumer<OutputStream> stream) throws Exception {
|
protected <R> R fileReadString(@NotNull DataFunction<String, R> loader) throws Exception {
|
||||||
|
try (InputStream is = Files.newInputStream(file.toPath())) {
|
||||||
|
try (Reader r = new InputStreamReader(is, charset())) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
char[] buf = new char[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = r.read(buf)) > 0) {
|
||||||
|
sb.append(buf, 0, len);
|
||||||
|
}
|
||||||
|
return loader.handle(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fileReadString(@NotNull DataConsumer<String> loader) throws Exception {
|
||||||
|
try (InputStream is = Files.newInputStream(file.toPath())) {
|
||||||
|
try (Reader r = new InputStreamReader(is, charset())) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
char[] buf = new char[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = r.read(buf)) > 0) {
|
||||||
|
sb.append(buf, 0, len);
|
||||||
|
}
|
||||||
|
loader.accept(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fileOutputStream(@NotNull DataConsumer<OutputStream> stream) throws Exception {
|
||||||
try (OutputStream os = Files.newOutputStream(file.toPath())) {
|
try (OutputStream os = Files.newOutputStream(file.toPath())) {
|
||||||
stream.accept(os);
|
stream.accept(os);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fileWriter(@NotNull Consumer<Writer> writer) throws Exception {
|
protected void fileWriter(@NotNull DataConsumer<Writer> writer) throws Exception {
|
||||||
try (OutputStream os = Files.newOutputStream(file.toPath())) {
|
try (OutputStream os = Files.newOutputStream(file.toPath())) {
|
||||||
try (Writer w = new OutputStreamWriter(os, charset())) {
|
try (Writer w = new OutputStreamWriter(os, charset())) {
|
||||||
writer.accept(w);
|
writer.accept(w);
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>cc.carm.lib</groupId>
|
||||||
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
|
<version>3.9.1</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>${project.jdk.version}</maven.compiler.source>
|
||||||
|
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<artifactId>easyconfiguration-feature-section</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>easyconfiguration-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
+37
-27
@@ -1,34 +1,39 @@
|
|||||||
package cc.carm.lib.configuration.source.json;
|
package cc.carm.lib.configuration.source.section;
|
||||||
|
|
||||||
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.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class JSONSection implements ConfigureSection {
|
public class MemorySection implements ConfigureSection {
|
||||||
|
|
||||||
protected final @NotNull ConfigureSource<? extends JSONSection, ?, ?> source;
|
public static @NotNull MemorySection root(@NotNull ConfigureSource<? extends MemorySection, ?, ?> source) {
|
||||||
|
return new MemorySection(source, new LinkedHashMap<>(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull MemorySection root(@NotNull ConfigureSource<? extends MemorySection, ?, ?> source,
|
||||||
|
@Nullable Map<?, ?> data) {
|
||||||
|
return new MemorySection(source, data == null ? new LinkedHashMap<>() : data, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final @NotNull ConfigureSource<? extends MemorySection, ?, ?> source;
|
||||||
protected final @NotNull Map<String, Object> data;
|
protected final @NotNull Map<String, Object> data;
|
||||||
protected final @Nullable JSONSection parent;
|
protected final @Nullable MemorySection parent;
|
||||||
|
|
||||||
public JSONSection(@NotNull ConfigureSource<? extends JSONSection, ?, ?> source,
|
public MemorySection(@NotNull ConfigureSource<? extends MemorySection, ?, ?> source,
|
||||||
@NotNull Map<?, ?> data, @Nullable JSONSection parent) {
|
@NotNull Map<?, ?> data, @Nullable MemorySection parent) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.data = new LinkedHashMap<>();
|
this.data = new LinkedHashMap<>();
|
||||||
|
|
||||||
for (Map.Entry<?, ?> entry : data.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 JSONSection(source, (Map<?, ?>) entry.getValue(), this));
|
this.data.put(key, createChild((Map<?, ?>) entry.getValue()));
|
||||||
} else if (entry.getValue() instanceof List) {
|
} else if (entry.getValue() instanceof List) {
|
||||||
List<Object> list = new ArrayList<>();
|
List<Object> list = new ArrayList<>();
|
||||||
for (Object obj : (List<?>) entry.getValue()) {
|
for (Object obj : (List<?>) entry.getValue()) {
|
||||||
if (obj instanceof Map) {
|
if (obj instanceof Map) {
|
||||||
list.add(new JSONSection(source, (Map<?, ?>) obj, this));
|
list.add(createChild((Map<?, ?>) obj));
|
||||||
} else {
|
} else {
|
||||||
list.add(obj);
|
list.add(obj);
|
||||||
}
|
}
|
||||||
@@ -40,8 +45,16 @@ public class JSONSection implements ConfigureSection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected @NotNull MemorySection createChild(@NotNull Map<?, ?> data) {
|
||||||
|
return new MemorySection(source(), data, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected @NotNull MemorySection createChild() {
|
||||||
|
return createChild(new LinkedHashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ConfigureSource<? extends JSONSection, ?, ?> source() {
|
public @NotNull ConfigureSource<? extends MemorySection, ?, ?> source() {
|
||||||
return this.source;
|
return this.source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +62,7 @@ public class JSONSection implements ConfigureSection {
|
|||||||
return this.data;
|
return this.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable JSONSection parent() {
|
public @Nullable MemorySection parent() {
|
||||||
return this.parent;
|
return this.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,11 +77,9 @@ public class JSONSection implements ConfigureSection {
|
|||||||
|
|
||||||
@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 = createChild((Map<?, ?>) value);
|
||||||
value = new JSONSection(source(), (Map<?, ?>) value, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONSection section = getSectionFor(path);
|
MemorySection section = getSectionFor(path);
|
||||||
if (section == this) {
|
if (section == this) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
this.data.remove(path);
|
this.data.remove(path);
|
||||||
@@ -87,7 +98,7 @@ public class JSONSection implements ConfigureSection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Object get(@NotNull String path) {
|
public @Nullable Object get(@NotNull String path) {
|
||||||
JSONSection section = getSectionFor(path);
|
MemorySection section = getSectionFor(path);
|
||||||
return section == this ? data.get(path) : section.get(getChild(path));
|
return section == this ? data.get(path) : section.get(getChild(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +115,7 @@ public class JSONSection implements ConfigureSection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSection(@NotNull String path) {
|
public boolean isSection(@NotNull String path) {
|
||||||
return get(path) instanceof JSONSection;
|
return get(path) instanceof ConfigureSection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -113,18 +124,18 @@ public class JSONSection implements ConfigureSection {
|
|||||||
return (val instanceof ConfigureSection) ? (ConfigureSection) val : null;
|
return (val instanceof ConfigureSection) ? (ConfigureSection) val : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JSONSection getSectionFor(String path) {
|
private MemorySection 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 JSONSection(source(), new LinkedHashMap<>(), this);
|
section = createChild();
|
||||||
this.data.put(root, section);
|
this.data.put(root, section);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (JSONSection) section;
|
return (MemorySection) section;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getChild(String path) {
|
private String getChild(String path) {
|
||||||
@@ -140,16 +151,15 @@ public class JSONSection implements ConfigureSection {
|
|||||||
* @param section The section to map the values from
|
* @param section The section to map the values from
|
||||||
* @param parent The parent path
|
* @param parent The parent path
|
||||||
* @param deep If the mapping should be deep
|
* @param deep If the mapping should be deep
|
||||||
* @author md_5, sk89q
|
|
||||||
*/
|
*/
|
||||||
protected void mapChildrenValues(@NotNull Map<String, Object> output, @NotNull JSONSection section,
|
protected void mapChildrenValues(@NotNull Map<String, Object> output, @NotNull MemorySection 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 + separator()) + 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 JSONSection) {
|
if (deep && entry.getValue() instanceof MemorySection) {
|
||||||
this.mapChildrenValues(output, (JSONSection) entry.getValue(), path, true);
|
this.mapChildrenValues(output, (MemorySection) entry.getValue(), path, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -19,7 +19,7 @@ public interface VersionedMetaTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void register(@NotNull ConfigurationInitializer initializer) {
|
static void register(@NotNull ConfigurationInitializer initializer) {
|
||||||
initializer.registerAnnotation(ConfigVersion.class, VERSION, ConfigVersion::value);
|
initializer.registerFieldAnnotation(ConfigVersion.class, VERSION, ConfigVersion::value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,9 @@
|
|||||||
<version>3.9.1</version>
|
<version>3.9.1</version>
|
||||||
<modules>
|
<modules>
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
<module>features/commentable</module>
|
<module>features/section</module>
|
||||||
<module>features/file</module>
|
<module>features/file</module>
|
||||||
|
<module>features/commentable</module>
|
||||||
<module>features/versioned</module>
|
<module>features/versioned</module>
|
||||||
|
|
||||||
<module>providers/yaml</module>
|
<module>providers/yaml</module>
|
||||||
|
|||||||
@@ -34,6 +34,13 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>easyconfiguration-feature-section</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.parent.groupId}</groupId>
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
<artifactId>easyconfiguration-demo</artifactId>
|
<artifactId>easyconfiguration-demo</artifactId>
|
||||||
|
|||||||
+5
-6
@@ -28,7 +28,7 @@ public class JSONConfigFactory extends FileConfigFactory<JSONSource, Configurati
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONConfigFactory self() {
|
protected JSONConfigFactory self() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,10 +37,6 @@ public class JSONConfigFactory extends FileConfigFactory<JSONSource, Configurati
|
|||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONConfigFactory gson(@NotNull Gson gson) {
|
|
||||||
return gson(() -> gson);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JSONConfigFactory gson(@NotNull Consumer<GsonBuilder> builder) {
|
public JSONConfigFactory gson(@NotNull Consumer<GsonBuilder> builder) {
|
||||||
return gson(() -> {
|
return gson(() -> {
|
||||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||||
@@ -49,6 +45,9 @@ public class JSONConfigFactory extends FileConfigFactory<JSONSource, Configurati
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JSONConfigFactory gson(@NotNull Gson gson) {
|
||||||
|
return gson(() -> gson);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ConfigurationHolder<JSONSource> build() {
|
public @NotNull ConfigurationHolder<JSONSource> build() {
|
||||||
@@ -59,7 +58,7 @@ public class JSONConfigFactory extends FileConfigFactory<JSONSource, Configurati
|
|||||||
String sourcePath = this.resourcePath;
|
String sourcePath = this.resourcePath;
|
||||||
|
|
||||||
return new ConfigurationHolder<JSONSource>(this.adapters, this.options, new ConcurrentHashMap<>(), this.initializer) {
|
return new ConfigurationHolder<JSONSource>(this.adapters, this.options, new ConcurrentHashMap<>(), this.initializer) {
|
||||||
final JSONSource source = new JSONSource(this, 0, configFile, sourcePath, gson);
|
final JSONSource source = new JSONSource(this, configFile, sourcePath, gson);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull JSONSource config() {
|
public @NotNull JSONSource config() {
|
||||||
|
|||||||
+22
-21
@@ -2,36 +2,38 @@ package cc.carm.lib.configuration.source.json;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.file.FileConfigSource;
|
import cc.carm.lib.configuration.source.file.FileConfigSource;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
import cc.carm.lib.configuration.source.section.MemorySection;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonSerializer;
|
import com.google.gson.JsonSerializer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class JSONSource extends FileConfigSource<JSONSection, Map<?, ?>, JSONSource> {
|
public class JSONSource extends FileConfigSource<MemorySection, Map<?, ?>, JSONSource> {
|
||||||
|
|
||||||
public static final @NotNull Gson DEFAULT_GSON = new GsonBuilder()
|
public static final @NotNull Gson DEFAULT_GSON = new GsonBuilder()
|
||||||
.serializeNulls().disableHtmlEscaping().setPrettyPrinting()
|
.serializeNulls().disableHtmlEscaping().setPrettyPrinting()
|
||||||
.registerTypeAdapter(
|
.registerTypeAdapter(
|
||||||
JSONSection.class,
|
MemorySection.class,
|
||||||
(JsonSerializer<JSONSection>) (src, typeOfSrc, context) -> context.serialize(src.data)
|
(JsonSerializer<MemorySection>) (src, t, c) -> c.serialize(src.data())
|
||||||
).create();
|
).create();
|
||||||
|
|
||||||
protected final @NotNull Gson gson;
|
protected final @NotNull Gson gson;
|
||||||
protected @Nullable JSONSection rootSection;
|
protected @Nullable MemorySection rootSection;
|
||||||
|
|
||||||
protected JSONSource(@NotNull ConfigurationHolder<? extends JSONSource> holder, long lastUpdateMillis,
|
protected JSONSource(@NotNull ConfigurationHolder<? extends JSONSource> holder,
|
||||||
@NotNull File file, @Nullable String resourcePath) {
|
@NotNull File file, @Nullable String resourcePath) {
|
||||||
this(holder, lastUpdateMillis, file, resourcePath, DEFAULT_GSON);
|
this(holder, file, resourcePath, DEFAULT_GSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JSONSource(@NotNull ConfigurationHolder<? extends JSONSource> holder, long lastUpdateMillis,
|
protected JSONSource(@NotNull ConfigurationHolder<? extends JSONSource> holder,
|
||||||
@NotNull File file, @Nullable String resourcePath, @NotNull Gson gson) {
|
@NotNull File file, @Nullable String resourcePath, @NotNull Gson gson) {
|
||||||
super(holder, lastUpdateMillis, file, resourcePath);
|
super(holder, 0, file, resourcePath);
|
||||||
this.gson = gson;
|
this.gson = gson;
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
@@ -50,19 +52,14 @@ public class JSONSource extends FileConfigSource<JSONSection, Map<?, ?>, JSONSou
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ConfigureSource<?, ?, ?> source() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Map<?, ?> original() {
|
public @NotNull Map<?, ?> original() {
|
||||||
return section().data();
|
return section().data();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull JSONSection section() {
|
public @NotNull MemorySection section() {
|
||||||
return Objects.requireNonNull(this.rootSection, "Section is not initialized");
|
return Objects.requireNonNull(this.rootSection, "Root section is not initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -70,11 +67,15 @@ public class JSONSource extends FileConfigSource<JSONSection, Map<?, ?>, JSONSou
|
|||||||
fileWriter(writer -> gson.toJson(original(), writer));
|
fileWriter(writer -> gson.toJson(original(), writer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NotNull String saveToString() {
|
||||||
|
return gson.toJson(original());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onReload() throws Exception {
|
protected void onReload() throws Exception {
|
||||||
Map<?, ?> data = fileReader(reader -> gson.fromJson(reader, LinkedHashMap.class));
|
this.rootSection = MemorySection.root(
|
||||||
if (data == null) data = new LinkedHashMap<>();
|
this, fileReader(reader -> gson.fromJson(reader, LinkedHashMap.class))
|
||||||
this.rootSection = new JSONSection(this, data, null);
|
);
|
||||||
this.lastUpdateMillis = System.currentTimeMillis(); // 更新时间
|
this.lastUpdateMillis = System.currentTimeMillis(); // 更新时间
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,20 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>easyconfiguration-feature-section</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>easyconfiguration-feature-commentable</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.yaml</groupId>
|
<groupId>org.yaml</groupId>
|
||||||
<artifactId>snakeyaml</artifactId>
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.source.yaml;
|
|
||||||
|
|
||||||
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.Nullable;
|
|
||||||
import org.jetbrains.annotations.UnmodifiableView;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class YAMLSection implements ConfigureSection {
|
|
||||||
|
|
||||||
protected final @NotNull ConfigureSource<? extends YAMLSection, ?, ?> source;
|
|
||||||
protected final @NotNull Map<String, Object> data;
|
|
||||||
protected final @Nullable YAMLSection parent;
|
|
||||||
|
|
||||||
public YAMLSection(@NotNull ConfigureSource<? extends YAMLSection, ?, ?> source,
|
|
||||||
@NotNull Map<String, Object> data, @Nullable YAMLSection parent) {
|
|
||||||
this.source = source;
|
|
||||||
this.data = data;
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ConfigureSource<?, ?, ?> source() {
|
|
||||||
return this.source;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable YAMLSection parent() {
|
|
||||||
return this.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull @UnmodifiableView 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 YAMLSection getSection(@NotNull String path) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Object get(@NotNull String path) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package sample;
|
|
||||||
|
|
||||||
public class Sample {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
// 1. Make a configuration provider from a file.
|
|
||||||
ConfigurationProvider<?> provider = EasyConfiguration.from("config.yml");
|
|
||||||
// 2. Initialize the configuration classes or instances.
|
|
||||||
provider.initialize(SampleConfig.class);
|
|
||||||
// 3. Enjoy using the configuration!
|
|
||||||
SampleConfig.ENABLED.set(false);
|
|
||||||
System.out.println("Your name is " + SampleConfig.INFO.NAME.getNotNull() + " !");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package sample;
|
package sample;
|
||||||
|
|
||||||
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;
|
||||||
@@ -9,6 +9,7 @@ import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
|||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ConfigPath(root = true)
|
||||||
@HeaderComment("Configurations for sample")
|
@HeaderComment("Configurations for sample")
|
||||||
public interface SampleConfig extends Configuration {
|
public interface SampleConfig extends Configuration {
|
||||||
|
|
||||||
@@ -16,12 +17,13 @@ public interface SampleConfig extends Configuration {
|
|||||||
ConfiguredValue<Boolean> ENABLED = ConfiguredValue.of(true);
|
ConfiguredValue<Boolean> ENABLED = ConfiguredValue.of(true);
|
||||||
|
|
||||||
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
|
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
|
||||||
.parseValue(UUID::fromString).serializeValue(UUID::toString)
|
.parse(UUID::fromString).serialize(UUID::toString)
|
||||||
.defaults(
|
.defaults(
|
||||||
UUID.fromString("00000000-0000-0000-0000-000000000000"),
|
UUID.fromString("00000000-0000-0000-0000-000000000000"),
|
||||||
UUID.fromString("00000000-0000-0000-0000-000000000001")
|
UUID.fromString("00000000-0000-0000-0000-000000000001")
|
||||||
).build();
|
).build();
|
||||||
|
|
||||||
|
@ConfigPath("info") // Custom path
|
||||||
interface INFO extends Configuration {
|
interface INFO extends Configuration {
|
||||||
|
|
||||||
@HeaderComment("Configure your name!") // Header comment
|
@HeaderComment("Configure your name!") // Header comment
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package sample;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import cc.carm.lib.configuration.source.yaml.YAMLConfigFactory;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class SampleTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
// 1. Make a configuration provider from a file.
|
||||||
|
ConfigurationHolder<?> holder = YAMLConfigFactory.from("target/config.yml")
|
||||||
|
.resourcePath("configs/sample.yml")
|
||||||
|
.indent(4) // Optional: Set the indentation of the configuration file.
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 2. Initialize the configuration classes or instances.
|
||||||
|
holder.initialize(SampleConfig.class);
|
||||||
|
// 3. Enjoy using the configuration!
|
||||||
|
SampleConfig.ENABLED.set(false);
|
||||||
|
System.out.println("Your name is " + SampleConfig.INFO.NAME.resolve() + " (age=" + SampleConfig.INFO.AGE.resolve() + ")!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user