1
mirror of https://github.com/CarmJos/EasyConfiguration.git synced 2026-06-04 10:38:19 +08:00

feat!(value): Finished the standard configured values

This commit is contained in:
2025-02-02 23:11:16 +08:00
parent 374a6198d8
commit 8ac1faf300
11 changed files with 291 additions and 82 deletions
@@ -38,7 +38,7 @@ public class ValueAdapter<TYPE>
return serializer;
}
public @Nullable ValueParser<TYPE> deserializer() {
public @Nullable ValueParser<TYPE> parser() {
return deserializer;
}
@@ -46,7 +46,7 @@ public class ValueAdapter<TYPE>
this.serializer = serializer;
}
public void deserializer(@Nullable ValueParser<TYPE> deserializer) {
public void parser(@Nullable ValueParser<TYPE> deserializer) {
this.deserializer = deserializer;
}
@@ -57,9 +57,9 @@ public class ValueAdapter<TYPE>
}
@Override
public TYPE deserialize(@NotNull ConfigurationProvider<?> provider, @NotNull ValueType<? super TYPE> type, @NotNull Object value) throws Exception {
public TYPE parse(@NotNull ConfigurationProvider<?> provider, @NotNull ValueType<? super TYPE> type, @NotNull Object value) throws Exception {
if (deserializer == null) throw new UnsupportedOperationException("Deserializer is not supported");
return deserializer.deserialize(provider, type, value);
return deserializer.parse(provider, type, value);
}
@Override
@@ -27,7 +27,7 @@ public class ValueAdapterRegistry {
if (fromAdapter == null) throw new IllegalArgumentException("No adapter for type " + from);
register(to,
serializer == null ? null : (provider, type, value) -> fromAdapter.serialize(provider, from, serializer.handle(value)),
parser == null ? null : (provider, type, data) -> parser.handle(fromAdapter.deserialize(provider, from, data))
parser == null ? null : (provider, type, data) -> parser.handle(fromAdapter.parse(provider, from, data))
);
}
@@ -55,7 +55,7 @@ public class ValueAdapterRegistry {
public <T> void register(@NotNull ValueType<T> type, @NotNull ValueParser<T> deserializer) {
ValueAdapter<T> existing = adapterOf(type);
if (existing != null) {
existing.deserializer(deserializer);
existing.parser(deserializer);
} else {
register(new ValueAdapter<>(type, null, deserializer));
}
@@ -66,7 +66,7 @@ public class ValueAdapterRegistry {
ValueAdapter<T> existing = adapterOf(type);
if (existing != null) {
if (serializer != null) existing.serializer(serializer);
if (deserializer != null) existing.deserializer(deserializer);
if (deserializer != null) existing.parser(deserializer);
} else {
register(new ValueAdapter<>(type, serializer, deserializer));
}
@@ -81,7 +81,7 @@ public class ValueAdapterRegistry {
}
@SuppressWarnings("unchecked")
public <T> ValueAdapter<T> adapterOf(@NotNull ValueType<T> type) {
public <T> @Nullable ValueAdapter<T> adapterOf(@NotNull ValueType<T> type) {
ValueAdapter<?> matched = adapters.stream().filter(adapter -> adapter.type().equals(type)).findFirst().orElse(null);
if (matched != null) return (ValueAdapter<T>) matched;
@@ -110,7 +110,7 @@ public class ValueAdapterRegistry {
if (type.isInstance(source)) return type.cast(source); // Not required to deserialize
ValueAdapter<T> adapter = adapterOf(type);
if (adapter == null) throw new RuntimeException("No adapter for type " + type);
return adapter.deserialize(provider, type, source);
return adapter.parse(provider, type, source);
}
@Contract("_,null -> null")
@@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull;
@FunctionalInterface
public interface ValueParser<TYPE> {
TYPE deserialize(
TYPE parse(
@NotNull ConfigurationProvider<?> provider,
@NotNull ValueType<? super TYPE> type, @NotNull Object data
) throws Exception;
@@ -18,7 +18,7 @@ public class PrimitiveAdapters<T> extends ValueAdapter<T> {
public static ValueAdapter<Enum<?>> ofEnum() {
ValueAdapter<Enum<?>> adapter = new ValueAdapter<>(new ValueType<Enum<?>>() {
});
adapter.deserializer((provider, type, data) -> Enum.valueOf((Class<Enum>) type.getRawType(), data.toString()));
adapter.parser((provider, type, data) -> Enum.valueOf((Class<Enum>) type.getRawType(), data.toString()));
adapter.serializer((provider, type, value) -> value.name());
return adapter;
}
@@ -34,44 +34,12 @@ public class ConfigValueBuilder<V> {
return from(String.class);
}
public @NotNull SourceValueBuilder<Integer, V> fromInteger() {
return from(Integer.class);
}
public @NotNull SourceValueBuilder<Long, V> fromLong() {
return from(Long.class);
}
public @NotNull SourceValueBuilder<Double, V> fromDouble() {
return from(Double.class);
}
public @NotNull SourceValueBuilder<Float, V> fromFloat() {
return from(Float.class);
}
public @NotNull SourceValueBuilder<Boolean, V> fromBoolean() {
return from(Boolean.class);
}
public @NotNull SourceValueBuilder<Character, V> fromCharacter() {
return from(Character.class);
}
public @NotNull SourceValueBuilder<Byte, V> fromByte() {
return from(Byte.class);
}
public @NotNull SourceValueBuilder<Short, V> fromShort() {
return from(Short.class);
}
public @NotNull SectionValueBuilder<V> fromSection() {
return new SectionValueBuilder<>(this.type);
}
public @NotNull SectionValueBuilder<V> fromSection(@NotNull ConfigValueHandler<ConfigurationSection, V> valueParser,
@NotNull ConfigValueHandler<V, ? extends Map<String, Object>> valueSerializer) {
@NotNull ConfigValueHandler<V, ? extends Map<Object, Object>> valueSerializer) {
return new SectionValueBuilder<>(this.type, valueParser, valueSerializer);
}
@@ -17,7 +17,7 @@ public class SectionValueBuilder<V> extends CommonConfigBuilder<V, SectionValueB
protected final @NotNull ValueType<V> valueType;
protected @NotNull ConfigValueHandler<ConfigurationSection, V> parser;
protected @NotNull ConfigValueHandler<V, ? extends Map<String, Object>> serializer;
protected @NotNull ConfigValueHandler<V, ? extends Map<Object, Object>> serializer;
public SectionValueBuilder(@NotNull ValueType<V> valueType) {
this(valueType, ConfigValueHandler.required(), ConfigValueHandler.required());
@@ -25,7 +25,7 @@ public class SectionValueBuilder<V> extends CommonConfigBuilder<V, SectionValueB
public SectionValueBuilder(@NotNull ValueType<V> valueType,
@NotNull ConfigValueHandler<ConfigurationSection, V> parser,
@NotNull ConfigValueHandler<V, ? extends Map<String, Object>> serializer) {
@NotNull ConfigValueHandler<V, ? extends Map<Object, Object>> serializer) {
this.valueType = valueType;
this.parser = parser;
this.serializer = serializer;
@@ -45,18 +45,18 @@ public class SectionValueBuilder<V> extends CommonConfigBuilder<V, SectionValueB
return this;
}
public @NotNull SectionValueBuilder<V> serialize(ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
public @NotNull SectionValueBuilder<V> serialize(ConfigDataFunction<V, ? extends Map<Object, Object>> serializer) {
return serialize((p, value) -> serializer.handle(value));
}
public @NotNull SectionValueBuilder<V> serialize(ConfigValueHandler<V, ? extends Map<String, Object>> serializer) {
public @NotNull SectionValueBuilder<V> serialize(ConfigValueHandler<V, ? extends Map<Object, Object>> serializer) {
this.serializer = serializer;
return this;
}
public @NotNull SectionValueBuilder<V> serialize(Consumer<Map<String, Object>> serializer) {
public @NotNull SectionValueBuilder<V> serialize(Consumer<Map<Object, Object>> serializer) {
return serialize((p, value) -> {
Map<String, Object> map = new LinkedHashMap<>();
Map<Object, Object> map = new LinkedHashMap<>();
serializer.accept(map);
return map;
});
@@ -64,7 +64,7 @@ public class SectionValueBuilder<V> extends CommonConfigBuilder<V, SectionValueB
@Override
public @NotNull ConfiguredValue<V> build() {
return new ConfiguredValue<>(
return ConfiguredValue.of(
buildManifest(),
(p, type, data) -> {
ConfigurationSection section = p.deserialize(ConfigurationSection.class, data);
@@ -72,7 +72,7 @@ public class SectionValueBuilder<V> extends CommonConfigBuilder<V, SectionValueB
return this.parser.handle(p, section);
},
(p, type, data) -> {
Map<String, Object> map = this.serializer.handle(p, data);
Map<Object, Object> map = this.serializer.handle(p, data);
return map == null || map.isEmpty() ? null : map; // Map is a type of original data
}
);
@@ -52,7 +52,7 @@ public class SourceValueBuilder<S, V> extends CommonConfigBuilder<V, SourceValue
@Override
public @NotNull ConfiguredValue<V> build() {
return new ConfiguredValue<>(
return ConfiguredValue.of(
buildManifest(),
(p, type, data) -> {
S source = p.deserialize(this.sourceType, data);
@@ -1,5 +1,8 @@
package cc.carm.lib.configuration.value.impl;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueParser;
import cc.carm.lib.configuration.adapter.ValueSerializer;
import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.ValueManifest;
import org.jetbrains.annotations.Contract;
@@ -55,4 +58,24 @@ public abstract class CachedConfigValue<T> extends ConfigValue<T> {
else return emptyValue;
}
/**
* @return Value's parser, parse base object to value.
*/
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());
if (registered == null) return null;
return registered.parser();
}
/**
* @return Value's serializer, parse value to base object.
*/
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());
if (registered == null) return null;
return registered.serializer();
}
}
@@ -1,5 +1,6 @@
package cc.carm.lib.configuration.value.standard;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueParser;
import cc.carm.lib.configuration.adapter.ValueSerializer;
import cc.carm.lib.configuration.adapter.ValueType;
@@ -11,54 +12,65 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements List<V> {
protected final @NotNull ValueType<V> valueType;
protected final @Nullable ValueParser<V> parser;
protected final @Nullable ValueSerializer<V> serializer;
protected final @NotNull Supplier<? extends List<V>> constructor;
protected final @NotNull ValueAdapter<V> paramAdapter;
private ConfiguredList(@NotNull ValueManifest<List<V>> manifest, @NotNull ValueType<V> valueType,
@Nullable ValueParser<V> parser, @Nullable ValueSerializer<V> serializer) {
private ConfiguredList(@NotNull ValueManifest<List<V>> manifest,
@NotNull Supplier<? extends List<V>> constructor,
@NotNull ValueAdapter<V> paramAdapter) {
super(manifest);
this.valueType = valueType;
this.parser = parser;
this.serializer = serializer;
this.constructor = constructor;
this.paramAdapter = paramAdapter;
}
/**
* @return Adapter of this value.
*/
public @NotNull ValueAdapter<V> adapter() {
return this.paramAdapter;
}
public @NotNull ValueType<V> paramType() {
return adapter().type();
}
/**
* @return Value's parser, parse base object to value.
*/
public @Nullable ValueParser<V> parser() {
return parser;
return parserFor(adapter());
}
/**
* @return Value's serializer, parse value to base object.
*/
public @Nullable ValueSerializer<V> serializer() {
return serializer;
return serializerFor(adapter());
}
public @NotNull ValueType<V> valueType() {
return valueType;
private @NotNull List<V> createList() {
return constructor.get();
}
@Override
public @NotNull List<V> get() {
if (!isExpired()) return getCachedOrDefault(new ArrayList<>());
if (!isExpired()) return getCachedOrDefault(createList());
// Data that is outdated and needs to be parsed again.
List<V> list = new ArrayList<>();
List<V> list = createList();
List<?> data = config().contains(path()) ? config().getList(path()) : null;
if (data == null) return getDefaultFirst(list);
ValueParser<V> parser = this.parser;
ValueParser<V> parser = parser();
if (parser == null) return getDefaultFirst(list);
for (Object dataVal : data) {
if (dataVal == null) continue;
try {
list.add(parser.deserialize(provider(), valueType(), dataVal));
list.add(parser.parse(provider(), paramType(), dataVal));
} catch (Exception e) {
e.printStackTrace();
}
@@ -80,7 +92,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(), valueType, val));
data.add(serializer.serialize(provider(), paramType(), val));
} catch (Exception ex) {
ex.printStackTrace();
}
@@ -0,0 +1,196 @@
package cc.carm.lib.configuration.value.standard;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueParser;
import cc.carm.lib.configuration.adapter.ValueSerializer;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.source.section.ConfigurationSection;
import cc.carm.lib.configuration.value.ValueManifest;
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements Map<K, V> {
protected final @NotNull Supplier<? extends Map<K, V>> constructor;
protected final @NotNull ValueAdapter<K> keyAdapter;
protected final @NotNull ValueAdapter<V> valueAdapter;
protected ConfiguredMap(@NotNull ValueManifest<Map<K, V>> manifest,
@NotNull Supplier<? extends Map<K, V>> constructor,
@NotNull ValueAdapter<K> keyAdapter, @NotNull ValueAdapter<V> valueAdapter) {
super(manifest);
this.constructor = constructor;
this.keyAdapter = keyAdapter;
this.valueAdapter = valueAdapter;
}
public @NotNull ValueAdapter<K> keyAdapter() {
return keyAdapter;
}
public @NotNull ValueType<K> keyType() {
return keyAdapter().type();
}
public @NotNull ValueAdapter<V> valueAdapter() {
return valueAdapter;
}
public @NotNull ValueType<V> valueType() {
return valueAdapter().type();
}
private Map<K, V> createMap() {
return this.constructor.get();
}
@Override
public @NotNull Map<K, V> get() {
if (!isExpired()) return getCachedOrDefault(createMap());
// If the value is expired, we need to update it
Map<K, V> map = createMap();
ConfigurationSection section = config().getSection(path());
if (section == null) return getDefaultFirst(map);
Set<String> keys = section.getKeys(false);
if (keys.isEmpty()) return getDefaultFirst(map);
ValueParser<K> keyParser = parserFor(keyAdapter);
ValueParser<V> valueParser = parserFor(valueAdapter);
if (keyParser == null || valueParser == null) return getDefaultFirst(map);
for (String dataKey : keys) {
Object dataVal = section.get(dataKey);
if (dataVal == null) continue;
try {
K key = keyParser.parse(provider(), keyType(), dataKey);
V value = valueParser.parse(provider(), valueType(), dataVal);
map.put(key, value);
} catch (Exception e) {
e.printStackTrace();
}
}
return updateCache(map);
}
@Override
public V get(Object key) {
return get().get(key);
}
public V getNotNull(Object key) {
return Objects.requireNonNull(get(key));
}
@Override
public void set(@Nullable Map<K, V> value) {
updateCache(value);
if (value == null) {
setData(null);
return;
}
ValueSerializer<K> keySerializer = serializerFor(keyAdapter);
ValueSerializer<V> valueSerializer = serializerFor(valueAdapter);
if (keySerializer == null || valueSerializer == null) return;
Map<Object, Object> data = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : value.entrySet()) {
try {
data.put(
keySerializer.serialize(provider(), keyType(), entry.getKey()),
valueSerializer.serialize(provider(), valueType(), entry.getValue())
);
} catch (Exception e) {
e.printStackTrace();
}
}
setData(data);
}
public <T> @NotNull T handle(Function<Map<K, V>, T> function) {
Map<K, V> m = get();
T result = function.apply(m);
set(m);
return result;
}
public @NotNull ConfiguredMap<K, V> modify(Consumer<Map<K, V>> consumer) {
Map<K, V> m = get();
consumer.accept(m);
set(m);
return this;
}
@Override
public int size() {
return get().size();
}
@Override
public boolean isEmpty() {
return get().isEmpty();
}
@Override
public boolean containsKey(Object key) {
return get().containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return get().containsValue(value);
}
@Nullable
@Override
public V put(K key, V value) {
return handle(m -> m.put(key, value));
}
@Override
public V remove(Object key) {
return handle(m -> m.remove(key));
}
@Override
public void putAll(@NotNull Map<? extends K, ? extends V> m) {
modify(map -> map.putAll(m));
}
@Override
public void clear() {
modify(Map::clear);
}
@NotNull
@Override
public Set<K> keySet() {
return get().keySet();
}
@NotNull
@Override
public Collection<V> values() {
return get().values();
}
@NotNull
@Override
@Unmodifiable
public Set<Entry<K, V>> entrySet() {
return get().entrySet();
}
}
@@ -1,10 +1,10 @@
package cc.carm.lib.configuration.value.standard;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueParser;
import cc.carm.lib.configuration.adapter.ValueSerializer;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.value.ConfigValueBuilder;
import cc.carm.lib.configuration.source.ConfigurationProvider;
import cc.carm.lib.configuration.value.ValueManifest;
import cc.carm.lib.configuration.value.impl.CachedConfigValue;
import org.jetbrains.annotations.NotNull;
@@ -49,32 +49,42 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
public static <V> ConfiguredValue<V> of(@NotNull ValueManifest<V> manifest,
@Nullable ValueParser<V> parser,
@Nullable ValueSerializer<V> serializer) {
return new ConfiguredValue<>(manifest, parser, serializer);
ValueAdapter<V> adapter = new ValueAdapter<>(manifest.type());
adapter.parser(parser);
adapter.serializer(serializer);
return of(manifest, adapter);
}
protected final @Nullable ValueParser<V> parser;
protected final @Nullable ValueSerializer<V> serializer;
public static <V> ConfiguredValue<V> of(@NotNull ValueManifest<V> manifest, @NotNull ValueAdapter<V> adapter) {
return new ConfiguredValue<>(manifest, adapter);
}
public ConfiguredValue(@NotNull ValueManifest<V> manifest,
@Nullable ValueParser<V> parser,
@Nullable ValueSerializer<V> serializer) {
protected final @NotNull ValueAdapter<V> adapter;
public ConfiguredValue(@NotNull ValueManifest<V> manifest, @NotNull ValueAdapter<V> adapter) {
super(manifest);
this.parser = parser;
this.serializer = serializer;
this.adapter = adapter;
}
/**
* @return Adapter of this value.
*/
public @NotNull ValueAdapter<V> adapter() {
return adapter;
}
/**
* @return Value's parser, parse base object to value.
*/
public @Nullable ValueParser<V> parser() {
return parser;
return parserFor(adapter());
}
/**
* @return Value's serializer, parse value to base object.
*/
public @Nullable ValueSerializer<V> serializer() {
return serializer;
return serializerFor(adapter());
}
@Override
@@ -90,7 +100,7 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
try {
// If there are no errors, update the cache and return.
return updateCache(parser.deserialize(provider(), type(), data));
return updateCache(parser.parse(provider(), type(), data));
} catch (Exception e) {
// There was a parsing error, prompted and returned the default value.
e.printStackTrace();