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

feat(map): 支持通过ConfigurationSection创建MapValue。

This commit is contained in:
2023-08-28 17:00:56 +08:00
parent c6cce5208f
commit 27a68ead7c
17 changed files with 404 additions and 208 deletions
@@ -1,9 +1,10 @@
package cc.carm.lib.configuration.core.builder.list;
import cc.carm.lib.configuration.core.annotation.InlineComment;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class ConfigListBuilder<V> {
@@ -13,7 +14,7 @@ public class ConfigListBuilder<V> {
this.valueClass = valueClass;
}
public @NotNull <S> SourceListBuilder<S, V> from(@NotNull Class<S> sourceClass,
public @NotNull <S> SourceListBuilder<S, V> from(@NotNull Class<? super S> sourceClass,
@NotNull ConfigDataFunction<Object, S> sourceParser,
@NotNull ConfigDataFunction<S, V> valueParser,
@NotNull ConfigDataFunction<V, S> valueSerializer,
@@ -45,4 +46,13 @@ public class ConfigListBuilder<V> {
);
}
public @NotNull SourceListBuilder<Map<String, Object>, V> fromMap() {
return from(
Map.class, obj -> (Map<String, Object>) obj,
ConfigDataFunction.required(),
ConfigDataFunction.required(),
ConfigDataFunction.toObject()
);
}
}
@@ -12,7 +12,7 @@ import java.util.List;
public class SourceListBuilder<S, V> extends CommonConfigBuilder<List<V>, SourceListBuilder<S, V>> {
protected final @NotNull Class<S> sourceClass;
protected final @NotNull Class<? super S> sourceClass;
protected @NotNull ConfigDataFunction<Object, S> sourceParser;
protected final @NotNull Class<V> valueClass;
@@ -21,7 +21,7 @@ public class SourceListBuilder<S, V> extends CommonConfigBuilder<List<V>, Source
protected @NotNull ConfigDataFunction<V, S> valueSerializer;
protected @NotNull ConfigDataFunction<S, Object> sourceSerializer;
public SourceListBuilder(@NotNull Class<S> sourceClass, @NotNull ConfigDataFunction<Object, S> sourceParser,
public SourceListBuilder(@NotNull Class<? super S> sourceClass, @NotNull ConfigDataFunction<Object, S> sourceParser,
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<S, V> valueParser,
@NotNull ConfigDataFunction<V, S> valueSerializer,
@NotNull ConfigDataFunction<S, Object> sourceSerializer) {
@@ -48,6 +48,14 @@ public class ConfigMapBuilder<M extends Map<K, V>, K, V> {
return fromString(ConfigDataFunction.castFromString(this.valueClass));
}
public SectionMapBuilder<M, K, V> fromSection() {
return new SectionMapBuilder<>(
supplier,
keyClass, ConfigDataFunction.castFromString(keyClass),
valueClass, ConfigDataFunction.required(),
ConfigDataFunction.castToString(), ConfigDataFunction.required());
}
public SourceMapBuilder<M, Object, K, V> fromObject(@NotNull ConfigDataFunction<Object, V> valueParser) {
return from(Object.class, valueParser, ConfigDataFunction.toObject());
}
@@ -0,0 +1,99 @@
package cc.carm.lib.configuration.core.builder.map;
import cc.carm.lib.configuration.core.builder.CommonConfigBuilder;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import cc.carm.lib.configuration.core.value.ValueManifest;
import cc.carm.lib.configuration.core.value.type.ConfiguredSectionMap;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class SectionMapBuilder<M extends Map<K, V>, K, V> extends CommonConfigBuilder<M, SectionMapBuilder<M, K, V>> {
protected final @NotNull Supplier<@NotNull M> supplier;
protected final @NotNull Class<K> keyClass;
protected @NotNull ConfigDataFunction<String, K> keyParser;
protected final @NotNull Class<V> valueClass;
protected @NotNull ConfigDataFunction<ConfigurationWrapper<?>, V> valueParser;
protected @NotNull ConfigDataFunction<K, String> keySerializer;
protected @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> valueSerializer;
public SectionMapBuilder(@NotNull Supplier<@NotNull M> supplier,
@NotNull Class<K> keyClass, @NotNull ConfigDataFunction<String, K> keyParser,
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<ConfigurationWrapper<?>, V> valueParser,
@NotNull ConfigDataFunction<K, String> keySerializer,
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> valueSerializer) {
this.supplier = supplier;
this.keyClass = keyClass;
this.keyParser = keyParser;
this.valueClass = valueClass;
this.valueParser = valueParser;
this.keySerializer = keySerializer;
this.valueSerializer = valueSerializer;
}
public <MAP extends Map<K, V>> SectionMapBuilder<MAP, K, V> supplier(@NotNull Supplier<MAP> supplier) {
return new SectionMapBuilder<>(supplier,
keyClass, keyParser, valueClass, valueParser, keySerializer, valueSerializer
);
}
public @NotNull SectionMapBuilder<M, K, V> defaults(@NotNull Consumer<M> factory) {
M map = supplier.get();
factory.accept(map);
return defaults(map);
}
public @NotNull SectionMapBuilder<M, K, V> parseKey(@NotNull ConfigDataFunction<String, K> parser) {
this.keyParser = parser;
return this;
}
public @NotNull SectionMapBuilder<M, K, V> parseValue(@NotNull ConfigDataFunction<ConfigurationWrapper<?>, V> parser) {
this.valueParser = parser;
return this;
}
public @NotNull SectionMapBuilder<M, K, V> serializeKey(@NotNull ConfigDataFunction<K, String> serializer) {
this.keySerializer = serializer;
return this;
}
public @NotNull SectionMapBuilder<M, K, V> serializeValue(@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
this.valueSerializer = serializer;
return this;
}
public @NotNull SectionMapBuilder<M, K, V> serializeValue(@NotNull BiConsumer<V, Map<String, Object>> serializer) {
return serializeValue(v -> {
Map<String, Object> map = new LinkedHashMap<>();
serializer.accept(v, map);
return map;
});
}
@Override
protected @NotNull SectionMapBuilder<M, K, V> getThis() {
return this;
}
@Override
public @NotNull ConfiguredSectionMap<K, V> build() {
return new ConfiguredSectionMap<>(
new ValueManifest<>(provider, path, headerComments, inlineComment, defaultValue),
this.supplier, this.keyClass, this.keyParser,
this.valueClass, this.valueParser,
this.keySerializer, this.valueSerializer
);
}
}
@@ -0,0 +1,214 @@
package cc.carm.lib.configuration.core.value.impl;
import cc.carm.lib.configuration.core.builder.map.ConfigMapCreator;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import cc.carm.lib.configuration.core.value.ValueManifest;
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 abstract class ConfigValueMap<K, V, S> extends CachedConfigValue<Map<K, V>> implements Map<K, V> {
public static <K, V> @NotNull ConfigMapCreator<K, V> builderOf(@NotNull Class<K> keyClass,
@NotNull Class<V> valueClass) {
return builder().asMap(keyClass, valueClass);
}
protected final @NotNull Supplier<? extends Map<K, V>> supplier;
protected final @NotNull Class<? super S> sourceClass;
protected final @NotNull Class<K> keyClass;
protected final @NotNull Class<V> valueClass;
protected final @NotNull ConfigDataFunction<String, K> keyParser;
protected final @NotNull ConfigDataFunction<S, V> valueParser;
protected final @NotNull ConfigDataFunction<K, String> keySerializer;
protected final @NotNull ConfigDataFunction<V, Object> valueSerializer;
protected ConfigValueMap(@NotNull ValueManifest<Map<K, V>> manifest, @NotNull Class<? super S> sourceClass,
@NotNull Supplier<? extends Map<K, V>> mapObjSupplier,
@NotNull Class<K> keyClass, @NotNull ConfigDataFunction<String, K> keyParser,
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<S, V> valueParser,
@NotNull ConfigDataFunction<K, String> keySerializer,
@NotNull ConfigDataFunction<V, Object> valueSerializer) {
super(manifest);
this.supplier = mapObjSupplier;
this.sourceClass = sourceClass;
this.keyClass = keyClass;
this.valueClass = valueClass;
this.keyParser = keyParser;
this.valueParser = valueParser;
this.keySerializer = keySerializer;
this.valueSerializer = valueSerializer;
}
public @NotNull Class<? super S> getSourceClass() {
return sourceClass;
}
public @NotNull Class<K> getKeyClass() {
return keyClass;
}
public @NotNull Class<V> getValueClass() {
return valueClass;
}
public @NotNull ConfigDataFunction<String, K> getKeyParser() {
return keyParser;
}
public @NotNull ConfigDataFunction<S, V> getValueParser() {
return valueParser;
}
public @NotNull ConfigDataFunction<K, String> getKeySerializer() {
return keySerializer;
}
public @NotNull ConfigDataFunction<V, Object> getValueSerializer() {
return valueSerializer;
}
public abstract S getSource(ConfigurationWrapper<?> section, String dataKey);
@Override
public @NotNull Map<K, V> get() {
if (!isExpired()) return getCachedOrDefault(supplier.get());
// 已过时的数据,需要重新解析一次。
Map<K, V> map = supplier.get();
ConfigurationWrapper<?> section = getConfiguration().getConfigurationSection(getConfigPath());
if (section == null) return getDefaultFirst(map);
Set<String> keys = section.getKeys(false);
if (keys.isEmpty()) return getDefaultFirst(map);
for (String dataKey : keys) {
S dataVal = getSource(section, dataKey);
if (dataVal == null) continue;
try {
K key = keyParser.parse(dataKey);
V value = valueParser.parse(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) setValue(null);
else {
Map<String, Object> data = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : value.entrySet()) {
try {
data.put(
keySerializer.parse(entry.getKey()),
valueSerializer.parse(entry.getValue())
);
} catch (Exception e) {
e.printStackTrace();
}
}
setValue(data);
}
}
public <T> @NotNull T modifyValue(Function<Map<K, V>, T> function) {
Map<K, V> m = get();
T result = function.apply(m);
set(m);
return result;
}
public @NotNull Map<K, V> modifyMap(Consumer<Map<K, V>> consumer) {
Map<K, V> m = get();
consumer.accept(m);
set(m);
return m;
}
@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 modifyValue(m -> m.put(key, value));
}
@Override
public V remove(Object key) {
return modifyValue(m -> m.remove(key));
}
@Override
public void putAll(@NotNull Map<? extends K, ? extends V> m) {
modifyMap(map -> map.putAll(m));
}
@Override
public void clear() {
modifyMap(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,40 +1,15 @@
package cc.carm.lib.configuration.core.value.type;
import cc.carm.lib.configuration.core.builder.map.ConfigMapCreator;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import cc.carm.lib.configuration.core.value.ValueManifest;
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
import cc.carm.lib.configuration.core.value.impl.ConfigValueMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
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> {
public static <K, V> @NotNull ConfigMapCreator<K, V> builderOf(@NotNull Class<K> keyClass,
@NotNull Class<V> valueClass) {
return builder().asMap(keyClass, valueClass);
}
protected final @NotNull Supplier<? extends Map<K, V>> supplier;
protected final @NotNull Class<K> keyClass;
protected final @NotNull Class<V> valueClass;
protected final @NotNull ConfigDataFunction<String, K> keyParser;
protected final @NotNull ConfigDataFunction<Object, V> valueParser;
protected final @NotNull ConfigDataFunction<K, String> keySerializer;
protected final @NotNull ConfigDataFunction<V, Object> valueSerializer;
public class ConfiguredMap<K, V> extends ConfigValueMap<K, V, Object> {
public ConfiguredMap(@NotNull ValueManifest<Map<K, V>> manifest,
@NotNull Supplier<? extends Map<K, V>> mapObjSupplier,
@@ -42,165 +17,12 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<Object, V> valueParser,
@NotNull ConfigDataFunction<K, String> keySerializer,
@NotNull ConfigDataFunction<V, Object> valueSerializer) {
super(manifest);
this.supplier = mapObjSupplier;
this.keyClass = keyClass;
this.valueClass = valueClass;
this.keyParser = keyParser;
this.valueParser = valueParser;
this.keySerializer = keySerializer;
this.valueSerializer = valueSerializer;
}
public @NotNull Class<K> getKeyClass() {
return keyClass;
}
public @NotNull Class<V> getValueClass() {
return valueClass;
}
public @NotNull ConfigDataFunction<String, K> getKeyParser() {
return keyParser;
}
public @NotNull ConfigDataFunction<Object, V> getValueParser() {
return valueParser;
}
public @NotNull ConfigDataFunction<K, String> getKeySerializer() {
return keySerializer;
}
public @NotNull ConfigDataFunction<V, Object> getValueSerializer() {
return valueSerializer;
super(manifest, Object.class, mapObjSupplier, keyClass, keyParser, valueClass, valueParser, keySerializer, valueSerializer);
}
@Override
public @NotNull Map<K, V> get() {
if (!isExpired()) return getCachedOrDefault(supplier.get());
// 已过时的数据,需要重新解析一次。
Map<K, V> map = supplier.get();
ConfigurationWrapper<?> section = getConfiguration().getConfigurationSection(getConfigPath());
if (section == null) return getDefaultFirst(map);
Set<String> keys = section.getKeys(false);
if (keys.isEmpty()) return getDefaultFirst(map);
for (String dataKey : keys) {
Object dataVal = section.get(dataKey);
if (dataVal == null) continue;
try {
K key = keyParser.parse(dataKey);
V value = valueParser.parse(dataVal);
map.put(key, value);
} catch (Exception e) {
e.printStackTrace();
}
}
return updateCache(map);
}
@Override
public V get(Object key) {
return get().get(key);
}
@Override
public void set(@Nullable Map<K, V> value) {
updateCache(value);
if (value == null) setValue(null);
else {
Map<String, Object> data = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : value.entrySet()) {
try {
data.put(
keySerializer.parse(entry.getKey()),
valueSerializer.parse(entry.getValue())
);
} catch (Exception e) {
e.printStackTrace();
}
}
setValue(data);
}
}
public <T> @NotNull T modifyValue(Function<Map<K, V>, T> function) {
Map<K, V> m = get();
T result = function.apply(m);
set(m);
return result;
}
public @NotNull Map<K, V> modifyMap(Consumer<Map<K, V>> consumer) {
Map<K, V> m = get();
consumer.accept(m);
set(m);
return m;
}
@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 modifyValue(m -> m.put(key, value));
}
@Override
public V remove(Object key) {
return modifyValue(m -> m.remove(key));
}
@Override
public void putAll(@NotNull Map<? extends K, ? extends V> m) {
modifyMap(map -> map.putAll(m));
}
@Override
public void clear() {
modifyMap(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();
public Object getSource(ConfigurationWrapper<?> section, String dataKey) {
return section.get(dataKey);
}
}
@@ -0,0 +1,32 @@
package cc.carm.lib.configuration.core.value.type;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import cc.carm.lib.configuration.core.value.ValueManifest;
import cc.carm.lib.configuration.core.value.impl.ConfigValueMap;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.function.Supplier;
public class ConfiguredSectionMap<K, V> extends ConfigValueMap<K, V, ConfigurationWrapper<?>> {
public ConfiguredSectionMap(@NotNull ValueManifest<Map<K, V>> manifest,
@NotNull Supplier<? extends Map<K, V>> mapObjSupplier,
@NotNull Class<K> keyClass, @NotNull ConfigDataFunction<String, K> keyParser,
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<ConfigurationWrapper<?>, V> valueParser,
@NotNull ConfigDataFunction<K, String> keySerializer,
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> valueSerializer) {
super(
manifest, ConfigurationWrapper.class, mapObjSupplier,
keyClass, keyParser, valueClass, valueParser,
keySerializer, valueSerializer.andThen(s -> (Object) s)
);
}
@Override
public ConfigurationWrapper<?> getSource(ConfigurationWrapper<?> section, String dataKey) {
return section.getConfigurationSection(dataKey);
}
}