mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 18:48:20 +08:00
feat: Implement more sections functions
This commit is contained in:
@@ -16,6 +16,7 @@ import java.util.Map;
|
|||||||
* @param <SECTION> The type of the root section.
|
* @param <SECTION> The type of the root section.
|
||||||
* @param <ORIGINAL> The original configuration object.
|
* @param <ORIGINAL> The original configuration object.
|
||||||
* @param <SELF> The type of the source itself, for further implement support.
|
* @param <SELF> The type of the source itself, for further implement support.
|
||||||
|
* @see ConfigureSection
|
||||||
*/
|
*/
|
||||||
public abstract class ConfigureSource<
|
public abstract class ConfigureSource<
|
||||||
SECTION extends ConfigureSection, ORIGINAL,
|
SECTION extends ConfigureSection, ORIGINAL,
|
||||||
|
|||||||
+14
@@ -5,6 +5,8 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class RawMapSection extends MapSection<RawMapSection> {
|
public class RawMapSection extends MapSection<RawMapSection> {
|
||||||
|
|
||||||
@@ -12,6 +14,18 @@ public class RawMapSection extends MapSection<RawMapSection> {
|
|||||||
return of((RawMapSection) null);
|
return of((RawMapSection) null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static RawMapSection of(@NotNull Consumer<Map<String, Object>> data) {
|
||||||
|
return of(() -> {
|
||||||
|
Map<String, Object> map = new LinkedHashMap<>();
|
||||||
|
data.accept(map);
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RawMapSection of(@NotNull Supplier<Map<?, ?>> data) {
|
||||||
|
return of(data.get(), null);
|
||||||
|
}
|
||||||
|
|
||||||
public static RawMapSection of(@NotNull Map<?, ?> data) {
|
public static RawMapSection of(@NotNull Map<?, ?> data) {
|
||||||
return of(data, null);
|
return of(data, null);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-139
@@ -1,144 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.source.section;
|
package cc.carm.lib.configuration.source.section;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Contract;
|
public class ShadedSection {
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public class ShadedSection extends MapSection<ShadedSection> {
|
|
||||||
|
|
||||||
private final @Nullable Supplier<@Nullable ConfigureSection> templateSupplier;
|
|
||||||
|
|
||||||
public ShadedSection(@Nullable ShadedSection parent, @Nullable Supplier<ConfigureSection> templateSupplier) {
|
|
||||||
super(parent);
|
|
||||||
this.templateSupplier = templateSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ShadedSection(@NotNull Map<?, ?> data, @Nullable ShadedSection parent, @Nullable Supplier<ConfigureSection> templateSupplier) {
|
|
||||||
super(parent);
|
|
||||||
this.templateSupplier = templateSupplier;
|
|
||||||
migrate(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ShadedSection self() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @NotNull ShadedSection createChild(@NotNull Map<?, ?> data) {
|
|
||||||
return new ShadedSection(data, this, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected @Nullable ConfigureSection template() {
|
|
||||||
return templateSupplier != null ? templateSupplier.get() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
protected <T> T template(@NotNull Function<ConfigureSection, T> function) {
|
|
||||||
return template(null, function);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Contract("!null, _ -> !null")
|
|
||||||
protected <T> T template(@Nullable T defaults, @NotNull Function<ConfigureSection, T> function) {
|
|
||||||
return Optional.ofNullable(template()).map(function).orElse(defaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Object get(@NotNull String path) {
|
|
||||||
// 优先从当前section获取
|
|
||||||
Object value = super.get(path);
|
|
||||||
if (value != null) {
|
|
||||||
return wrapNestedValues(path, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当前section无数据时从模板获取
|
|
||||||
if (templateSupplier != null) {
|
|
||||||
Object templateValue = template((template) -> template.get(path));
|
|
||||||
return wrapTemplateNestedValues(path, templateValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object wrapNestedValues(String path, Object value) {
|
|
||||||
if (value instanceof ConfigureSection) {
|
|
||||||
return new ShadedSection(
|
|
||||||
((ConfigureSection) value).getValues(false),
|
|
||||||
this, () -> template(s -> s.getSection(path))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object wrapTemplateNestedValues(String path, Object templateValue) {
|
|
||||||
if (templateValue instanceof ConfigureSection) {
|
|
||||||
// 模板子Section作为新Section的模板
|
|
||||||
return new ShadedSection(
|
|
||||||
((ConfigureSection) templateValue).getValues(false),
|
|
||||||
this,
|
|
||||||
((ConfigureSection) templateValue) // 模板继承
|
|
||||||
);
|
|
||||||
} else if (templateValue instanceof List) {
|
|
||||||
// 处理模板列表中的嵌套结构
|
|
||||||
return processTemplateList(path, (List<?>) templateValue);
|
|
||||||
}
|
|
||||||
return templateValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Object> processTemplateList(String path, List<?> list) {
|
|
||||||
List<Object> processed = new ArrayList<>();
|
|
||||||
for (Object item : list) {
|
|
||||||
if (item instanceof ConfigureSection) {
|
|
||||||
processed.add(new ShadedSection(
|
|
||||||
((ConfigureSection) item).getValues(false), this,
|
|
||||||
(ConfigureSection) item
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
processed.add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return processed;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(@NotNull String path, @Nullable Object value) {
|
|
||||||
// 获取模板值并深度比较
|
|
||||||
Object templateValue = templateSupplier != null ? templateSupplier.get(path) : null;
|
|
||||||
Object processedValue = preprocessValue(path, value);
|
|
||||||
|
|
||||||
if (isDeepEqual(processedValue, templateValue)) {
|
|
||||||
return; // 与模板一致则跳过
|
|
||||||
}
|
|
||||||
|
|
||||||
super.set(path, processedValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object preprocessValue(String path, Object value) {
|
|
||||||
if (value instanceof Map) {
|
|
||||||
return new ShadedSection(
|
|
||||||
(Map<?, ?>) value, this,
|
|
||||||
() -> template(s -> s.getSection(path))
|
|
||||||
);
|
|
||||||
} else if (value instanceof List) {
|
|
||||||
return processList(path, (List<?>) value);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isDeepEqual(Object a, Object b) {
|
|
||||||
if (a == b) return true;
|
|
||||||
if (a == null || b == null) return false;
|
|
||||||
|
|
||||||
if (a instanceof ConfigureSection && b instanceof ConfigureSection) {
|
|
||||||
return ((ConfigureSection) a).getValues(true)
|
|
||||||
.equals(((ConfigureSection) b).getValues(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Objects.equals(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package test.section;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
|
import cc.carm.lib.configuration.source.section.RawMapSection;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lyzen
|
||||||
|
* @date 21/2/2025 下午2:18
|
||||||
|
*/
|
||||||
|
public class ShadeTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
ConfigureSection template = RawMapSection.of(data -> {
|
||||||
|
data.put("name", "GentleMan");
|
||||||
|
data.put("age", 12);
|
||||||
|
data.put("gender", "male");
|
||||||
|
Map<String, Object> address = new LinkedHashMap<>();
|
||||||
|
address.put("Hotel", "Nanjing Road 101");
|
||||||
|
address.put("Parent", "BeijingRoad 404");
|
||||||
|
data.put("addresses", address);
|
||||||
|
data.put("cards", Arrays.asList("00000", "11111", "22222"));
|
||||||
|
});
|
||||||
|
|
||||||
|
ConfigureSection source = RawMapSection.of(data -> {
|
||||||
|
data.put("age", 25);
|
||||||
|
Map<String, Object> address = new LinkedHashMap<>();
|
||||||
|
address.put("NewOne", "Guangdong Road 505");
|
||||||
|
data.put("addresses", address);
|
||||||
|
data.put("cards", Arrays.asList("33333", "55555")); // 应当直接覆盖原先的List
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user