[patchwork, core, extensions] Hugely simplify Patchworks

This commit is contained in:
2025-06-13 22:04:16 +02:00
parent 694f993b8c
commit 6e5c9a23c2
72 changed files with 987 additions and 1977 deletions

View File

@@ -1,6 +0,0 @@
package de.siphalor.tweed5.data.extension.api;
public interface EntryReaderWriterDefinition {
TweedEntryReader<?, ?> reader();
TweedEntryWriter<?, ?> writer();
}

View File

@@ -1,6 +0,0 @@
package de.siphalor.tweed5.data.extension.api;
public interface ReadWriteEntryDataExtension {
TweedEntryReader<?, ?> entryReaderChain();
TweedEntryWriter<?, ?> entryWriterChain();
}

View File

@@ -2,29 +2,120 @@ package de.siphalor.tweed5.data.extension.api;
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import de.siphalor.tweed5.core.api.extension.TweedExtension;
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteContextExtensionsData;
import de.siphalor.tweed5.data.extension.api.readwrite.TweedEntryReaderWriter;
import de.siphalor.tweed5.data.extension.impl.ReadWriteExtensionImpl;
import de.siphalor.tweed5.dataapi.api.TweedDataReader;
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
import de.siphalor.tweed5.patchwork.api.Patchwork;
import org.jspecify.annotations.Nullable;
import java.util.function.Consumer;
import java.util.function.Function;
public interface ReadWriteExtension extends TweedExtension {
Class<? extends ReadWriteExtension> DEFAULT = ReadWriteExtensionImpl.class;
void setEntryReaderWriterDefinition(ConfigEntry<?> entry, EntryReaderWriterDefinition readerWriterDefinition);
static <T> Consumer<ConfigEntry<T>> entryReaderWriter(
TweedEntryReaderWriter<T, ? extends ConfigEntry<T>> entryReaderWriter
) {
return entryReaderWriter(entryReaderWriter, entryReaderWriter);
}
ReadWriteContextExtensionsData createReadWriteContextExtensionsData();
static <T> Consumer<ConfigEntry<T>> entryReaderWriter(
TweedEntryReader<T, ? extends ConfigEntry<T>> entryReader,
TweedEntryWriter<T, ? extends ConfigEntry<T>> entryWriter
) {
return entry -> {
ReadWriteExtension extension = entry.container().extension(ReadWriteExtension.class)
.orElseThrow(() -> new IllegalStateException("No ReadWriteExtension present"));
extension.setEntryReader(entry, entryReader);
extension.setEntryWriter(entry, entryWriter);
};
}
<T extends @Nullable Object> T read(
static <T> Consumer<ConfigEntry<T>> entryReader(TweedEntryReader<T, ? extends ConfigEntry<T>> entryReader) {
return entry -> {
ReadWriteExtension extension = entry.container().extension(ReadWriteExtension.class)
.orElseThrow(() -> new IllegalStateException("No ReadWriteExtension present"));
extension.setEntryReader(entry, entryReader);
};
}
static <T> Consumer<ConfigEntry<T>> entryWriter(TweedEntryWriter<T, ? extends ConfigEntry<T>> entryWriter) {
return entry -> {
ReadWriteExtension extension = entry.container().extension(ReadWriteExtension.class)
.orElseThrow(() -> new IllegalStateException("No ReadWriteExtension present"));
extension.setEntryWriter(entry, entryWriter);
};
}
static <T extends @Nullable Object> Function<ConfigEntry<T>, T> read(TweedDataReader reader) {
return read(reader, null);
}
static <T extends @Nullable Object> Function<ConfigEntry<T>, T> read(
TweedDataReader reader,
@Nullable Consumer<Patchwork> contextExtensionsDataCustomizer
) {
return entry -> {
try {
ReadWriteExtension extension = entry.container().extension(ReadWriteExtension.class)
.orElseThrow(() -> new IllegalStateException("No ReadWriteExtension present"));
Patchwork contextExtensionsData = extension.createReadWriteContextExtensionsData();
if (contextExtensionsDataCustomizer != null) {
contextExtensionsDataCustomizer.accept(contextExtensionsData);
}
return extension.read(reader, entry, contextExtensionsData);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
static <T extends @Nullable Object> Consumer<ConfigEntry<T>> write(TweedDataVisitor writer, T value) {
return write(writer, value, null);
}
static <T extends @Nullable Object> Consumer<ConfigEntry<T>> write(
TweedDataVisitor writer,
T value,
@Nullable Consumer<Patchwork> contextExtensionsDataCustomizer
) {
return entry -> {
try {
ReadWriteExtension extension = entry.container().extension(ReadWriteExtension.class)
.orElseThrow(() -> new IllegalStateException("No ReadWriteExtension present"));
Patchwork contextExtensionsData = extension.createReadWriteContextExtensionsData();
if (contextExtensionsDataCustomizer != null) {
contextExtensionsDataCustomizer.accept(contextExtensionsData);
}
extension.write(writer, value, entry, contextExtensionsData);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
<T, C extends ConfigEntry<T>> void setEntryReaderWriter(
ConfigEntry<T> entry,
ReadWriteContextExtensionsData contextExtensionsData
) throws TweedEntryReadException;
TweedEntryReader<T, C> entryReader,
TweedEntryWriter<T, C> entryWriter
);
<T, C extends ConfigEntry<T>> void setEntryReader(ConfigEntry<T> entry, TweedEntryReader<T, C> entryReader);
<T, C extends ConfigEntry<T>> void setEntryWriter(ConfigEntry<T> entry, TweedEntryWriter<T, C> entryWriter);
Patchwork createReadWriteContextExtensionsData();
<T extends @Nullable Object> T read(TweedDataReader reader, ConfigEntry<T> entry, Patchwork contextExtensionsData)
throws TweedEntryReadException;
<T extends @Nullable Object> void write(
TweedDataVisitor writer,
T value,
ConfigEntry<T> entry,
ReadWriteContextExtensionsData contextExtensionsData
Patchwork contextExtensionsData
) throws TweedEntryWriteException;
<T, C extends ConfigEntry<T>> TweedEntryReader<T, C> getReaderChain(C entry);
<T, C extends ConfigEntry<T>> TweedEntryWriter<T, C> getWriterChain(C entry);
}

View File

@@ -1,7 +1,8 @@
package de.siphalor.tweed5.data.extension.api;
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteContextExtensionsData;
import de.siphalor.tweed5.patchwork.api.Patchwork;
public interface TweedReadContext {
ReadWriteContextExtensionsData extensionsData();
ReadWriteExtension readWriteExtension();
Patchwork extensionsData();
}

View File

@@ -1,7 +1,8 @@
package de.siphalor.tweed5.data.extension.api;
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteContextExtensionsData;
import de.siphalor.tweed5.patchwork.api.Patchwork;
public interface TweedWriteContext {
ReadWriteContextExtensionsData extensionsData();
ReadWriteExtension readWriteExtension();
Patchwork extensionsData();
}

View File

@@ -1,6 +0,0 @@
package de.siphalor.tweed5.data.extension.api.extension;
import de.siphalor.tweed5.patchwork.api.Patchwork;
public interface ReadWriteContextExtensionsData extends Patchwork<ReadWriteContextExtensionsData> {
}

View File

@@ -1,7 +1,7 @@
package de.siphalor.tweed5.data.extension.api.extension;
import de.siphalor.tweed5.core.api.extension.RegisteredExtensionData;
import de.siphalor.tweed5.patchwork.api.PatchworkPartAccess;
public interface ReadWriteExtensionSetupContext {
<E> RegisteredExtensionData<ReadWriteContextExtensionsData, E> registerReadWriteContextExtensionData(Class<E> extensionDataClass);
<E> PatchworkPartAccess<E> registerReadWriteContextExtensionData(Class<E> extensionDataClass);
}

View File

@@ -3,5 +3,6 @@ package de.siphalor.tweed5.data.extension.api.readwrite;
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import de.siphalor.tweed5.data.extension.api.TweedEntryReader;
import de.siphalor.tweed5.data.extension.api.TweedEntryWriter;
import org.jspecify.annotations.Nullable;
public interface TweedEntryReaderWriter<T, C extends ConfigEntry<T>> extends TweedEntryReader<T, C>, TweedEntryWriter<T, C> {}
public interface TweedEntryReaderWriter<T extends @Nullable Object, C extends ConfigEntry<T>> extends TweedEntryReader<T, C>, TweedEntryWriter<T, C> {}

View File

@@ -3,56 +3,41 @@ package de.siphalor.tweed5.data.extension.impl;
import com.google.auto.service.AutoService;
import de.siphalor.tweed5.core.api.container.ConfigContainer;
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import de.siphalor.tweed5.core.api.extension.EntryExtensionsData;
import de.siphalor.tweed5.core.api.extension.RegisteredExtensionData;
import de.siphalor.tweed5.core.api.extension.TweedExtension;
import de.siphalor.tweed5.core.api.extension.TweedExtensionSetupContext;
import de.siphalor.tweed5.core.api.middleware.DefaultMiddlewareContainer;
import de.siphalor.tweed5.data.extension.api.*;
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteContextExtensionsData;
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteExtensionSetupContext;
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteRelatedExtension;
import de.siphalor.tweed5.dataapi.api.TweedDataReadException;
import de.siphalor.tweed5.dataapi.api.TweedDataReader;
import de.siphalor.tweed5.dataapi.api.TweedDataWriteException;
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
import de.siphalor.tweed5.dataapi.api.TweedDataWriteException;
import de.siphalor.tweed5.patchwork.api.Patchwork;
import de.siphalor.tweed5.patchwork.api.PatchworkClassCreator;
import de.siphalor.tweed5.patchwork.impl.PatchworkClass;
import de.siphalor.tweed5.patchwork.impl.PatchworkClassGenerator;
import de.siphalor.tweed5.patchwork.impl.PatchworkClassPart;
import lombok.Setter;
import lombok.Value;
import de.siphalor.tweed5.patchwork.api.PatchworkFactory;
import de.siphalor.tweed5.patchwork.api.PatchworkPartAccess;
import lombok.Data;
import lombok.val;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import java.lang.invoke.MethodHandle;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@AutoService(ReadWriteExtension.class)
public class ReadWriteExtensionImpl implements ReadWriteExtension {
private final ConfigContainer<?> configContainer;
private final RegisteredExtensionData<EntryExtensionsData, EntryReaderWriterDefinition>
readerWriterDefinitionExtension;
private final RegisteredExtensionData<EntryExtensionsData, ReadWriteEntryDataExtension> readWriteEntryDataExtension;
private final PatchworkPartAccess<CustomEntryData> customEntryDataAccess;
private DefaultMiddlewareContainer<TweedEntryReader<?, ?>>
entryReaderMiddlewareContainer
= new DefaultMiddlewareContainer<>();
private DefaultMiddlewareContainer<TweedEntryWriter<?, ?>>
entryWriterMiddlewareContainer
= new DefaultMiddlewareContainer<>();
private final Map<Class<?>, RegisteredExtensionDataImpl<ReadWriteContextExtensionsData, ?>>
readWriteContextExtensionsDataClasses
= new HashMap<>();
private @Nullable PatchworkClass<@NonNull ReadWriteContextExtensionsData> readWriteContextExtensionsDataPatchwork;
private @Nullable PatchworkFactory readWriteContextPatchworkFactory;
public ReadWriteExtensionImpl(ConfigContainer<?> configContainer, TweedExtensionSetupContext context) {
this.configContainer = configContainer;
this.readerWriterDefinitionExtension = context.registerEntryExtensionData(EntryReaderWriterDefinition.class);
this.readWriteEntryDataExtension = context.registerEntryExtensionData(ReadWriteEntryDataExtension.class);
this.customEntryDataAccess = context.registerEntryExtensionData(CustomEntryData.class);
}
@Override
@@ -64,23 +49,8 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
public void extensionsFinalized() {
Collection<TweedExtension> extensions = configContainer.extensions();
ReadWriteExtensionSetupContext setupContext = new ReadWriteExtensionSetupContext() {
@Override
public <E> RegisteredExtensionData<ReadWriteContextExtensionsData, E> registerReadWriteContextExtensionData(
Class<E> extensionDataClass
) {
if (readWriteContextExtensionsDataClasses.containsKey(extensionDataClass)) {
throw new IllegalArgumentException("Context extension "
+ extensionDataClass.getName()
+ " is already registered");
}
RegisteredExtensionDataImpl<ReadWriteContextExtensionsData, E>
registeredExtensionData
= new RegisteredExtensionDataImpl<>();
readWriteContextExtensionsDataClasses.put(extensionDataClass, registeredExtensionData);
return registeredExtensionData;
}
};
PatchworkFactory.Builder readWriteContextPatchworkFactorBuilder = PatchworkFactory.builder();
ReadWriteExtensionSetupContext setupContext = readWriteContextPatchworkFactorBuilder::registerPart;
entryReaderMiddlewareContainer = new DefaultMiddlewareContainer<>();
entryWriterMiddlewareContainer = new DefaultMiddlewareContainer<>();
@@ -102,79 +72,62 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
}
}
readWriteContextPatchworkFactory = readWriteContextPatchworkFactorBuilder.build();
entryReaderMiddlewareContainer.seal();
entryWriterMiddlewareContainer.seal();
}
val patchworkClassCreator = PatchworkClassCreator.<ReadWriteContextExtensionsData>builder()
.patchworkInterface(ReadWriteContextExtensionsData.class)
.classPackage("de.siphalor.tweed5.data.extension.generated")
.classPrefix("ReadWriteContextExtensionsData$")
.build();
@Override
public <T, C extends ConfigEntry<T>> void setEntryReaderWriter(
ConfigEntry<T> entry,
TweedEntryReader<T, C> entryReader,
TweedEntryWriter<T, C> entryWriter
) {
CustomEntryData customEntryData = getOrCreateCustomEntryData(entry);
customEntryData.readerDefinition(entryReader);
customEntryData.writerDefinition(entryWriter);
}
try {
readWriteContextExtensionsDataPatchwork =
patchworkClassCreator.createClass(readWriteContextExtensionsDataClasses.keySet());
for (PatchworkClassPart patchworkClassPart : readWriteContextExtensionsDataPatchwork.parts()) {
RegisteredExtensionDataImpl<ReadWriteContextExtensionsData, ?>
registeredExtension
= readWriteContextExtensionsDataClasses.get(patchworkClassPart.partInterface());
registeredExtension.setter = patchworkClassPart.fieldSetter();
}
} catch (PatchworkClassGenerator.GenerationException e) {
throw new IllegalStateException(
"Failed to generate read write context extensions' data patchwork class",
e
);
}
@Override
public <T, C extends ConfigEntry<T>> void setEntryReader(ConfigEntry<T> entry, TweedEntryReader<T, C> entryReader) {
getOrCreateCustomEntryData(entry).readerDefinition(entryReader);
}
@Override
public <T, C extends ConfigEntry<T>> void setEntryWriter(ConfigEntry<T> entry, TweedEntryWriter<T, C> entryWriter) {
getOrCreateCustomEntryData(entry).writerDefinition(entryWriter);
}
@Override
public void initEntry(ConfigEntry<?> configEntry) {
TweedEntryReader<?, ?> baseReader;
TweedEntryWriter<?, ?> baseWriter;
if (configEntry.extensionsData().isPatchworkPartSet(EntryReaderWriterDefinition.class)) {
EntryReaderWriterDefinition rwDefintion = (EntryReaderWriterDefinition) configEntry.extensionsData();
baseReader = rwDefintion.reader();
baseWriter = rwDefintion.writer();
} else {
baseReader = TweedEntryReaderWriterImpls.NOOP_READER_WRITER;
baseWriter = TweedEntryReaderWriterImpls.NOOP_READER_WRITER;
CustomEntryData customEntryData = getOrCreateCustomEntryData(configEntry);
customEntryData.readerChain(entryReaderMiddlewareContainer.process(customEntryData.readerDefinition()));
customEntryData.writerChain(entryWriterMiddlewareContainer.process(customEntryData.writerDefinition()));
}
private CustomEntryData getOrCreateCustomEntryData(ConfigEntry<?> entry) {
CustomEntryData entryData = entry.extensionsData().get(customEntryDataAccess);
if (entryData == null) {
entryData = new CustomEntryData();
entry.extensionsData().set(customEntryDataAccess, entryData);
}
readWriteEntryDataExtension.set(
configEntry.extensionsData(), new ReadWriteEntryDataExtensionImpl(
entryReaderMiddlewareContainer.process(baseReader),
entryWriterMiddlewareContainer.process(baseWriter)
)
);
return entryData;
}
@Override
public void setEntryReaderWriterDefinition(
@NonNull ConfigEntry<?> entry,
@NonNull EntryReaderWriterDefinition readerWriterDefinition
) {
readerWriterDefinitionExtension.set(entry.extensionsData(), readerWriterDefinition);
public Patchwork createReadWriteContextExtensionsData() {
assert readWriteContextPatchworkFactory != null;
return readWriteContextPatchworkFactory.create();
}
@Override
public ReadWriteContextExtensionsData createReadWriteContextExtensionsData() {
try {
assert readWriteContextExtensionsDataPatchwork != null;
return (ReadWriteContextExtensionsData) readWriteContextExtensionsDataPatchwork.constructor().invoke();
} catch (Throwable e) {
throw new IllegalStateException("Failed to instantiate read write context extensions' data", e);
}
}
@Override
public <T extends @Nullable Object> T read(
@NonNull TweedDataReader reader,
@NonNull ConfigEntry<T> entry,
@NonNull ReadWriteContextExtensionsData contextExtensionsData
TweedDataReader reader,
ConfigEntry<T> entry,
Patchwork contextExtensionsData
) throws TweedEntryReadException {
try {
return getReaderChain(entry).read(reader, entry, new TweedReadWriteContextImpl(contextExtensionsData));
return getReaderChain(entry).read(reader, entry, new TweedReadWriteContextImpl(this, contextExtensionsData));
} catch (TweedDataReadException e) {
throw new TweedEntryReadException("Failed to read entry", e);
}
@@ -182,46 +135,35 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
@Override
public <T extends @Nullable Object> void write(
@NonNull TweedDataVisitor writer,
TweedDataVisitor writer,
@Nullable T value,
@NonNull ConfigEntry<T> entry,
@NonNull ReadWriteContextExtensionsData contextExtensionsData
ConfigEntry<T> entry,
Patchwork contextExtensionsData
) throws TweedEntryWriteException {
try {
getWriterChain(entry).write(writer, value, entry, new TweedReadWriteContextImpl(contextExtensionsData));
getWriterChain(entry).write(writer, value, entry, new TweedReadWriteContextImpl(this, contextExtensionsData));
} catch (TweedDataWriteException e) {
throw new TweedEntryWriteException("Failed to write entry", e);
}
}
@Value
private static class ReadWriteEntryDataExtensionImpl implements ReadWriteEntryDataExtension {
TweedEntryReader<?, ?> entryReaderChain;
TweedEntryWriter<?, ?> entryWriterChain;
@Data
private static class CustomEntryData {
private TweedEntryReader<?, ?> readerDefinition = TweedEntryReaderWriterImpls.NOOP_READER_WRITER;
private TweedEntryWriter<?, ?> writerDefinition = TweedEntryReaderWriterImpls.NOOP_READER_WRITER;
private TweedEntryReader<?, ?> readerChain;
private TweedEntryWriter<?, ?> writerChain;
}
@Setter
private static class RegisteredExtensionDataImpl<U extends Patchwork<@NonNull U>, E>
implements RegisteredExtensionData<U, E> {
private MethodHandle setter;
@Override
public void set(U patchwork, E extension) {
try {
setter.invokeWithArguments(patchwork, extension);
} catch (Throwable e) {
throw new IllegalStateException(e);
}
}
}
static <T> TweedEntryReader<T, @NonNull ConfigEntry<T>> getReaderChain(ConfigEntry<T> elementEntry) {
@Override
public <T, C extends ConfigEntry<T>> TweedEntryReader<T, C> getReaderChain(C entry) {
//noinspection unchecked
return (TweedEntryReader<T, @NonNull ConfigEntry<T>>) ((ReadWriteEntryDataExtension) elementEntry.extensionsData()).entryReaderChain();
return (TweedEntryReader<T, C>) entry.extensionsData().get(customEntryDataAccess).readerChain();
}
static <T> TweedEntryWriter<T, @NonNull ConfigEntry<T>> getWriterChain(ConfigEntry<T> elementEntry) {
@Override
public <T, C extends ConfigEntry<T>> TweedEntryWriter<T, C> getWriterChain(C entry) {
//noinspection unchecked
return (TweedEntryWriter<T, @NonNull ConfigEntry<T>>) ((ReadWriteEntryDataExtension) elementEntry.extensionsData()).entryWriterChain();
return (TweedEntryWriter<T, C>) entry.extensionsData().get(customEntryDataAccess).writerChain();
}
}

View File

@@ -10,7 +10,6 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import java.util.*;
@@ -63,7 +62,7 @@ public class TweedEntryReaderWriterImpls {
}
@RequiredArgsConstructor
private static class PrimitiveReaderWriter<T extends @NonNull Object> implements TweedEntryReaderWriter<T, ConfigEntry<T>> {
private static class PrimitiveReaderWriter<T extends @Nullable Object> implements TweedEntryReaderWriter<T, ConfigEntry<T>> {
private final Function<TweedDataToken, T> readerCall;
private final BiConsumer<TweedDataVisitor, T> writerCall;
@@ -79,7 +78,7 @@ public class TweedEntryReaderWriterImpls {
}
}
public static class CollectionReaderWriter<T extends @NonNull Object, C extends Collection<T>> implements TweedEntryReaderWriter<C, CollectionConfigEntry<T, C>> {
public static class CollectionReaderWriter<T extends @Nullable Object, C extends Collection<T>> implements TweedEntryReaderWriter<C, CollectionConfigEntry<T, C>> {
@Override
public C read(TweedDataReader reader, CollectionConfigEntry<T, C> entry, TweedReadContext context) throws TweedEntryReadException, TweedDataReadException {
assertIsToken(reader.readToken(), TweedDataToken::isListStart, "Expected list start");
@@ -89,9 +88,9 @@ public class TweedEntryReaderWriterImpls {
}
ConfigEntry<T> elementEntry = entry.elementEntry();
TweedEntryReader<T, ConfigEntry<T>> elementReader = ReadWriteExtensionImpl.getReaderChain(elementEntry);
TweedEntryReader<T, ConfigEntry<T>> elementReader = context.readWriteExtension().getReaderChain(elementEntry);
List<T> list = new ArrayList<>(20);
List<@Nullable T> list = new ArrayList<>(20);
while (true) {
token = reader.peekToken();
if (token.isListEnd()) {
@@ -119,7 +118,7 @@ public class TweedEntryReaderWriterImpls {
}
ConfigEntry<T> elementEntry = entry.elementEntry();
TweedEntryWriter<T, ConfigEntry<T>> elementWriter = ReadWriteExtensionImpl.getWriterChain(elementEntry);
TweedEntryWriter<T, ConfigEntry<T>> elementWriter = context.readWriteExtension().getWriterChain(elementEntry);
writer.visitListStart();
for (T element : value) {
@@ -129,7 +128,7 @@ public class TweedEntryReaderWriterImpls {
}
}
public static class CompoundReaderWriter<T extends @NonNull Object> implements TweedEntryReaderWriter<T, CompoundConfigEntry<T>> {
public static class CompoundReaderWriter<T> implements TweedEntryReaderWriter<T, CompoundConfigEntry<T>> {
@Override
public T read(TweedDataReader reader, CompoundConfigEntry<T> entry, TweedReadContext context) throws TweedEntryReadException, TweedDataReadException {
assertIsToken(reader.readToken(), TweedDataToken::isMapStart, "Expected map start");
@@ -145,7 +144,7 @@ public class TweedEntryReaderWriterImpls {
//noinspection unchecked
ConfigEntry<Object> subEntry = (ConfigEntry<Object>) compoundEntries.get(key);
TweedEntryReader<Object, ConfigEntry<Object>> subEntryReaderChain = ReadWriteExtensionImpl.getReaderChain(subEntry);
TweedEntryReader<Object, ConfigEntry<Object>> subEntryReaderChain = context.readWriteExtension().getReaderChain(subEntry);
Object subEntryValue = subEntryReaderChain.read(reader, subEntry, context);
entry.set(compoundValue, key, subEntryValue);
} else {
@@ -167,7 +166,7 @@ public class TweedEntryReaderWriterImpls {
String key = e.getKey();
ConfigEntry<Object> subEntry = e.getValue();
TweedEntryWriter<Object, ConfigEntry<Object>> subEntryWriterChain = ReadWriteExtensionImpl.getWriterChain(subEntry);
TweedEntryWriter<Object, ConfigEntry<Object>> subEntryWriterChain = context.readWriteExtension().getWriterChain(subEntry);
writer.visitMapEntryKey(key);
subEntryWriterChain.write(writer, entry.get(value, key), subEntry, context);

View File

@@ -1,11 +1,13 @@
package de.siphalor.tweed5.data.extension.impl;
import de.siphalor.tweed5.data.extension.api.ReadWriteExtension;
import de.siphalor.tweed5.data.extension.api.TweedReadContext;
import de.siphalor.tweed5.data.extension.api.TweedWriteContext;
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteContextExtensionsData;
import de.siphalor.tweed5.patchwork.api.Patchwork;
import lombok.Value;
@Value
public class TweedReadWriteContextImpl implements TweedReadContext, TweedWriteContext {
ReadWriteContextExtensionsData extensionsData;
ReadWriteExtension readWriteExtension;
Patchwork extensionsData;
}

View File

@@ -1,23 +1,18 @@
package de.siphalor.tweed5.data.extension.impl;
import de.siphalor.tweed5.core.api.container.ConfigContainer;
import de.siphalor.tweed5.core.api.extension.EntryExtensionsData;
import de.siphalor.tweed5.core.api.extension.RegisteredExtensionData;
import de.siphalor.tweed5.core.api.entry.CollectionConfigEntry;
import de.siphalor.tweed5.core.api.entry.CompoundConfigEntry;
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.data.extension.api.EntryReaderWriterDefinition;
import de.siphalor.tweed5.data.extension.api.ReadWriteExtension;
import de.siphalor.tweed5.data.extension.api.TweedEntryReader;
import de.siphalor.tweed5.data.extension.api.TweedEntryWriter;
import de.siphalor.tweed5.data.extension.api.readwrite.TweedEntryReaderWriter;
import de.siphalor.tweed5.data.extension.api.readwrite.TweedEntryReaderWriters;
import de.siphalor.tweed5.data.hjson.HjsonLexer;
import de.siphalor.tweed5.data.hjson.HjsonReader;
import de.siphalor.tweed5.data.hjson.HjsonWriter;
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
import lombok.RequiredArgsConstructor;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -27,6 +22,8 @@ import java.io.Writer;
import java.util.*;
import java.util.function.Function;
import static de.siphalor.tweed5.data.extension.api.ReadWriteExtension.entryReaderWriter;
import static de.siphalor.tweed5.data.extension.api.readwrite.TweedEntryReaderWriters.*;
import static de.siphalor.tweed5.testutils.MapTestUtils.sequencedMap;
import static java.util.Map.entry;
import static org.assertj.core.api.Assertions.assertThat;
@@ -36,7 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
class ReadWriteExtensionImplTest {
private final StringWriter stringWriter = new StringWriter();
private final ConfigContainer<Map<String, Object>> configContainer = new DefaultConfigContainer<>();
private StaticMapCompoundConfigEntryImpl<Map<String, Object>> rootEntry;
private CompoundConfigEntry<Map<String, Object>> rootEntry;
@SuppressWarnings("unchecked")
@BeforeEach
@@ -44,14 +41,16 @@ class ReadWriteExtensionImplTest {
configContainer.registerExtension(ReadWriteExtension.DEFAULT);
configContainer.finishExtensionSetup();
SimpleConfigEntryImpl<Integer> intEntry = new SimpleConfigEntryImpl<>(configContainer, Integer.class);
SimpleConfigEntryImpl<Boolean> booleanEntry = new SimpleConfigEntryImpl<>(configContainer, Boolean.class);
CollectionConfigEntryImpl<Boolean, List<Boolean>> listEntry = new CollectionConfigEntryImpl<>(
SimpleConfigEntry<Integer> intEntry = new SimpleConfigEntryImpl<>(configContainer, Integer.class)
.apply(entryReaderWriter(intReaderWriter()));
CollectionConfigEntry<Boolean, List<Boolean>> listEntry = new CollectionConfigEntryImpl<>(
configContainer,
(Class<List<Boolean>>) (Class<?>) List.class,
ArrayList::new,
booleanEntry
);
new SimpleConfigEntryImpl<>(configContainer, Boolean.class)
.apply(entryReaderWriter(booleanReaderWriter()))
).apply(entryReaderWriter(collectionReaderWriter()));
rootEntry = new StaticMapCompoundConfigEntryImpl<>(
configContainer,
@@ -61,16 +60,9 @@ class ReadWriteExtensionImplTest {
entry("int", intEntry),
entry("list", listEntry)
))
);
).apply(entryReaderWriter(compoundReaderWriter()));
configContainer.attachTree(rootEntry);
RegisteredExtensionData<EntryExtensionsData, EntryReaderWriterDefinition> readerWriterData = (RegisteredExtensionData<EntryExtensionsData, EntryReaderWriterDefinition>) configContainer.entryDataExtensions().get(EntryReaderWriterDefinition.class);
readerWriterData.set(rootEntry.extensionsData(), new TrivialEntryReaderWriterDefinition(TweedEntryReaderWriters.compoundReaderWriter()));
readerWriterData.set(intEntry.extensionsData(), new TrivialEntryReaderWriterDefinition(TweedEntryReaderWriters.intReaderWriter()));
readerWriterData.set(listEntry.extensionsData(), new TrivialEntryReaderWriterDefinition(TweedEntryReaderWriters.collectionReaderWriter()));
readerWriterData.set(booleanEntry.extensionsData(), new TrivialEntryReaderWriterDefinition(TweedEntryReaderWriters.booleanReaderWriter()));
configContainer.initialize();
}
@@ -128,19 +120,4 @@ class ReadWriteExtensionImplTest {
private TweedDataVisitor setupWriter(Function<Writer, TweedDataVisitor> writerFactory) {
return writerFactory.apply(stringWriter);
}
@RequiredArgsConstructor
private static class TrivialEntryReaderWriterDefinition implements EntryReaderWriterDefinition {
private final TweedEntryReaderWriter<?, ?> readerWriter;
@Override
public TweedEntryReader<?, ?> reader() {
return readerWriter;
}
@Override
public TweedEntryWriter<?, ?> writer() {
return readerWriter;
}
}
}