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

feat!(core): Update files sources

This commit is contained in:
2025-02-10 03:16:48 +08:00
parent 45ca8b02d4
commit 2093091923
30 changed files with 402 additions and 218 deletions
@@ -1,6 +1,6 @@
package cc.carm.lib.configuration.adapter;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -53,13 +53,13 @@ public class ValueAdapter<TYPE>
}
@Override
public Object serialize(@NotNull ConfigurationProvider<?> provider, @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");
return serializer.serialize(provider, type, value);
}
@Override
public TYPE parse(@NotNull ConfigurationProvider<?> provider, @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");
return deserializer.parse(provider, type, value);
}
@@ -1,7 +1,7 @@
package cc.carm.lib.configuration.adapter;
import cc.carm.lib.configuration.function.DataFunction;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -100,12 +100,12 @@ public class ValueAdapterRegistry {
}
@Contract("_,_,null -> null")
public <T> T deserialize(@NotNull ConfigurationProvider<?> provider, @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);
}
@Contract("_,_,null -> null")
public <T> T deserialize(@NotNull ConfigurationProvider<?> provider, @NotNull ValueType<T> type, @Nullable Object source) throws Exception {
public <T> T deserialize(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<T> type, @Nullable Object source) throws Exception {
if (source == null) return null; // Null check
if (type.isInstance(source)) return type.cast(source); // Not required to deserialize
ValueAdapter<T> adapter = adapterOf(type);
@@ -114,7 +114,7 @@ public class ValueAdapterRegistry {
}
@Contract("_,null -> null")
public <T> Object serialize(@NotNull ConfigurationProvider<?> provider, @Nullable T value) throws Exception {
public <T> Object serialize(@NotNull ConfigurationHolder<?> holder, @Nullable T value) throws Exception {
if (value == null) return null; // Null check
ValueType<T> type = ValueType.of(value);
ValueAdapter<T> adapter = adapterOf(type);
@@ -1,6 +1,6 @@
package cc.carm.lib.configuration.adapter;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
/**
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
public interface ValueParser<TYPE> {
TYPE parse(
@NotNull ConfigurationProvider<?> provider,
@NotNull ConfigurationHolder<?> holder,
@NotNull ValueType<? super TYPE> type, @NotNull Object data
) throws Exception;
@@ -1,6 +1,6 @@
package cc.carm.lib.configuration.adapter;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
/**
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
public interface ValueSerializer<TYPE> {
Object serialize(
@NotNull ConfigurationProvider<?> provider,
@NotNull ConfigurationHolder<?> holder,
@NotNull ValueType<? super TYPE> type, @NotNull TYPE value
) throws Exception;
@@ -1,7 +1,7 @@
package cc.carm.lib.configuration.builder;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
import cc.carm.lib.configuration.value.ConfigValue;
@@ -14,7 +14,7 @@ import java.util.function.Consumer;
import java.util.function.Supplier;
public abstract class AbstractConfigBuilder<
TYPE, RESULT extends ConfigValue<TYPE>, PROVIDER extends ConfigurationProvider<?>,
TYPE, RESULT extends ConfigValue<TYPE>, PROVIDER extends ConfigurationHolder<?>,
SELF extends AbstractConfigBuilder<TYPE, RESULT, PROVIDER, SELF>
> {
@@ -25,7 +25,7 @@ public abstract class AbstractConfigBuilder<
protected @Nullable String path;
protected @NotNull Supplier<TYPE> defaultValueSupplier = () -> null;
protected @NotNull BiConsumer<ConfigurationProvider<?>, String> initializer = (provider, path) -> {
protected @NotNull BiConsumer<ConfigurationHolder<?>, String> initializer = (provider, path) -> {
};
protected AbstractConfigBuilder(Class<? super PROVIDER> providerClass, ValueType<TYPE> type) {
@@ -51,16 +51,16 @@ public abstract class AbstractConfigBuilder<
return self();
}
public @NotNull SELF initializer(@NotNull BiConsumer<ConfigurationProvider<?>, String> initializer) {
public @NotNull SELF initializer(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
this.initializer = initializer;
return self();
}
public @NotNull SELF append(@NotNull BiConsumer<ConfigurationProvider<?>, String> initializer) {
public @NotNull SELF append(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
return initializer(initializer.andThen(initializer));
}
public @NotNull SELF append(@NotNull Consumer<ConfigurationProvider<?>> initializer) {
public @NotNull SELF append(@NotNull Consumer<ConfigurationHolder<?>> initializer) {
return append((provider, path) -> initializer.accept(provider));
}
@@ -1,14 +1,14 @@
package cc.carm.lib.configuration.builder;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.value.ConfigValue;
public abstract class CommonConfigBuilder<TYPE, RESULT extends ConfigValue<TYPE>, SELF extends CommonConfigBuilder<TYPE, RESULT, SELF>>
extends AbstractConfigBuilder<TYPE, RESULT, ConfigurationProvider<?>, SELF> {
extends AbstractConfigBuilder<TYPE, RESULT, ConfigurationHolder<?>, SELF> {
protected CommonConfigBuilder(ValueType<TYPE> type) {
super(ConfigurationProvider.class, type);
super(ConfigurationHolder.class, type);
}
}
@@ -2,7 +2,7 @@ package cc.carm.lib.configuration.function;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -12,7 +12,7 @@ import java.util.Objects;
@FunctionalInterface
public interface ValueHandler<T, R> {
@Nullable R handle(@NotNull ConfigurationProvider<?> provider, @NotNull T data) throws Exception;
@Nullable R handle(@NotNull ConfigurationHolder<?> holder, @NotNull T data) throws Exception;
default <V> ValueHandler<T, V> andThen(@NotNull ValueHandler<R, V> after) {
Objects.requireNonNull(after);
@@ -47,7 +47,7 @@ public interface ValueHandler<T, R> {
@Contract(pure = true)
static <T> @NotNull ValueHandler<T, Object> toObject() {
return ConfigurationProvider::serialize;
return ConfigurationHolder::serialize;
}
@Contract(pure = true)
@@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
import java.util.function.Function;
public abstract class ConfigurationFactory<SOURCE extends ConfigurationSource<SOURCE, ?>, PROVIDER extends ConfigurationProvider<SOURCE>, SELF> {
public abstract class ConfigurationFactory<SOURCE extends ConfigurationSource<SOURCE, ?>, PROVIDER extends ConfigurationHolder<SOURCE>, SELF> {
protected Function<PROVIDER, ConfigurationInitializer> loaderFunction = PROVIDER -> new ConfigurationInitializer();
protected Consumer<ConfigurationInitializer> loaderConsumer = loader -> {
@@ -13,22 +13,22 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Objects;
public class ConfigurationProvider<S extends ConfigurationSource<S, ?>> {
public class ConfigurationHolder<S extends ConfigurationSource<S, ?>> {
protected final @NotNull S source;
protected final @NotNull ValueAdapterRegistry adapters;
protected final @NotNull ConfigurationOptionHolder options;
protected final @NotNull Map<String, ConfigurationMetaHolder> metadata;
protected final @NotNull ConfigurationInitializer initializer;
public ConfigurationProvider(@NotNull S source,
@NotNull ValueAdapterRegistry adapters,
protected @Nullable S source;
public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters,
@NotNull ConfigurationOptionHolder options,
@NotNull Map<String, ConfigurationMetaHolder> metadata,
@NotNull ConfigurationInitializer initializer) {
this.source = source;
this.initializer = initializer;
this.adapters = adapters;
this.options = options;
@@ -36,7 +36,7 @@ public class ConfigurationProvider<S extends ConfigurationSource<S, ?>> {
}
public @NotNull S source() {
return source;
return Objects.requireNonNull(source, "Source is not initialized");
}
public void reload() throws Exception {
@@ -100,7 +100,7 @@ public class ConfigurationProvider<S extends ConfigurationSource<S, ?>> {
}
public void load(@NotNull ValueManifest<?> value) {
value.provider(this);
value.holder(this);
}
}
@@ -1,6 +1,6 @@
package cc.carm.lib.configuration.source.loader;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -12,7 +12,7 @@ public interface ConfigInitializeHandler<T> {
};
}
void whenInitialize(@NotNull ConfigurationProvider<?> provider, @Nullable String path, @NotNull T value) throws Exception;
void whenInitialize(@NotNull ConfigurationHolder<?> holder, @Nullable String path, @NotNull T value) throws Exception;
default ConfigInitializeHandler<T> andThen(ConfigInitializeHandler<T> after) {
return (provider, path, value) -> {
@@ -1,7 +1,7 @@
package cc.carm.lib.configuration.source.loader;
import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
import cc.carm.lib.configuration.source.option.StandardOptions;
import cc.carm.lib.configuration.value.ConfigValue;
@@ -83,28 +83,28 @@ public class ConfigurationInitializer {
}
public @Nullable String getFieldPath(ConfigurationProvider<?> provider, @Nullable String parentPath, @NotNull Field field) {
public @Nullable String getFieldPath(ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) {
return pathGenerator.getFieldPath(provider, parentPath, field);
}
public @Nullable String getClassPath(ConfigurationProvider<?> provider, @Nullable String parentPath,
public @Nullable String getClassPath(ConfigurationHolder<?> holder, @Nullable String parentPath,
@NotNull Class<?> clazz, @Nullable Field clazzField) {
return pathGenerator.getClassPath(provider, parentPath, clazz, clazzField);
}
public void initialize(ConfigurationProvider<?> provider, @NotNull Configuration config) throws Exception {
public void initialize(ConfigurationHolder<?> holder, @NotNull Configuration config) throws Exception {
initializeInstance(provider, config, null, null);
if (provider.options().get(StandardOptions.SET_DEFAULTS)) provider.save();
}
public void initialize(ConfigurationProvider<?> provider, @NotNull Class<? extends Configuration> clazz) throws Exception {
public void initialize(ConfigurationHolder<?> holder, @NotNull Class<? extends Configuration> clazz) throws Exception {
initializeStaticClass(provider, clazz, null, null);
if (provider.options().get(StandardOptions.SET_DEFAULTS)) provider.save();
}
// 针对实例类的初始化方法
protected void initializeInstance(@NotNull ConfigurationProvider<?> provider,
protected void initializeInstance(@NotNull ConfigurationHolder<?> holder,
@NotNull Configuration root, @Nullable String parentPath, @Nullable Field configField) {
String path = getClassPath(provider, parentPath, root.getClass(), configField);
try {
@@ -117,7 +117,7 @@ public class ConfigurationInitializer {
// 针对静态类的初始化方法
@SuppressWarnings("unchecked")
protected void initializeStaticClass(@NotNull ConfigurationProvider<?> provider,
protected void initializeStaticClass(@NotNull ConfigurationHolder<?> holder,
@NotNull Class<?> clazz, @Nullable String parentPath, @Nullable Field configField) {
if (!Configuration.class.isAssignableFrom(clazz)) return; // 只解析继承了 ConfigurationRoot 的类
@@ -141,7 +141,7 @@ public class ConfigurationInitializer {
}
}
protected void initializeField(@NotNull ConfigurationProvider<?> provider,
protected void initializeField(@NotNull ConfigurationHolder<?> holder,
@NotNull Object source, @NotNull Field field, @Nullable String parent) {
try {
field.setAccessible(true);
@@ -1,7 +1,7 @@
package cc.carm.lib.configuration.source.loader;
import cc.carm.lib.configuration.annotation.ConfigPath;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.option.StandardOptions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,14 +37,14 @@ public class PathGenerator {
return pathConverter.apply(name);
}
public @Nullable String getFieldPath(@NotNull ConfigurationProvider<?> provider,
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder,
@Nullable String parentPath, @NotNull Field field) {
ConfigPath path = field.getAnnotation(ConfigPath.class);
if (path == null) return link(provider, parentPath, false, field.getName()); // No annotation, use field name.
else return link(provider, parentPath, path.root(), select(path.value(), field.getName()));
}
public @Nullable String getClassPath(@NotNull ConfigurationProvider<?> provider,
public @Nullable String getClassPath(@NotNull ConfigurationHolder<?> holder,
@Nullable String parentPath, @NotNull Class<?> clazz, @Nullable Field clazzField) {
// For standard path generator, we generate path following by:
// 1. Check if the class has a ConfigPath annotation, if so, use the root and value as the path.
@@ -67,7 +67,7 @@ public class PathGenerator {
else return isBlank(path) ? null : path;
}
protected @Nullable String link(@NotNull ConfigurationProvider<?> provider,
protected @Nullable String link(@NotNull ConfigurationHolder<?> holder,
@Nullable String parent, boolean root, @Nullable String path) {
if (path == null || path.isEmpty()) return root ? null : parent;
return root || parent == null ? covertPath(path) : parent + pathSeparator(provider) + covertPath(path);
@@ -77,7 +77,7 @@ public class PathGenerator {
return path == null || path.replace(" ", "").isEmpty();
}
public static char pathSeparator(ConfigurationProvider<?> provider) {
public static char pathSeparator(ConfigurationHolder<?> holder) {
return provider.options().get(StandardOptions.PATH_SEPARATOR);
}
@@ -1,6 +1,7 @@
package cc.carm.lib.configuration.source.option;
import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import static cc.carm.lib.configuration.source.option.ConfigurationOption.of;
@@ -26,7 +27,7 @@ public interface StandardOptions {
* <br> if false, the values will be parsed when calling
* {@link cc.carm.lib.configuration.value.ConfigValue#get()}
* <br> if true, the values will be parsed when
* {@link cc.carm.lib.configuration.source.ConfigurationProvider#load(Configuration)}.
* {@link ConfigurationHolder#load(Configuration)}.
*/
ConfigurationOption<Boolean> PRELOAD = of(false);
@@ -1,19 +1,27 @@
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 long updateMillis;
protected final @NotNull ConfigurationHolder<? extends SELF> holder;
protected long lastUpdateMillis;
protected ConfigurationSource(long updateMillis) {
this.updateMillis = updateMillis;
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.updateMillis = System.currentTimeMillis();
this.lastUpdateMillis = System.currentTimeMillis();
}
protected abstract SELF self();
@@ -27,12 +35,12 @@ public abstract class ConfigurationSource<SELF extends ConfigurationSource<SELF,
protected abstract void onReload() throws Exception;
public long getUpdateMillis() {
return this.updateMillis;
public long getLastUpdateMillis() {
return this.lastUpdateMillis;
}
public boolean isExpired(long parsedTime) {
return getUpdateMillis() > parsedTime;
return getLastUpdateMillis() > parsedTime;
}
}
@@ -1,6 +1,6 @@
package cc.carm.lib.configuration.value;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,7 +46,7 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
/**
* 设定该配置的值。
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationProvider#save()} 方法。
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationHolder#save()} 方法。
*
* @param value 配置的值
*/
@@ -54,7 +54,7 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
/**
* 初始化该配置的默认值。
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationProvider#save()} 方法。
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationHolder#save()} 方法。
*/
public void setDefault() {
setDefault(false);
@@ -62,7 +62,7 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
/**
* 将该配置的值设置为默认值。
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationProvider#save()} 方法。
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationHolder#save()} 方法。
*
* @param override 是否覆盖已设定的值
*/
@@ -83,13 +83,13 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
/**
* Try to save the configuration.
* <br>To save multiple modifications,
* it is recommended to call {@link ConfigurationProvider#save()}
* it is recommended to call {@link ConfigurationHolder#save()}
* after all modifications are completed instead of this.
*
* @throws Exception
*/
public void save() throws Exception {
provider().save();
holder().save();
}
}
@@ -1,7 +1,7 @@
package cc.carm.lib.configuration.value;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
import cc.carm.lib.configuration.source.section.ConfigurationSource;
import org.jetbrains.annotations.NotNull;
@@ -13,9 +13,9 @@ import java.util.function.Supplier;
public class ValueManifest<T> {
protected final @NotNull ValueType<T> type;
protected final @NotNull BiConsumer<@NotNull ConfigurationProvider<?>, @NotNull String> initializer;
protected final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer;
protected @Nullable ConfigurationProvider<?> provider;
protected @Nullable ConfigurationHolder<?> holder;
protected @Nullable String path; // Section path
protected @NotNull Supplier<@Nullable T> defaultSupplier;
@@ -34,41 +34,41 @@ public class ValueManifest<T> {
}
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier,
@NotNull BiConsumer<@NotNull ConfigurationProvider<?>, @NotNull String> initializer) {
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer) {
this(type, defaultSupplier, initializer, null, null);
}
public ValueManifest(@NotNull ValueType<T> type, @NotNull Supplier<@Nullable T> defaultSupplier,
@NotNull BiConsumer<@NotNull ConfigurationProvider<?>, @NotNull String> initializer,
@Nullable ConfigurationProvider<?> provider, @Nullable String path) {
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer,
@Nullable ConfigurationHolder<?> holder, @Nullable String path) {
this.type = type;
this.initializer = initializer;
this.defaultSupplier = defaultSupplier;
this.provider = provider;
this.holder = holder;
this.path = path;
initialize();
}
protected ValueManifest(@NotNull ValueManifest<T> manifest) {
this(manifest.type, manifest.defaultSupplier, manifest.initializer, manifest.provider, manifest.path);
this(manifest.type, manifest.defaultSupplier, manifest.initializer, manifest.holder, manifest.path);
}
public void initialize(@NotNull ConfigurationProvider<?> provider, @NotNull String path) {
this.provider = provider;
public void initialize(@NotNull ConfigurationHolder<?> holder, @NotNull String path) {
this.holder = holder;
this.path = path;
initialize();
}
protected void initialize() {
if (provider != null && path != null) this.initializer.accept(provider, path);
if (holder != null && path != null) this.initializer.accept(holder, path);
}
public @NotNull ValueType<T> type() {
return this.type;
}
public void provider(@NotNull ConfigurationProvider<?> provider) {
this.provider = provider;
public void holder(@NotNull ConfigurationHolder<?> holder) {
this.holder = holder;
}
public void path(@NotNull String path) {
@@ -96,17 +96,17 @@ public class ValueManifest<T> {
else throw new IllegalStateException("No section path provided.");
}
public @NotNull ConfigurationProvider<?> provider() {
if (this.provider != null) return this.provider;
public @NotNull ConfigurationHolder<?> holder() {
if (this.holder != null) return this.holder;
throw new IllegalStateException("Value does not have a provider.");
}
public @NotNull ConfigurationSource<?, ?> config() {
return provider().source();
return holder().source();
}
public ConfigurationMetaHolder metadata() {
return provider().metadata(path());
return holder().metadata(path());
}
protected Object getData() {
@@ -118,7 +118,7 @@ public class ValueManifest<T> {
}
private static final @NotNull BiConsumer<@NotNull ConfigurationProvider<?>, @NotNull String> EMPTY_INITIALIZER = (provider, path) -> {
private static final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> EMPTY_INITIALIZER = (provider, path) -> {
};
}
@@ -28,7 +28,7 @@ public abstract class CachedConfigValue<T> extends ConfigValue<T> {
return cachedValue;
}
public boolean isExpired() {
public boolean cacheExpired() {
return this.parsedTime <= 0 || config().isExpired(this.parsedTime);
}
@@ -63,7 +63,7 @@ public abstract class CachedConfigValue<T> extends ConfigValue<T> {
*/
protected <O> @Nullable ValueParser<O> parserFor(@NotNull ValueAdapter<O> adapter) {
if (adapter.parser() != null) return adapter.parser();
ValueAdapter<O> registered = provider().adapters().adapterOf(adapter.type());
ValueAdapter<O> registered = holder().adapters().adapterOf(adapter.type());
if (registered == null) return null;
return registered.parser();
}
@@ -73,7 +73,7 @@ public abstract class CachedConfigValue<T> extends ConfigValue<T> {
*/
protected <O> @Nullable ValueSerializer<O> serializerFor(@NotNull ValueAdapter<O> adapter) {
if (adapter.serializer() != null) return adapter.serializer();
ValueAdapter<O> registered = provider().adapters().adapterOf(adapter.type());
ValueAdapter<O> registered = holder().adapters().adapterOf(adapter.type());
if (registered == null) return null;
return registered.serializer();
}
@@ -67,7 +67,7 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
@Override
public @NotNull List<V> get() {
if (!isExpired()) return getCachedOrDefault(createList());
if (!cacheExpired()) return getCachedOrDefault(createList());
// Data that is outdated and needs to be parsed again.
List<V> list = createList();
List<?> data = config().contains(path()) ? config().getList(path()) : null;
@@ -79,7 +79,7 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
for (Object dataVal : data) {
if (dataVal == null) continue;
try {
list.add(parser.parse(provider(), paramType(), dataVal));
list.add(parser.parse(holder(), paramType(), dataVal));
} catch (Exception e) {
e.printStackTrace();
}
@@ -101,7 +101,7 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
for (V val : value) {
if (val == null) continue;
try {
data.add(serializer.serialize(provider(), paramType(), val));
data.add(serializer.serialize(holder(), paramType(), val));
} catch (Exception ex) {
ex.printStackTrace();
}
@@ -54,7 +54,7 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
@Override
public @NotNull Map<K, V> get() {
if (!isExpired()) return getCachedOrDefault(createMap());
if (!cacheExpired()) return getCachedOrDefault(createMap());
// If the value is expired, we need to update it
Map<K, V> map = createMap();
@@ -72,8 +72,8 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
Object dataVal = section.get(dataKey);
if (dataVal == null) continue;
try {
K key = keyParser.parse(provider(), keyType(), dataKey);
V value = valueParser.parse(provider(), valueType(), dataVal);
K key = keyParser.parse(holder(), keyType(), dataKey);
V value = valueParser.parse(holder(), valueType(), dataVal);
map.put(key, value);
} catch (Exception e) {
e.printStackTrace();
@@ -109,8 +109,8 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
for (Map.Entry<K, V> entry : value.entrySet()) {
try {
data.put(
keySerializer.serialize(provider(), keyType(), entry.getKey()),
valueSerializer.serialize(provider(), valueType(), entry.getValue())
keySerializer.serialize(holder(), keyType(), entry.getKey()),
valueSerializer.serialize(holder(), valueType(), entry.getValue())
);
} catch (Exception e) {
e.printStackTrace();
@@ -89,7 +89,7 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
@Override
public V get() {
if (!isExpired()) return getCachedOrDefault();
if (!cacheExpired()) return getCachedOrDefault();
// Data that is outdated and needs to be parsed again.
Object data = getData();
@@ -100,7 +100,7 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
try {
// If there are no errors, update the cache and return.
return updateCache(parser.parse(provider(), type(), data));
return updateCache(parser.parse(holder(), type(), data));
} catch (Exception e) {
// There was a parsing error, prompted and returned the default value.
e.printStackTrace();
@@ -127,7 +127,7 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
if (serializer == null) return; // No serializer, do nothing.
try {
setData(serializer.serialize(provider(), type(), value));
setData(serializer.serialize(holder(), type(), value));
} catch (Exception e) {
e.printStackTrace();
}
+2 -2
View File
@@ -1,7 +1,7 @@
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.ConfigurationProvider;
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;
@@ -28,7 +28,7 @@ public class AdaptTest {
data -> Duration.between(LocalTime.now(), data)
);
ConfigurationProvider<TestSource> provider = new ConfigurationProvider<>(
ConfigurationHolder<TestSource> provider = new ConfigurationHolder<>(
new TestSource(), registry, new ConfigurationOptionHolder(),
new ConcurrentHashMap<>(), new ConfigurationInitializer()
);
@@ -3,7 +3,7 @@ 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.ConfigurationProvider;
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.junit.Test;
@@ -14,7 +14,7 @@ public class LoaderTest {
@Test
public void test() throws Exception {
ConfigurationProvider<TestSource> provider = new ConfigurationProvider<>(
ConfigurationHolder<TestSource> provider = new ConfigurationHolder<>(
new TestSource(), new ValueAdapterRegistry(), new ConfigurationOptionHolder(),
new ConcurrentHashMap<>(), new ConfigurationInitializer()
);
@@ -2,7 +2,7 @@ package cc.carm.lib.configuration.commentable;
import cc.carm.lib.configuration.annotation.HeaderComment;
import cc.carm.lib.configuration.annotation.InlineComment;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
import org.jetbrains.annotations.NotNull;
@@ -24,7 +24,7 @@ public interface CommentableMetaTypes {
ConfigurationMetadata<String> INLINE_COMMENT = ConfigurationMetadata.of();
static void register(@NotNull ConfigurationProvider<?> provider) {
static void register(@NotNull ConfigurationHolder<?> provider) {
register(provider.initializer());
}
@@ -2,7 +2,15 @@ package cc.carm.lib.configuration.option;
import cc.carm.lib.configuration.source.option.ConfigurationOption;
public class FileConfigOptions {
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public interface FileConfigOptions {
/**
* The charset of the file.
*/
ConfigurationOption<Charset> CHARSET = ConfigurationOption.of(StandardCharsets.UTF_8);
/**
* Whether to copy files from resource if exists.
@@ -1,87 +0,0 @@
//package cc.carm.lib.configuration.core.source.impl;
//
//import org.jetbrains.annotations.NotNull;
//import org.jetbrains.annotations.Nullable;
//
//import java.io.File;
//import java.io.IOException;
//import java.io.InputStream;
//import java.io.OutputStream;
//import java.net.URL;
//import java.net.URLConnection;
//import java.nio.file.Files;
//import java.util.Objects;
//
//public abstract class FileConfigProvider<W extends ConfigurationWrapper<?>> extends ConfigurationProvider<W> {
//
// protected final @NotNull File file;
//
// protected FileConfigProvider(@NotNull File file) {
// this.file = file;
// }
//
// public @NotNull File getFile() {
// return file;
// }
//
// public void initializeFile(@Nullable String sourcePath) throws IOException {
// if (this.file.exists()) return;
//
// File parent = this.file.getParentFile();
// if (parent != null && !parent.exists() && !parent.mkdirs()) {
// throw new IOException("Failed to create directory " + file.getParentFile().getAbsolutePath());
// }
//
// if (!this.file.createNewFile()) {
// throw new IOException("Failed to create file " + file.getAbsolutePath());
// }
//
// if (sourcePath != null) {
// try {
// saveResource(sourcePath, true);
// } catch (IllegalArgumentException ignored) {
// }
// }
// }
//
// public void saveResource(@NotNull String resourcePath, boolean replace)
// throws IOException, IllegalArgumentException {
// Objects.requireNonNull(resourcePath, "ResourcePath cannot be null");
// if (resourcePath.isEmpty()) throw new IllegalArgumentException("ResourcePath cannot be empty");
//
// resourcePath = resourcePath.replace('\\', '/');
//
// URL url = this.getClass().getClassLoader().getResource(resourcePath);
// if (url == null) throw new IllegalArgumentException("The resource '" + resourcePath + "' not exists");
//
// File outDir = file.getParentFile();
//
// if (!outDir.exists() && !outDir.mkdirs()) throw new IOException("Failed to create directory " + outDir);
// if (!file.exists() || replace) {
// try (OutputStream out = Files.newOutputStream(file.toPath())) {
// URLConnection connection = url.openConnection();
// connection.setUseCaches(false);
// try (InputStream in = connection.getInputStream()) {
// byte[] buf = new byte[1024];
// int len;
// while ((len = in.read(buf)) > 0) {
// out.write(buf, 0, len);
// }
// }
// }
// }
// }
//
// @Nullable
// public InputStream getResource(@NotNull String filename) {
// try {
// URL url = this.getClass().getClassLoader().getResource(filename);
// if (url == null) return null;
// URLConnection connection = url.openConnection();
// connection.setUseCaches(false);
// return connection.getInputStream();
// } catch (IOException ex) {
// return null;
// }
// }
//}
@@ -1,6 +1,125 @@
package cc.carm.lib.configuration.source;
public class FileConfigSource {
import cc.carm.lib.configuration.function.DataFunction;
import cc.carm.lib.configuration.option.FileConfigOptions;
import cc.carm.lib.configuration.source.section.ConfigurationSource;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Objects;
import java.util.function.Consumer;
public abstract class FileConfigSource<SELF extends FileConfigSource<SELF, ORIGINAL>, ORIGINAL>
extends ConfigurationSource<SELF, ORIGINAL> {
protected final @NotNull File file;
protected final @Nullable String resourcePath;
protected FileConfigSource(@NotNull ConfigurationHolder<? extends SELF> holder, long lastUpdateMillis,
@NotNull File file, @Nullable String resourcePath) {
super(holder, lastUpdateMillis);
this.file = file;
this.resourcePath = resourcePath;
}
public Charset charset() {
return holder().options().get(FileConfigOptions.CHARSET);
}
public boolean copyDefaults() {
return holder().options().get(FileConfigOptions.COPY_DEFAULTS);
}
public void initializeFile() throws IOException {
if (this.file.exists()) return;
File parent = this.file.getParentFile();
if (parent != null && !parent.exists() && !parent.mkdirs()) {
throw new IOException("Failed to create directory " + file.getParentFile().getAbsolutePath());
}
if (!this.file.createNewFile()) {
throw new IOException("Failed to create file " + file.getAbsolutePath());
}
if (resourcePath != null && copyDefaults()) {
try {
saveResource(resourcePath, false);
} catch (IllegalArgumentException ignored) {
}
}
}
protected <R> R fileInputStream(@NotNull DataFunction<InputStream, R> loader) {
try (FileInputStream is = new FileInputStream(file)) {
return loader.handle(is);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
protected <R> R fileReader(@NotNull DataFunction<Reader, R> loader) {
return fileInputStream(is -> loader.handle(new InputStreamReader(is, charset())));
}
protected void fileOutputStream(@NotNull Consumer<FileOutputStream> stream) {
try (FileOutputStream os = new FileOutputStream(file)) {
stream.accept(os);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void fileWriter(@NotNull Consumer<Writer> writer) {
fileOutputStream(os -> writer.accept(new OutputStreamWriter(os, charset())));
}
protected void saveResource(@NotNull String resourcePath, boolean replace)
throws IOException, IllegalArgumentException {
Objects.requireNonNull(resourcePath, "ResourcePath cannot be null");
if (resourcePath.isEmpty()) throw new IllegalArgumentException("ResourcePath cannot be empty");
resourcePath = resourcePath.replace('\\', '/');
URL url = this.getClass().getClassLoader().getResource(resourcePath);
if (url == null) throw new IllegalArgumentException("The resource '" + resourcePath + "' not exists");
File outDir = file.getParentFile();
if (!outDir.exists() && !outDir.mkdirs()) throw new IOException("Failed to create directory " + outDir);
if (!file.exists() || replace) {
try (OutputStream out = Files.newOutputStream(file.toPath())) {
URLConnection connection = url.openConnection();
connection.setUseCaches(false);
try (InputStream in = connection.getInputStream()) {
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
}
}
}
@Nullable
protected InputStream getResource(@NotNull String filename) {
try {
URL url = this.getClass().getClassLoader().getResource(filename);
if (url == null) return null;
URLConnection connection = url.openConnection();
connection.setUseCaches(false);
return connection.getInputStream();
} catch (IOException ex) {
return null;
}
}
}
@@ -1,21 +0,0 @@
package cc.carm.lib.configuration.source;
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
import cc.carm.lib.configuration.source.section.ConfigurationSource;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public abstract class FileProvider<S extends ConfigurationSource<S, ?>> extends ConfigurationProvider<S> {
public FileProvider(@NotNull S source, @NotNull ConfigurationInitializer loader,
@NotNull ValueAdapterRegistry adapters, @NotNull ConfigurationOptionHolder options,
@NotNull Map<String, Map<ConfigurationMetadata<?>, Object>> pathMetadata) {
super(source, loader, adapters, options, pathMetadata);
}
}
@@ -1,7 +1,6 @@
package cc.carm.lib.configuration.json;
import cc.carm.lib.configuration.source.comment.ConfigurationComments;
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSerializer;
@@ -20,12 +19,7 @@ import java.util.LinkedHashMap;
*/
public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
protected final Gson gson = new GsonBuilder()
.serializeNulls().disableHtmlEscaping().setPrettyPrinting()
.registerTypeAdapter(
JSONConfigWrapper.class,
(JsonSerializer<JSONConfigWrapper>) (src, typeOfSrc, context) -> context.serialize(src.data)
).create();
protected JSONConfigWrapper configuration;
protected ConfigInitializer<JSONConfigProvider> initializer;
@@ -0,0 +1,109 @@
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;
}
}
@@ -0,0 +1,53 @@
package cc.carm.lib.configuration.json;
import cc.carm.lib.configuration.source.section.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class JSONConfigurationSection implements ConfigurationSection {
@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;
}
}