test(serde-ext): Add a test for mutable structured entry serde

This commit is contained in:
2026-05-02 19:32:11 +02:00
parent 94c63dc03c
commit 94a69f2607
2 changed files with 114 additions and 2 deletions
@@ -3,16 +3,23 @@ package de.siphalor.tweed5.serde.extension.impl;
import de.siphalor.tweed5.core.api.container.ConfigContainer;
import de.siphalor.tweed5.core.api.entry.CollectionConfigEntry;
import de.siphalor.tweed5.core.api.entry.CompoundConfigEntry;
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import de.siphalor.tweed5.core.api.entry.ConfigEntryValueVisitor;
import de.siphalor.tweed5.core.api.entry.ConfigEntryVisitor;
import de.siphalor.tweed5.core.api.entry.MutableStructuredConfigEntry;
import de.siphalor.tweed5.core.api.entry.SimpleConfigEntry;
import de.siphalor.tweed5.core.impl.DefaultConfigContainer;
import de.siphalor.tweed5.core.impl.entry.CollectionConfigEntryImpl;
import de.siphalor.tweed5.core.impl.entry.SimpleConfigEntryImpl;
import de.siphalor.tweed5.core.impl.entry.StaticMapCompoundConfigEntryImpl;
import de.siphalor.tweed5.patchwork.api.Patchwork;
import de.siphalor.tweed5.serde.extension.api.ReadWriteExtension;
import de.siphalor.tweed5.serde.hjson.HjsonLexer;
import de.siphalor.tweed5.serde.hjson.HjsonReader;
import de.siphalor.tweed5.serde.hjson.HjsonWriter;
import de.siphalor.tweed5.serde_api.api.TweedDataVisitor;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -51,13 +58,21 @@ class ReadWriteExtensionImplTest {
.apply(entryReaderWriter(booleanReaderWriter()))
).apply(entryReaderWriter(collectionReaderWriter()));
MutableStructuredConfigEntry<Map<String, Integer>> mapEntry = new TestMapConfigEntry<>(
configContainer,
(Class<Map<String, Integer>>)(Class) Map.class,
new SimpleConfigEntryImpl<>(configContainer, Integer.class)
.apply(entryReaderWriter(intReaderWriter()))
).apply(entryReaderWriter(mutableStructuredReaderWriter()));
rootEntry = new StaticMapCompoundConfigEntryImpl<>(
configContainer,
((Class<Map<String, Object>>) (Class<?>) Map.class),
LinkedHashMap::new,
sequencedMap(List.of(
entry("int", intEntry),
entry("list", listEntry)
entry("list", listEntry),
entry("map", mapEntry)
))
).apply(entryReaderWriter(compoundReaderWriter()));
@@ -71,6 +86,7 @@ class ReadWriteExtensionImplTest {
Map<String, Object> value = new HashMap<>();
value.put("int", 123);
value.put("list", Arrays.asList(true, false, true));
value.put("map", sequencedMap(List.of(entry("a", 1), entry("b", 2))));
ReadWriteExtension readWriteExtension = configContainer.extension(ReadWriteExtension.class).orElseThrow();
assertDoesNotThrow(() -> readWriteExtension.write(
@@ -88,6 +104,10 @@ class ReadWriteExtensionImplTest {
\t\tfalse
\t\ttrue
\t]
\tmap: {
\t\ta: 1
\t\tb: 2
\t}
}
"""
);
@@ -105,6 +125,10 @@ class ReadWriteExtensionImplTest {
\t\tfalse
\t\ttrue
\t]
\tmap: {
\t\ta: 1
\t\tb: 2
\t}
}
"""))),
rootEntry,
@@ -115,7 +139,8 @@ class ReadWriteExtensionImplTest {
assertThat(result.hasValue()).isTrue();
assertThat(result.value()).isEqualTo(Map.of(
"int", 123,
"list", Arrays.asList(true, false, true)
"list", Arrays.asList(true, false, true),
"map", Map.of("a", 1, "b", 2)
));
}
@@ -0,0 +1,87 @@
package de.siphalor.tweed5.serde.extension.impl;
import de.siphalor.tweed5.core.api.Arity;
import de.siphalor.tweed5.core.api.container.ConfigContainer;
import de.siphalor.tweed5.core.api.entry.BaseConfigEntry;
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import de.siphalor.tweed5.core.api.entry.ConfigEntryValueVisitor;
import de.siphalor.tweed5.core.api.entry.ConfigEntryVisitor;
import de.siphalor.tweed5.core.api.entry.MutableStructuredConfigEntry;
import de.siphalor.tweed5.core.api.entry.SubEntryKey;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import java.util.LinkedHashMap;
import java.util.Map;
public class TestMapConfigEntry<V>
extends BaseConfigEntry<Map<String, V>>
implements MutableStructuredConfigEntry<Map<String, V>> {
private final ConfigEntry<V> valueEntry;
public TestMapConfigEntry(
ConfigContainer<?> container,
Class<Map<String, V>> valueClass,
ConfigEntry<V> valueEntry
) {
super(container, valueClass);
this.valueEntry = valueEntry;
}
@Override
public @NonNull Map<String, V> instantiateValue() {
return new LinkedHashMap<>();
}
@Override
public void set(Map<String, V> value, String dataKey, Object subValue) {
value.put(dataKey, (V) subValue);
}
@Override
public @Nullable ConfigEntry<?> getEntry(String dataKey) {
return valueEntry;
}
@Override
public Object get(Map<String, V> value, String dataKey) {
return value.get(dataKey);
}
@Override
public Map<String, ConfigEntry<?>> subEntries() {
return Map.of(":value", valueEntry);
}
@Override
public void visitInOrder(ConfigEntryVisitor visitor) {
if (visitor.enterStructuredEntry(this)) {
if (visitor.enterStructuredSubEntry(":value", Arity.ANY)) {
valueEntry.visitInOrder(visitor);
visitor.leaveStructuredSubEntry(":value", Arity.ANY);
}
visitor.leaveStructuredEntry(this);
}
}
@Override
public void visitInOrder(ConfigEntryValueVisitor visitor, Map<String, V> value) {
if (visitor.enterStructuredEntry(this, value)) {
value.forEach((key, subValue) -> {
SubEntryKey subEntryKey = SubEntryKey.addressable(":value", key, key);
if (visitor.enterSubEntry(subEntryKey)) {
valueEntry.visitInOrder(visitor, subValue);
visitor.leaveSubEntry(subEntryKey);
}
});
visitor.leaveStructuredEntry(this, value);
}
}
@Override
public Map<String, V> deepCopy(Map<String, V> value) {
Map<String, V> copy = instantiateValue();
value.forEach((key, subValue) -> copy.put(key, valueEntry.deepCopy(subValue)));
return copy;
}
}