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

feat(section): Implement more sections

This commit is contained in:
2025-02-21 03:07:43 +08:00
parent d8191b7c6d
commit 3f1ffadeff
5 changed files with 205 additions and 27 deletions
@@ -19,7 +19,7 @@ import java.util.stream.Stream;
* @since 4.0.0
*/
public interface ConfigureSection extends Cloneable {
/**
* Gets the parent section of this section.
* <p>
@@ -136,7 +136,9 @@ public interface ConfigureSection extends Cloneable {
* @param path The path to check.
* @return True if the value is present, false otherwise.
*/
boolean contains(@NotNull String path);
default boolean contains(@NotNull String path) {
return get(path) != null;
}
/**
* Predicate the value of given path is specific type.
@@ -166,7 +168,10 @@ public interface ConfigureSection extends Cloneable {
* @param path The path to get the {@link List}.
* @return The list if the path exists and is a list, otherwise null.
*/
@Nullable List<?> getList(@NotNull String path);
default @Nullable List<?> getList(@NotNull String path) {
Object val = get(path);
return (val instanceof List<?>) ? (List<?>) val : null;
}
/**
* Predicate the value of given path is a {@link ConfigureSection}.
@@ -7,7 +7,6 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
/**
@@ -104,21 +103,11 @@ public abstract class ConfigureSource<
section().set(path, value);
}
@Override
public boolean contains(@NotNull String path) {
return section().contains(path);
}
@Override
public void remove(@NotNull String path) {
section().remove(path);
}
@Override
public @Nullable List<?> getList(@NotNull String path) {
return section().getList(path);
}
@Override
public @Nullable ConfigureSection getSection(@NotNull String path) {
return section().getSection(path);
@@ -8,6 +8,14 @@ import java.util.*;
public abstract class MapSection<R extends MapSection<R>> implements ConfigureSection {
public static RawMapSection of() {
return new RawMapSection(new LinkedHashMap<>(), null);
}
public static RawMapSection of(@NotNull Map<?, ?> data) {
return new RawMapSection(data, null);
}
protected final @NotNull Map<String, Object> data;
protected final @Nullable R parent;
@@ -50,11 +58,11 @@ public abstract class MapSection<R extends MapSection<R>> implements ConfigureSe
}
@UnmodifiableView
public @NotNull Map<String, Object> original() {
public @NotNull Map<String, Object> rawMap() {
Map<String, Object> output = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : this.data.entrySet()) {
if (entry.getValue() instanceof MapSection<?>) {
output.put(entry.getKey(), ((MapSection<?>) entry.getValue()).original());
output.put(entry.getKey(), ((MapSection<?>) entry.getValue()).rawMap());
} else {
output.put(entry.getKey(), entry.getValue());
}
@@ -104,23 +112,12 @@ public abstract class MapSection<R extends MapSection<R>> implements ConfigureSe
}
}
@Override
public boolean contains(@NotNull String path) {
return get(path) != null;
}
@Override
public @Nullable Object get(@NotNull String path) {
R section = getSectionFor(path);
return section == this ? data.get(path) : section.get(childPath(path));
}
@Override
public @Nullable List<?> getList(@NotNull String path) {
Object val = get(path);
return (val instanceof List<?>) ? (List<?>) val : null;
}
@Override
public @Nullable ConfigureSection getSection(@NotNull String path) {
Object val = get(path);
@@ -160,4 +157,5 @@ public abstract class MapSection<R extends MapSection<R>> implements ConfigureSe
}
return output;
}
}
@@ -0,0 +1,25 @@
package cc.carm.lib.configuration.source.section;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public class RawMapSection extends MapSection<RawMapSection> {
protected RawMapSection(@NotNull Map<?, ?> raw, @Nullable RawMapSection parent) {
super(parent);
migrate(raw);
}
@Override
public @NotNull RawMapSection self() {
return this;
}
@Override
protected @NotNull RawMapSection createChild(@NotNull Map<?, ?> data) {
return new RawMapSection(data, this);
}
}
@@ -0,0 +1,161 @@
package cc.carm.lib.configuration.source.section;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ShadedSection extends MapSection<ShadedSection> {
private final ConfigureSection template;
// 构造方法
public ShadedSection(@Nullable ShadedSection parent, @Nullable ConfigureSection template) {
super(parent);
this.template = template;
}
public ShadedSection(@NotNull Map<?, ?> data, @Nullable ShadedSection parent, @Nullable ConfigureSection template) {
super(parent);
this.template = template;
migrate(data);
}
@Override
public @NotNull ShadedSection self() {
return this;
}
@Override
protected @NotNull ShadedSection createChild(@NotNull Map<?, ?> data) {
return new ShadedSection(data, this, null);
}
@Override
public @Nullable Object get(@NotNull String path) {
// 优先从当前section获取
Object value = super.get(path);
if (value != null) {
return wrapNestedValues(path, value);
}
// 当前section无数据时从模板获取
if (template != null) {
Object templateValue = template.get(path);
return wrapTemplateNestedValues(path, templateValue);
}
return null;
}
private Object wrapNestedValues(String path, Object value) {
if (value instanceof ConfigureSection) {
// 包装子Section,继承当前模板的对应子Section
ConfigureSection templateChild = template != null ? template.getSection(path) : null;
return new ShadedSection(
((ConfigureSection) value).getValues(false),
this,
templateChild
);
} else if (value instanceof List) {
// 处理列表中的嵌套结构
return processList(path, (List<?>) value);
}
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> processList(String path, List<?> list) {
List<Object> processed = new ArrayList<>();
for (Object item : list) {
if (item instanceof Map) {
processed.add(new ShadedSection(
(Map<?, ?>) item, this,
template != null ? template.getSection(path) : null
));
} else if (item instanceof ConfigureSection) {
processed.add(new ShadedSection(
((ConfigureSection) item).getValues(false), this,
template != null ? template.getSection(path) : null
));
} else {
processed.add(item);
}
}
return processed;
}
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 = template != null ? template.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 != null ? template.getSection(path) : null
);
} 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));
} else if (a instanceof List && b instanceof List) {
List<?> listA = (List<?>) a;
List<?> listB = (List<?>) b;
if (listA.size() != listB.size()) return false;
for (int i = 0; i < listA.size(); i++) {
if (!isDeepEqual(listA.get(i), listB.get(i))) return false;
}
return true;
}
return a.equals(b);
}
}