[patchwork, core, extensions] Hugely simplify Patchworks
This commit is contained in:
@@ -1,6 +0,0 @@
|
||||
package de.siphalor.tweed5.data.extension.api;
|
||||
|
||||
public interface EntryReaderWriterDefinition {
|
||||
TweedEntryReader<?, ?> reader();
|
||||
TweedEntryWriter<?, ?> writer();
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package de.siphalor.tweed5.data.extension.api;
|
||||
|
||||
public interface ReadWriteEntryDataExtension {
|
||||
TweedEntryReader<?, ?> entryReaderChain();
|
||||
TweedEntryWriter<?, ?> entryWriterChain();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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> {}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user